Skip to content

Commit d9b4a5a

Browse files
authored
Unrolled build for #142598
Rollup merge of #142598 - ostylk:fix/ppc64_llvmabi, r=nikic,workingjubilee Set elf e_flags on ppc64 targets according to abi (This PR contains the non user-facing changes of #142321) Fixes #85589 by making sure that ld.lld errors out instead of generating a broken binary. Basically the problem is that ld.lld assumes that all ppc64 object files with e_flags=0 are object files which use the ELFv2 ABI (this here is the check https://github.com/llvm/llvm-project/blob/main/lld/ELF/Arch/PPC64.cpp#L639). This pull request sets the correct e_flags to indicate the used ABI so ld.lld errors out when encountering ELFv1 ABI files instead of generating a broken binary. For example compare code generation for this program (file name ``min.rs``): ```rust #![feature(no_core, lang_items, repr_simd)] #![crate_type = "bin"] #![no_core] #![no_main] #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} #[lang = "panic_cannot_unwind"] pub fn panic() -> ! { loop {} } pub fn my_rad_unmangled_function() { loop {} } pub fn my_rad_function() { loop {} } #[no_mangle] pub fn _start() { my_rad_unmangled_function(); my_rad_function(); } ``` Compile with ``rustc --target=powerpc64-unknown-linux-gnu -C linker=ld.lld -C relocation-model=static min.rs`` Before change: ``` $ llvm-objdump -d min Disassembly of section .text: 000000001001030c <.text>: ... 10010334: 7c 08 02 a6 mflr 0 10010338: f8 21 ff 91 stdu 1, -112(1) 1001033c: f8 01 00 80 std 0, 128(1) 10010340: 48 02 00 39 bl 0x10030378 <_ZN3min25my_rad_unmangled_function17h7471c49af58039f5E> 10010344: 60 00 00 00 nop 10010348: 48 02 00 49 bl 0x10030390 <_ZN3min15my_rad_function17h37112b8fd1008c9bE> 1001034c: 60 00 00 00 nop ... ``` The branch instructions ``bl 0x10030378`` and ``bl 0x10030390`` are jumping into the ``.opd`` section which is data. That is a broken binary (because fixing those branches is the task of the linker). After change: ``` error: linking with `ld.lld` failed: exit status: 1 | = note: "ld.lld" "/tmp/rustcNYKZCS/symbols.o" "<1 object files omitted>" "--as-needed" "-L" "/tmp/rustcNYKZCS/raw-dylibs" "-Bdynamic" "--eh-frame-hdr" "-z" "noexecstack" "-L" "<sysroot>/lib/rustlib/powerpc64-unknown-linux-gnu/lib" "-o" "min" "--gc-sections" "-z" "relro" "-z" "now" = note: some arguments are omitted. use `--verbose` to show all linker arguments = note: ld.lld: error: /tmp/rustcNYKZCS/symbols.o: ABI version 1 is not supported ``` Which is correct because ld.lld doesn't support ELFv1 ABI.
2 parents 86d0aef + 9c1180b commit d9b4a5a

9 files changed

+26
-0
lines changed

compiler/rustc_codegen_ssa/src/back/metadata.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,24 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
379379
};
380380
e_flags
381381
}
382+
Architecture::PowerPc64 => {
383+
const EF_PPC64_ABI_UNKNOWN: u32 = 0;
384+
const EF_PPC64_ABI_ELF_V1: u32 = 1;
385+
const EF_PPC64_ABI_ELF_V2: u32 = 2;
386+
387+
match sess.target.options.llvm_abiname.as_ref() {
388+
// If the flags do not correctly indicate the ABI,
389+
// linkers such as ld.lld assume that the ppc64 object files are always ELFv2
390+
// which leads to broken binaries if ELFv1 is used for the object files.
391+
"elfv1" => EF_PPC64_ABI_ELF_V1,
392+
"elfv2" => EF_PPC64_ABI_ELF_V2,
393+
"" if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
394+
bug!("No ABI specified for this PPC64 ELF target");
395+
}
396+
// Fall back
397+
_ => EF_PPC64_ABI_UNKNOWN,
398+
}
399+
}
382400
_ => 0,
383401
}
384402
}

compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
1111
base.max_atomic_width = Some(64);
1212
base.stack_probes = StackProbeType::Inline;
13+
base.llvm_abiname = "elfv2".into();
1314

1415
Target {
1516
llvm_target: "powerpc64-unknown-freebsd".into(),

compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
1111
base.max_atomic_width = Some(64);
1212
base.stack_probes = StackProbeType::Inline;
13+
base.llvm_abiname = "elfv1".into();
1314

1415
Target {
1516
llvm_target: "powerpc64-unknown-linux-gnu".into(),

compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub(crate) fn target() -> Target {
1212
base.stack_probes = StackProbeType::Inline;
1313
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
1414
base.crt_static_default = true;
15+
base.llvm_abiname = "elfv2".into();
1516

1617
Target {
1718
llvm_target: "powerpc64-unknown-linux-musl".into(),

compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
1111
base.max_atomic_width = Some(64);
1212
base.stack_probes = StackProbeType::Inline;
13+
base.llvm_abiname = "elfv2".into();
1314

1415
Target {
1516
llvm_target: "powerpc64-unknown-openbsd".into(),

compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
1111
base.max_atomic_width = Some(64);
1212
base.stack_probes = StackProbeType::Inline;
13+
base.llvm_abiname = "elfv1".into();
1314

1415
Target {
1516
llvm_target: "powerpc64-unknown-linux-gnu".into(),

compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
88
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
99
base.max_atomic_width = Some(64);
1010
base.stack_probes = StackProbeType::Inline;
11+
base.llvm_abiname = "elfv2".into();
1112

1213
Target {
1314
llvm_target: "powerpc64le-unknown-freebsd".into(),

compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
88
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
99
base.max_atomic_width = Some(64);
1010
base.stack_probes = StackProbeType::Inline;
11+
base.llvm_abiname = "elfv2".into();
1112

1213
Target {
1314
llvm_target: "powerpc64le-unknown-linux-gnu".into(),

compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010
base.stack_probes = StackProbeType::Inline;
1111
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
1212
base.crt_static_default = true;
13+
base.llvm_abiname = "elfv2".into();
1314

1415
Target {
1516
llvm_target: "powerpc64le-unknown-linux-musl".into(),

0 commit comments

Comments
 (0)