blob: 381d8129b85733413f3c28f1127360c01d609d20 [file] [log] [blame]
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