Don't add DT_INIT/DT_FINI for undef and shared symbols.

The freebsd dynamic linker doesn't check if the value is null (and it
is reasonable for it to do that). That means that producing a .so with
a null DT_INIT/DT_FINI causes the base address to be called.

This should fix the libreoffice build.

llvm-svn: 291944
This commit is contained in:
Rafael Espindola 2017-01-13 19:18:11 +00:00
parent 99a2ce2af2
commit 8a59f5c79f
4 changed files with 25 additions and 5 deletions

View File

@ -467,6 +467,14 @@ template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
return SymVector[V.Idx]->body(); return SymVector[V.Idx]->body();
} }
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::findDefined(StringRef Name) {
if (SymbolBody *S = find(Name))
if (S->isDefined() && !S->isShared())
return S;
return nullptr;
}
template <class ELFT> template <class ELFT>
void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
const object::Archive::Symbol Sym) { const object::Archive::Symbol Sym) {

View File

@ -82,6 +82,7 @@ public:
void scanVersionScript(); void scanVersionScript();
SymbolBody *find(StringRef Name); SymbolBody *find(StringRef Name);
SymbolBody *findDefined(StringRef Name);
void trace(StringRef Name); void trace(StringRef Name);
void wrap(StringRef Name); void wrap(StringRef Name);

View File

@ -883,9 +883,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize}); add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize});
} }
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init)) if (SymbolBody *B = Symtab<ELFT>::X->findDefined(Config->Init))
add({DT_INIT, B}); add({DT_INIT, B});
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini)) if (SymbolBody *B = Symtab<ELFT>::X->findDefined(Config->Fini))
add({DT_FINI, B}); add({DT_FINI, B});
bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;

View File

@ -17,11 +17,22 @@
// RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar // RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s // RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
// Should add a dynamic table entry even if a given symbol stay undefined // Don't add an entry for undef. The freebsd dynamic linker doesn't
// check if the value is null. If it is, it will just call the
// load address.
// RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef // RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s // RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s
// UNDEF: INIT 0x0 // UNDEF-NOT: INIT
// UNDEF: FINI 0x0 // UNDEF-NOT: FINI
// Don't add an entry for shared. For the same reason as undef.
// RUN: ld.lld -shared %t -o %t.so
// RUN: echo > %t.s
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t2.o
// RUN: ld.lld -shared %t2.o %t.so -o %t2
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=SHARED %s
// SHARED-NOT: INIT
// SHARED-NOT: FINI
// Should not add new entries to the symbol table // Should not add new entries to the symbol table
// and should not require given symbols to be resolved // and should not require given symbols to be resolved