From fb91e5ed2fe72c6ce38abe0ec2ca47cbeac78d8d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Apr 2020 00:46:45 +0300 Subject: [PATCH 1/5] rustc_target: Stop using "string typing" for relocation models Introduce `enum RelocModel` instead. --- src/librustc_codegen_llvm/back/write.rs | 26 ++++---- src/librustc_codegen_llvm/context.rs | 27 ++------- src/librustc_codegen_llvm/lib.rs | 4 +- src/librustc_codegen_llvm/llvm/ffi.rs | 1 - src/librustc_codegen_ssa/back/link.rs | 13 +--- src/librustc_interface/tests.rs | 4 +- src/librustc_session/config.rs | 7 +-- src/librustc_session/options.rs | 20 +++++-- src/librustc_session/session.rs | 6 +- .../spec/aarch64_unknown_none.rs | 4 +- .../spec/aarch64_unknown_none_softfloat.rs | 4 +- .../spec/armebv7r_none_eabi.rs | 5 +- .../spec/armebv7r_none_eabihf.rs | 5 +- src/librustc_target/spec/armv7a_none_eabi.rs | 4 +- .../spec/armv7a_none_eabihf.rs | 4 +- src/librustc_target/spec/armv7r_none_eabi.rs | 5 +- .../spec/armv7r_none_eabihf.rs | 5 +- src/librustc_target/spec/hermit_base.rs | 4 +- .../spec/hermit_kernel_base.rs | 4 +- src/librustc_target/spec/linux_kernel_base.rs | 4 +- src/librustc_target/spec/mod.rs | 60 +++++++++++++++++-- src/librustc_target/spec/msp430_none_elf.rs | 4 +- .../spec/riscv32i_unknown_none_elf.rs | 5 +- .../spec/riscv32imac_unknown_none_elf.rs | 5 +- .../spec/riscv32imc_unknown_none_elf.rs | 5 +- .../spec/riscv64gc_unknown_none_elf.rs | 5 +- .../spec/riscv64imac_unknown_none_elf.rs | 5 +- src/librustc_target/spec/thumb_base.rs | 4 +- src/librustc_target/spec/wasm32_base.rs | 4 +- src/rustllvm/PassWrapper.cpp | 5 +- 30 files changed, 150 insertions(+), 108 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index b57ad102d634..8630d4173593 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -7,7 +7,7 @@ use crate::back::profiling::{ use crate::base; use crate::common; use crate::consts; -use crate::context::{get_reloc_model, is_pie_binary}; +use crate::context::is_pie_binary; use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; use crate::llvm_util; use crate::type_::Type; @@ -25,6 +25,7 @@ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; use rustc_session::Session; +use rustc_target::spec::RelocModel; use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::CString; @@ -35,16 +36,6 @@ use std::slice; use std::str; use std::sync::Arc; -pub const RELOC_MODEL_ARGS: [(&str, llvm::RelocMode); 7] = [ - ("pic", llvm::RelocMode::PIC), - ("static", llvm::RelocMode::Static), - ("default", llvm::RelocMode::Default), - ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic), - ("ropi", llvm::RelocMode::ROPI), - ("rwpi", llvm::RelocMode::RWPI), - ("ropi-rwpi", llvm::RelocMode::ROPI_RWPI), -]; - pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[ ("small", llvm::CodeModel::Small), ("kernel", llvm::CodeModel::Kernel), @@ -126,6 +117,17 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel } } +fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocMode { + match relocation_model { + RelocModel::Static => llvm::RelocMode::Static, + RelocModel::Pic => llvm::RelocMode::PIC, + RelocModel::DynamicNoPic => llvm::RelocMode::DynamicNoPic, + RelocModel::Ropi => llvm::RelocMode::ROPI, + RelocModel::Rwpi => llvm::RelocMode::RWPI, + RelocModel::RopiRwpi => llvm::RelocMode::ROPI_RWPI, + } +} + // If find_features is true this won't access `sess.crate_types` by assuming // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. @@ -134,7 +136,7 @@ pub fn target_machine_factory( optlvl: config::OptLevel, find_features: bool, ) -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { - let reloc_model = get_reloc_model(sess); + let reloc_model = to_llvm_relocation_model(sess.relocation_model()); let (opt_level, _) = to_llvm_opt_settings(optlvl); let use_softfp = sess.opts.cg.soft_float; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index d385c0730747..f614df6045c5 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -21,7 +21,7 @@ use rustc_session::Session; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::Symbol; use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx}; -use rustc_target::spec::{HasTargetSpec, Target}; +use rustc_target::spec::{HasTargetSpec, RelocModel, Target}; use std::cell::{Cell, RefCell}; use std::ffi::CStr; @@ -87,22 +87,6 @@ pub struct CodegenCx<'ll, 'tcx> { local_gen_sym_counter: Cell, } -pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { - let reloc_model_arg = match sess.opts.cg.relocation_model { - Some(ref s) => &s[..], - None => &sess.target.target.options.relocation_model[..], - }; - - match crate::back::write::RELOC_MODEL_ARGS.iter().find(|&&arg| arg.0 == reloc_model_arg) { - Some(x) => x.1, - _ => { - sess.err(&format!("{:?} is not a valid relocation mode", reloc_model_arg)); - sess.abort_if_errors(); - bug!(); - } - } -} - fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { let tls_model_arg = match sess.opts.debugging_opts.tls_model { Some(ref s) => &s[..], @@ -119,12 +103,9 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { } } -fn is_any_library(sess: &Session) -> bool { - sess.crate_types.borrow().iter().any(|ty| *ty != config::CrateType::Executable) -} - pub fn is_pie_binary(sess: &Session) -> bool { - !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC + sess.relocation_model() == RelocModel::Pic + && !sess.crate_types.borrow().iter().any(|ty| *ty != config::CrateType::Executable) } fn strip_function_ptr_alignment(data_layout: String) -> String { @@ -200,7 +181,7 @@ pub unsafe fn create_module( let llvm_target = SmallCStr::new(&sess.target.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); - if get_reloc_model(sess) == llvm::RelocMode::PIC { + if sess.relocation_model() == RelocModel::Pic { llvm::LLVMRustSetModulePICLevel(llmod); } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 641586797407..9d6f21508411 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -201,7 +201,9 @@ impl CodegenBackend for LlvmCodegenBackend { match req { PrintRequest::RelocationModels => { println!("Available relocation models:"); - for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() { + for name in + &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"] + { println!(" {}", name); } println!(); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index aeb34e5c9c95..85e90226f981 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -446,7 +446,6 @@ pub struct SanitizerOptions { #[derive(Copy, Clone, PartialEq)] #[repr(C)] pub enum RelocMode { - Default, Static, PIC, DynamicNoPic, diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 8725bfaa0257..9d42db8ec429 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -12,7 +12,7 @@ use rustc_session::search_paths::PathKind; /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel}; +use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel}; use super::archive::ArchiveBuilder; use super::command::Command; @@ -1352,7 +1352,7 @@ fn add_position_independent_executable_args( if sess.target.target.options.position_independent_executables { let attr_link_args = &*codegen_results.crate_info.link_args; let mut user_defined_link_args = sess.opts.cg.link_args.iter().chain(attr_link_args); - if is_pic(sess) + if sess.relocation_model() == RelocModel::Pic && !sess.crt_static(Some(crate_type)) && !user_defined_link_args.any(|x| x == "-static") { @@ -1992,12 +1992,3 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool { config::Lto::No | config::Lto::ThinLocal => false, } } - -fn is_pic(sess: &Session) -> bool { - let reloc_model_arg = match sess.opts.cg.relocation_model { - Some(ref s) => &s[..], - None => &sess.target.target.options.relocation_model[..], - }; - - reloc_model_arg == "pic" -} diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 211850486c02..f0e7581b7605 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -14,7 +14,7 @@ use rustc_session::{build_session, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; -use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; +use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelocModel, RelroLevel}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::path::PathBuf; @@ -430,7 +430,7 @@ fn test_codegen_options_tracking_hash() { tracked!(prefer_dynamic, true); tracked!(profile_generate, SwitchWithOptPath::Enabled(None)); tracked!(profile_use, Some(PathBuf::from("abc"))); - tracked!(relocation_model, Some(String::from("relocation model"))); + tracked!(relocation_model, Some(RelocModel::Pic)); tracked!(soft_float, true); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index f6d7e091e00d..1ab02f84c11a 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1311,10 +1311,6 @@ fn collect_print_requests( prints.push(PrintRequest::TargetFeatures); cg.target_feature = String::new(); } - if cg.relocation_model.as_ref().map_or(false, |s| s == "help") { - prints.push(PrintRequest::RelocationModels); - cg.relocation_model = None; - } if cg.code_model.as_ref().map_or(false, |s| s == "help") { prints.push(PrintRequest::CodeModels); cg.code_model = None; @@ -2005,7 +2001,7 @@ crate mod dep_tracking { use crate::utils::NativeLibraryKind; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; - use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple}; + use rustc_target::spec::{MergeFunctions, PanicStrategy, RelocModel, RelroLevel, TargetTriple}; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2053,6 +2049,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option<(String, u64)>); impl_dep_tracking_hash_via_hash!(Option>); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 54b2f2fe4703..804e929bc812 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -6,7 +6,7 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLibraryKind; use rustc_target::spec::TargetTriple; -use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; +use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelocModel, RelroLevel}; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; @@ -265,14 +265,13 @@ macro_rules! options { pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)"; pub const parse_src_file_hash: &str = "either `md5` or `sha1`"; + pub const parse_relocation_model: &str = + "one of supported relocation models (`rustc --print relocation-models`)"; } #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath, - SymbolManglingVersion, CFGuard, SourceFileHashAlgorithm}; - use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; - use std::path::PathBuf; + use super::*; use std::str::FromStr; // Sometimes different options need to build a common structure. @@ -598,6 +597,15 @@ macro_rules! options { true } + fn parse_relocation_model(slot: &mut Option, v: Option<&str>) -> bool { + match v.and_then(|s| RelocModel::from_str(s).ok()) { + Some(relocation_model) => *slot = Some(relocation_model), + None if v == Some("default") => *slot = None, + _ => return false, + } + true + } + fn parse_symbol_mangling_version( slot: &mut SymbolManglingVersion, v: Option<&str>, @@ -697,7 +705,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "compile the program with profiling instrumentation"), profile_use: Option = (None, parse_opt_pathbuf, [TRACKED], "use the given `.profdata` file for profile-guided optimization"), - relocation_model: Option = (None, parse_opt_string, [TRACKED], + relocation_model: Option = (None, parse_relocation_model, [TRACKED], "choose the relocation model to use (`rustc --print relocation-models` for details)"), remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED], "print remarks for these optimization passes (space separated, or \"all\")"), diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index f0bbe1d0a18b..226d93920958 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -22,7 +22,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported use rustc_span::edition::Edition; use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; use rustc_span::SourceFileHashAlgorithm; -use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; +use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target, TargetTriple}; use std::cell::{self, RefCell}; use std::env; @@ -584,6 +584,10 @@ impl Session { } } + pub fn relocation_model(&self) -> RelocModel { + self.opts.cg.relocation_model.unwrap_or(self.target.target.options.relocation_model) + } + pub fn must_not_eliminate_frame_pointers(&self) -> bool { // "mcount" function relies on stack pointer. // See . diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs index 13e62b60ca8f..7177c4e251e7 100644 --- a/src/librustc_target/spec/aarch64_unknown_none.rs +++ b/src/librustc_target/spec/aarch64_unknown_none.rs @@ -6,14 +6,14 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), features: "+strict-align,+neon,+fp-armv8".to_string(), executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, disable_redzone: true, linker_is_gnu: true, max_atomic_width: Some(128), diff --git a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs index cf46252555cd..986300c677df 100644 --- a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs +++ b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs @@ -6,14 +6,14 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), features: "+strict-align,-neon,-fp-armv8".to_string(), executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, disable_redzone: true, linker_is_gnu: true, max_atomic_width: Some(128), diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs index ebe901e4f274..a1f68f6706a2 100644 --- a/src/librustc_target/spec/armebv7r_none_eabi.rs +++ b/src/librustc_target/spec/armebv7r_none_eabi.rs @@ -1,6 +1,7 @@ // Targets the Big endian Cortex-R4/R5 processor (ARMv7-R) -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -18,7 +19,7 @@ pub fn target() -> TargetResult { options: TargetOptions { executables: true, linker: Some("rust-lld".to_owned()), - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(32), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/armebv7r_none_eabihf.rs b/src/librustc_target/spec/armebv7r_none_eabihf.rs index 8652d1051ad0..4d81c21f52a7 100644 --- a/src/librustc_target/spec/armebv7r_none_eabihf.rs +++ b/src/librustc_target/spec/armebv7r_none_eabihf.rs @@ -1,6 +1,7 @@ // Targets the Cortex-R4F/R5F processor (ARMv7-R) -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -18,7 +19,7 @@ pub fn target() -> TargetResult { options: TargetOptions { executables: true, linker: Some("rust-lld".to_owned()), - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, features: "+vfp3,-d32,-fp16".to_string(), max_atomic_width: Some(32), diff --git a/src/librustc_target/spec/armv7a_none_eabi.rs b/src/librustc_target/spec/armv7a_none_eabi.rs index 2fbef154f814..09f1494e81cd 100644 --- a/src/librustc_target/spec/armv7a_none_eabi.rs +++ b/src/librustc_target/spec/armv7a_none_eabi.rs @@ -17,14 +17,14 @@ // - `relocation-model` set to `static`; also no PIE, no relro and no dynamic // linking. rationale: matches `thumb` targets -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(), executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(64), panic_strategy: PanicStrategy::Abort, diff --git a/src/librustc_target/spec/armv7a_none_eabihf.rs b/src/librustc_target/spec/armv7a_none_eabihf.rs index f31e68c5bd12..653ca76435bc 100644 --- a/src/librustc_target/spec/armv7a_none_eabihf.rs +++ b/src/librustc_target/spec/armv7a_none_eabihf.rs @@ -5,14 +5,14 @@ // changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal // `thumb` & `aarch64` targets. -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(), executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(64), panic_strategy: PanicStrategy::Abort, diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs index b7fcda63db00..29dfa1703973 100644 --- a/src/librustc_target/spec/armv7r_none_eabi.rs +++ b/src/librustc_target/spec/armv7r_none_eabi.rs @@ -1,6 +1,7 @@ // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R) -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -18,7 +19,7 @@ pub fn target() -> TargetResult { options: TargetOptions { executables: true, linker: Some("rust-lld".to_owned()), - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(32), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs index 340090fd43b7..e6b0187c3313 100644 --- a/src/librustc_target/spec/armv7r_none_eabihf.rs +++ b/src/librustc_target/spec/armv7r_none_eabihf.rs @@ -1,6 +1,7 @@ // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R) -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -18,7 +19,7 @@ pub fn target() -> TargetResult { options: TargetOptions { executables: true, linker: Some("rust-lld".to_owned()), - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, features: "+vfp3,-d32,-fp16".to_string(), max_atomic_width: Some(32), diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs index b9f94023e7a7..cb12055290e2 100644 --- a/src/librustc_target/spec/hermit_base.rs +++ b/src/librustc_target/spec/hermit_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -15,7 +15,7 @@ pub fn opts() -> TargetOptions { pre_link_args, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, target_family: None, tls_model: "initial-exec".to_string(), ..Default::default() diff --git a/src/librustc_target/spec/hermit_kernel_base.rs b/src/librustc_target/spec/hermit_kernel_base.rs index 1f9b195e2e69..11599fda4090 100644 --- a/src/librustc_target/spec/hermit_kernel_base.rs +++ b/src/librustc_target/spec/hermit_kernel_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -16,7 +16,7 @@ pub fn opts() -> TargetOptions { pre_link_args, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, target_family: None, tls_model: "initial-exec".to_string(), ..Default::default() diff --git a/src/librustc_target/spec/linux_kernel_base.rs b/src/librustc_target/spec/linux_kernel_base.rs index 4a900d1b02cb..201d6a0fff93 100644 --- a/src/librustc_target/spec/linux_kernel_base.rs +++ b/src/librustc_target/spec/linux_kernel_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -16,7 +16,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, needs_plt: true, relro_level: RelroLevel::Full, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, target_family: Some("unix".to_string()), pre_link_args, diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d90404633172..77fc78e81482 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -265,6 +265,46 @@ impl ToJson for MergeFunctions { } } +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum RelocModel { + Static, + Pic, + DynamicNoPic, + Ropi, + Rwpi, + RopiRwpi, +} + +impl FromStr for RelocModel { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "static" => RelocModel::Static, + "pic" => RelocModel::Pic, + "dynamic-no-pic" => RelocModel::DynamicNoPic, + "ropi" => RelocModel::Ropi, + "rwpi" => RelocModel::Rwpi, + "ropi-rwpi" => RelocModel::RopiRwpi, + _ => return Err(()), + }) + } +} + +impl ToJson for RelocModel { + fn to_json(&self) -> Json { + match *self { + RelocModel::Static => "static", + RelocModel::Pic => "pic", + RelocModel::DynamicNoPic => "dynamic-no-pic", + RelocModel::Ropi => "ropi", + RelocModel::Rwpi => "rwpi", + RelocModel::RopiRwpi => "ropi-rwpi", + } + .to_json() + } +} + pub enum LoadTargetError { BuiltinTargetNotFound(String), Other(String), @@ -614,8 +654,8 @@ pub struct TargetOptions { /// libraries. Defaults to false. pub executables: bool, /// Relocation model to use in object file. Corresponds to `llc - /// -relocation-model=$relocation_model`. Defaults to "pic". - pub relocation_model: String, + /// -relocation-model=$relocation_model`. Defaults to `Pic`. + pub relocation_model: RelocModel, /// Code model to use. Corresponds to `llc -code-model=$code_model`. pub code_model: Option, /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec" @@ -821,7 +861,7 @@ impl Default for TargetOptions { dynamic_linking: false, only_cdylib: false, executables: false, - relocation_model: "pic".to_string(), + relocation_model: RelocModel::Pic, code_model: None, tls_model: "global-dynamic".to_string(), disable_redzone: false, @@ -1008,6 +1048,18 @@ impl Target { Some(Ok(())) })).unwrap_or(Ok(())) } ); + ($key_name:ident, RelocModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s.parse::() { + Ok(relocation_model) => base.options.$key_name = relocation_model, + _ => return Some(Err(format!("'{}' is not a valid relocation model. \ + Run `rustc --print relocation-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, PanicStrategy) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { @@ -1146,7 +1198,7 @@ impl Target { key!(dynamic_linking, bool); key!(only_cdylib, bool); key!(executables, bool); - key!(relocation_model); + key!(relocation_model, RelocModel)?; key!(code_model, optional); key!(tls_model); key!(disable_redzone, bool); diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs index 9a90ac7ccece..c6d0308f8f82 100644 --- a/src/librustc_target/spec/msp430_none_elf.rs +++ b/src/librustc_target/spec/msp430_none_elf.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -40,7 +40,7 @@ pub fn target() -> TargetResult { // Similarly, one almost always never wants to use relocatable // code because of the extra costs it involves. - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, // Right now we invoke an external assembler and this isn't // compatible with multiple codegen units, and plus we probably diff --git a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs index a7020bc8f919..aade1e708232 100644 --- a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs @@ -1,4 +1,5 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,7 +22,7 @@ pub fn target() -> TargetResult { features: String::new(), executables: true, panic_strategy: PanicStrategy::Abort, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, abi_blacklist: super::riscv_base::abi_blacklist(), eliminate_frame_pointer: false, diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs index 6ec49410aebe..e2990eeb826f 100644 --- a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs @@ -1,4 +1,5 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,7 +22,7 @@ pub fn target() -> TargetResult { features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, abi_blacklist: super::riscv_base::abi_blacklist(), eliminate_frame_pointer: false, diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs index 70346347fb38..55a4d58dfccc 100644 --- a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs @@ -1,4 +1,5 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,7 +22,7 @@ pub fn target() -> TargetResult { features: "+m,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, abi_blacklist: super::riscv_base::abi_blacklist(), eliminate_frame_pointer: false, diff --git a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs index ca0f3d64d4a0..9dbbcb1f4bd6 100644 --- a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs @@ -1,4 +1,5 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,7 +22,7 @@ pub fn target() -> TargetResult { features: "+m,+a,+f,+d,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, code_model: Some("medium".to_string()), emit_debug_gdb_scripts: false, abi_blacklist: super::riscv_base::abi_blacklist(), diff --git a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs index 614403fe02af..7e9390561a70 100644 --- a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs @@ -1,4 +1,5 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,7 +22,7 @@ pub fn target() -> TargetResult { features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, code_model: Some("medium".to_string()), emit_debug_gdb_scripts: false, abi_blacklist: super::riscv_base::abi_blacklist(), diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index eca095b59428..646a149a3362 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -27,7 +27,7 @@ // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of // build scripts / gcc flags. -use crate::spec::{PanicStrategy, TargetOptions}; +use crate::spec::{PanicStrategy, RelocModel, TargetOptions}; pub fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults @@ -40,7 +40,7 @@ pub fn opts() -> TargetOptions { panic_strategy: PanicStrategy::Abort, // Similarly, one almost always never wants to use relocatable code because of the extra // costs it involves. - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, abi_blacklist: super::arm_base::abi_blacklist(), // When this section is added a volatile load to its start address is also generated. This // volatile load is a footgun as it can end up loading an invalid memory address, depending diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs index 47e80e8db19f..08bade2abf4a 100644 --- a/src/librustc_target/spec/wasm32_base.rs +++ b/src/librustc_target/spec/wasm32_base.rs @@ -1,4 +1,4 @@ -use super::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions}; use std::collections::BTreeMap; pub fn options() -> TargetOptions { @@ -130,7 +130,7 @@ pub fn options() -> TargetOptions { // that eventually we can ship a `pic`-compatible standard library which // works with `static` as well (or works with some method of generating // non-relative calls and such later on). - relocation_model: "static".to_string(), + relocation_model: RelocModel::Static, // When the atomics feature is activated then these two keys matter, // otherwise they're basically ignored by the standard library. In this diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index b221c17b422f..95c5eb2f183e 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -347,7 +347,6 @@ static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level } enum class LLVMRustRelocMode { - Default, Static, PIC, DynamicNoPic, @@ -356,10 +355,8 @@ enum class LLVMRustRelocMode { ROPIRWPI, }; -static Optional fromRust(LLVMRustRelocMode RustReloc) { +static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) { switch (RustReloc) { - case LLVMRustRelocMode::Default: - return None; case LLVMRustRelocMode::Static: return Reloc::Static; case LLVMRustRelocMode::PIC: From 045272558309a7600cb4618db5a2c52384f1d14e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Apr 2020 20:49:00 +0300 Subject: [PATCH 2/5] codegen_llvm: `RelocMode` -> `RelocModel` --- src/librustc_codegen_llvm/back/write.rs | 14 +++++++------- src/librustc_codegen_llvm/llvm/ffi.rs | 4 ++-- src/rustllvm/PassWrapper.cpp | 18 +++++++++--------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 8630d4173593..8fa577d87129 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -117,14 +117,14 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel } } -fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocMode { +fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel { match relocation_model { - RelocModel::Static => llvm::RelocMode::Static, - RelocModel::Pic => llvm::RelocMode::PIC, - RelocModel::DynamicNoPic => llvm::RelocMode::DynamicNoPic, - RelocModel::Ropi => llvm::RelocMode::ROPI, - RelocModel::Rwpi => llvm::RelocMode::RWPI, - RelocModel::RopiRwpi => llvm::RelocMode::ROPI_RWPI, + RelocModel::Static => llvm::RelocModel::Static, + RelocModel::Pic => llvm::RelocModel::PIC, + RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic, + RelocModel::Ropi => llvm::RelocModel::ROPI, + RelocModel::Rwpi => llvm::RelocModel::RWPI, + RelocModel::RopiRwpi => llvm::RelocModel::ROPI_RWPI, } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 85e90226f981..fd03812cccda 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -445,7 +445,7 @@ pub struct SanitizerOptions { /// LLVMRelocMode #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum RelocMode { +pub enum RelocModel { Static, PIC, DynamicNoPic, @@ -1945,7 +1945,7 @@ extern "C" { Features: *const c_char, Abi: *const c_char, Model: CodeModel, - Reloc: RelocMode, + Reloc: RelocModel, Level: CodeGenOptLevel, UseSoftFP: bool, PositionIndependentExecutable: bool, diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 95c5eb2f183e..e31dd77d8afd 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -346,7 +346,7 @@ static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level } } -enum class LLVMRustRelocMode { +enum class LLVMRustRelocModel { Static, PIC, DynamicNoPic, @@ -355,19 +355,19 @@ enum class LLVMRustRelocMode { ROPIRWPI, }; -static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) { +static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) { switch (RustReloc) { - case LLVMRustRelocMode::Static: + case LLVMRustRelocModel::Static: return Reloc::Static; - case LLVMRustRelocMode::PIC: + case LLVMRustRelocModel::PIC: return Reloc::PIC_; - case LLVMRustRelocMode::DynamicNoPic: + case LLVMRustRelocModel::DynamicNoPic: return Reloc::DynamicNoPIC; - case LLVMRustRelocMode::ROPI: + case LLVMRustRelocModel::ROPI: return Reloc::ROPI; - case LLVMRustRelocMode::RWPI: + case LLVMRustRelocModel::RWPI: return Reloc::RWPI; - case LLVMRustRelocMode::ROPIRWPI: + case LLVMRustRelocModel::ROPIRWPI: return Reloc::ROPI_RWPI; } report_fatal_error("Bad RelocModel."); @@ -437,7 +437,7 @@ extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( const char *TripleStr, const char *CPU, const char *Feature, - const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, + const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc, LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool PositionIndependentExecutable, bool FunctionSections, bool DataSections, From 76d85de22359d7a924b84dde6830650e92e44b89 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Apr 2020 21:10:01 +0300 Subject: [PATCH 3/5] codegen_llvm: Simplify logic for relaxing PIC into PIE --- src/librustc_codegen_llvm/back/write.rs | 24 +++++++--------------- src/librustc_codegen_llvm/context.rs | 13 ++++++++---- src/librustc_codegen_llvm/lib.rs | 11 +++------- src/librustc_codegen_llvm/llvm_util.rs | 4 ++-- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 4 ---- 6 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 8fa577d87129..bf79c5b593e4 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -7,7 +7,7 @@ use crate::back::profiling::{ use crate::base; use crate::common; use crate::consts; -use crate::context::is_pie_binary; +use crate::context::all_outputs_are_pic_executables; use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; use crate::llvm_util; use crate::type_::Type; @@ -75,19 +75,13 @@ pub fn write_output_file( } } -pub fn create_informational_target_machine( - sess: &Session, - find_features: bool, -) -> &'static mut llvm::TargetMachine { - target_machine_factory(sess, config::OptLevel::No, find_features)() +pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine { + target_machine_factory(sess, config::OptLevel::No)() .unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise()) } -pub fn create_target_machine( - tcx: TyCtxt<'_>, - find_features: bool, -) -> &'static mut llvm::TargetMachine { - target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE), find_features)() +pub fn create_target_machine(tcx: TyCtxt<'_>) -> &'static mut llvm::TargetMachine { + target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))() .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise()) } @@ -128,13 +122,9 @@ fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel { } } -// If find_features is true this won't access `sess.crate_types` by assuming -// that `is_pie_binary` is false. When we discover LLVM target features -// `sess.crate_types` is uninitialized so we cannot access it. pub fn target_machine_factory( sess: &Session, optlvl: config::OptLevel, - find_features: bool, ) -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { let reloc_model = to_llvm_relocation_model(sess.relocation_model()); @@ -177,7 +167,7 @@ pub fn target_machine_factory( let features = features.join(","); let features = CString::new(features).unwrap(); let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname); - let is_pie_binary = !find_features && is_pie_binary(sess); + let pic_is_pie = all_outputs_are_pic_executables(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes; @@ -194,7 +184,7 @@ pub fn target_machine_factory( reloc_model, opt_level, use_softfp, - is_pie_binary, + pic_is_pie, ffunction_sections, fdata_sections, trap_unreachable, diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index f614df6045c5..df442609052b 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -103,9 +103,14 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { } } -pub fn is_pie_binary(sess: &Session) -> bool { +/// PIE is potentially more effective than PIC, but can only be used in executables. +/// If all our outputs are executables, then we can relax PIC to PIE when producing object code. +/// If the list of crate types is not yet known we conservatively return `false`. +pub fn all_outputs_are_pic_executables(sess: &Session) -> bool { sess.relocation_model() == RelocModel::Pic - && !sess.crate_types.borrow().iter().any(|ty| *ty != config::CrateType::Executable) + && sess.crate_types.try_get().map_or(false, |crate_types| { + crate_types.iter().all(|ty| *ty == config::CrateType::Executable) + }) } fn strip_function_ptr_alignment(data_layout: String) -> String { @@ -138,7 +143,7 @@ pub unsafe fn create_module( // Ensure the data-layout values hardcoded remain the defaults. if sess.target.target.options.is_builtin { - let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false); + let tm = crate::back::write::create_informational_target_machine(tcx.sess); llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); llvm::LLVMRustDisposeTargetMachine(tm); @@ -185,7 +190,7 @@ pub unsafe fn create_module( llvm::LLVMRustSetModulePICLevel(llmod); } - if is_pie_binary(sess) { + if all_outputs_are_pic_executables(sess) { llvm::LLVMRustSetModulePIELevel(llmod); } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 9d6f21508411..330d6ea75d27 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -110,9 +110,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend { &self, sess: &Session, optlvl: OptLevel, - find_features: bool, ) -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { - back::write::target_machine_factory(sess, optlvl, find_features) + back::write::target_machine_factory(sess, optlvl) } fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str { llvm_util::target_cpu(sess) @@ -353,7 +352,7 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, false) } + ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx) } } } @@ -361,11 +360,7 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { - llmod_raw, - llcx, - tm: create_informational_target_machine(&tcx.sess, false), - } + ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) } } } diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 6f16b0fb79c3..a36e95771e8b 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -270,7 +270,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { } pub fn target_features(sess: &Session) -> Vec { - let target_machine = create_informational_target_machine(sess, true); + let target_machine = create_informational_target_machine(sess); target_feature_whitelist(sess) .iter() .filter_map(|&(feature, gate)| { @@ -322,7 +322,7 @@ pub fn print_passes() { pub(crate) fn print(req: PrintRequest, sess: &Session) { require_inited(); - let tm = create_informational_target_machine(sess, true); + let tm = create_informational_target_machine(sess); unsafe { match req { PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm), diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 37034141bb77..c84f38670f77 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1037,7 +1037,7 @@ fn start_executing_work( regular_module_config: regular_config, metadata_module_config: metadata_config, allocator_module_config: allocator_config, - tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol, false)), + tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol)), total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 91be123beb0b..6cbb47efa99f 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -110,14 +110,10 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se tcx: TyCtxt<'_>, cgu_name: Symbol, ) -> (ModuleCodegen, u64); - // If find_features is true this won't access `sess.crate_types` by assuming - // that `is_pie_binary` is false. When we discover LLVM target features - // `sess.crate_types` is uninitialized so we cannot access it. fn target_machine_factory( &self, sess: &Session, opt_level: config::OptLevel, - find_features: bool, ) -> Arc Result + Send + Sync>; fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str; } From a4199b45c246b757b4ac000d0a5a83d7cede9b5f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 24 Apr 2020 00:53:25 +0300 Subject: [PATCH 4/5] rustc-book: Document `-C relocation-model` --- src/doc/rustc/src/codegen-options/index.md | 43 ++++++++++++++++++++-- src/librustc_session/options.rs | 3 +- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index a503679f19bf..dc5d797ebbcd 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -319,11 +319,46 @@ to a valid `.profdata` file. See the chapter on ## relocation-model -This option lets you choose which -[relocation](https://en.wikipedia.org/wiki/Relocation_\(computing\)) model to -use. +This option controls generation of +[position-independent code (PIC)](https://en.wikipedia.org/wiki/Position-independent_code). -To find the valid options for this flag, run `rustc --print relocation-models`. +Supported values for this option are: + +#### Primary relocation models + +- `static` - non-relocatable code, machine instructions may use absolute addressing modes. + +- `pic` - fully relocatable position independent code, +machine instructions need to use relative addressing modes. +Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers, +depending on the produced crate types. +This is the default model for majority of supported targets. + +#### Special relocation models + +- `dynamic-no-pic` - relocatable external references, non-relocatable code. +Only makes sense on Darwin and is rarely used. +If StackOverflow tells you to use this as an opt-out of PIC or PIE, don't believe it, +use `-C relocation-model=static` instead. +- `ropi`, `rwpi` and `ropi-rwpi` - relocatable code and read-only data, relocatable read-write data, +and combination of both, respectively. +Only makes sense for certain embedded ARM targets. +- `default` - relocation model default to the current target. +Only makes sense as an override for some other explicitly specified relocation model +previously set on the command line. + +Supported values can also be discovered by running `rustc --print relocation-models`. + +#### Linking effects + +In addition to codegen effects, `relocation-model` has effects during linking. + +If the relocation model is `pic` and the current target supports position-independent executables +(PIE), the linker will be instructed (`-pie`) to produce one. +If the target doesn't support both position-independent and statically linked executables, +then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`, +and the linker is instructed (`-static`) to produce a statically linked +but not position-independent executable. ## remark diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 804e929bc812..2279c16748c1 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -706,7 +706,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, profile_use: Option = (None, parse_opt_pathbuf, [TRACKED], "use the given `.profdata` file for profile-guided optimization"), relocation_model: Option = (None, parse_relocation_model, [TRACKED], - "choose the relocation model to use (`rustc --print relocation-models` for details)"), + "control generation of position-independent code (PIC) \ + (`rustc --print relocation-models` for details)"), remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED], "print remarks for these optimization passes (space separated, or \"all\")"), rpath: bool = (false, parse_bool, [UNTRACKED], From 45fbe8f21c959bfe52b3b94b1ad775e9fbab529e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 24 Apr 2020 00:56:19 +0300 Subject: [PATCH 5/5] tests: Remove unnecessary `-C relocation-model=dynamic-no-pic`s The referenced `sanitizer-address/Makefile` no longer exists, so perhaps these options are no longer necessary as well. Even if they are still necessary, they should use `-C relocation-model=static` instead. --- src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile | 7 ++----- src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile index 35317dca1e82..5d46be87eac6 100644 --- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile @@ -11,10 +11,7 @@ LOG := $(TMPDIR)/log.txt # are compiled with address sanitizer, and we assert that a fault in the cdylib # is correctly detected. -# See comment in sanitizer-address/Makefile for why this is here -EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic - all: - $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs - $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs + $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile index 24d2ebd8f48a..f62c3a6654ed 100644 --- a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile @@ -11,10 +11,7 @@ LOG := $(TMPDIR)/log.txt # are compiled with address sanitizer, and we assert that a fault in the dylib # is correctly detected. -# See comment in sanitizer-address/Makefile for why this is here -EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic - all: - $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs - $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs + $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow