Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pie as another relocation-model value #88820

Merged
merged 1 commit into from
Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
match relocation_model {
RelocModel::Static => llvm::RelocModel::Static,
RelocModel::Pic => llvm::RelocModel::PIC,
// LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute.
RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
RelocModel::Ropi => llvm::RelocModel::ROPI,
RelocModel::Rwpi => llvm::RelocModel::RWPI,
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,14 @@ pub unsafe fn create_module(
let llvm_target = SmallCStr::new(&sess.target.llvm_target);
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());

if sess.relocation_model() == RelocModel::Pic {
let reloc_model = sess.relocation_model();
if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
llvm::LLVMRustSetModulePICLevel(llmod);
// 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.
if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
if reloc_model == RelocModel::Pie
|| sess.crate_types().iter().all(|ty| *ty == CrateType::Executable)
{
llvm::LLVMRustSetModulePIELevel(llmod);
}
}
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,16 @@ impl CodegenBackend for LlvmCodegenBackend {
match req {
PrintRequest::RelocationModels => {
println!("Available relocation models:");
for name in
&["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"]
{
for name in &[
"static",
"pic",
"pie",
"dynamic-no-pic",
"ropi",
"rwpi",
"ropi-rwpi",
"default",
] {
println!(" {}", name);
}
println!();
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ impl CodegenCx<'ll, 'tcx> {
return true;
}

// With pie relocation model calls of functions defined in the translation
// unit can use copy relocations.
if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration {
return true;
}

return false;
}
}
8 changes: 6 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1490,9 +1490,13 @@ fn exec_linker(
fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
(CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
(CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
(CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => {
LinkOutputKind::DynamicPicExe
}
(CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
(CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
(CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => {
LinkOutputKind::StaticPicExe
}
(CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe,
(_, true, _) => LinkOutputKind::StaticDylib,
(_, false, _) => LinkOutputKind::DynamicDylib,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl ToJson for MergeFunctions {
pub enum RelocModel {
Static,
Pic,
Pie,
DynamicNoPic,
Ropi,
Rwpi,
Expand All @@ -300,6 +301,7 @@ impl FromStr for RelocModel {
Ok(match s {
"static" => RelocModel::Static,
"pic" => RelocModel::Pic,
"pie" => RelocModel::Pie,
"dynamic-no-pic" => RelocModel::DynamicNoPic,
"ropi" => RelocModel::Ropi,
"rwpi" => RelocModel::Rwpi,
Expand All @@ -314,6 +316,7 @@ impl ToJson for RelocModel {
match *self {
RelocModel::Static => "static",
RelocModel::Pic => "pic",
RelocModel::Pie => "pie",
RelocModel::DynamicNoPic => "dynamic-no-pic",
RelocModel::Ropi => "ropi",
RelocModel::Rwpi => "rwpi",
Expand Down
4 changes: 4 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,10 @@ 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.

- `pie` - position independent executable, relocatable code but without support for symbol
interpositioning (replacing symbols by name using `LD_PRELOAD` and similar). Equivalent to the "uppercase" `-fPIE` option in other compilers. `pie`
code cannot be linked into shared libraries (you'll get a linking error on attempt to do this).

#### Special relocation models

- `dynamic-no-pic` - relocatable external references, non-relocatable code. \
Expand Down
35 changes: 35 additions & 0 deletions src/test/assembly/pic-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// revisions: x64
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic
// [x64] needs-llvm-components: x86


#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK-LABEL: call_other_fn:
// CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip)
#[no_mangle]
pub fn call_other_fn() -> u8 {
unsafe {
other_fn()
}
}

// CHECK-LABEL: other_fn:
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {
unsafe {
foreign_fn()
}
}

extern "C" {fn foreign_fn() -> u8;}
38 changes: 38 additions & 0 deletions src/test/assembly/pie-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// revisions: x64
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie
// [x64] needs-llvm-components: x86


#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK-LABEL: call_other_fn:
// With PIE local functions are called "directly".
// CHECK: {{(jmp|callq)}} other_fn
#[no_mangle]
pub fn call_other_fn() -> u8 {
unsafe {
other_fn()
}
}

// CHECK-LABEL: other_fn:
// External functions are still called through GOT, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {
unsafe {
foreign_fn()
}
}

extern "C" {fn foreign_fn() -> u8;}
16 changes: 16 additions & 0 deletions src/test/codegen/pic-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// compile-flags: -C relocation-model=pic

#![crate_type = "rlib"]

// CHECK: define i8 @call_foreign_fn()
#[no_mangle]
pub fn call_foreign_fn() -> u8 {
unsafe {
foreign_fn()
}
}

// CHECK: declare zeroext i8 @foreign_fn()
extern "C" {fn foreign_fn() -> u8;}

// CHECK: !{i32 7, !"PIC Level", i32 2}
22 changes: 22 additions & 0 deletions src/test/codegen/pie-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// compile-flags: -C relocation-model=pie
// only-x86_64-unknown-linux-gnu

#![crate_type = "rlib"]

// With PIE we know local functions cannot be interpositioned, we can mark them
// as dso_local.
// CHECK: define dso_local i8 @call_foreign_fn()
#[no_mangle]
pub fn call_foreign_fn() -> u8 {
unsafe {
foreign_fn()
}
}

// External functions are still marked as non-dso_local, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: declare zeroext i8 @foreign_fn()
extern "C" {fn foreign_fn() -> u8;}

// CHECK: !{i32 7, !"PIC Level", i32 2}
// CHECK: !{i32 7, !"PIE Level", i32 2}