Linking FreeBSD with lld: update on CPU architecture support

lld now implements almost all of the functionality necessary to function as a system linker for FreeBSD/amd64, and I’ve started investigating other CPU architectures that FreeBSD supports. Of course some of these are known to have limited support in lld, but I want to capture a snapshot of where things stand today.

sparc64 and riscv are excluded as they have no lld support. sparc64 is not of much interest in FreeBSD any longer (we support only long-obsolete CPUs), but we have a strong interest in linking FreeBSD/riscv with lld.

PRs or patches will follow after individual issues are diagnosed.

Per-arch status:

amd64 (aka x86-64)

With WIP patches to both lld and FreeBSD it is possible to link a working base system kernel and userland.

The primary lld limitation relates to wildcards in extern “C++” blocks in version scripts. We also need to rework the way the FreeBSD boot components are built.

Known issues have PRs or patches in review. I hope that we’ll soon start extensively testing the ports collection (the 25K third party software packages) using lld as the linker.

I posted an update, with a proposed set of steps for importing lld into FreeBSD, at https://lists.freebsd.org/pipermail/freebsd-toolchain/2016-August/002240.html.

arm

Fails very early on in the build, while linking the target libc.so.7.

relocation R_ARM_REL32 cannot refer to absolute symbol GLOBAL_OFFSET_TABLE

can’t create dynamic relocation R_ARM_GOTOFF32 against symbol _libc_arm_fpu_present

can’t create dynamic relocation R_ARM_NONE against symbol __aeabi_unwind_cpp_pr0

arm64

Userland link completes with the same set of WIP patches as above. Minimal testing has been done on the resulting binaries. The kernel link fails with thousands of “relocation R_AARCH64_ADR_PREL_PG_HI21 out of range” errors.

i386

The userland link completes, along with the kernel itself; results untested. Kernel modules fail with:

can’t create dynamic relocation R_386_32 against readonly segment

can’t create dynamic relocation R_386_PC32 against symbol device_get_parent

mips64

mips64 uses libstdc++ (not libc++) and the lack of version script wildcard support for symbols in extern “C++” blocks prevent building it with lld. Tracked in pr29093. After disabling C++ support much of the userland does link, but is untested.

Three base system binaries (and related variants of them) fail to build: gcc, gdb, and svn. The error is “relocation R_MIPS_GOT_DISP out of range”. It’s not too surprising as these binaries are expected to be among the larger ones in the base system, although they do successfully link with GNU ld. The kernel link fails wtih “duplicate symbol: _gp in (internal) and (internal)”.

mips

C++ is disabled as described above for mips64. One userland component (ubldr) failed to build due to a linker script error, to be investigated. The kernel link fails with “duplicate symbol: _gp in (internal) and (internal)”.

powerpc (32-bit)

Fails early, linking the target libc.so.7.

can’t create dynamic relocation R_PPC_GOT16 against symbol .LANCHOR0
can’t create dynamic relocation R_PPC_GOT16 against symbol __cxa_finalize
can’t create dynamic relocation R_PPC_GOT16 against symbol __dso_handle
can’t create dynamic relocation R_PPC_PLTREL24 against symbol __cxa_finalize

% sed -E -n “s/can’t create dynamic relocation ([^ ]).$/\1/p” build.log | sort | uniq -c | sort -rn

17658 R_PPC_PLTREL24
9647 R_PPC_GOT16
3274 R_PPC_REL32
231 R_PPC_GOT_TLSGD16
101 R_PPC_LOCAL24PC

powerpc64 (64-bit)

Fails early, linking the target libc.so.7.

can’t create dynamic relocation R_PPC64_REL24 against readonly segment

can’t create dynamic relocation R_PPC64_REL24 against readonly segment
can’t create dynamic relocation R_PPC64_REL24 against symbol _collate_wxfrm
can’t create dynamic relocation R_PPC64_REL24 against symbol __get_locale
can’t create dynamic relocation R_PPC64_REL24 against symbol __get_locale

% sed -E -n “s/can’t create dynamic relocation ([^ ]).$/\1/p” build.log | sort | uniq -c | sort -rn

6899 R_PPC64_REL24
2902 R_PPC64_REL32
27 R_PPC64_REL64

Hello Ed,

Thanks very much for running the tests. There is quite a lot of work
to be done on the ARM port. Feel free to add my email to any bug
reports you raise.

Initial suspicion for the _GLOBAL_OFFSET_TABLE_ failure is that ARM
code seems to make more use of this linker defined symbol than other
architectures. There is probably an assumption that
_GLOBAL_OFFSET_TABLE_ is defined to be the base of the .got section
rather than an absolute 0.

Peter