Auto merge of #96930 - ayrtonm:mips32-tmp-file, r=petrochenkov
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 is invalid for 32-bit MIPS targets. Even though symbols.o doesn't contain code, linking these targets with [lld fails](https://github.com/llvm/llvm-project/blob/main/lld/ELF/Arch/MipsArchTree.cpp#L76-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 [mipsel-sony-psx target](https://github.com/ayrtonm/psx-sdk-rs/issues/9), the builtin mipsel-sony-psp target (cc `@overdrivenpotato)` and probably 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 to avoid similar issues with the object file arch and PIC. 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.
This commit is contained in:
commit
1c80ac003b
@ -2509,9 +2509,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.28.1"
|
version = "0.28.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ce8b38d41f9f3618fc23f908faae61510f8d8ce2d99cbe910641e8f1971f084"
|
checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"flate2",
|
"flate2",
|
||||||
@ -3617,7 +3617,7 @@ dependencies = [
|
|||||||
"itertools",
|
"itertools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
"object 0.28.1",
|
"object 0.28.4",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc_apfloat",
|
"rustc_apfloat",
|
||||||
@ -5207,7 +5207,7 @@ checksum = "dd95b4559c196987c8451b4e14d08a4c796c2844f9adf4d2a2dbc9b3142843be"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli 0.26.1",
|
"gimli 0.26.1",
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
"object 0.28.1",
|
"object 0.28.4",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -41,6 +41,6 @@ rustc_target = { path = "../rustc_target" }
|
|||||||
rustc_session = { path = "../rustc_session" }
|
rustc_session = { path = "../rustc_session" }
|
||||||
|
|
||||||
[dependencies.object]
|
[dependencies.object]
|
||||||
version = "0.28.0"
|
version = "0.28.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
|
features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
|
||||||
|
@ -20,7 +20,7 @@ use rustc_metadata::EncodedMetadata;
|
|||||||
use rustc_session::cstore::MetadataLoader;
|
use rustc_session::cstore::MetadataLoader;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_target::abi::Endian;
|
use rustc_target::abi::Endian;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::{RelocModel, Target};
|
||||||
|
|
||||||
use crate::METADATA_FILENAME;
|
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);
|
let mut file = write::Object::new(binary_format, architecture, endianness);
|
||||||
match architecture {
|
match architecture {
|
||||||
Architecture::Mips => {
|
Architecture::Mips => {
|
||||||
// copied from `mipsel-linux-gnu-gcc foo.c -c` and
|
let arch = match sess.target.options.cpu.as_ref() {
|
||||||
// inspecting the resulting `e_flags` field.
|
"mips1" => elf::EF_MIPS_ARCH_1,
|
||||||
let e_flags = elf::EF_MIPS_CPIC
|
"mips2" => elf::EF_MIPS_ARCH_2,
|
||||||
| elf::EF_MIPS_PIC
|
"mips3" => elf::EF_MIPS_ARCH_3,
|
||||||
| if sess.target.options.cpu.contains("r6") {
|
"mips4" => elf::EF_MIPS_ARCH_4,
|
||||||
elf::EF_MIPS_ARCH_32R6 | elf::EF_MIPS_NAN2008
|
"mips5" => elf::EF_MIPS_ARCH_5,
|
||||||
} else {
|
s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6,
|
||||||
elf::EF_MIPS_ARCH_32R2
|
_ => 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 };
|
file.flags = FileFlags::Elf { e_flags };
|
||||||
}
|
}
|
||||||
Architecture::Mips64 => {
|
Architecture::Mips64 => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user