diff options
author | Chih-Hung Hsieh <chh@google.com> | 2018-03-13 23:16:53 -0700 |
---|---|---|
committer | Yi Kong <yikong@google.com> | 2019-03-01 10:37:33 -0800 |
commit | 3ee225094a683a0f52ad9a00299a7f2004a2c997 (patch) | |
tree | 709edd9eed789e36e5501d4db10add8cc4d03f86 | |
parent | 35c021c49f44cd4e06875c4b1398a2b3464132bb (diff) | |
download | lld-main.tar.gz |
Revert two changes that break Android builds.HEADmastermainllvm-r353983
* Earlier versions of lld were able to replace Android's
lld.gold and link most files.
* With two recent lld changes, debuggerd_test64 and some other files
failed to link because libunwindstack.a is linked like --whole-archive.
We need to revert the following two changes:
* "Put undefined symbols from shared libraries in the symbol table."
lld/trunk@326242
* "Make undefined symbol in DSO to pull out object files from archive files."
lld/trunk@325849
Bug: 74755833
Change-Id: I21b0df5e3c19bdfff4ea6c0ff9e9e562bd73f921
-rw-r--r-- | ELF/Driver.cpp | 4 | ||||
-rw-r--r-- | ELF/InputFiles.cpp | 5 | ||||
-rw-r--r-- | ELF/InputFiles.h | 8 | ||||
-rw-r--r-- | ELF/LinkerScript.cpp | 4 | ||||
-rw-r--r-- | ELF/SymbolTable.cpp | 24 | ||||
-rw-r--r-- | ELF/SymbolTable.h | 1 | ||||
-rw-r--r-- | test/ELF/shlib-undefined-archive.s | 19 | ||||
-rw-r--r-- | test/ELF/trace-symbols.s | 2 |
8 files changed, 43 insertions, 24 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index e2aa7e944..ad4d549ec 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -1544,6 +1544,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // They also might be exported if referenced by DSOs. Script->declareSymbols(); + // Handle undefined symbols in DSOs. + if (!Config->Shared) + Symtab->scanShlibUndefined<ELFT>(); + // Handle the -exclude-libs option. if (Args.hasArg(OPT_exclude_libs)) excludeLibs<ELFT>(Args); diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index c3e5b2f48..edeb80cc0 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -1018,10 +1018,7 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { } if (Sym.isUndefined()) { - Symbol *S = Symtab->addUndefined<ELFT>(Name, Sym.getBinding(), - Sym.st_other, Sym.getType(), - /*CanOmitFromDynSym=*/false, this); - S->ExportDynamic = true; + this->Undefs.insert(Name); continue; } diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 105e5ecbd..1d7081bca 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -93,6 +93,13 @@ public: return Symbols; } + // Returns undefined symbols of a shared library. + // It is a runtime error to call this function on files of other types. + const llvm::DenseSet<StringRef> &getUndefinedSymbols() { + assert(FileKind == SharedKind); + return Undefs; + } + // Filename of .a which contained this file. If this file was // not in an archive file, it is the empty string. We use this // string for creating error messages. @@ -139,6 +146,7 @@ protected: InputFile(Kind K, MemoryBufferRef M); std::vector<InputSectionBase *> Sections; std::vector<Symbol *> Symbols; + llvm::DenseSet<StringRef> Undefs; private: const Kind FileKind; diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index 2341938a1..4beb5b2c4 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -156,6 +156,10 @@ static bool shouldDefineSym(SymbolAssignment *Cmd) { Symbol *B = Symtab->find(Cmd->Name); if (B && !B->isDefined()) return true; + // It might also be referenced by a DSO. + for (InputFile *F : SharedFiles) + if (F->getUndefinedSymbols().count(Cmd->Name)) + return true; return false; } diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index e25682f80..f5fb41ce1 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -599,6 +599,24 @@ template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) { addFile<ELFT>(File); } +// This function takes care of the case in which shared libraries depend on +// the user program (not the other way, which is usual). Shared libraries +// may have undefined symbols, expecting that the user program provides +// the definitions for them. An example is BSD's __progname symbol. +// We need to put such symbols to the main program's .dynsym so that +// shared libraries can find them. +// Except this, we ignore undefined symbols in DSOs. +template <class ELFT> void SymbolTable::scanShlibUndefined() { + for (InputFile *F : SharedFiles) { + for (StringRef U : F->getUndefinedSymbols()) { + Symbol *Sym = find(U); + if (!Sym || !Sym->isDefined()) + continue; + Sym->ExportDynamic = true; + } + } +} + // Initialize DemangledSyms with a map from demangled symbols to symbol // objects. Used to handle "extern C++" directive in version scripts. // @@ -814,3 +832,9 @@ template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &, template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &, const typename ELF64BE::Sym &, uint32_t Alignment, uint32_t); + +template void SymbolTable::scanShlibUndefined<ELF32LE>(); +template void SymbolTable::scanShlibUndefined<ELF32BE>(); +template void SymbolTable::scanShlibUndefined<ELF64LE>(); +template void SymbolTable::scanShlibUndefined<ELF64BE>(); + diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h index 9822ed75c..654e362f1 100644 --- a/ELF/SymbolTable.h +++ b/ELF/SymbolTable.h @@ -71,6 +71,7 @@ public: template <class ELFT> void fetchLazy(Symbol *Sym); + template <class ELFT> void scanShlibUndefined(); void scanVersionScript(); Symbol *find(StringRef Name); diff --git a/test/ELF/shlib-undefined-archive.s b/test/ELF/shlib-undefined-archive.s deleted file mode 100644 index 940d8d7bc..000000000 --- a/test/ELF/shlib-undefined-archive.s +++ /dev/null @@ -1,19 +0,0 @@ -# REQUIRES: x86 - -# Undefined symbols in a DSO should pull out object files from archives -# to resolve them. - -# RUN: echo '.globl foo' | llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t1.o - -# RUN: ld.lld -shared -o %t.so %t1.o - -# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t2.o %s -# RUN: rm -f %t.a -# RUN: llvm-ar cru %t.a %t2.o -# RUN: ld.lld -o %t.exe %t.so %t.a -# RUN: llvm-nm -D %t.exe | FileCheck %s - -# CHECK: T foo - -.globl foo -foo: - ret diff --git a/test/ELF/trace-symbols.s b/test/ELF/trace-symbols.s index 63004b7c1..58aeb5d3d 100644 --- a/test/ELF/trace-symbols.s +++ b/test/ELF/trace-symbols.s @@ -72,7 +72,7 @@ # RUN: ld.lld -y foo -y bar %t %t1.so %t2.so -o %t3 | \ # RUN: FileCheck -check-prefix=SHLIBRBAR %s -# SHLIBRBAR: trace-symbols.s.tmp1.so: reference to bar +# SHLIBRBAR-NOT: trace-symbols.s.tmp1.so: reference to bar # RUN: ld.lld -y foo -y bar %t -u bar --start-lib %t1 %t2 --end-lib -o %t3 | \ # RUN: FileCheck -check-prefix=STARTLIB %s |