@@ -15,14 +15,15 @@ use rustc_codegen_ssa::traits::*;
1515use rustc_codegen_ssa:: MemFlags ;
1616use rustc_data_structures:: small_c_str:: SmallCStr ;
1717use rustc_hir:: def_id:: DefId ;
18+ use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
1819use rustc_middle:: ty:: layout:: {
1920 FnAbiError , FnAbiOfHelpers , FnAbiRequest , LayoutError , LayoutOfHelpers , TyAndLayout ,
2021} ;
2122use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
2223use rustc_span:: Span ;
23- use rustc_symbol_mangling:: typeid:: kcfi_typeid_for_fnabi;
24+ use rustc_symbol_mangling:: typeid:: { kcfi_typeid_for_fnabi, typeid_for_fnabi , TypeIdOptions } ;
2425use rustc_target:: abi:: { self , call:: FnAbi , Align , Size , WrappingRange } ;
25- use rustc_target:: spec:: { HasTargetSpec , Target } ;
26+ use rustc_target:: spec:: { HasTargetSpec , SanitizerSet , Target } ;
2627use std:: borrow:: Cow ;
2728use std:: ffi:: CStr ;
2829use std:: iter;
@@ -216,6 +217,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
216217 fn invoke (
217218 & mut self ,
218219 llty : & ' ll Type ,
220+ fn_attrs : Option < & CodegenFnAttrs > ,
219221 fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
220222 llfn : & ' ll Value ,
221223 args : & [ & ' ll Value ] ,
@@ -230,19 +232,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
230232 let funclet_bundle = funclet_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
231233 let mut bundles = vec ! [ funclet_bundle] ;
232234
233- // Set KCFI operand bundle
234- let is_indirect_call = unsafe { llvm:: LLVMIsAFunction ( llfn) . is_none ( ) } ;
235- let kcfi_bundle =
236- if self . tcx . sess . is_sanitizer_kcfi_enabled ( ) && let Some ( fn_abi) = fn_abi && is_indirect_call {
237- let kcfi_typeid = kcfi_typeid_for_fnabi ( self . tcx , fn_abi) ;
238- Some ( llvm:: OperandBundleDef :: new ( "kcfi" , & [ self . const_u32 ( kcfi_typeid) ] ) )
239- } else {
240- None
241- } ;
242- if kcfi_bundle. is_some ( ) {
243- let kcfi_bundle = kcfi_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
244- bundles. push ( kcfi_bundle) ;
245- }
235+ // Emit CFI pointer type membership test
236+ self . cfi_type_test ( fn_attrs, fn_abi, llfn) ;
237+
238+ // Emit KCFI operand bundle
239+ let kcfi_bundle = self . kcfi_operand_bundle ( fn_attrs, fn_abi, llfn) ;
240+ let kcfi_bundle = kcfi_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
241+ bundles. push ( kcfi_bundle) ;
246242
247243 bundles. retain ( |bundle| bundle. is_some ( ) ) ;
248244 let invoke = unsafe {
@@ -1183,6 +1179,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11831179 fn call (
11841180 & mut self ,
11851181 llty : & ' ll Type ,
1182+ fn_attrs : Option < & CodegenFnAttrs > ,
11861183 fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
11871184 llfn : & ' ll Value ,
11881185 args : & [ & ' ll Value ] ,
@@ -1195,19 +1192,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11951192 let funclet_bundle = funclet_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
11961193 let mut bundles = vec ! [ funclet_bundle] ;
11971194
1198- // Set KCFI operand bundle
1199- let is_indirect_call = unsafe { llvm:: LLVMIsAFunction ( llfn) . is_none ( ) } ;
1200- let kcfi_bundle =
1201- if let Some ( fn_abi) = fn_abi && self . tcx . sess . is_sanitizer_kcfi_enabled ( ) && is_indirect_call {
1202- let kcfi_typeid = kcfi_typeid_for_fnabi ( self . tcx , fn_abi) ;
1203- Some ( llvm:: OperandBundleDef :: new ( "kcfi" , & [ self . const_u32 ( kcfi_typeid) ] ) )
1204- } else {
1205- None
1206- } ;
1207- if kcfi_bundle. is_some ( ) {
1208- let kcfi_bundle = kcfi_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
1209- bundles. push ( kcfi_bundle) ;
1210- }
1195+ // Emit CFI pointer type membership test
1196+ self . cfi_type_test ( fn_attrs, fn_abi, llfn) ;
1197+
1198+ // Emit KCFI operand bundle
1199+ let kcfi_bundle = self . kcfi_operand_bundle ( fn_attrs, fn_abi, llfn) ;
1200+ let kcfi_bundle = kcfi_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
1201+ bundles. push ( kcfi_bundle) ;
12111202
12121203 bundles. retain ( |bundle| bundle. is_some ( ) ) ;
12131204 let call = unsafe {
@@ -1456,7 +1447,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
14561447
14571448 pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
14581449 let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1459- self . call ( ty, None , f, args, None )
1450+ self . call ( ty, None , None , f, args, None )
14601451 }
14611452
14621453 fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
@@ -1518,7 +1509,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15181509 format ! ( "llvm.{}.sat.i{}.f{}" , instr, int_width, float_width)
15191510 } ;
15201511 let f = self . declare_cfn ( & name, llvm:: UnnamedAddr :: No , self . type_func ( & [ src_ty] , dest_ty) ) ;
1521- self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , f, & [ val] , None )
1512+ self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None )
15221513 }
15231514
15241515 pub ( crate ) fn landing_pad (
@@ -1535,4 +1526,71 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15351526 llvm:: LLVMBuildLandingPad ( self . llbuilder , ty, None , num_clauses as c_uint , UNNAMED )
15361527 }
15371528 }
1529+
1530+ // Emits CFI pointer type membership tests.
1531+ fn cfi_type_test (
1532+ & mut self ,
1533+ fn_attrs : Option < & CodegenFnAttrs > ,
1534+ fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
1535+ llfn : & ' ll Value ,
1536+ ) {
1537+ let is_indirect_call = unsafe { llvm:: LLVMIsAFunction ( llfn) . is_none ( ) } ;
1538+ if is_indirect_call && fn_abi. is_some ( ) && self . tcx . sess . is_sanitizer_cfi_enabled ( ) {
1539+ if fn_attrs. is_some ( ) && fn_attrs. unwrap ( ) . no_sanitize . contains ( SanitizerSet :: CFI ) {
1540+ return ;
1541+ }
1542+
1543+ let mut options = TypeIdOptions :: empty ( ) ;
1544+ if self . tcx . sess . is_sanitizer_cfi_generalize_pointers_enabled ( ) {
1545+ options. insert ( TypeIdOptions :: GENERALIZE_POINTERS ) ;
1546+ }
1547+ if self . tcx . sess . is_sanitizer_cfi_normalize_integers_enabled ( ) {
1548+ options. insert ( TypeIdOptions :: NORMALIZE_INTEGERS ) ;
1549+ }
1550+
1551+ let typeid = typeid_for_fnabi ( self . tcx , fn_abi. unwrap ( ) , options) ;
1552+ let typeid_metadata = self . cx . typeid_metadata ( typeid) . unwrap ( ) ;
1553+
1554+ // Test whether the function pointer is associated with the type identifier.
1555+ let cond = self . type_test ( llfn, typeid_metadata) ;
1556+ let bb_pass = self . append_sibling_block ( "type_test.pass" ) ;
1557+ let bb_fail = self . append_sibling_block ( "type_test.fail" ) ;
1558+ self . cond_br ( cond, bb_pass, bb_fail) ;
1559+
1560+ self . switch_to_block ( bb_fail) ;
1561+ self . abort ( ) ;
1562+ self . unreachable ( ) ;
1563+
1564+ self . switch_to_block ( bb_pass) ;
1565+ }
1566+ }
1567+
1568+ // Emits KCFI operand bundles.
1569+ fn kcfi_operand_bundle (
1570+ & mut self ,
1571+ fn_attrs : Option < & CodegenFnAttrs > ,
1572+ fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
1573+ llfn : & ' ll Value ,
1574+ ) -> Option < llvm:: OperandBundleDef < ' ll > > {
1575+ let is_indirect_call = unsafe { llvm:: LLVMIsAFunction ( llfn) . is_none ( ) } ;
1576+ let kcfi_bundle = if is_indirect_call && self . tcx . sess . is_sanitizer_kcfi_enabled ( ) {
1577+ if fn_attrs. is_some ( ) && fn_attrs. unwrap ( ) . no_sanitize . contains ( SanitizerSet :: KCFI ) {
1578+ return None ;
1579+ }
1580+
1581+ let mut options = TypeIdOptions :: empty ( ) ;
1582+ if self . tcx . sess . is_sanitizer_cfi_generalize_pointers_enabled ( ) {
1583+ options. insert ( TypeIdOptions :: GENERALIZE_POINTERS ) ;
1584+ }
1585+ if self . tcx . sess . is_sanitizer_cfi_normalize_integers_enabled ( ) {
1586+ options. insert ( TypeIdOptions :: NORMALIZE_INTEGERS ) ;
1587+ }
1588+
1589+ let kcfi_typeid = kcfi_typeid_for_fnabi ( self . tcx , fn_abi. unwrap ( ) , options) ;
1590+ Some ( llvm:: OperandBundleDef :: new ( "kcfi" , & [ self . const_u32 ( kcfi_typeid) ] ) )
1591+ } else {
1592+ None
1593+ } ;
1594+ kcfi_bundle
1595+ }
15381596}
0 commit comments