Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 3be4e82

Browse files
committed
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 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@339301 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 1859a60 commit 3be4e82

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

ELF/Driver.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,21 @@ template <class ELFT> static void handleUndefined(StringRef Name) {
12121212
Symtab->fetchLazy<ELFT>(Sym);
12131213
}
12141214

1215+
template <class ELFT> static void handleLibcall(StringRef Name) {
1216+
Symbol *Sym = Symtab->find(Name);
1217+
if (!Sym || !Sym->isLazy())
1218+
return;
1219+
1220+
MemoryBufferRef MB;
1221+
if (auto *LO = dyn_cast<LazyObject>(Sym))
1222+
MB = LO->File->MB;
1223+
else
1224+
MB = cast<LazyArchive>(Sym)->getMemberBuffer();
1225+
1226+
if (isBitcode(MB))
1227+
Symtab->fetchLazy<ELFT>(Sym);
1228+
}
1229+
12151230
template <class ELFT> static bool shouldDemote(Symbol &Sym) {
12161231
// If all references to a DSO happen to be weak, the DSO is not added to
12171232
// DT_NEEDED. If that happens, we need to eliminate shared symbols created
@@ -1388,11 +1403,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
13881403
// in a bitcode file in an archive member, we need to arrange to use LTO to
13891404
// compile those archive members by adding them to the link beforehand.
13901405
//
1391-
// With this the symbol table should be complete. After this, no new names
1392-
// except a few linker-synthesized ones will be added to the symbol table.
1406+
// However, adding all libcall symbols to the link can have undesired
1407+
// consequences. For example, the libgcc implementation of
1408+
// __sync_val_compare_and_swap_8 on 32-bit ARM pulls in an .init_array entry
1409+
// that aborts the program if the Linux kernel does not support 64-bit
1410+
// atomics, which would prevent the program from running even if it does not
1411+
// use 64-bit atomics.
1412+
//
1413+
// Therefore, we only add libcall symbols to the link before LTO if we have
1414+
// to, i.e. if the symbol's definition is in bitcode. Any other required
1415+
// libcall symbols will be added to the link after LTO when we add the LTO
1416+
// object file to the link.
13931417
if (!BitcodeFiles.empty())
13941418
for (const char *S : LibcallRoutineNames)
1395-
handleUndefined<ELFT>(S);
1419+
handleLibcall<ELFT>(S);
13961420

13971421
// Return if there were name resolution errors.
13981422
if (errorCount())
@@ -1434,6 +1458,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
14341458

14351459
// Do link-time optimization if given files are LLVM bitcode files.
14361460
// This compiles bitcode files into real object files.
1461+
//
1462+
// With this the symbol table should be complete. After this, no new names
1463+
// except a few linker-synthesized ones will be added to the symbol table.
14371464
Symtab->addCombinedLTOObject<ELFT>();
14381465
if (errorCount())
14391466
return;

ELF/Symbols.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,15 @@ void Symbol::parseSymbolVersion() {
204204

205205
InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); }
206206

207+
MemoryBufferRef LazyArchive::getMemberBuffer() {
208+
Archive::Child C = CHECK(
209+
Sym.getMember(), "could not get the member for symbol " + Sym.getName());
210+
211+
return CHECK(C.getMemoryBufferRef(),
212+
"could not get the buffer for the member defining symbol " +
213+
Sym.getName());
214+
}
215+
207216
uint8_t Symbol::computeBinding() const {
208217
if (Config->Relocatable)
209218
return Binding;

ELF/Symbols.h

+1
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ class LazyArchive : public Symbol {
286286
static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }
287287

288288
InputFile *fetch();
289+
MemoryBufferRef getMemberBuffer();
289290

290291
private:
291292
const llvm::object::Archive::Symbol Sym;

test/ELF/lto/Inputs/libcall-archive.s

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.globl __sync_val_compare_and_swap_8
2+
__sync_val_compare_and_swap_8:

test/ELF/lto/libcall-archive.ll

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
; RUN: rm -f %t.a
33
; RUN: llvm-as -o %t.o %s
44
; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll
5-
; RUN: llvm-ar rcs %t.a %t2.o
5+
; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t3.o %S/Inputs/libcall-archive.s
6+
; RUN: llvm-ar rcs %t.a %t2.o %t3.o
67
; RUN: ld.lld -o %t %t.o %t.a
78
; RUN: llvm-nm %t | FileCheck %s
9+
; RUN: ld.lld -o %t2 %t.o --start-lib %t2.o %t3.o --end-lib
10+
; RUN: llvm-nm %t2 | FileCheck %s
811

12+
; CHECK-NOT: T __sync_val_compare_and_swap_8
913
; CHECK: T _start
1014
; CHECK: T memcpy
1115

0 commit comments

Comments
 (0)