Skip to content

Commit 5b7b3bd

Browse files
committed
Unify creation of discrimination data and fill in missing get_fn_addr call sites
1 parent d355ced commit 5b7b3bd

19 files changed

Lines changed: 272 additions & 52 deletions

File tree

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>(
3232
llfn: &'ll llvm::Value,
3333
schema: PointerAuthSchema,
3434
) -> &'ll llvm::Value {
35-
if cx.tcx.sess.pointer_authentication_functions().is_none() {
36-
return llfn;
37-
}
35+
assert!(cx.tcx.sess.pointer_authentication_functions().is_some());
3836

3937
// Only free functions or methods
4038
let def_id = instance.def_id();

compiler/rustc_codegen_llvm/src/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::mir::interpret::{
1515
};
1616
use rustc_middle::mono::MonoItem;
1717
use rustc_middle::ptrauth::{
18-
build_fn_ptr_type_discriminator_input, compute_fn_ptr_type_discriminator,
18+
build_fn_ptr_type_discriminator_input_from_ty, compute_fn_ptr_type_discriminator,
1919
};
2020
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
2121
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,16 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
973973

974974
let tcx = self.tcx;
975975
let llfn = match tcx.lang_items().eh_personality() {
976+
// We intentionally do NOT apply pointer authentication (and/or function type
977+
// discriminators to the EH personality function).
978+
//
979+
// Although `get_fn_addr` normally produces a signed function pointer for
980+
// externally-callable functions, the EH personality is not an indirect call
981+
// target in the SSA sense. Instead, it is a compile-time constant attached to
982+
// the Function object (via LLVM's `setPersonalityFn`) and consumed only by
983+
// exception handling metadata generation (landing pads / unwind tables).
984+
// LLVM never loads or invokes the personality via a function pointer value;
985+
// it is not part of the program's call graph or data flow.
976986
Some(def_id) if name.is_none() => self.get_fn_addr(
977987
ty::Instance::expect_resolve(
978988
tcx,
@@ -981,7 +991,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
981991
ty::List::empty(),
982992
DUMMY_SP,
983993
),
984-
tcx.sess.pointer_authentication_functions(),
994+
None,
985995
),
986996
_ => {
987997
let name = name.unwrap_or("rust_eh_personality");

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
492492
// We want to create the wrapper only when the codegen unit is the primary one
493493
return None;
494494
}
495-
496-
let main_llfn = cx.get_fn_addr(instance, cx.sess().pointer_authentication_functions());
495+
// No function pointer signing / type discriminator is needed here. Although `get_fn_addr` is
496+
// used to obtain function pointers, both the user's `main` and `LangItem::Start` use the Rust
497+
// ABI (currently pointer authentication is only supported for C/System ABI). The same applies
498+
// to the logic in `create_entry_fn` further below.
499+
let main_llfn = cx.get_fn_addr(instance, None);
497500

498501
let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
499502
return Some(entry_fn);
@@ -554,8 +557,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
554557
cx.tcx().mk_args(&[main_ret_ty.into()]),
555558
DUMMY_SP,
556559
);
557-
let start_fn =
558-
cx.get_fn_addr(start_instance, cx.sess().pointer_authentication_functions());
560+
561+
let start_fn = cx.get_fn_addr(start_instance, None);
559562

560563
let i8_ty = cx.type_i8();
561564
let arg_sigpipe = bx.const_u8(sigpipe);

compiler/rustc_codegen_ssa/src/common.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
use rustc_hir::LangItem;
44
use rustc_hir::attrs::PeImportNameType;
5+
use rustc_middle::ptrauth::{
6+
build_fn_ptr_type_discriminator_input_from_instance, compute_fn_ptr_type_discriminator,
7+
};
58
use rustc_middle::ty::layout::TyAndLayout;
69
use rustc_middle::ty::{self, Instance, TyCtxt};
710
use rustc_middle::{bug, mir, span_bug};
@@ -117,11 +120,19 @@ pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
117120
let tcx = bx.tcx();
118121
let def_id = tcx.require_lang_item(li, span);
119122
let instance = ty::Instance::mono(tcx, def_id);
120-
(
121-
bx.fn_abi_of_instance(instance, ty::List::empty()),
122-
bx.get_fn_addr(instance, tcx.sess.pointer_authentication_functions()),
123-
instance,
124-
)
123+
let mut schema = bx.sess().pointer_authentication_functions().clone();
124+
125+
if let Some(ref mut s) = schema
126+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
127+
{
128+
// It is unlikely that any of LangItem will follow the extern C/System ABI, but it future
129+
// proofs the implementation.
130+
let disc_input = build_fn_ptr_type_discriminator_input_from_instance(tcx, instance);
131+
let disc = compute_fn_ptr_type_discriminator(tcx, &disc_input) as u16;
132+
133+
s.constant_discriminator = disc;
134+
}
135+
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance, schema), instance)
125136
}
126137

127138
pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ use rustc_hir::attrs::AttributeKind;
1111
use rustc_hir::lang_items::LangItem;
1212
use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER;
1313
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
14+
use rustc_middle::ptrauth::{
15+
build_fn_ptr_type_discriminator_input_from_instance, compute_fn_ptr_type_discriminator,
16+
};
1417
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1518
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1619
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
@@ -684,12 +687,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
684687
virtual_drop,
685688
)
686689
}
687-
_ => (
688-
false,
689-
bx.get_fn_addr(drop_fn, bx.sess().pointer_authentication_functions()),
690-
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
691-
drop_fn,
692-
),
690+
_ => {
691+
let mut schema = bx.sess().pointer_authentication_functions().clone();
692+
693+
if let Some(ref mut s) = schema
694+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
695+
{
696+
let disc_input =
697+
build_fn_ptr_type_discriminator_input_from_instance(bx.tcx(), drop_fn);
698+
let disc = compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
699+
700+
s.constant_discriminator = disc;
701+
}
702+
(
703+
false,
704+
bx.get_fn_addr(drop_fn, schema),
705+
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
706+
drop_fn,
707+
)
708+
}
693709
};
694710

695711
// We generate a null check for the drop_fn. This saves a bunch of relocations being
@@ -1102,13 +1118,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11021118
)
11031119
.unwrap();
11041120

1105-
(
1106-
None,
1107-
Some(bx.get_fn_addr(
1121+
let mut schema = bx.sess().pointer_authentication_functions().clone();
1122+
1123+
if let Some(ref mut s) = schema
1124+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
1125+
{
1126+
let disc_input = build_fn_ptr_type_discriminator_input_from_instance(
1127+
bx.tcx(),
11081128
instance,
1109-
bx.sess().pointer_authentication_functions(),
1110-
)),
1111-
)
1129+
);
1130+
let disc =
1131+
compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
1132+
1133+
s.constant_discriminator = disc;
1134+
};
1135+
1136+
(None, Some(bx.get_fn_addr(instance, schema)))
11121137
}
11131138
_ => (Some(instance), None),
11141139
}
@@ -1422,7 +1447,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14221447

14231448
let fn_ptr = match (instance, llfn) {
14241449
(Some(instance), None) => {
1425-
bx.get_fn_addr(instance, bx.sess().pointer_authentication_functions())
1450+
let mut schema = bx.sess().pointer_authentication_functions().clone();
1451+
1452+
if let Some(ref mut s) = schema
1453+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
1454+
{
1455+
let disc_input =
1456+
build_fn_ptr_type_discriminator_input_from_instance(bx.tcx(), instance);
1457+
let disc = compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
1458+
1459+
s.constant_discriminator = disc;
1460+
}
1461+
1462+
bx.get_fn_addr(instance, schema)
14261463
}
14271464
(_, Some(llfn)) => llfn,
14281465
_ => span_bug!(fn_span, "no instance or llfn for call"),

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use itertools::Itertools as _;
22
use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT};
33
use rustc_middle::ptrauth::{
4-
build_fn_ptr_type_discriminator_input, compute_fn_ptr_type_discriminator,
4+
build_fn_ptr_type_discriminator_input_from_ty, compute_fn_ptr_type_discriminator,
55
};
66
use rustc_middle::ty::adjustment::PointerCoercion;
77
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
@@ -70,8 +70,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
7070
) -> Bx::Value {
7171
let tcx = bx.tcx();
7272

73-
let src_input = build_fn_ptr_type_discriminator_input(tcx, info.src_ty);
74-
let dst_input = build_fn_ptr_type_discriminator_input(tcx, info.dst_ty);
73+
let src_input = build_fn_ptr_type_discriminator_input_from_ty(tcx, info.src_ty);
74+
let dst_input = build_fn_ptr_type_discriminator_input_from_ty(tcx, info.dst_ty);
7575

7676
let src_disc = match src_input {
7777
Some(src) => compute_fn_ptr_type_discriminator(tcx, &src),
@@ -612,7 +612,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
612612

613613
if let Some(ref mut s) = schema {
614614
if bx.sess().pointer_authentication_fn_ptr_type_discrimination() {
615-
if let Some(input) = build_fn_ptr_type_discriminator_input(
615+
if let Some(input) = build_fn_ptr_type_discriminator_input_from_ty(
616616
bx.tcx(),
617617
operand.layout.ty,
618618
) {
@@ -640,9 +640,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
640640
ty::ClosureKind::FnOnce,
641641
);
642642
OperandValue::Immediate(
643+
// A closure coerced to a function pointer retains the Rust
644+
// ABI. Pointer authentication only applies to extern
645+
// "C"/System ABI function pointer, hence pass None to
646+
// `get_fn_addr`.
643647
bx.cx().get_fn_addr(
644648
instance,
645-
bx.sess().pointer_authentication_functions(),
649+
None,
646650
),
647651
)
648652
}
@@ -868,8 +872,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
868872
def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)),
869873
args: ty::GenericArgs::empty(),
870874
};
871-
let fn_ptr =
872-
bx.get_fn_addr(instance, bx.sess().pointer_authentication_functions());
875+
// This is the address of a compiler-generated TLS shim function. It is not an
876+
// externally visible function pointer and does not require function pointer
877+
// authentication signing.
878+
let fn_ptr = bx.get_fn_addr(instance, None);
873879
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
874880
let fn_ty = bx.fn_decl_backend_type(fn_abi);
875881
let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() {

compiler/rustc_middle/src/ptrauth/discriminator.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ The computation is structured into three conceptual stages:
4242
4343
- Public API
4444
- `FnPtrTypeDiscriminatorInput`
45-
- `build_fn_ptr_type_discriminator_input`
45+
- `build_fn_ptr_type_discriminator_input_from_instance`
46+
- `build_fn_ptr_type_discriminator_input_from_sig`
47+
- `build_fn_ptr_type_discriminator_input_from_ty`
4648
- `compute_fn_ptr_type_discriminator`
4749
4850
- Signature extraction
@@ -68,7 +70,7 @@ function types only. It does NOT attempt to model full type system rules.
6870
*/
6971

7072
use rustc_abi::ExternAbi;
71-
use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized};
73+
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, Unnormalized};
7274
use rustc_span::sym;
7375

7476
use crate::ptrauth::llvm_siphash::llvm_pointer_auth_stable_siphash;
@@ -84,7 +86,7 @@ pub struct FnPtrTypeDiscriminatorInput<'tcx> {
8486
}
8587

8688
impl<'tcx> FnPtrTypeDiscriminatorInput<'tcx> {
87-
pub fn from_sig(sig: ty::FnSig<'tcx>) -> Self {
89+
fn from_sig(sig: ty::FnSig<'tcx>) -> Self {
8890
FnPtrTypeDiscriminatorInput {
8991
inputs: sig.inputs(),
9092
output: sig.output(),
@@ -93,10 +95,7 @@ impl<'tcx> FnPtrTypeDiscriminatorInput<'tcx> {
9395
}
9496
}
9597

96-
pub fn from_sig_tys(
97-
sig: ty::FnSigTys<TyCtxt<'tcx>>,
98-
header: &ty::FnHeader<TyCtxt<'tcx>>,
99-
) -> Self {
98+
fn from_sig_tys(sig: ty::FnSigTys<TyCtxt<'tcx>>, header: &ty::FnHeader<TyCtxt<'tcx>>) -> Self {
10099
FnPtrTypeDiscriminatorInput {
101100
inputs: sig.inputs(),
102101
output: sig.output(),
@@ -137,7 +136,7 @@ pub fn extract_fn_ptr_type<'tcx>(tcx: TyCtxt<'tcx>, mut ty: Ty<'tcx>) -> Option<
137136
///
138137
/// FnDef is only accepted for convenience; the discriminator is still computed
139138
/// from the instantiated function signature.
140-
pub fn build_fn_ptr_type_discriminator_input<'tcx>(
139+
pub fn build_fn_ptr_type_discriminator_input_from_ty<'tcx>(
141140
tcx: TyCtxt<'tcx>,
142141
ty: Ty<'tcx>,
143142
) -> Option<FnPtrTypeDiscriminatorInput<'tcx>> {
@@ -160,6 +159,37 @@ pub fn build_fn_ptr_type_discriminator_input<'tcx>(
160159
}
161160
}
162161

162+
/// Builds type discrimination input from a monomorphized function instance.
163+
///
164+
/// The instance's signature is instantiated using its generic arguments and
165+
/// normalized before constructing the canonical discriminator input. Unlike
166+
/// `build_fn_ptr_type_discriminator_input_from_ty`, this function cannot fail
167+
/// because an `Instance` always represents a callable item with a well-defined
168+
/// function signature.
169+
pub fn build_fn_ptr_type_discriminator_input_from_instance<'tcx>(
170+
tcx: TyCtxt<'tcx>,
171+
instance: Instance<'tcx>,
172+
) -> FnPtrTypeDiscriminatorInput<'tcx> {
173+
let sig = tcx
174+
.instantiate_and_normalize_erasing_regions(
175+
instance.args,
176+
ty::TypingEnv::fully_monomorphized(),
177+
tcx.fn_sig(instance.def_id()),
178+
)
179+
.skip_binder();
180+
181+
FnPtrTypeDiscriminatorInput::from_sig(sig)
182+
}
183+
184+
/// Builds type discrimination input from a function signature.
185+
///
186+
/// The signature is assumed to already be instantiated and normalized.
187+
pub fn build_fn_ptr_type_discriminator_input_from_sig<'tcx>(
188+
sig: ty::FnSig<'tcx>,
189+
) -> FnPtrTypeDiscriminatorInput<'tcx> {
190+
FnPtrTypeDiscriminatorInput::from_sig(sig)
191+
}
192+
163193
pub fn compute_fn_ptr_type_discriminator<'tcx>(
164194
tcx: TyCtxt<'tcx>,
165195
input: &FnPtrTypeDiscriminatorInput<'tcx>,

compiler/rustc_middle/src/ptrauth/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod discriminator;
22
pub mod llvm_siphash;
33

44
pub use discriminator::{
5-
FnPtrTypeDiscriminatorInput, build_fn_ptr_type_discriminator_input,
5+
FnPtrTypeDiscriminatorInput, build_fn_ptr_type_discriminator_input_from_instance,
6+
build_fn_ptr_type_discriminator_input_from_sig, build_fn_ptr_type_discriminator_input_from_ty,
67
compute_fn_ptr_type_discriminator,
78
};

compiler/rustc_session/src/session.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub enum PointerAuthARM8_3Key {
9696
}
9797

9898
/// Forms of extra discrimination.
99-
#[derive(Clone, PartialEq)]
99+
#[derive(Clone, Debug, PartialEq)]
100100
pub enum PointerAuthDiscrimination {
101101
/// No additional discrimination.
102102
None,
@@ -109,7 +109,7 @@ pub enum PointerAuthDiscrimination {
109109
}
110110

111111
/// Types of address discrimination.
112-
#[derive(Clone)]
112+
#[derive(Clone, Debug)]
113113
pub enum PointerAuthAddressDiscriminator {
114114
/// Enable/disable hardware address discrimination.
115115
HardwareAddress(bool),
@@ -118,7 +118,7 @@ pub enum PointerAuthAddressDiscriminator {
118118
Synthetic(u64),
119119
}
120120

121-
#[derive(Clone)]
121+
#[derive(Clone, Debug)]
122122
pub struct PointerAuthSchema {
123123
pub is_address_discriminated: PointerAuthAddressDiscriminator,
124124
pub discrimination_kind: PointerAuthDiscrimination,

0 commit comments

Comments
 (0)