Subtitle: Is LLD a drop-in replacement for GNU ld?
Piotr Kubaj said that this is a probably more of a marketing term than a technical term, the term tries to lure existing users into thinking "it's the same you know, but better!".
I think that this is fair in some senses: for many applications LLD has achieved much faster speed and much lower memory usage than GNU ld.
- GNU ld reports
gc-sections requires either an entry or an undefined symbol
in a-r --gc-section
link. LLD doesn't error (https://reviews.llvm.org/D84131#2162411). I am unsure whether such a diagnostic will be useful (an uncommon use case where the GC roots are more than the explict linker options). - The default image base for
-no-pie
links is different. For example, on x86-64, GNU ld defaults to 0x400000 while LLD defaults to 0x200000. - GNU ld synthesizes a
STT_FILE
symbol when copying non-STT_SECTION
STB_LOCAL
symbols. LLD doesn't.
- I filed https://bugs.llvm.org/show_bug.cgi?id=48023 and sent Synthesized STT_FILE symbols with absolute paths and local determinism (no response yet)
- The
STT_FILE
symbol name is the input filename. For compiler driver specified startup files likecrti.o
andcrtn.o
, their absolute paths will end up in the linked image. This breaks local determinism (toolchain paths are leaked) for some users.
- Text relocations.
- In GNU ld,
-z notext
/-z text
/unspecified are a tri-state. For-z notext
/unspecified, the dynamic tagsDT_TEXTREL
andDF_TEXTREL
are added on demand. If unspecified and GNU ld is configured with--enable-textrel-check=warning
, a warning will be issued. - LLD has two states and add
DT_TEXTREL
andDF_TEXTREL
if-z notext
is specified.
- Mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER input sections in an output section.
- LLD performs sorting within an input section description and allows arbitrary mixes.
- GNU ld does not allow mixed sections https://sourceware.org/bugzilla/show_bug.cgi?id=26256 (H.J. Lu has a patch)
- LLD defaults to
-z relro
by default. This is probably not a good default but it is difficult to change now. I have a comment https://bugs.llvm.org/show_bug.cgi?id=48549 - Different archive selection semantics. See http://lld.llvm.org/ELF/warn_backrefs.html for details.
- LLD places
.rodata
(among otherSHF_ALLOC
and non-SHF_WRITE
-non-SHF_EXECINSTR
sections) before.text
(among otherSHF_ALLOC
andSHF_EXECINSTR
sections). - Slightly different
--wrap
semantics. I use "slightly" because in most use cases users will not observe a difference.
- In GNU ld,
--wrap
only applies to undefined symbols. - In LLD,
--wrap
happens after all other symbol resolution steps. The implementation is to mangle the symbol table of each object file (foo -> __wrap_foo; __real_foo -> foo
) so that all relocations tofoo
or__real_foo
will be redirected. - The LLD semantics have the advantage that non-LTO and LTO behaviors are consistent. I filed https://sourceware.org/bugzilla/show_bug.cgi?id=26358 for GNU ld.
- GNU ld adds
PT_PHDR
andPT_INTERP
together. A shared object usually does not have two two program headers. In LLD,PT_PHDR
is always added unless the address assignment makes is unsuitable to place program headers at all. - Default program headers.
- With traditional
-z noseparate-code
, GNU ld defaults to aRX/R/RW
program header layout. With-z separate-code
(default on Linux/x86 from binutils 2.31 onwards), GNU ld defaults to aR/RX/R/RW
program header layout. - LLD defaults to
R/RX/RW(RELRO)/RW(non-RELRO)
. With--rosegment
, LLD usesRX/RW(RELRO)/RW(non-RELRO)
. - Placing all R before RX is preferable because it can save one program header and reduce alignment costs.
- This breaks some assumptions that the (so-called) "text segment" precedes the (so-called) "data segment".
- For example, certain programs expect
.text
is the first section of the text segment and specify-Ttext=0
to place thePF_R|PF_X
program header at p_vaddr=0. This is a brittle assumption and should be avoided. If PT_PHDR is needed,--image-base=0
is a replacement. If PT_PHDR is not needed,.text 0 : { *(.text .text.*) }
is a replacement.
Linker scripts
- Some linker script commands are unimplemented in LLD, e.g.
BLOCK()
as a compatibility alias forALIGN()
.BLOCK
is documented in GNU ld as a compatibility alias and it is not widely used, so there is no reason to keep the kludge in LLD. - Some syntax is not recognized by LLD, e.g. LLD recognizes
*(EXCLUDE_FILE(a.o) .text)
but notEXCLUDE_FILE(a.o) *(.text)
(https://bugs.llvm.org/show_bug.cgi?id=45764)
- To me the unrecognized syntax is misleading.
- Different orphan section placement. GNU ld has very complex rules and certain section names have special semantics. LLD adopted some of its core ideas but made a lot of simplication:
- output sections are given ranks
- output sections are placed after symbol assignments
At some point we should document it. https://bugs.llvm.org/show_bug.cgi?id=42327 1. For an error detected when processing a linker script, LLD may report it multiple times (e.g. ASSERT
failure). GNU ld has such issues, too, but probably much rarer.
I'll also mention some LLD release notes which can demonstrate some GNU incompatibility in previous versions. (For example, if one thing is supported in version N, then the implication is that it is unsupported in previous versions. Well, it could be that it worked in older versions but regressed at some version. However, I don't know the existence of such things.)
LLD 12.0.0
-r --gc-sections
is supported.
LLD 11.0.0
- LLD can discard unused symbols with
--discard-all
/--discard-locals
when-r
or--emit-relocs
is specified. https://reviews.llvm.org/D77807 --emit-relocs --strip-debug
can be used. https://reviews.llvm.org/D74375SHT_GNU_verneed
in shared objects are parsed, and versioned undefined symbols in shared objects are respected. Previously non-default version symbols could cause spurious--no-allow-shlib-undefined
errors. https://reviews.llvm.org/D80059DF_1_PIE
is set for position-independent executables. https://reviews.llvm.org/D80872
LLD 10.0.0
- LLD supports
\
(treating the next character like a non-meta character) and[!...]
(negation) in glob patterns. https://reviews.llvm.org/D66613
LLD 9.0.0
- The
DF_STATIC_TLS
flag is set for i386 and x86-64 when initial-exec TLS models are used. - Many configurations of the Linux kernel's arm32_7, arm64, powerpc64le and x86_64 ports can be linked by LLD.
LLD 8.0.0
SHT_NOTE
sections get very high ranks (they usually precede other sections). https://reviews.llvm.org/D55800
LLD 7.0.0
- https://reviews.llvm.org/D44264 is my first meaningful (albeit trivial) patch to LLD. Next I made contribution to
--warn-backrefs
. Then I started to fix tricky issues like copy relocations, duplicate--wrap
, section ranks.