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 https://github.com/rust-lang/rust/pull/142321) Fixes https://github.com/rust-lang/rust/issues/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.
This commit is contained in:
@@ -379,6 +379,24 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
|
|||||||
};
|
};
|
||||||
e_flags
|
e_flags
|
||||||
}
|
}
|
||||||
|
Architecture::PowerPc64 => {
|
||||||
|
const EF_PPC64_ABI_UNKNOWN: u32 = 0;
|
||||||
|
const EF_PPC64_ABI_ELF_V1: u32 = 1;
|
||||||
|
const EF_PPC64_ABI_ELF_V2: u32 = 2;
|
||||||
|
|
||||||
|
match sess.target.options.llvm_abiname.as_ref() {
|
||||||
|
// If the flags do not correctly indicate the ABI,
|
||||||
|
// linkers such as ld.lld assume that the ppc64 object files are always ELFv2
|
||||||
|
// which leads to broken binaries if ELFv1 is used for the object files.
|
||||||
|
"elfv1" => EF_PPC64_ABI_ELF_V1,
|
||||||
|
"elfv2" => EF_PPC64_ABI_ELF_V2,
|
||||||
|
"" if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
|
||||||
|
bug!("No ABI specified for this PPC64 ELF target");
|
||||||
|
}
|
||||||
|
// Fall back
|
||||||
|
_ => EF_PPC64_ABI_UNKNOWN,
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64-unknown-freebsd".into(),
|
llvm_target: "powerpc64-unknown-freebsd".into(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv1".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64-unknown-linux-gnu".into(),
|
llvm_target: "powerpc64-unknown-linux-gnu".into(),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
|
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
|
||||||
base.crt_static_default = true;
|
base.crt_static_default = true;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64-unknown-linux-musl".into(),
|
llvm_target: "powerpc64-unknown-linux-musl".into(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64-unknown-openbsd".into(),
|
llvm_target: "powerpc64-unknown-openbsd".into(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv1".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64-unknown-linux-gnu".into(),
|
llvm_target: "powerpc64-unknown-linux-gnu".into(),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64le-unknown-freebsd".into(),
|
llvm_target: "powerpc64le-unknown-freebsd".into(),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64le-unknown-linux-gnu".into(),
|
llvm_target: "powerpc64le-unknown-linux-gnu".into(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.stack_probes = StackProbeType::Inline;
|
base.stack_probes = StackProbeType::Inline;
|
||||||
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
|
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
|
||||||
base.crt_static_default = true;
|
base.crt_static_default = true;
|
||||||
|
base.llvm_abiname = "elfv2".into();
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "powerpc64le-unknown-linux-musl".into(),
|
llvm_target: "powerpc64le-unknown-linux-musl".into(),
|
||||||
|
|||||||
Reference in New Issue
Block a user