Change:
When compiling for , the resulting binaries should have the OS/ABI () field in the ELF header set to Standalone () as per the LLVM target, which it did before . Now, it is set to "UNIX - System V", which I only tested on Linux. identified the introduction of synthetic object files for exported symbols from to have changed this: I did not have a deep dive into the code yet, but I assume the synthetic object file has the host's OS/ABI, which is prevalent over the other OS/ABI. do you have any insight? Related:
Hmm, the crate sets to , which seems to be an alias of . Unfortunately currently crate provide no ways to set this field, so to fix this I suppose some postprocessing of the generated ELF file would be needed. I am surprised that this doesn't show up earlier, given that exactly the same routine is used to create rmeta files. Does hermit not support dylibs?
Ah, yes, sets the OS/ABI here: . I think there are three possibilities: proper support for setting OS/ABI in . This would probably take a lot of effort. before passing it to in This can be done quite easily. the synthetic object file after (?) the real ones. I think lld infers the OS/ABI from the first proper input object file, if I am reading this correctly:  For 1 and 2 we would need to know the proper OS/ABI from the real object files though. I am not sure how easy that would be to come by. What do you think? Hermit is a unikernel, which is linked statically to the application. There is no support for dynamic libraries. A similar problem occurs when using though (). This issue was closed, because we did not need anyways.
Here's how LLVM determines what OSABI to use: We could look at and use the same logic to determine the OSABI. The synthetic object can be placed after real object files (it only needs to be linked before any libraries), but assuming the linker only looks at the first object file sounds a bit hacky. cc what's your take on this issue?
object-rs has only recently been taught to set expected by some MIPS targets (). In think we can teach object-rs to set too, and then just set it, if some linker expects it.
All right. Thanks for the quick feedback. I'll cook something up in the coming days.
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-low
I opened , but first the necessary changes in have to be released.

Discussion:
source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" dependencies = [ <ins> "ahash", </ins> "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core",

] [[package]] <ins> name = "object" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", "hashbrown 0.12.0", "indexmap", "memchr", ] [[package]] </ins> name = "odht" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index"

"itertools", "jobserver", "libc", <del> "object 0.28.4", </del> <ins> "object 0.29.0", </ins> "pathdiff", "regex", "rustc_apfloat",

rustc_session = { path = "../rustc_session" } [dependencies.object] <del> version = "0.28.4" </del> <ins> version = "0.29.0" </ins> default-features = false features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]

}; let mut file = write::Object::new(binary_format, architecture, endianness); <del> match architecture { </del> <ins> let e_flags = match architecture { </ins> Architecture::Mips => { let arch = match sess.target.options.cpu.as_ref() { "mips1" => elf::EF_MIPS_ARCH_1,

if sess.target.options.cpu.contains("r6") { e_flags |= elf::EF_MIPS_NAN2008; } <del> file.flags = FileFlags::Elf { e_flags }; </del> <ins> e_flags </ins> } Architecture::Mips64 => { // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`

} else { elf::EF_MIPS_ARCH_64R2 }; <del> file.flags = FileFlags::Elf { e_flags }; </del> <ins> e_flags </ins> } Architecture::Riscv64 if sess.target.options.features.contains("+d") => { // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though // that the `+d` target feature represents whether the double // float abi is enabled. let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; <del> file.flags = FileFlags::Elf { e_flags }; </del> <ins> e_flags </ins> } <del> _ => {} </del> <ins> _ => 0, }; // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` let os_abi = match sess.target.options.os.as_ref() { "hermit" => elf::ELFOSABI_STANDALONE, "freebsd" => elf::ELFOSABI_FREEBSD, "solaris" => elf::ELFOSABI_SOLARIS, _ => elf::ELFOSABI_NONE, </ins> }; <ins> let abi_version = 0; file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; </ins> Some(file) }