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
// 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())
// 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;
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;
; 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