[lld] r339301 - ELF: Only add libcall symbols to the link if defined in bitcode.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 8 16:48:12 PDT 2018


Author: pcc
Date: Wed Aug  8 16:48:12 2018
New Revision: 339301

URL: http://llvm.org/viewvc/llvm-project?rev=339301&view=rev
Log:
ELF: Only add libcall symbols to the link if defined in bitcode.

Adding all libcall symbols to the link can have undesired consequences.
For example, the libgcc implementation of __sync_val_compare_and_swap_8
on 32-bit ARM pulls in an .init_array entry that aborts the program if
the Linux kernel does not support 64-bit atomics, which would prevent
the program from running even if it does not use 64-bit atomics.

This change makes it so that we only add libcall symbols to the
link before LTO if we have to, i.e. if the symbol's definition is in
bitcode. Any other required libcall symbols will be added to the link
after LTO when we add the LTO object file to the link.

Differential Revision: https://reviews.llvm.org/D50475

Added:
    lld/trunk/test/ELF/lto/Inputs/libcall-archive.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/test/ELF/lto/libcall-archive.ll

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=339301&r1=339300&r2=339301&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Aug  8 16:48:12 2018
@@ -1212,6 +1212,21 @@ template <class ELFT> static void handle
     Symtab->fetchLazy<ELFT>(Sym);
 }
 
+template <class ELFT> static void handleLibcall(StringRef Name) {
+  Symbol *Sym = Symtab->find(Name);
+  if (!Sym || !Sym->isLazy())
+    return;
+
+  MemoryBufferRef MB;
+  if (auto *LO = dyn_cast<LazyObject>(Sym))
+    MB = LO->File->MB;
+  else
+    MB = cast<LazyArchive>(Sym)->getMemberBuffer();
+
+  if (isBitcode(MB))
+    Symtab->fetchLazy<ELFT>(Sym);
+}
+
 template <class ELFT> static bool shouldDemote(Symbol &Sym) {
   // If all references to a DSO happen to be weak, the DSO is not added to
   // DT_NEEDED. If that happens, we need to eliminate shared symbols created
@@ -1388,11 +1403,20 @@ template <class ELFT> void LinkerDriver:
   // in a bitcode file in an archive member, we need to arrange to use LTO to
   // compile those archive members by adding them to the link beforehand.
   //
-  // With this the symbol table should be complete. After this, no new names
-  // except a few linker-synthesized ones will be added to the symbol table.
+  // However, adding all libcall symbols to the link can have undesired
+  // consequences. For example, the libgcc implementation of
+  // __sync_val_compare_and_swap_8 on 32-bit ARM pulls in an .init_array entry
+  // that aborts the program if the Linux kernel does not support 64-bit
+  // atomics, which would prevent the program from running even if it does not
+  // use 64-bit atomics.
+  //
+  // Therefore, we only add libcall symbols to the link before LTO if we have
+  // to, i.e. if the symbol's definition is in bitcode. Any other required
+  // libcall symbols will be added to the link after LTO when we add the LTO
+  // object file to the link.
   if (!BitcodeFiles.empty())
     for (const char *S : LibcallRoutineNames)
-      handleUndefined<ELFT>(S);
+      handleLibcall<ELFT>(S);
 
   // Return if there were name resolution errors.
   if (errorCount())
@@ -1434,6 +1458,9 @@ template <class ELFT> void LinkerDriver:
 
   // Do link-time optimization if given files are LLVM bitcode files.
   // This compiles bitcode files into real object files.
+  //
+  // With this the symbol table should be complete. After this, no new names
+  // except a few linker-synthesized ones will be added to the symbol table.
   Symtab->addCombinedLTOObject<ELFT>();
   if (errorCount())
     return;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=339301&r1=339300&r2=339301&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Wed Aug  8 16:48:12 2018
@@ -204,6 +204,15 @@ void Symbol::parseSymbolVersion() {
 
 InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); }
 
+MemoryBufferRef LazyArchive::getMemberBuffer() {
+  Archive::Child C = CHECK(
+      Sym.getMember(), "could not get the member for symbol " + Sym.getName());
+
+  return CHECK(C.getMemoryBufferRef(),
+               "could not get the buffer for the member defining symbol " +
+                   Sym.getName());
+}
+
 uint8_t Symbol::computeBinding() const {
   if (Config->Relocatable)
     return Binding;

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=339301&r1=339300&r2=339301&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Wed Aug  8 16:48:12 2018
@@ -286,6 +286,7 @@ public:
   static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }
 
   InputFile *fetch();
+  MemoryBufferRef getMemberBuffer();
 
 private:
   const llvm::object::Archive::Symbol Sym;

Added: lld/trunk/test/ELF/lto/Inputs/libcall-archive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/Inputs/libcall-archive.s?rev=339301&view=auto
==============================================================================
--- lld/trunk/test/ELF/lto/Inputs/libcall-archive.s (added)
+++ lld/trunk/test/ELF/lto/Inputs/libcall-archive.s Wed Aug  8 16:48:12 2018
@@ -0,0 +1,2 @@
+.globl __sync_val_compare_and_swap_8
+__sync_val_compare_and_swap_8:

Modified: lld/trunk/test/ELF/lto/libcall-archive.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/libcall-archive.ll?rev=339301&r1=339300&r2=339301&view=diff
==============================================================================
--- lld/trunk/test/ELF/lto/libcall-archive.ll (original)
+++ lld/trunk/test/ELF/lto/libcall-archive.ll Wed Aug  8 16:48:12 2018
@@ -2,10 +2,14 @@
 ; RUN: rm -f %t.a
 ; RUN: llvm-as -o %t.o %s
 ; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll
-; RUN: llvm-ar rcs %t.a %t2.o
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t3.o %S/Inputs/libcall-archive.s
+; RUN: llvm-ar rcs %t.a %t2.o %t3.o
 ; RUN: ld.lld -o %t %t.o %t.a
 ; RUN: llvm-nm %t | FileCheck %s
+; RUN: ld.lld -o %t2 %t.o --start-lib %t2.o %t3.o --end-lib
+; RUN: llvm-nm %t2 | FileCheck %s
 
+; CHECK-NOT: T __sync_val_compare_and_swap_8
 ; CHECK: T _start
 ; CHECK: T memcpy
 




More information about the llvm-commits mailing list