codegen_llvm: Simplify logic for relaxing PIC into PIE

This commit is contained in:
Vadim Petrochenkov 2020-04-23 21:10:01 +03:00
parent 0452725583
commit 76d85de223
6 changed files with 22 additions and 36 deletions

View File

@ -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<dyn Fn() -> 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,

View File

@ -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);
}

View File

@ -110,9 +110,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
&self,
sess: &Session,
optlvl: OptLevel,
find_features: bool,
) -> Arc<dyn Fn() -> 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) }
}
}

View File

@ -270,7 +270,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
}
pub fn target_features(sess: &Session) -> Vec<Symbol> {
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),

View File

@ -1037,7 +1037,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
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(),

View File

@ -110,14 +110,10 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
tcx: TyCtxt<'_>,
cgu_name: Symbol,
) -> (ModuleCodegen<Self::Module>, 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<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>;
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
}