Set elf e_flags on ppc64 targets according to abi by ostylk · Pull Request #142598 · rust-lang/rust (original) (raw)

(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):

#![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.