blob: dd58aef8cfa013c62dd420c7e05be628db962618 [file] [log] [blame]
From b7d8c86490f64ce836a1a6ba2738b1cae5464a00 Mon Sep 17 00:00:00 2001
From: Yabin Cui <yabinc@google.com>
Date: Thu, 10 Jun 2021 12:21:26 -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: 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 de26afddd28b..1cb4241d3da1 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2349,6 +2349,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// They also might be exported if referenced by DSOs.
script->declareSymbols();
+ 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 4da371c619f4..3e0f5922cfea 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1520,12 +1520,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() && sym.getBinding() != STB_WEAK &&
- 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 6febea3f437d..26650aef96e2 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -61,6 +61,7 @@ private:
protected:
SmallVector<InputSectionBase *, 0> sections;
+ llvm::DenseSet<StringRef> Undefs;
public:
enum Kind : uint8_t {
@@ -96,6 +97,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;
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index bfb583453735..58b86b314f88 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -209,6 +209,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 ec425cd7e1d1..4604fe66ef95 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -114,6 +114,24 @@ Symbol *SymbolTable::find(StringRef name) {
return symVector[it->second];
}
+// 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 extracts it.
@@ -330,3 +348,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 04c81f642fe0..b30950ffb947 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -41,6 +41,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.35.1.894.gb6a874cedc-goog