The first bug found while building world on FreeBSD =) sbrk() access _end (directly!) to understand where .bss ends. The linker should probably insert that in the generated executable (at least when -Bstatic is used). It seems gold doesn't strip the symbol even if not referenced. % ./clang sbrk.c -fuse-ld=lld2 -o sbrs -static undefined symbol: _end in sbrk.o clang-3.8: error: linker command failed with exit code 1 (use -v to see invocation) Linker invocation: "/exps/llvm-lld/build/bin/./ld.lld2" -Bstatic -o sbrs /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbeginT.o -L/usr/lib /tmp/sbrk-63b6db.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/crtend.o /usr/lib/crtn.o % cat sbrk.c #include <sys/types.h> #include <unistd.h> int main(void) { void *me = sbrk(42); return (0); }
Repro: % objdump -t ./end | grep _end [...] 0000000000665df0 g *ABS* 0000000000000000 _end % ./clang end.c -fuse-ld=lld2 -o blah -static undefined symbol: _end in /tmp/blah-289342.o % cat end.c extern int _end; int main(void) { return (_end + 5); }
These linker-created symbols are similar to __init_array_end and the like but are different in such way that they are relative to segments. __init_array_end and the like are defined for sections. We cannot calculate the address of _end symbol until we bin all sections into segments. But before doing that, all symbols need to be defined and available since we need to create GOT/PLT segments contents. So I think this needs to be done in two-pass. In the first pass, we add _end symbol with a dummy address 0, and backfill that address once we create segments.
http://reviews.llvm.org/D14833
Should be fixed in r253637.