Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fine-grained LLVM CFI support to the Rust compiler #95548

Merged
merged 2 commits into from
Jul 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4441,6 +4441,7 @@ dependencies = [
name = "rustc_symbol_mangling"
version = "0.0.0"
dependencies = [
"bitflags",
"punycode",
"rustc-demangle",
"rustc_data_structures",
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,16 +784,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// TODO(antoyo)
}

fn type_metadata(&mut self, _function: RValue<'gcc>, _typeid: String) {
// Unsupported.
}

fn typeid_metadata(&mut self, _typeid: String) -> RValue<'gcc> {
// Unsupported.
self.context.new_rvalue_from_int(self.int_type, 0)
}


fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
self.store_with_flags(val, ptr, align, MemFlags::empty())
}
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_codegen_gcc/src/type_.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::convert::TryInto;

use gccjit::{RValue, Struct, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods};
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
use rustc_codegen_ssa::common::TypeKind;
use rustc_middle::{bug, ty};
use rustc_middle::ty::layout::TyAndLayout;
Expand Down Expand Up @@ -290,3 +290,14 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout

(result, packed)
}

impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn set_type_metadata(&self, _function: RValue<'gcc>, _typeid: String) {
// Unsupported.
}

fn typeid_metadata(&self, _typeid: String) -> RValue<'gcc> {
// Unsupported.
self.context.new_rvalue_from_int(self.int_type, 0)
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ rustc_middle = { path = "../rustc_middle" }
rustc-demangle = "0.1.21"
rustc_attr = { path = "../rustc_attr" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fs_util = { path = "../rustc_fs_util" }
Expand All @@ -30,6 +29,7 @@ rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
Expand Down
26 changes: 0 additions & 26 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,32 +626,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
}

fn type_metadata(&mut self, function: &'ll Value, typeid: String) {
let typeid_metadata = self.typeid_metadata(typeid);
let v = [self.const_usize(0), typeid_metadata];
unsafe {
llvm::LLVMGlobalSetMetadata(
function,
llvm::MD_type as c_uint,
llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
self.cx.llcx,
v.as_ptr(),
v.len() as c_uint,
)),
)
}
}

fn typeid_metadata(&mut self, typeid: String) -> Self::Value {
unsafe {
llvm::LLVMMDStringInContext(
self.cx.llcx,
typeid.as_ptr() as *const c_char,
typeid.as_bytes().len() as c_uint,
)
}
}

fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
self.store_with_flags(val, ptr, align, MemFlags::empty())
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_codegen_llvm/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use crate::llvm;
use crate::llvm::AttributePlace::Function;
use crate::type_::Type;
use crate::value::Value;
use rustc_codegen_ssa::traits::TypeMembershipMethods;
use rustc_middle::ty::Ty;
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
use smallvec::SmallVec;
use tracing::debug;

Expand Down Expand Up @@ -97,6 +99,12 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
fn_abi.llvm_type(self),
);
fn_abi.apply_attrs_llfn(self, llfn);

if self.tcx.sess.is_sanitizer_cfi_enabled() {
let typeid = typeid_for_fnabi(self.tcx, fn_abi);
self.set_type_metadata(llfn, typeid);
}

llfn
}

Expand Down
30 changes: 29 additions & 1 deletion compiler/rustc_codegen_llvm/src/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rustc_target::abi::{AddressSpace, Align, Integer, Size};
use std::fmt;
use std::ptr;

use libc::c_uint;
use libc::{c_char, c_uint};

impl PartialEq for Type {
fn eq(&self, other: &Self) -> bool {
Expand Down Expand Up @@ -289,3 +289,31 @@ impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
ty.llvm_type(self)
}
}

impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn set_type_metadata(&self, function: &'ll Value, typeid: String) {
let typeid_metadata = self.typeid_metadata(typeid);
let v = [self.const_usize(0), typeid_metadata];
unsafe {
llvm::LLVMGlobalSetMetadata(
function,
llvm::MD_type as c_uint,
llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
self.llcx,
v.as_ptr(),
v.len() as c_uint,
)),
)
}
}

fn typeid_metadata(&self, typeid: String) -> &'ll Value {
unsafe {
llvm::LLVMMDStringInContext(
self.llcx,
typeid.as_ptr() as *const c_char,
typeid.len() as c_uint,
)
}
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
use rustc_symbol_mangling::typeid_for_fnabi;
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
use rustc_target::abi::{self, HasDataLayout, InitKind, WrappingRange};
use rustc_target::spec::abi::Abi;
Expand Down Expand Up @@ -920,7 +920,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// FIXME(rcvalle): Add support for generalized identifiers.
// FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers.
let typeid = typeid_for_fnabi(bx.tcx(), fn_abi);
let typeid_metadata = bx.typeid_metadata(typeid);
let typeid_metadata = self.cx.typeid_metadata(typeid);

// Test whether the function pointer is associated with the type identifier.
let cond = bx.type_test(fn_ptr, typeid_metadata);
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable, TypeVisitable};
use rustc_symbol_mangling::typeid_for_fnabi;
use rustc_target::abi::call::{FnAbi, PassMode};

use std::iter;
Expand Down Expand Up @@ -247,13 +246,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
for (bb, _) in traversal::reverse_postorder(&mir) {
fx.codegen_block(bb);
}

// For backends that support CFI using type membership (i.e., testing whether a given pointer
// is associated with a type identifier).
if cx.tcx().sess.is_sanitizer_cfi_enabled() {
let typeid = typeid_for_fnabi(cx.tcx(), fn_abi);
bx.type_metadata(llfn, typeid);
}
}

/// Produces, for each argument, a `Value` pointing at the
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_codegen_ssa/src/traits/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,6 @@ pub trait BuilderMethods<'a, 'tcx>:

fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
fn nonnull_metadata(&mut self, load: Self::Value);
fn type_metadata(&mut self, function: Self::Function, typeid: String);
fn typeid_metadata(&mut self, typeid: String) -> Self::Value;

fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
fn store_with_flags(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ pub use self::intrinsic::IntrinsicCallMethods;
pub use self::misc::MiscMethods;
pub use self::statics::{StaticBuilderMethods, StaticMethods};
pub use self::type_::{
ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods,
ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMembershipMethods,
TypeMethods,
};
pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};

Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_codegen_ssa/src/traits/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
) -> Self::Type;
}

// For backends that support CFI using type membership (i.e., testing whether a given pointer is
// associated with a type identifier).
pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
fn set_type_metadata(&self, function: Self::Function, typeid: String);
fn typeid_metadata(&self, typeid: String) -> Self::Value;
}

pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
fn store_fn_arg(
&mut self,
Expand All @@ -133,6 +140,12 @@ pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type;
}

pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}
pub trait TypeMethods<'tcx>:
DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
{
}

impl<'tcx, T> TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}
impl<'tcx, T> TypeMethods<'tcx> for T where
Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
{
}
1 change: 1 addition & 0 deletions compiler/rustc_symbol_mangling/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
doctest = false

[dependencies]
bitflags = "1.2.1"
tracing = "0.1"
punycode = "0.4.0"
rustc-demangle = "0.1.21"
Expand Down
9 changes: 2 additions & 7 deletions compiler/rustc_symbol_mangling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,16 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_session::config::SymbolManglingVersion;
use rustc_target::abi::call::FnAbi;

use tracing::debug;

mod legacy;
mod v0;

pub mod test;
pub mod typeid;

/// This function computes the symbol name for the given `instance` and the
/// given instantiating crate. That is, if you know that instance X is
Expand Down Expand Up @@ -150,11 +150,6 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty
ty::SymbolName::new(tcx, &symbol_name)
}

/// This function computes the typeid for the given function ABI.
pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
v0::mangle_typeid_for_fnabi(tcx, fn_abi)
}

pub fn typeid_for_trait_ref<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyExistentialTraitRef<'tcx>,
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_symbol_mangling/src/typeid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// For more information about type metadata and type metadata identifiers for cross-language LLVM
// CFI support, see Type metadata in the design document in the tracking issue #89653.

use rustc_middle::ty::{FnSig, Ty, TyCtxt};
use rustc_target::abi::call::FnAbi;

mod typeid_itanium_cxx_abi;
use typeid_itanium_cxx_abi::TypeIdOptions;

/// Returns a type metadata identifier for the specified FnAbi.
pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, TypeIdOptions::NO_OPTIONS)
}

/// Returns a type metadata identifier for the specified FnSig.
pub fn typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> String {
typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS)
}
Loading