| From 73d888a4f67df5e59eb1f762cca326c89afc4776 Mon Sep 17 00:00:00 2001 |
| From: Chih-Hung Hsieh <[email protected]> |
| Date: Mon, 3 Jun 2019 11:10:52 -0700 |
| Subject: [PATCH] Revert two changes that break Android builds. |
| |
| * 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: I18a59ec2e4d13b6698b75ed3e4ac6de290431779 |
| --- |
| lld/ELF/Driver.cpp | 4 ++++ |
| lld/ELF/InputFiles.cpp | 4 +--- |
| lld/ELF/InputFiles.h | 8 ++++++++ |
| lld/ELF/LinkerScript.cpp | 4 ++++ |
| lld/ELF/SymbolTable.cpp | 23 +++++++++++++++++++++++ |
| lld/ELF/SymbolTable.h | 1 + |
| lld/test/ELF/shlib-undefined-archive.s | 19 ------------------- |
| lld/test/ELF/trace-symbols.s | 2 +- |
| 8 files changed, 42 insertions(+), 23 deletions(-) |
| delete mode 100644 lld/test/ELF/shlib-undefined-archive.s |
| |
| diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp |
| index ca1a9ed9213..e4969692a83 100644 |
| --- a/lld/ELF/Driver.cpp |
| +++ b/lld/ELF/Driver.cpp |
| @@ -1833,6 +1833,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(args); |
| diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp |
| index 7dc72361abd..755573298f9 100644 |
| --- a/lld/ELF/InputFiles.cpp |
| +++ b/lld/ELF/InputFiles.cpp |
| @@ -1294,9 +1294,7 @@ template <class ELFT> void SharedFile::parse() { |
| } |
| |
| if (sym.isUndefined()) { |
| - Symbol *s = symtab->addSymbol( |
| - Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); |
| - s->exportDynamic = true; |
| + this->Undefs.insert(name); |
| continue; |
| } |
| |
| diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h |
| index a310ba551bd..bf2fb3ea927 100644 |
| --- a/lld/ELF/InputFiles.h |
| +++ b/lld/ELF/InputFiles.h |
| @@ -94,6 +94,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. |
| @@ -146,6 +153,7 @@ public: |
| protected: |
| InputFile(Kind k, MemoryBufferRef m); |
| std::vector<InputSectionBase *> sections; |
| + llvm::DenseSet<StringRef> Undefs; |
| |
| private: |
| const Kind fileKind; |
| diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp |
| index cebbd89168b..da2a7b829bd 100644 |
| --- a/lld/ELF/LinkerScript.cpp |
| +++ b/lld/ELF/LinkerScript.cpp |
| @@ -152,6 +152,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/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp |
| index f7a8a99cf8f..34d6d41a63b 100644 |
| --- a/lld/ELF/SymbolTable.cpp |
| +++ b/lld/ELF/SymbolTable.cpp |
| @@ -103,6 +103,24 @@ Symbol *SymbolTable::find(StringRef name) { |
| return sym; |
| } |
| |
| +// 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. |
| // |
| @@ -265,5 +283,10 @@ void SymbolTable::scanVersionScript() { |
| handleDynamicList(); |
| } |
| |
| +template void SymbolTable::scanShlibUndefined<ELF32LE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF32BE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF64LE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF64BE>(); |
| + |
| } // namespace elf |
| } // namespace lld |
| diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h |
| index d3be0cb6450..15bcb045e26 100644 |
| --- a/lld/ELF/SymbolTable.h |
| +++ b/lld/ELF/SymbolTable.h |
| @@ -45,6 +45,7 @@ public: |
| |
| Symbol *addSymbol(const Symbol &newSym); |
| |
| + template <class ELFT> void scanShlibUndefined(); |
| void scanVersionScript(); |
| |
| Symbol *find(StringRef name); |
| diff --git a/lld/test/ELF/shlib-undefined-archive.s b/lld/test/ELF/shlib-undefined-archive.s |
| deleted file mode 100644 |
| index 940d8d7bc0c..00000000000 |
| --- a/lld/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/lld/test/ELF/trace-symbols.s b/lld/test/ELF/trace-symbols.s |
| index b6f8bea79d1..bc944b482c8 100644 |
| --- a/lld/test/ELF/trace-symbols.s |
| +++ b/lld/test/ELF/trace-symbols.s |
| @@ -77,7 +77,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 |
| -- |
| 2.25.0.341.g760bfbb309-goog |
| |