diff options
| author | Ayrton <a.munoz3327@gmail.com> | 2022-05-01 21:45:50 -0400 |
|---|---|---|
| committer | Ayrton <a.munoz3327@gmail.com> | 2022-05-10 22:48:19 -0400 |
| commit | 3d5b1eeb7592da43442866d26af5e503c3169b6c (patch) | |
| tree | 65aa557db8907097cb793dcf157f68aae8cee616 /compiler/rustc_codegen_ssa/src | |
| parent | ecd44958e0a21110d09862ee080d95a4ca6c52f8 (diff) | |
| download | rust-3d5b1eeb7592da43442866d26af5e503c3169b6c.tar.gz rust-3d5b1eeb7592da43442866d26af5e503c3169b6c.zip | |
Fix e_flags for 32-bit MIPS targets in generated object file
In #95604 the compiler started generating a temporary symbols.o which is added
to the linker invocation. This object file has an `e_flags` which may be invalid
for 32-bit MIPS targets. Even though symbols.o doesn't contain code, linking
with [lld fails](https://github.com/llvm/llvm-project/blob/main/lld/ELF/Arch/MipsArchTree.cpp#L79) with
```
rust-lld: error: foo-cgu.0.rcgu.o: ABI 'o32' is incompatible with target ABI 'n64'
```
because it omits the ABI bits (EF_MIPS_ABI_O32) so lld assumes it's using the
N64 ABI. This breaks linking on nightly for the out-of-tree [psx
target](https://github.com/ayrtonm/psx-sdk-rs/issues/9), the builtin
mipsel-sony-psp target (cc @overdrivenpotato) and any other 32-bit MIPS
target using lld.
This PR sets the ABI in `e_flags` to O32 since that's the only ABI for 32-bit
MIPS that LLVM supports. It also sets other `e_flags` bits based on the target.
I had to bump the object crate version since some of these constants were [added
recently](https://github.com/gimli-rs/object/pull/433). I'm not sure if this
PR needs a test, but I can confirm that it fixes the linking issue on both
targets I mentioned.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 2e422728056..6aa96f9f403 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -20,7 +20,7 @@ use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; use rustc_session::Session; use rustc_target::abi::Endian; -use rustc_target::spec::Target; +use rustc_target::spec::{RelocModel, Target}; use crate::METADATA_FILENAME; @@ -132,15 +132,23 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static let mut file = write::Object::new(binary_format, architecture, endianness); match architecture { Architecture::Mips => { - // copied from `mipsel-linux-gnu-gcc foo.c -c` and - // inspecting the resulting `e_flags` field. - let e_flags = elf::EF_MIPS_CPIC - | elf::EF_MIPS_PIC - | if sess.target.options.cpu.contains("r6") { - elf::EF_MIPS_ARCH_32R6 | elf::EF_MIPS_NAN2008 - } else { - elf::EF_MIPS_ARCH_32R2 - }; + let arch = match sess.target.options.cpu.as_ref() { + "mips1" => elf::EF_MIPS_ARCH_1, + "mips2" => elf::EF_MIPS_ARCH_2, + "mips3" => elf::EF_MIPS_ARCH_3, + "mips4" => elf::EF_MIPS_ARCH_4, + "mips5" => elf::EF_MIPS_ARCH_5, + s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6, + _ => elf::EF_MIPS_ARCH_32R2, + }; + // The only ABI LLVM supports for 32-bit MIPS CPUs is o32. + let mut e_flags = elf::EF_MIPS_CPIC | elf::EF_MIPS_ABI_O32 | arch; + if sess.target.options.relocation_model != RelocModel::Static { + e_flags |= elf::EF_MIPS_PIC; + } + if sess.target.options.cpu.contains("r6") { + e_flags |= elf::EF_MIPS_NAN2008; + } file.flags = FileFlags::Elf { e_flags }; } Architecture::Mips64 => { |
