@@ -15,14 +15,15 @@ use rustc_codegen_ssa::traits::*;
15
15
use rustc_codegen_ssa:: MemFlags ;
16
16
use rustc_data_structures:: small_c_str:: SmallCStr ;
17
17
use rustc_hir:: def_id:: DefId ;
18
+ use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
18
19
use rustc_middle:: ty:: layout:: {
19
20
FnAbiError , FnAbiOfHelpers , FnAbiRequest , LayoutError , LayoutOfHelpers , TyAndLayout ,
20
21
} ;
21
22
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
22
23
use 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 } ;
24
25
use rustc_target:: abi:: { self , call:: FnAbi , Align , Size , WrappingRange } ;
25
- use rustc_target:: spec:: { HasTargetSpec , Target } ;
26
+ use rustc_target:: spec:: { HasTargetSpec , SanitizerSet , Target } ;
26
27
use std:: borrow:: Cow ;
27
28
use std:: ffi:: CStr ;
28
29
use std:: iter;
@@ -216,6 +217,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
216
217
fn invoke (
217
218
& mut self ,
218
219
llty : & ' ll Type ,
220
+ fn_attrs : Option < & CodegenFnAttrs > ,
219
221
fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
220
222
llfn : & ' ll Value ,
221
223
args : & [ & ' ll Value ] ,
@@ -230,19 +232,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
230
232
let funclet_bundle = funclet_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
231
233
let mut bundles = vec ! [ funclet_bundle] ;
232
234
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) ;
246
242
247
243
bundles. retain ( |bundle| bundle. is_some ( ) ) ;
248
244
let invoke = unsafe {
@@ -1183,6 +1179,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1183
1179
fn call (
1184
1180
& mut self ,
1185
1181
llty : & ' ll Type ,
1182
+ fn_attrs : Option < & CodegenFnAttrs > ,
1186
1183
fn_abi : Option < & FnAbi < ' tcx , Ty < ' tcx > > > ,
1187
1184
llfn : & ' ll Value ,
1188
1185
args : & [ & ' ll Value ] ,
@@ -1195,19 +1192,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1195
1192
let funclet_bundle = funclet_bundle. as_ref ( ) . map ( |b| & * b. raw ) ;
1196
1193
let mut bundles = vec ! [ funclet_bundle] ;
1197
1194
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) ;
1211
1202
1212
1203
bundles. retain ( |bundle| bundle. is_some ( ) ) ;
1213
1204
let call = unsafe {
@@ -1456,7 +1447,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1456
1447
1457
1448
pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1458
1449
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 )
1460
1451
}
1461
1452
1462
1453
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> {
1518
1509
format ! ( "llvm.{}.sat.i{}.f{}" , instr, int_width, float_width)
1519
1510
} ;
1520
1511
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 )
1522
1513
}
1523
1514
1524
1515
pub ( crate ) fn landing_pad (
@@ -1535,4 +1526,71 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1535
1526
llvm:: LLVMBuildLandingPad ( self . llbuilder , ty, None , num_clauses as c_uint , UNNAMED )
1536
1527
}
1537
1528
}
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
+ }
1538
1596
}
0 commit comments