Page MenuHomeFreeBSD

Always pass -m to ld for converting binary files to ELF objects
ClosedPublic

Authored by emaste on Sep 8 2016, 5:45 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mar 16 2024, 10:00 PM
Unknown Object (File)
Mar 16 2024, 8:20 PM
Unknown Object (File)
Feb 22 2024, 1:21 AM
Unknown Object (File)
Feb 21 2024, 11:13 PM
Unknown Object (File)
Feb 21 2024, 3:43 PM
Unknown Object (File)
Feb 20 2024, 1:01 PM
Unknown Object (File)
Dec 25 2023, 8:50 AM
Unknown Object (File)
Dec 20 2023, 1:49 AM

Details

Summary

This is in preparation for linking with LLVM's lld, which does not have a compiled-in default output emulation. lld requires that it is specified via the -m option, or obtained from the object file(s) being linked.

We also need to have lld accept elf_amd64_fbsd as an alias for elf_x86_64_fbsd, like so:

diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index d0d6c2c..0548816 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -71,6 +71,7 @@ static std::pair<ELFKind, uint16_t> parseEmulation(StringRef Emul) {
           .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
           .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
           .Case("elf64ppc", {ELF64BEKind, EM_PPC64})
+          .Case("elf_amd64", {ELF64LEKind, EM_X86_64})
           .Case("elf_i386", {ELF32LEKind, EM_386})
           .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
           .Case("elf_x86_64", {ELF64LEKind, EM_X86_64})
Test Plan

Test that:

  • FreeBSD/amd64 kernel links with lld
  • make universe passes with this change

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

emaste retitled this revision from to Always pass -m to ld for converting binary files to ELF objects.
emaste updated this object.
emaste edited the test plan for this revision. (Show Details)
emaste added a reviewer: bdrewery.
emaste added a subscriber: imp.

Also note local.meta.sys.mk has:

LDFLAGS+= -Wl,-m -Wl,elf_${MACHINE_ARCH}_fbsd

we could perhaps centralize this somewhere (something like LD_EMULATION=elf_${MACHINE_ARCH}_fbsd) and use the new variable there and in the files in this review?

MIPS fails with:

ld: unrecognised emulation mode: elf_mips_fbsd
Supported emulations: elf32btsmip_fbsd elf32btsmip_fbsd elf32ltsmip_fbsd elf64btsmip_fbsd elf64ltsmip_fbsd elf32btsmipn32_fbsd elf32ltsmipn32_fbsd

sparc64 fails with:

ld: unrecognised emulation mode: elf_sparc64_fbsd
Supported emulations: elf64_sparc_fbsd elf64_sparc elf32_sparc

I'm not super optimistic this will work out and still retain support for binutils ld without a super-long list / lookup table somewhere. Maybe a ${LD_TARGET_${MACHINE_ARCH}} sort of thing. I also don't think that binutils ld takes this arg in the binary type. IIRC, I had all kinds of hoops to jump through when I tried it.

sys/conf/kern.pre.mk
122 ↗(On Diff #20206)

Good luck with this. the names are no-where near this regular. As you've discovered mips is an especially crazy minefield. Though in userland we've moved away from directly encoding binary blobs because of issues like this.

sys/conf/kmod.mk
181 ↗(On Diff #20206)

Having this code replicated in 3 place is ugly enough, but to have it replicated twice in both branches of the if statement. Woof!

I'm not super optimistic this will work out and still retain support for binutils ld without a super-long list / lookup table somewhere.

Yeah, I don't think we have an alternative though. We already have LDFLAGS+= -Wl,-m -Wl,elf_${MACHINE_ARCH}_fbsd in share/mk/local.meta.sys.mk which implies meta mode doesn't work for mips or sparc64.

powerpc:

ld: unrecognised emulation mode: elf_powerpc_fbsd
Supported emulations: elf32ppc_fbsd

powerpc64:

t4fw_cfg.txt /scratch/tmp/emaste/freebsd/sys/modules/cxgbe/t4_firmware/../../../dev/cxgbe/firmware/t4fw_cfg.txt
ld: unrecognised emulation mode: elf_powerpc64_fbsd

arm:

ld: unrecognised emulation mode: elf_armv6_fbsd
Supported emulations: armelf_fbsd

arm64:

/usr/local/aarch64-freebsd/bin/ld: unrecognised emulation mode: elf_aarch64_fbsd
Supported emulations: aarch64fbsd aarch64fbsdb aarch64elf

amd64:

ld: unrecognised emulation mode: elf_amd64_fbsd
Supported emulations: elf_x86_64_fbsd elf_i386_fbsd

It would end up as something like this:

.if ${MACHINE_CPUARCH} == "aarch64"
LD_EMULATION=   aarch64elf
.lif ${MACHINE_CPUARCH} == "amd64"
LD_EMULATION=   elf_x86_64_fbsd
.lif ${MACHINE_ARCH} == "arm"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_ARCH} == "armeb"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_ARCH} == "armv6"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_CPUARCH} == "i386"
LD_EMULTAION=   elf_i386_fbsd
.elif ${MACHINE_ARCH} == "mips"
LD_EMULTAION=   elf32btsmip_fbsd
.elif ${MACHINE_ARCH} == "mips64"
LD_EMULTAION=   elf64btsmip_fbsd
.elif ${MACHINE_ARCH} == "mips64el"
LD_EMULTAION=   elf64ltsmip_fbsd
.elif ${MACHINE_ARCH} == "mipsel"
LD_EMULTAION=   elf32ltsmip_fbsd
.elif ${MACHINE_ARCH} == "mipsn32"
LD_EMULTAION=   elf32btsmipn32_fbsd
.elif ${MACHINE_ARCH} == "mipsn32el"
LD_EMULTAION=   elf32ltsmipn32_fbsd
.elif ${MACHINE_ARCH} == "powerpc"
LD_EMULTAION=   elf32ppc_fbsd
.elif ${MACHINE_ARCH} == "powerpc64"
LD_EMULTAION=   elf_powerpc64_fbsd
.elif ${MACHINE_CPUARCH} == "riscv"
LD_EMULTAION=   elf_riscv_fbsd
.elif ${MACHINE_CPUARCH} == "sparc64"
LD_EMULTAION=   elf64_sparc_fbsd
.endif

It would end up as something like this:

.if ${MACHINE_CPUARCH} == "aarch64"
LD_EMULATION=   aarch64elf
.lif ${MACHINE_CPUARCH} == "amd64"
LD_EMULATION=   elf_x86_64_fbsd
.lif ${MACHINE_ARCH} == "arm"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_ARCH} == "armeb"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_ARCH} == "armv6"
LD_EMULTAION=   armelf_fbsd
.lif ${MACHINE_CPUARCH} == "i386"
LD_EMULTAION=   elf_i386_fbsd
.elif ${MACHINE_ARCH} == "mips"
LD_EMULTAION=   elf32btsmip_fbsd
.elif ${MACHINE_ARCH} == "mips64"
LD_EMULTAION=   elf64btsmip_fbsd
.elif ${MACHINE_ARCH} == "mips64el"
LD_EMULTAION=   elf64ltsmip_fbsd
.elif ${MACHINE_ARCH} == "mipsel"
LD_EMULTAION=   elf32ltsmip_fbsd
.elif ${MACHINE_ARCH} == "mipsn32"
LD_EMULTAION=   elf32btsmipn32_fbsd
.elif ${MACHINE_ARCH} == "mipsn32el"
LD_EMULTAION=   elf32ltsmipn32_fbsd
.elif ${MACHINE_ARCH} == "powerpc"
LD_EMULTAION=   elf32ppc_fbsd
.elif ${MACHINE_ARCH} == "powerpc64"
LD_EMULTAION=   elf_powerpc64_fbsd
.elif ${MACHINE_CPUARCH} == "riscv"
LD_EMULTAION=   elf_riscv_fbsd
.elif ${MACHINE_CPUARCH} == "sparc64"
LD_EMULTAION=   elf64_sparc_fbsd
.endif

More like

LD_EMULATION_aarch64=aarch64elf
LD_EMULATION_amd64=elf_x86_64_fbsd
LD_EMULATION_arm=armelf_fbsd
LD_EMULATION_armeb=armelf_fbsd
LD_EMULATION_armv6=armelf_fbsd
LD_EMULATION_i386=elf_i386_fbsd
LD_EMULATION_mips= elf32btsmip_fbsd
LD_EMULATION_mips64= elf64btsmip_fbsd
LD_EMULATION_mipsel= elf32ltsmip_fbsd
LD_EMULATION_mips64el= elf64ltsmip_fbsd
LD_EMULATION_mipsn32= elf32btsmipn32_fbsd
LD_EMULATION_mipsn32el= elf32btsmipn32_fbsd   # I don't think this is a thing that works
LD_EMULATION_powerpc= elf32ppc_fbsd
LD_EMULATION_powerpc64= elf32ppc_fbsd
LD_EMULATION_riscv= elf32ppc_fbsd
LD_EMULATION_sparc64= elf32ppc_fbsd
LD_EMULATION=${LD_EMULATIONION_${MACHINE_ARCH}}

(you could "clean" that up with an :tu). It's also a lot shorter...

You had a confusing mix of MACHINE_ARCH and MACHINE_CPUARCH and only used the latter when it was only ever identical to the former.

But we'd want this centralized.

What's confusing to me about META mode is that amd64 wouldn't work with those settings...

More like

LD_EMULATION_aarch64=aarch64elf

Yes, much better. Do you think this belongs in a new file (share/mk/bsd.ld-emulation.mk?) or should we add it to an existing file?

More like

LD_EMULATION_aarch64=aarch64elf

Yes, much better. Do you think this belongs in a new file (share/mk/bsd.ld-emulation.mk?) or should we add it to an existing file?

I'm not sure it does, unless there's multiple places that need it that aren't already including another file...

I'm not sure it does, unless there's multiple places that need it that aren't already including another file...

It will be needed in:

  • share/mk/local.meta.sys.mk
  • sys/conf/kern.pre.mk
  • sys/conf/kmod.mk

these don't really overlap in a sensible common .include.

I'm not sure it does, unless there's multiple places that need it that aren't already including another file...

It will be needed in:

  • share/mk/local.meta.sys.mk
  • sys/conf/kern.pre.mk
  • sys/conf/kmod.mk

these don't really overlap in a sensible common .include.

The two kernel files overlap (despite people not understanding that and putting common stuff in two places). The third one would be harder, though... Seems like a natural extension of bsd.compiler.mk, which they both already include. Though I'm less sure of local.meta.sys.mk.... It's included indirectly from sys.mk when we're doing meta builds...

add bsd.ld-emulation with style suggested by @imp

Seems like a natural extension of bsd.compiler.mk

Yeah, if we squint and read that one as "bsd.toolchain.mk" it seems to make sense. (I wouldn't rename it since it would just be churn.)

emaste added inline comments.
share/mk/bsd.ld-emulation.mk
16 ↗(On Diff #20389)

looks like this one is wrong

17 ↗(On Diff #20389)

Wrong emulation, @br do you know what it should be?

18 ↗(On Diff #20389)

elf64_sparc_fbsd

sys/conf/kern.pre.mk
20 ↗(On Diff #20389)

So much duplication. :(

122 ↗(On Diff #20389)

We should move these to kern.mk and out of here and kmod.mk.

sys/conf/kmod.mk
170 ↗(On Diff #20389)

I'd think we could hoist this up to kern.mk since it is more general than the kern.pre.mk stuff

correct powerpc64, riscv (guessed) and sparc64 emulations

The two kernel files overlap (despite people not understanding that and putting common stuff in two places).

I agree "putting common stuff in two places" is bad, but can you clarify here? I believe the case is "someone should refactor these .mk files to avoid having to duplicate common stuff in two places", not "people duplicated stuff in two places rather than putting it in the proper, shared file".

The two kernel files overlap (despite people not understanding that and putting common stuff in two places).

I agree "putting common stuff in two places" is bad, but can you clarify here? I believe the case is "someone should refactor these .mk files to avoid having to duplicate common stuff in two places", not "people duplicated stuff in two places rather than putting it in the proper, shared file".

The files already were refactored once. People keep adding things to two places even though a common place already exists. This patch just changes some bits that people have bogusly duplicated (though the if statement that differs only in trivia on either side of the complex command is a bit much). Especially when the ln and rm should really be done in a target not in a shell script. That's close to within scope for this patch.

kern.mk already exists, is common to both and could easily accommodate this use case.

But perhaps the larger problem is out of scope for this change.

kern.mk already exists

but kern.mk is not included in kern.pre.mk

kern.mk already exists

but kern.mk is not included in kern.pre.mk

It's included by kern.post.mk. kern.pre.mk is never used w/o kern.post.mk and order of variable assignment doesn't matter (usually and in this case).

I've confirmed that I can put the LD_EMULATION stuff you have in bsd.ld-emulations.mk into kern.mk and have both modules and the kernel build see them.

emaste edited reviewers, added: imp; removed: bdrewery.
emaste added a subscriber: bdrewery.

move variable setting to sys/conf/kern.mk

imp edited edge metadata.
This revision is now accepted and ready to land.Sep 20 2016, 2:22 AM
This revision was automatically updated to reflect the committed changes.