Skip to content

Commit

Permalink
Apply LLVM sanitize attributes to generated entry wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
tmiasko committed Feb 5, 2020
1 parent b846b42 commit 1caa875
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 32 deletions.
46 changes: 26 additions & 20 deletions src/librustc_codegen_llvm/attributes.rs
Expand Up @@ -46,6 +46,31 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
};
}

/// Apply LLVM sanitize attributes.
#[inline]
pub fn sanitize(cx: &CodegenCx<'ll, '_>, codegen_fn_flags: CodegenFnAttrFlags, llfn: &'ll Value) {
if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
match *sanitizer {
Sanitizer::Address => {
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
}
}
Sanitizer::Memory => {
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
}
}
Sanitizer::Thread => {
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
}
}
Sanitizer::Leak => {}
}
}
}

/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
#[inline]
pub fn emit_uwtable(val: &'ll Value, emit: bool) {
Expand Down Expand Up @@ -288,26 +313,7 @@ pub fn from_fn_attrs(
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
Attribute::NoAlias.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
}
if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
match *sanitizer {
Sanitizer::Address => {
if !codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
}
}
Sanitizer::Memory => {
if !codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
}
}
Sanitizer::Thread => {
if !codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
}
}
Sanitizer::Leak => {}
}
}
sanitize(cx, codegen_fn_attrs.flags, llfn);

unwind(
llfn,
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_codegen_llvm/base.rs
Expand Up @@ -15,6 +15,7 @@

use super::ModuleLlvm;

use crate::attributes;
use crate::builder::Builder;
use crate::common;
use crate::context::CodegenCx;
Expand All @@ -23,7 +24,7 @@ use crate::metadata;
use crate::value::Value;

use rustc::dep_graph;
use rustc::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::exported_symbols;
use rustc::mir::mono::{Linkage, Visibility};
Expand Down Expand Up @@ -131,7 +132,9 @@ pub fn compile_codegen_unit(

// If this codegen unit contains the main function, also create the
// wrapper here
maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
if let Some(entry) = maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx) {
attributes::sanitize(&cx, CodegenFnAttrFlags::empty(), entry);
}

// Run replace-all-uses-with for statics that need it
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
Expand Down
22 changes: 12 additions & 10 deletions src/librustc_codegen_ssa/base.rs
Expand Up @@ -391,36 +391,36 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(

/// Creates the `main` function which will initialize the rust runtime and call
/// users main function.
pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'a Bx::CodegenCx) {
pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
) -> Option<Bx::Function> {
let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
Some((def_id, _)) => (def_id, cx.tcx().def_span(def_id)),
None => return,
None => return None,
};

let instance = Instance::mono(cx.tcx(), main_def_id);

if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
// We want to create the wrapper in the same codegen unit as Rust's main
// function.
return;
return None;
}

let main_llfn = cx.get_fn_addr(instance);

let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
match et {
Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
None => {} // Do nothing.
}
return cx.tcx().entry_fn(LOCAL_CRATE).map(|(_, et)| {
let use_start_lang_item = EntryFnType::Start != et;
create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, use_start_lang_item)
});

fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
sp: Span,
rust_main: Bx::Value,
rust_main_def_id: DefId,
use_start_lang_item: bool,
) {
) -> Bx::Function {
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
// depending on whether the target needs `argc` and `argv` to be passed in.
let llfty = if cx.sess().target.target.options.main_needs_argc_argv {
Expand Down Expand Up @@ -481,6 +481,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
let result = bx.call(start_fn, &args, None);
let cast = bx.intcast(result, cx.type_int(), true);
bx.ret(cast);

llfn
}
}

Expand Down

0 comments on commit 1caa875

Please sign in to comment.