Skip to content

Commit edcd1e2

Browse files
committed
CFI: Fix drop and drop_in_place
Fix drop and drop_in_place by transforming self of drop and drop_in_place methods into a Drop trait object and handling drop method calls separatedly (and also transforming self into a Drop trait object). This has the same effect of what CFI does for impl methods by transforming self into trait objects that match the trait objects in the calls after type erasure.
1 parent 8821dfa commit edcd1e2

File tree

14 files changed

+189
-44
lines changed

14 files changed

+189
-44
lines changed

compiler/rustc_codegen_gcc/src/asm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
541541
let builtin_unreachable: RValue<'gcc> = unsafe {
542542
std::mem::transmute(builtin_unreachable)
543543
};
544-
self.call(self.type_void(), None, None, builtin_unreachable, &[], None);
544+
self.call(self.type_void(), None, None, builtin_unreachable, &[], None, false);
545545
}
546546

547547
// Write results to outputs.

compiler/rustc_codegen_gcc/src/builder.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
592592
then: Block<'gcc>,
593593
catch: Block<'gcc>,
594594
_funclet: Option<&Funclet>,
595+
_is_drop: bool
595596
) -> RValue<'gcc> {
596597
let try_block = self.current_func().new_block("try");
597598

598599
let current_block = self.block.clone();
599600
self.block = try_block;
600-
let call = self.call(typ, fn_attrs, None, func, args, None); // TODO(antoyo): use funclet here?
601+
let call = self.call(typ, fn_attrs, None, func, args, None, false); // TODO(antoyo): use funclet here?
601602
self.block = current_block;
602603

603604
let return_value =
@@ -629,8 +630,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
629630
then: Block<'gcc>,
630631
catch: Block<'gcc>,
631632
_funclet: Option<&Funclet>,
633+
_is_drop: bool
632634
) -> RValue<'gcc> {
633-
let call_site = self.call(typ, fn_attrs, None, func, args, None);
635+
let call_site = self.call(typ, fn_attrs, None, func, args, None, false);
634636
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
635637
self.llbb().end_with_conditional(self.location, condition, then, catch);
636638
if let Some(_fn_abi) = fn_abi {
@@ -1667,6 +1669,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
16671669
func: RValue<'gcc>,
16681670
args: &[RValue<'gcc>],
16691671
funclet: Option<&Funclet>,
1672+
_is_drop: bool
16701673
) -> RValue<'gcc> {
16711674
// FIXME(antoyo): remove when having a proper API.
16721675
let gcc_func = unsafe { std::mem::transmute(func) };

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
133133
func,
134134
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
135135
None,
136+
false
136137
)
137138
}
138139
sym::likely => self.expect(args[0].immediate(), true),
@@ -401,7 +402,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
401402
fn abort(&mut self) {
402403
let func = self.context.get_builtin_function("abort");
403404
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
404-
self.call(self.type_void(), None, None, func, &[], None);
405+
self.call(self.type_void(), None, None, func, &[], None, false);
405406
}
406407

407408
fn assume(&mut self, value: Self::Value) {
@@ -1103,7 +1104,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
11031104
dest: RValue<'gcc>,
11041105
) {
11051106
if bx.sess().panic_strategy() == PanicStrategy::Abort {
1106-
bx.call(bx.type_void(), None, None, try_func, &[data], None);
1107+
bx.call(bx.type_void(), None, None, try_func, &[data], None, false);
11071108
// Return 0 unconditionally from the intrinsic call;
11081109
// we can never unwind.
11091110
let ret_align = bx.tcx.data_layout.i32_align.abi;
@@ -1177,21 +1178,21 @@ fn codegen_gnu_try<'gcc>(
11771178
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
11781179
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
11791180
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
1180-
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
1181+
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, false);
11811182
bx.ret(bx.const_i32(1));
11821183

11831184
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
11841185
// generate a try/catch.
11851186
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
11861187
bx.switch_to_block(current_block);
1187-
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
1188+
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, false);
11881189
});
11891190

11901191
let func = unsafe { std::mem::transmute(func) };
11911192

11921193
// Note that no invoke is used here because by definition this function
11931194
// can't panic (that's what it's catching).
1194-
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None);
1195+
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, false);
11951196
let i32_align = bx.tcx().data_layout.i32_align.abi;
11961197
bx.store(ret, dest, i32_align);
11971198
}

compiler/rustc_codegen_llvm/src/asm.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,11 @@ pub(crate) fn inline_asm_call<'ll>(
466466

467467
let call = if !labels.is_empty() {
468468
assert!(catch_funclet.is_none());
469-
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None)
469+
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, false)
470470
} else if let Some((catch, funclet)) = catch_funclet {
471-
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet)
471+
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, false)
472472
} else {
473-
bx.call(fty, None, None, v, inputs, None)
473+
bx.call(fty, None, None, v, inputs, None, false)
474474
};
475475

476476
// Store mark in a metadata node so we can map LLVM errors

compiler/rustc_codegen_llvm/src/builder.rs

+27-11
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ use rustc_middle::ty::layout::{
2121
};
2222
use rustc_middle::ty::{self, Ty, TyCtxt};
2323
use rustc_span::Span;
24-
use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
24+
use rustc_symbol_mangling::typeid::{
25+
kcfi_typeid_for_drop_fnabi, kcfi_typeid_for_fnabi, typeid_for_drop_fnabi, typeid_for_fnabi,
26+
TypeIdOptions,
27+
};
2528
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
2629
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
2730
use smallvec::SmallVec;
@@ -221,6 +224,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
221224
then: &'ll BasicBlock,
222225
catch: &'ll BasicBlock,
223226
funclet: Option<&Funclet<'ll>>,
227+
is_drop: bool,
224228
) -> &'ll Value {
225229
debug!("invoke {:?} with args ({:?})", llfn, args);
226230

@@ -233,10 +237,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
233237
}
234238

235239
// Emit CFI pointer type membership test
236-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
240+
self.cfi_type_test(fn_attrs, fn_abi, llfn, is_drop);
237241

238242
// Emit KCFI operand bundle
239-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
243+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn, is_drop);
240244
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
241245
if let Some(kcfi_bundle) = kcfi_bundle {
242246
bundles.push(kcfi_bundle);
@@ -1231,6 +1235,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12311235
llfn: &'ll Value,
12321236
args: &[&'ll Value],
12331237
funclet: Option<&Funclet<'ll>>,
1238+
is_drop: bool,
12341239
) -> &'ll Value {
12351240
debug!("call {:?} with args ({:?})", llfn, args);
12361241

@@ -1243,10 +1248,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12431248
}
12441249

12451250
// Emit CFI pointer type membership test
1246-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
1251+
self.cfi_type_test(fn_attrs, fn_abi, llfn, is_drop);
12471252

12481253
// Emit KCFI operand bundle
1249-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
1254+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn, is_drop);
12501255
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
12511256
if let Some(kcfi_bundle) = kcfi_bundle {
12521257
bundles.push(kcfi_bundle);
@@ -1468,7 +1473,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
14681473

14691474
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
14701475
let (ty, f) = self.cx.get_intrinsic(intrinsic);
1471-
self.call(ty, None, None, f, args, None)
1476+
self.call(ty, None, None, f, args, None, false)
14721477
}
14731478

14741479
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
@@ -1526,7 +1531,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15261531
format!("llvm.{instr}.sat.i{int_width}.f{float_width}")
15271532
};
15281533
let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
1529-
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None)
1534+
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None, false)
15301535
}
15311536

15321537
pub(crate) fn landing_pad(
@@ -1554,6 +1559,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15541559
default_dest: &'ll BasicBlock,
15551560
indirect_dest: &[&'ll BasicBlock],
15561561
funclet: Option<&Funclet<'ll>>,
1562+
is_drop: bool,
15571563
) -> &'ll Value {
15581564
debug!("invoke {:?} with args ({:?})", llfn, args);
15591565

@@ -1566,10 +1572,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15661572
}
15671573

15681574
// Emit CFI pointer type membership test
1569-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
1575+
self.cfi_type_test(fn_attrs, fn_abi, llfn, is_drop);
15701576

15711577
// Emit KCFI operand bundle
1572-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
1578+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn, is_drop);
15731579
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
15741580
if let Some(kcfi_bundle) = kcfi_bundle {
15751581
bundles.push(kcfi_bundle);
@@ -1602,6 +1608,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16021608
fn_attrs: Option<&CodegenFnAttrs>,
16031609
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
16041610
llfn: &'ll Value,
1611+
is_drop: bool,
16051612
) {
16061613
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
16071614
if self.tcx.sess.is_sanitizer_cfi_enabled()
@@ -1622,7 +1629,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16221629
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
16231630
}
16241631

1625-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
1632+
let typeid = if is_drop {
1633+
typeid_for_drop_fnabi(self.tcx, fn_abi, options)
1634+
} else {
1635+
typeid_for_fnabi(self.tcx, fn_abi, options)
1636+
};
16261637
let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
16271638

16281639
// Test whether the function pointer is associated with the type identifier.
@@ -1645,6 +1656,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16451656
fn_attrs: Option<&CodegenFnAttrs>,
16461657
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
16471658
llfn: &'ll Value,
1659+
is_drop: bool,
16481660
) -> Option<llvm::OperandBundleDef<'ll>> {
16491661
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
16501662
let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled()
@@ -1665,7 +1677,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16651677
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
16661678
}
16671679

1668-
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
1680+
let kcfi_typeid = if is_drop {
1681+
kcfi_typeid_for_drop_fnabi(self.tcx, fn_abi, options)
1682+
} else {
1683+
kcfi_typeid_for_fnabi(self.tcx, fn_abi, options)
1684+
};
16691685
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
16701686
} else {
16711687
None

0 commit comments

Comments
 (0)