Skip to content

Commit 96c1bb5

Browse files
authored
Rollup merge of #71490 - petrochenkov:passcheck2, r=davidtwco
Cleanup and document `-C relocation-model` As the title says, this is mostly a refactoring and documentation. One potentially observable change here is that `-C relocation-model=default` now takes the default from the Rust target, rather than from the underlying LLVM target. In other words, `-C relocation-model=default` is now equivalent to not specifying the relocation model on command line at all. Apparently no one used that option because it has other bugs as well, e.g. PIC `default` wasn't treated as PIC in some places.
2 parents ec1f28f + 45fbe8f commit 96c1bb5

36 files changed

+225
-167
lines changed

src/doc/rustc/src/codegen-options/index.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,46 @@ to a valid `.profdata` file. See the chapter on
319319

320320
## relocation-model
321321

322-
This option lets you choose which
323-
[relocation](https://en.wikipedia.org/wiki/Relocation_\(computing\)) model to
324-
use.
322+
This option controls generation of
323+
[position-independent code (PIC)](https://en.wikipedia.org/wiki/Position-independent_code).
325324

326-
To find the valid options for this flag, run `rustc --print relocation-models`.
325+
Supported values for this option are:
326+
327+
#### Primary relocation models
328+
329+
- `static` - non-relocatable code, machine instructions may use absolute addressing modes.
330+
331+
- `pic` - fully relocatable position independent code,
332+
machine instructions need to use relative addressing modes.
333+
Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers,
334+
depending on the produced crate types.
335+
This is the default model for majority of supported targets.
336+
337+
#### Special relocation models
338+
339+
- `dynamic-no-pic` - relocatable external references, non-relocatable code.
340+
Only makes sense on Darwin and is rarely used.
341+
If StackOverflow tells you to use this as an opt-out of PIC or PIE, don't believe it,
342+
use `-C relocation-model=static` instead.
343+
- `ropi`, `rwpi` and `ropi-rwpi` - relocatable code and read-only data, relocatable read-write data,
344+
and combination of both, respectively.
345+
Only makes sense for certain embedded ARM targets.
346+
- `default` - relocation model default to the current target.
347+
Only makes sense as an override for some other explicitly specified relocation model
348+
previously set on the command line.
349+
350+
Supported values can also be discovered by running `rustc --print relocation-models`.
351+
352+
#### Linking effects
353+
354+
In addition to codegen effects, `relocation-model` has effects during linking.
355+
356+
If the relocation model is `pic` and the current target supports position-independent executables
357+
(PIE), the linker will be instructed (`-pie`) to produce one.
358+
If the target doesn't support both position-independent and statically linked executables,
359+
then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`,
360+
and the linker is instructed (`-static`) to produce a statically linked
361+
but not position-independent executable.
327362

328363
## remark
329364

src/librustc_codegen_llvm/back/write.rs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::back::profiling::{
77
use crate::base;
88
use crate::common;
99
use crate::consts;
10-
use crate::context::{get_reloc_model, is_pie_binary};
10+
use crate::context::all_outputs_are_pic_executables;
1111
use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
1212
use crate::llvm_util;
1313
use crate::type_::Type;
@@ -25,6 +25,7 @@ use rustc_middle::bug;
2525
use rustc_middle::ty::TyCtxt;
2626
use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
2727
use rustc_session::Session;
28+
use rustc_target::spec::RelocModel;
2829

2930
use libc::{c_char, c_int, c_uint, c_void, size_t};
3031
use std::ffi::CString;
@@ -35,16 +36,6 @@ use std::slice;
3536
use std::str;
3637
use std::sync::Arc;
3738

38-
pub const RELOC_MODEL_ARGS: [(&str, llvm::RelocMode); 7] = [
39-
("pic", llvm::RelocMode::PIC),
40-
("static", llvm::RelocMode::Static),
41-
("default", llvm::RelocMode::Default),
42-
("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
43-
("ropi", llvm::RelocMode::ROPI),
44-
("rwpi", llvm::RelocMode::RWPI),
45-
("ropi-rwpi", llvm::RelocMode::ROPI_RWPI),
46-
];
47-
4839
pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[
4940
("small", llvm::CodeModel::Small),
5041
("kernel", llvm::CodeModel::Kernel),
@@ -84,19 +75,13 @@ pub fn write_output_file(
8475
}
8576
}
8677

87-
pub fn create_informational_target_machine(
88-
sess: &Session,
89-
find_features: bool,
90-
) -> &'static mut llvm::TargetMachine {
91-
target_machine_factory(sess, config::OptLevel::No, find_features)()
78+
pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
79+
target_machine_factory(sess, config::OptLevel::No)()
9280
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
9381
}
9482

95-
pub fn create_target_machine(
96-
tcx: TyCtxt<'_>,
97-
find_features: bool,
98-
) -> &'static mut llvm::TargetMachine {
99-
target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE), find_features)()
83+
pub fn create_target_machine(tcx: TyCtxt<'_>) -> &'static mut llvm::TargetMachine {
84+
target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))()
10085
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
10186
}
10287

@@ -126,15 +111,22 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
126111
}
127112
}
128113

129-
// If find_features is true this won't access `sess.crate_types` by assuming
130-
// that `is_pie_binary` is false. When we discover LLVM target features
131-
// `sess.crate_types` is uninitialized so we cannot access it.
114+
fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
115+
match relocation_model {
116+
RelocModel::Static => llvm::RelocModel::Static,
117+
RelocModel::Pic => llvm::RelocModel::PIC,
118+
RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
119+
RelocModel::Ropi => llvm::RelocModel::ROPI,
120+
RelocModel::Rwpi => llvm::RelocModel::RWPI,
121+
RelocModel::RopiRwpi => llvm::RelocModel::ROPI_RWPI,
122+
}
123+
}
124+
132125
pub fn target_machine_factory(
133126
sess: &Session,
134127
optlvl: config::OptLevel,
135-
find_features: bool,
136128
) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
137-
let reloc_model = get_reloc_model(sess);
129+
let reloc_model = to_llvm_relocation_model(sess.relocation_model());
138130

139131
let (opt_level, _) = to_llvm_opt_settings(optlvl);
140132
let use_softfp = sess.opts.cg.soft_float;
@@ -175,7 +167,7 @@ pub fn target_machine_factory(
175167
let features = features.join(",");
176168
let features = CString::new(features).unwrap();
177169
let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
178-
let is_pie_binary = !find_features && is_pie_binary(sess);
170+
let pic_is_pie = all_outputs_are_pic_executables(sess);
179171
let trap_unreachable = sess.target.target.options.trap_unreachable;
180172
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
181173

@@ -192,7 +184,7 @@ pub fn target_machine_factory(
192184
reloc_model,
193185
opt_level,
194186
use_softfp,
195-
is_pie_binary,
187+
pic_is_pie,
196188
ffunction_sections,
197189
fdata_sections,
198190
trap_unreachable,

src/librustc_codegen_llvm/context.rs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_session::Session;
2121
use rustc_span::source_map::{Span, DUMMY_SP};
2222
use rustc_span::symbol::Symbol;
2323
use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx};
24-
use rustc_target::spec::{HasTargetSpec, Target};
24+
use rustc_target::spec::{HasTargetSpec, RelocModel, Target};
2525

2626
use std::cell::{Cell, RefCell};
2727
use std::ffi::CStr;
@@ -87,22 +87,6 @@ pub struct CodegenCx<'ll, 'tcx> {
8787
local_gen_sym_counter: Cell<usize>,
8888
}
8989

90-
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
91-
let reloc_model_arg = match sess.opts.cg.relocation_model {
92-
Some(ref s) => &s[..],
93-
None => &sess.target.target.options.relocation_model[..],
94-
};
95-
96-
match crate::back::write::RELOC_MODEL_ARGS.iter().find(|&&arg| arg.0 == reloc_model_arg) {
97-
Some(x) => x.1,
98-
_ => {
99-
sess.err(&format!("{:?} is not a valid relocation mode", reloc_model_arg));
100-
sess.abort_if_errors();
101-
bug!();
102-
}
103-
}
104-
}
105-
10690
fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
10791
let tls_model_arg = match sess.opts.debugging_opts.tls_model {
10892
Some(ref s) => &s[..],
@@ -119,12 +103,14 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
119103
}
120104
}
121105

122-
fn is_any_library(sess: &Session) -> bool {
123-
sess.crate_types.borrow().iter().any(|ty| *ty != config::CrateType::Executable)
124-
}
125-
126-
pub fn is_pie_binary(sess: &Session) -> bool {
127-
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
106+
/// PIE is potentially more effective than PIC, but can only be used in executables.
107+
/// If all our outputs are executables, then we can relax PIC to PIE when producing object code.
108+
/// If the list of crate types is not yet known we conservatively return `false`.
109+
pub fn all_outputs_are_pic_executables(sess: &Session) -> bool {
110+
sess.relocation_model() == RelocModel::Pic
111+
&& sess.crate_types.try_get().map_or(false, |crate_types| {
112+
crate_types.iter().all(|ty| *ty == config::CrateType::Executable)
113+
})
128114
}
129115

130116
fn strip_function_ptr_alignment(data_layout: String) -> String {
@@ -157,7 +143,7 @@ pub unsafe fn create_module(
157143

158144
// Ensure the data-layout values hardcoded remain the defaults.
159145
if sess.target.target.options.is_builtin {
160-
let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
146+
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
161147
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
162148
llvm::LLVMRustDisposeTargetMachine(tm);
163149

@@ -200,11 +186,11 @@ pub unsafe fn create_module(
200186
let llvm_target = SmallCStr::new(&sess.target.target.llvm_target);
201187
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
202188

203-
if get_reloc_model(sess) == llvm::RelocMode::PIC {
189+
if sess.relocation_model() == RelocModel::Pic {
204190
llvm::LLVMRustSetModulePICLevel(llmod);
205191
}
206192

207-
if is_pie_binary(sess) {
193+
if all_outputs_are_pic_executables(sess) {
208194
llvm::LLVMRustSetModulePIELevel(llmod);
209195
}
210196

src/librustc_codegen_llvm/lib.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
110110
&self,
111111
sess: &Session,
112112
optlvl: OptLevel,
113-
find_features: bool,
114113
) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
115-
back::write::target_machine_factory(sess, optlvl, find_features)
114+
back::write::target_machine_factory(sess, optlvl)
116115
}
117116
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
118117
llvm_util::target_cpu(sess)
@@ -201,7 +200,9 @@ impl CodegenBackend for LlvmCodegenBackend {
201200
match req {
202201
PrintRequest::RelocationModels => {
203202
println!("Available relocation models:");
204-
for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
203+
for name in
204+
&["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"]
205+
{
205206
println!(" {}", name);
206207
}
207208
println!();
@@ -351,19 +352,15 @@ impl ModuleLlvm {
351352
unsafe {
352353
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
353354
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
354-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, false) }
355+
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx) }
355356
}
356357
}
357358

358359
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
359360
unsafe {
360361
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
361362
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
362-
ModuleLlvm {
363-
llmod_raw,
364-
llcx,
365-
tm: create_informational_target_machine(&tcx.sess, false),
366-
}
363+
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
367364
}
368365
}
369366

src/librustc_codegen_llvm/llvm/ffi.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,7 @@ pub struct SanitizerOptions {
445445
/// LLVMRelocMode
446446
#[derive(Copy, Clone, PartialEq)]
447447
#[repr(C)]
448-
pub enum RelocMode {
449-
Default,
448+
pub enum RelocModel {
450449
Static,
451450
PIC,
452451
DynamicNoPic,
@@ -1946,7 +1945,7 @@ extern "C" {
19461945
Features: *const c_char,
19471946
Abi: *const c_char,
19481947
Model: CodeModel,
1949-
Reloc: RelocMode,
1948+
Reloc: RelocModel,
19501949
Level: CodeGenOptLevel,
19511950
UseSoftFP: bool,
19521951
PositionIndependentExecutable: bool,

src/librustc_codegen_llvm/llvm_util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
270270
}
271271

272272
pub fn target_features(sess: &Session) -> Vec<Symbol> {
273-
let target_machine = create_informational_target_machine(sess, true);
273+
let target_machine = create_informational_target_machine(sess);
274274
target_feature_whitelist(sess)
275275
.iter()
276276
.filter_map(|&(feature, gate)| {
@@ -322,7 +322,7 @@ pub fn print_passes() {
322322

323323
pub(crate) fn print(req: PrintRequest, sess: &Session) {
324324
require_inited();
325-
let tm = create_informational_target_machine(sess, true);
325+
let tm = create_informational_target_machine(sess);
326326
unsafe {
327327
match req {
328328
PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),

src/librustc_codegen_ssa/back/link.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_session::search_paths::PathKind;
1212
/// need out of the shared crate context before we get rid of it.
1313
use rustc_session::{filesearch, Session};
1414
use rustc_span::symbol::Symbol;
15-
use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel};
15+
use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel};
1616

1717
use super::archive::ArchiveBuilder;
1818
use super::command::Command;
@@ -1352,7 +1352,7 @@ fn add_position_independent_executable_args(
13521352
if sess.target.target.options.position_independent_executables {
13531353
let attr_link_args = &*codegen_results.crate_info.link_args;
13541354
let mut user_defined_link_args = sess.opts.cg.link_args.iter().chain(attr_link_args);
1355-
if is_pic(sess)
1355+
if sess.relocation_model() == RelocModel::Pic
13561356
&& !sess.crt_static(Some(crate_type))
13571357
&& !user_defined_link_args.any(|x| x == "-static")
13581358
{
@@ -1992,12 +1992,3 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
19921992
config::Lto::No | config::Lto::ThinLocal => false,
19931993
}
19941994
}
1995-
1996-
fn is_pic(sess: &Session) -> bool {
1997-
let reloc_model_arg = match sess.opts.cg.relocation_model {
1998-
Some(ref s) => &s[..],
1999-
None => &sess.target.target.options.relocation_model[..],
2000-
};
2001-
2002-
reloc_model_arg == "pic"
2003-
}

src/librustc_codegen_ssa/back/write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10371037
regular_module_config: regular_config,
10381038
metadata_module_config: metadata_config,
10391039
allocator_module_config: allocator_config,
1040-
tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol, false)),
1040+
tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol)),
10411041
total_cgus,
10421042
msvc_imps_needed: msvc_imps_needed(tcx),
10431043
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),

src/librustc_codegen_ssa/traits/backend.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,10 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
110110
tcx: TyCtxt<'_>,
111111
cgu_name: Symbol,
112112
) -> (ModuleCodegen<Self::Module>, u64);
113-
// If find_features is true this won't access `sess.crate_types` by assuming
114-
// that `is_pie_binary` is false. When we discover LLVM target features
115-
// `sess.crate_types` is uninitialized so we cannot access it.
116113
fn target_machine_factory(
117114
&self,
118115
sess: &Session,
119116
opt_level: config::OptLevel,
120-
find_features: bool,
121117
) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>;
122118
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
123119
}

src/librustc_interface/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_session::{build_session, Session};
1414
use rustc_span::edition::{Edition, DEFAULT_EDITION};
1515
use rustc_span::symbol::sym;
1616
use rustc_span::SourceFileHashAlgorithm;
17-
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
17+
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelocModel, RelroLevel};
1818
use std::collections::{BTreeMap, BTreeSet};
1919
use std::iter::FromIterator;
2020
use std::path::PathBuf;
@@ -430,7 +430,7 @@ fn test_codegen_options_tracking_hash() {
430430
tracked!(prefer_dynamic, true);
431431
tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
432432
tracked!(profile_use, Some(PathBuf::from("abc")));
433-
tracked!(relocation_model, Some(String::from("relocation model")));
433+
tracked!(relocation_model, Some(RelocModel::Pic));
434434
tracked!(soft_float, true);
435435
tracked!(target_cpu, Some(String::from("abc")));
436436
tracked!(target_feature, String::from("all the features, all of them"));

0 commit comments

Comments
 (0)