[ELF] --no-dynamic-linker: don't emit undefined weak symbols to .dynsym
authorFangrui Song <maskray@google.com>
Thu, 23 Jan 2020 19:52:03 +0000 (11:52 -0800)
committerFangrui Song <maskray@google.com>
Thu, 23 Jan 2020 20:25:15 +0000 (12:25 -0800)
commit0fbf28f7aae0ceb70071cac56de345e3ff04439c
tree96923d7586645e3b2bd9d0e85a9440d81de2225c
parente5caa156b446150adc2343760f68ba3e1555c277
[ELF] --no-dynamic-linker: don't emit undefined weak symbols to .dynsym

I felt really sad to push this commit for my selfish purpose to make
glibc -static-pie build with lld. Some code constructs in glibc require
R_X86_64_GOTPCREL/R_X86_64_REX_GOTPCRELX referencing undefined weak to
be resolved to a GOT entry not relocated by R_X86_64_GLOB_DAT (GNU ld
behavior), e.g.

csu/libc-start.c
  if (__pthread_initialize_minimal != NULL)
    __pthread_initialize_minimal ();

elf/dl-object.c
  void
  _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
  {
    /* We modify the list of loaded objects.  */
    __rtld_lock_lock_recursive (GL(dl_load_write_lock));

Emitting a GLOB_DAT will make the address equal &__ehdr_start (true
value) and cause elf/ldconfig to segfault. glibc really should move away
from weak references, which do not have defined semantics.

Temporarily special case --no-dynamic-linker.
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/Symbols.cpp
lld/test/ELF/weak-undef-no-dynamic-linker.s [new file with mode: 0644]