Skip to content

Commit

Permalink
Fix e_flags for 32-bit MIPS targets in generated object file
Browse files Browse the repository at this point in the history
In rust-lang#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](ayrtonm/psx-sdk-rs#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](gimli-rs/object#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.
  • Loading branch information
ayrtonm committed May 11, 2022
1 parent ecd4495 commit 3d5b1ee
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 15 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2509,9 +2509,9 @@ dependencies = [

[[package]]
name = "object"
version = "0.28.1"
version = "0.28.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce8b38d41f9f3618fc23f908faae61510f8d8ce2d99cbe910641e8f1971f084"
checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
dependencies = [
"crc32fast",
"flate2",
Expand Down Expand Up @@ -3617,7 +3617,7 @@ dependencies = [
"itertools",
"jobserver",
"libc",
"object 0.28.1",
"object 0.28.4",
"pathdiff",
"regex",
"rustc_apfloat",
Expand Down Expand Up @@ -5207,7 +5207,7 @@ checksum = "dd95b4559c196987c8451b4e14d08a4c796c2844f9adf4d2a2dbc9b3142843be"
dependencies = [
"gimli 0.26.1",
"hashbrown 0.11.2",
"object 0.28.1",
"object 0.28.4",
"tracing",
]

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }

[dependencies.object]
version = "0.28.0"
version = "0.28.4"
default-features = false
features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
28 changes: 18 additions & 10 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 => {
Expand Down

0 comments on commit 3d5b1ee

Please sign in to comment.