| From a0ce8d6aa14c8e334de1e3d033cf6969eed10189 Mon Sep 17 00:00:00 2001 |
| From: Yabin Cui <yabinc@google.com> |
| Date: Thu, 10 Jun 2021 12:21:26 -0700 |
| Subject: [PATCH] [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: Idf05ca82d8dc5d8f1593e6f6a64c609d3fa10c14 |
| --- |
| lld/ELF/Driver.cpp | 4 ++++ |
| lld/ELF/InputFiles.cpp | 7 +------ |
| 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(+), 26 deletions(-) |
| delete mode 100644 lld/test/ELF/shlib-undefined-archive.s |
| |
| diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp |
| index c3adeeca6e46..7b6784d79af5 100644 |
| --- a/lld/ELF/Driver.cpp |
| +++ b/lld/ELF/Driver.cpp |
| @@ -2199,6 +2199,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 --exclude-libs. This is before scanVersionScript() due to a |
| // workaround for Android ndk: for a defined versioned symbol in an archive |
| // without a version node in the version script, Android does not expect a |
| diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp |
| index 3e0c1d77823f..dd074cd1c2cd 100644 |
| --- a/lld/ELF/InputFiles.cpp |
| +++ b/lld/ELF/InputFiles.cpp |
| @@ -1564,12 +1564,7 @@ template <class ELFT> void SharedFile::parse() { |
| name = |
| saver.save((name + "@" + verName).toStringRef(versionedNameBuffer)); |
| } |
| - Symbol *s = symtab->addSymbol( |
| - Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); |
| - s->exportDynamic = true; |
| - if (s->isUndefined() && !s->isWeak() && |
| - config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) |
| - requiredSymbols.push_back(s); |
| + this->Undefs.insert(name); |
| continue; |
| } |
| |
| diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h |
| index f66d7a25d954..9bc605595caf 100644 |
| --- a/lld/ELF/InputFiles.h |
| +++ b/lld/ELF/InputFiles.h |
| @@ -92,6 +92,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; |
| + } |
| + |
| // Get filename to use for linker script processing. |
| StringRef getNameForScript() const; |
| |
| @@ -150,6 +157,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 ffba25c21009..3e2a190d222d 100644 |
| --- a/lld/ELF/LinkerScript.cpp |
| +++ b/lld/ELF/LinkerScript.cpp |
| @@ -154,6 +154,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 70aea288c53f..f63621b90c16 100644 |
| --- a/lld/ELF/SymbolTable.cpp |
| +++ b/lld/ELF/SymbolTable.cpp |
| @@ -111,6 +111,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; |
| + } |
| + } |
| +} |
| + |
| // A version script/dynamic list is only meaningful for a Defined symbol. |
| // A CommonSymbol will be converted to a Defined in replaceCommonSymbols(). |
| // A lazy symbol may be made Defined if an LTO libcall fetches it. |
| @@ -277,3 +295,8 @@ void SymbolTable::scanVersionScript() { |
| // --dynamic-list. |
| handleDynamicList(); |
| } |
| + |
| +template void SymbolTable::scanShlibUndefined<ELF32LE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF32BE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF64LE>(); |
| +template void SymbolTable::scanShlibUndefined<ELF64BE>(); |
| diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h |
| index 507af8d2be75..6f99c6557737 100644 |
| --- a/lld/ELF/SymbolTable.h |
| +++ b/lld/ELF/SymbolTable.h |
| @@ -49,6 +49,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 940d8d7bc0c5..000000000000 |
| --- 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 f5211b367eb4..4dfeced7b9f4 100644 |
| --- a/lld/test/ELF/trace-symbols.s |
| +++ b/lld/test/ELF/trace-symbols.s |
| @@ -82,7 +82,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.32.0.272.g935e593368-goog |
| |