diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/attributes.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/lib.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_driver/src/lib.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h | 3 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 6 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs | 4 |
12 files changed, 171 insertions, 12 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 659cf9ea070..8e6329a997f 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; use rustc_session::Session; use rustc_target::spec::abi::Abi; -use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType}; +use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -161,6 +161,17 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } +fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let sspattr = match cx.sess().stack_protector() { + StackProtector::None => return, + StackProtector::All => Attribute::StackProtectReq, + StackProtector::Strong => Attribute::StackProtectStrong, + StackProtector::Basic => Attribute::StackProtect, + }; + + sspattr.apply_llfn(Function, llfn) +} + pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( @@ -271,6 +282,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); + set_stackprotector(cx, llfn); if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { Attribute::Cold.apply_llfn(Function, llfn); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 64fedb7bc1a..c66d7d872c9 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -288,6 +288,31 @@ impl CodegenBackend for LlvmCodegenBackend { } println!(); } + PrintRequest::StackProtectorStrategies => { + println!( + r#"Available stack protector strategies: + all + Generate stack canaries in all functions. + + strong + Generate stack canaries in a function if it either: + - has a local variable of `[T; N]` type, regardless of `T` and `N` + - takes the address of a local variable. + + (Note that a local variable being borrowed is not equivalent to its + address being taken: e.g. some borrows may be removed by optimization, + while by-value argument passing may be implemented with reference to a + local stack variable in the ABI.) + + basic + Generate stack canaries in functions with: + - local variables of `[T; N]` type, where `T` is byte-sized and `N` > 8. + + none + Do not generate stack canaries. +"# + ); + } req => llvm_util::print(req, sess), } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 749eec459ac..1d255c07559 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -166,6 +166,9 @@ pub enum Attribute { InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, } /// LLVMIntPredicate diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 09fe3a552a0..6ff94341142 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -736,7 +736,12 @@ impl RustcDefaultCalls { println!("{}", cfg); } } - RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => { + RelocationModels + | CodeModels + | TlsModels + | TargetCPUs + | StackProtectorStrategies + | TargetFeatures => { codegen_backend.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ab12c936710..24d4b050421 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -20,7 +20,9 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, +}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -713,8 +715,8 @@ fn test_debugging_options_tracking_hash() { // This list is in alphabetical order. tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); - tracked!(assume_incomplete_release, true); tracked!(asm_comments, true); + tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); @@ -731,8 +733,8 @@ fn test_debugging_options_tracking_hash() { tracked!(human_readable_cgu_names, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); - tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); + tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); @@ -764,7 +766,6 @@ fn test_debugging_options_tracking_hash() { tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); - tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_memory_track_origins, 2); @@ -772,15 +773,17 @@ fn test_debugging_options_tracking_hash() { tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); + tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); + tracked!(stack_protector, StackProtector::All); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); - tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); + tracked!(tune_cpu, Some(String::from("abc"))); tracked!(unleash_the_miri_inside_of_you, true); tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index ebe495872c4..e2ce7da0e84 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -79,6 +79,9 @@ enum LLVMRustAttribute { InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index f3d8eb2602a..bb6d42c1a9c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -213,6 +213,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::SanitizeHWAddress; case WillReturn: return Attribute::WillReturn; + case StackProtectReq: + return Attribute::StackProtectReq; + case StackProtectStrong: + return Attribute::StackProtectStrong; + case StackProtect: + return Attribute::StackProtect; } report_fatal_error("bad AttributeKind"); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3f0a6b0e2f6..58e5087c72f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -538,6 +538,7 @@ pub enum PrintRequest { TlsModels, TargetSpec, NativeStaticLibs, + StackProtectorStrategies, } #[derive(Copy, Clone)] @@ -1110,8 +1111,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { "print", "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ - target-cpus|target-features|relocation-models|\ - code-models|tls-models|target-spec-json|native-static-libs]", + target-cpus|target-features|relocation-models|code-models|\ + tls-models|target-spec-json|native-static-libs|stack-protector-strategies]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1527,6 +1528,7 @@ fn collect_print_requests( "code-models" => PrintRequest::CodeModels, "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, + "stack-protector-strategies" => PrintRequest::StackProtectorStrategies, "target-spec-json" => { if dopts.unstable_options { PrintRequest::TargetSpec @@ -2494,7 +2496,9 @@ crate mod dep_tracking { use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel}; + use rustc_target::spec::{ + RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + }; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2568,6 +2572,7 @@ crate mod dep_tracking { Edition, LinkerPluginLto, SplitDebuginfo, + StackProtector, SwitchWithOptPath, SymbolManglingVersion, SourceFileHashAlgorithm, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cba05f6aa59..a84e16b9dc3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -5,7 +5,9 @@ use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; -use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, +}; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; @@ -385,6 +387,8 @@ mod desc { pub const parse_split_debuginfo: &str = "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; pub const parse_gcc_ld: &str = "one of: no value, `lld`"; + pub const parse_stack_protector: &str = + "one of (`none` (default), `basic`, `strong`, or `all`)"; } mod parse { @@ -917,6 +921,14 @@ mod parse { } true } + + crate fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool { + match v.and_then(|s| StackProtector::from_str(s).ok()) { + Some(ssp) => *slot = ssp, + _ => return false, + } + true + } } options! { @@ -1330,6 +1342,8 @@ options! { "exclude spans when debug-printing compiler state (default: no)"), src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED], "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), + stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], + "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 74b3cfa44c3..69494e6d9b3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -27,7 +27,9 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; -use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel}; +use rustc_target::spec::{ + SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, +}; use std::cell::{self, RefCell}; use std::env; @@ -732,6 +734,14 @@ impl Session { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } + pub fn stack_protector(&self) -> StackProtector { + if self.target.options.supports_stack_protector { + self.opts.debugging_opts.stack_protector + } else { + StackProtector::None + } + } + pub fn target_can_use_split_dwarf(&self) -> bool { !self.target.is_like_windows && !self.target.is_like_osx } @@ -1411,6 +1421,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.err("`-Zsanitizer=cfi` requires `-Clto`"); } } + + if sess.opts.debugging_opts.stack_protector != StackProtector::None { + if !sess.target.options.supports_stack_protector { + sess.warn(&format!( + "`-Z stack-protector={}` is not supported for target {} and will be ignored", + sess.opts.debugging_opts.stack_protector, sess.opts.target_triple + )) + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0771f998535..0d49c7f6ee8 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -712,6 +712,59 @@ impl ToJson for FramePointer { } } +/// Controls use of stack canaries. +#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)] +pub enum StackProtector { + /// Disable stack canary generation. + None, + + /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see + /// llvm/docs/LangRef.rst). This triggers stack canary generation in + /// functions which contain an array of a byte-sized type with more than + /// eight elements. + Basic, + + /// On LLVM, mark all generated LLVM functions with the `sspstrong` + /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary + /// generation in functions which either contain an array, or which take + /// the address of a local variable. + Strong, + + /// Generate stack canaries in all functions. + All, +} + +impl StackProtector { + fn as_str(&self) -> &'static str { + match self { + StackProtector::None => "none", + StackProtector::Basic => "basic", + StackProtector::Strong => "strong", + StackProtector::All => "all", + } + } +} + +impl FromStr for StackProtector { + type Err = (); + + fn from_str(s: &str) -> Result<StackProtector, ()> { + Ok(match s { + "none" => StackProtector::None, + "basic" => StackProtector::Basic, + "strong" => StackProtector::Strong, + "all" => StackProtector::All, + _ => return Err(()), + }) + } +} + +impl fmt::Display for StackProtector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -1360,6 +1413,10 @@ pub struct TargetOptions { /// Whether or not the DWARF `.debug_aranges` section should be generated. pub generate_arange_section: bool, + + /// Whether the target supports stack canary checks. `true` by default, + /// since this is most common among tier 1 and tier 2 targets. + pub supports_stack_protector: bool, } impl Default for TargetOptions { @@ -1466,6 +1523,7 @@ impl Default for TargetOptions { default_adjusted_cabi: None, c_enum_min_bits: 32, generate_arange_section: true, + supports_stack_protector: true, } } } @@ -2052,6 +2110,7 @@ impl Target { key!(default_adjusted_cabi, Option<Abi>)?; key!(c_enum_min_bits, u64); key!(generate_arange_section, bool); + key!(supports_stack_protector, bool); if base.is_builtin { // This can cause unfortunate ICEs later down the line. @@ -2292,6 +2351,7 @@ impl ToJson for Target { target_option_val!(supported_sanitizers); target_option_val!(c_enum_min_bits); target_option_val!(generate_arange_section); + target_option_val!(supports_stack_protector); if let Some(abi) = self.default_adjusted_cabi { d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index 083262cf351..ba32a312910 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -44,6 +44,10 @@ pub fn target() -> Target { // produce kernel functions that call other kernel functions. // This behavior is not supported by PTX ISA. merge_functions: MergeFunctions::Disabled, + + // The LLVM backend does not support stack canaries for this target + supports_stack_protector: false, + ..Default::default() }, } |
