diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 6afe3dde9bab..eceb6dc96e14 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -467,6 +467,14 @@ template SymbolBody *SymbolTable::find(StringRef Name) { return SymVector[V.Idx]->body(); } +template +SymbolBody *SymbolTable::findDefined(StringRef Name) { + if (SymbolBody *S = find(Name)) + if (S->isDefined() && !S->isShared()) + return S; + return nullptr; +} + template void SymbolTable::addLazyArchive(ArchiveFile *F, const object::Archive::Symbol Sym) { diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 1e5a335acc16..bfed1a79829f 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -82,6 +82,7 @@ public: void scanVersionScript(); SymbolBody *find(StringRef Name); + SymbolBody *findDefined(StringRef Name); void trace(StringRef Name); void wrap(StringRef Name); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 5486b38eec10..302a6ee51fc1 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -883,9 +883,9 @@ template void DynamicSection::finalize() { add({DT_FINI_ARRAYSZ, Out::FiniArray, Entry::SecSize}); } - if (SymbolBody *B = Symtab::X->find(Config->Init)) + if (SymbolBody *B = Symtab::X->findDefined(Config->Init)) add({DT_INIT, B}); - if (SymbolBody *B = Symtab::X->find(Config->Fini)) + if (SymbolBody *B = Symtab::X->findDefined(Config->Fini)) add({DT_FINI, B}); bool HasVerNeed = In::VerNeed->getNeedNum() != 0; diff --git a/lld/test/ELF/init-fini.s b/lld/test/ELF/init-fini.s index 400679066636..37d8b0149077 100644 --- a/lld/test/ELF/init-fini.s +++ b/lld/test/ELF/init-fini.s @@ -17,11 +17,22 @@ // RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar // 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: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s -// UNDEF: INIT 0x0 -// UNDEF: FINI 0x0 +// UNDEF-NOT: INIT +// 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 // and should not require given symbols to be resolved