@@ -7,7 +7,7 @@ pub(crate) mod autodiff;
77pub ( crate ) mod gpu_offload;
88
99use libc:: { c_char, c_uint} ;
10- use rustc_abi:: { self as abi, Align , Size , WrappingRange } ;
10+ use rustc_abi:: { self as abi, Align , CanonAbi , Size , WrappingRange } ;
1111use rustc_codegen_ssa:: MemFlags ;
1212use rustc_codegen_ssa:: common:: { IntPredicate , RealPredicate , SynchronizationScope , TypeKind } ;
1313use rustc_codegen_ssa:: mir:: operand:: { OperandRef , OperandValue } ;
@@ -26,7 +26,7 @@ use rustc_sanitizers::{cfi, kcfi};
2626use rustc_session:: config:: OptLevel ;
2727use rustc_span:: Span ;
2828use rustc_target:: callconv:: { FnAbi , PassMode } ;
29- use rustc_target:: spec:: { Arch , HasTargetSpec , SanitizerSet , Target } ;
29+ use rustc_target:: spec:: { Arch , HasTargetSpec , LlvmAbi , SanitizerSet , Target } ;
3030use smallvec:: SmallVec ;
3131use tracing:: { debug, instrument} ;
3232
@@ -475,6 +475,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
475475 bundles. push ( kcfi_bundle) ;
476476 }
477477
478+ let pauth = self . ptrauth_operand_bundle ( llfn, fn_abi) ;
479+ if let Some ( p) = pauth. as_ref ( ) . map ( |b| b. as_ref ( ) ) {
480+ bundles. push ( p) ;
481+ }
482+
478483 let invoke = unsafe {
479484 llvm:: LLVMBuildInvokeWithOperandBundles (
480485 self . llbuilder ,
@@ -1472,6 +1477,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14721477 bundles. push ( kcfi_bundle) ;
14731478 }
14741479
1480+ let pauth = self . ptrauth_operand_bundle ( llfn, fn_abi) ;
1481+ if let Some ( p) = pauth. as_ref ( ) . map ( |b| b. as_ref ( ) ) {
1482+ bundles. push ( p) ;
1483+ }
1484+
14751485 let call = unsafe {
14761486 llvm:: LLVMBuildCallWithOperandBundles (
14771487 self . llbuilder ,
@@ -1902,6 +1912,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19021912 bundles. push ( kcfi_bundle) ;
19031913 }
19041914
1915+ let pauth = self . ptrauth_operand_bundle ( llfn, fn_abi) ;
1916+ if let Some ( p) = pauth. as_ref ( ) . map ( |b| b. as_ref ( ) ) {
1917+ bundles. push ( p) ;
1918+ }
1919+
19051920 let callbr = unsafe {
19061921 llvm:: LLVMBuildCallBr (
19071922 self . llbuilder ,
@@ -2021,6 +2036,40 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
20212036 kcfi_bundle
20222037 }
20232038
2039+ // Emits pauth operand bundle.
2040+ fn ptrauth_operand_bundle (
2041+ & mut self ,
2042+ llfn : & ' ll Value ,
2043+ fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
2044+ ) -> Option < llvm:: OperandBundleBox < ' ll > > {
2045+ if self . sess ( ) . target . llvm_abiname != LlvmAbi :: Pauthtest {
2046+ return None ;
2047+ }
2048+ // Pointer authentication support is currently limited to extern "C" calls; filter out other
2049+ // ABIs.
2050+ if fn_abi?. conv != CanonAbi :: C {
2051+ return None ;
2052+ }
2053+ // Filter out LLVM intrinsics.
2054+ if llvm:: get_value_name ( llfn) . starts_with ( b"llvm." ) {
2055+ return None ;
2056+ }
2057+
2058+ // FIXME(jchlanda) Operand bundles should only be attached to indirect function calls.
2059+ // However, function pointer signing is currently performed in `get_fn_addr`, which causes
2060+ // the logic to be applied too broadly, including to function values (not just pointers).
2061+ // As a result, direct calls using signed function values must also receive operand
2062+ // bundles.
2063+ // Once this is resolved, we should analyze each call and skip direct calls. See the
2064+ // discussion in the rust-lang issue: <https://github.com/rust-lang/rust/issues/152532>
2065+ let key: u32 = 0 ;
2066+ let discriminator: u64 = 0 ;
2067+ Some ( llvm:: OperandBundleBox :: new (
2068+ "ptrauth" ,
2069+ & [ self . const_u32 ( key) , self . const_u64 ( discriminator) ] ,
2070+ ) )
2071+ }
2072+
20242073 /// Emits a call to `llvm.instrprof.increment`. Used by coverage instrumentation.
20252074 #[ instrument( level = "debug" , skip( self ) ) ]
20262075 pub ( crate ) fn instrprof_increment (
0 commit comments