Add cross-language LLVM CFI support to the Rust compiler
This commit adds cross-language LLVM Control Flow Integrity (CFI) support to the Rust compiler by adding the `-Zsanitizer-cfi-normalize-integers` option to be used with Clang `-fsanitize-cfi-icall-normalize-integers` for normalizing integer types (see https://reviews.llvm.org/D139395). It provides forward-edge control flow protection for C or C++ and Rust -compiled code "mixed binaries" (i.e., for when C or C++ and Rust -compiled code share the same virtual address space). For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, see design document in the tracking issue #89653. Cross-language LLVM CFI can be enabled with -Zsanitizer=cfi and -Zsanitizer-cfi-normalize-integers, and requires proper (i.e., non-rustc) LTO (i.e., -Clinker-plugin-lto).
This commit is contained in:
parent
fec9adcdbc
commit
004aa15b47
70 changed files with 1384 additions and 387 deletions
|
@ -110,6 +110,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
self.call(
|
||||
simple_ty,
|
||||
None,
|
||||
None,
|
||||
simple_fn,
|
||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
None,
|
||||
|
@ -444,7 +445,7 @@ fn try_intrinsic<'ll>(
|
|||
) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
bx.call(try_func_ty, None, try_func, &[data], None);
|
||||
bx.call(try_func_ty, None, None, try_func, &[data], None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
// we can never unwind.
|
||||
let ret_align = bx.tcx().data_layout.i32_align.abi;
|
||||
|
@ -543,7 +544,7 @@ fn codegen_msvc_try<'ll>(
|
|||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let slot = bx.alloca(bx.type_i8p(), ptr_align);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, try_func, &[data], normal, catchswitch, None);
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
|
||||
|
||||
bx.switch_to_block(normal);
|
||||
bx.ret(bx.const_i32(0));
|
||||
|
@ -587,7 +588,7 @@ fn codegen_msvc_try<'ll>(
|
|||
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
|
||||
let ptr = bx.load(bx.type_i8p(), slot, ptr_align);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
bx.call(catch_ty, None, catch_func, &[data, ptr], Some(&funclet));
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
|
||||
bx.catch_ret(&funclet, caught);
|
||||
|
||||
// The flag value of 64 indicates a "catch-all".
|
||||
|
@ -595,7 +596,7 @@ fn codegen_msvc_try<'ll>(
|
|||
let flags = bx.const_i32(64);
|
||||
let null = bx.const_null(bx.type_i8p());
|
||||
let funclet = bx.catch_pad(cs, &[null, flags, null]);
|
||||
bx.call(catch_ty, None, catch_func, &[data, null], Some(&funclet));
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
|
||||
bx.catch_ret(&funclet, caught);
|
||||
|
||||
bx.switch_to_block(caught);
|
||||
|
@ -604,7 +605,7 @@ fn codegen_msvc_try<'ll>(
|
|||
|
||||
// Note that no invoke is used here because by definition this function
|
||||
// can't panic (that's what it's catching).
|
||||
let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
|
||||
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
|
||||
let i32_align = bx.tcx().data_layout.i32_align.abi;
|
||||
bx.store(ret, dest, i32_align);
|
||||
}
|
||||
|
@ -647,7 +648,7 @@ fn codegen_gnu_try<'ll>(
|
|||
let data = llvm::get_param(bx.llfn(), 1);
|
||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||
|
||||
bx.switch_to_block(then);
|
||||
bx.ret(bx.const_i32(0));
|
||||
|
@ -665,13 +666,13 @@ fn codegen_gnu_try<'ll>(
|
|||
bx.add_clause(vals, tydesc);
|
||||
let ptr = bx.extract_value(vals, 0);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
bx.call(catch_ty, None, catch_func, &[data, ptr], None);
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
});
|
||||
|
||||
// Note that no invoke is used here because by definition this function
|
||||
// can't panic (that's what it's catching).
|
||||
let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
|
||||
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
|
||||
let i32_align = bx.tcx().data_layout.i32_align.abi;
|
||||
bx.store(ret, dest, i32_align);
|
||||
}
|
||||
|
@ -711,7 +712,7 @@ fn codegen_emcc_try<'ll>(
|
|||
let data = llvm::get_param(bx.llfn(), 1);
|
||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||
|
||||
bx.switch_to_block(then);
|
||||
bx.ret(bx.const_i32(0));
|
||||
|
@ -750,13 +751,13 @@ fn codegen_emcc_try<'ll>(
|
|||
let catch_data = bx.bitcast(catch_data, bx.type_i8p());
|
||||
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
bx.call(catch_ty, None, catch_func, &[data, catch_data], None);
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
});
|
||||
|
||||
// Note that no invoke is used here because by definition this function
|
||||
// can't panic (that's what it's catching).
|
||||
let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
|
||||
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
|
||||
let i32_align = bx.tcx().data_layout.i32_align.abi;
|
||||
bx.store(ret, dest, i32_align);
|
||||
}
|
||||
|
@ -1205,6 +1206,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let c = bx.call(
|
||||
fn_ty,
|
||||
None,
|
||||
None,
|
||||
f,
|
||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
None,
|
||||
|
@ -1423,6 +1425,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let v = bx.call(
|
||||
fn_ty,
|
||||
None,
|
||||
None,
|
||||
f,
|
||||
&[args[1].immediate(), alignment, mask, args[0].immediate()],
|
||||
None,
|
||||
|
@ -1564,6 +1567,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let v = bx.call(
|
||||
fn_ty,
|
||||
None,
|
||||
None,
|
||||
f,
|
||||
&[args[0].immediate(), args[1].immediate(), alignment, mask],
|
||||
None,
|
||||
|
@ -2037,7 +2041,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
|
||||
let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty);
|
||||
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
|
||||
let v = bx.call(fn_ty, None, f, &[lhs, rhs], None);
|
||||
let v = bx.call(fn_ty, None, None, f, &[lhs, rhs], None);
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue