summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/OutputSections.cpp9
-rw-r--r--lld/ELF/SymbolTable.cpp8
-rw-r--r--lld/ELF/Symbols.h9
-rw-r--r--lld/ELF/Writer.cpp10
-rw-r--r--lld/test/ELF/relocation-copy-alias.s6
-rw-r--r--lld/test/ELF/weak-undef-shared.s19
6 files changed, 48 insertions, 13 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 6eeaa3ffc8e..146eaff0b7c 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -1363,12 +1363,13 @@ static bool sortMipsSymbols(const std::pair<SymbolBody *, unsigned> &L,
}
static uint8_t getSymbolBinding(SymbolBody *Body) {
- uint8_t Visibility = Body->Backref->Visibility;
+ Symbol *S = Body->Backref;
+ uint8_t Visibility = S->Visibility;
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return STB_LOCAL;
- if (Config->NoGnuUnique && Body->Binding == STB_GNU_UNIQUE)
+ if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
return STB_GLOBAL;
- return Body->Binding;
+ return S->Binding;
}
template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
@@ -1442,7 +1443,7 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
}
ESym->st_name = P.second;
ESym->st_size = Body.template getSize<ELFT>();
- ESym->setBindingAndType(Body.Binding, Body.Type);
+ ESym->setBindingAndType(STB_LOCAL, Body.Type);
Buf += sizeof(*ESym);
}
}
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index b3f971eea90..d67ad8699f3 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -244,6 +244,7 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
SymbolBody *Existing = Sym->Body;
if (auto *L = dyn_cast<Lazy>(Existing)) {
+ Sym->Binding = New->Binding;
if (New->isUndefined()) {
addMemberFile(New, L);
return;
@@ -270,8 +271,11 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
error(S);
return;
}
- if (Comp < 0)
+ if (Comp < 0) {
Sym->Body = New;
+ if (!New->isShared())
+ Sym->Binding = New->Binding;
+ }
}
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
@@ -300,6 +304,7 @@ template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
if (P.second) {
Sym = new (Alloc) Symbol;
Sym->Body = New;
+ Sym->Binding = New->isShared() ? STB_GLOBAL : New->Binding;
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
@@ -353,7 +358,6 @@ void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) {
// but we also need to preserve its binding and type.
if (Undef->isWeak()) {
// FIXME: Consider moving these members to Symbol.
- L->Binding = Undef->Binding;
L->Type = Undef->Type;
return;
}
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 7aed12d4020..64b9fea9fd2 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -44,6 +44,13 @@ std::string demangle(StringRef Name);
struct Symbol {
SymbolBody *Body;
+ // Symbol binding. This is on the Symbol to track changes during resolution.
+ // In particular:
+ // An undefined weak is still weak when it resolves to a shared library.
+ // An undefined weak will not fetch archive members, but we have to remember
+ // it is weak.
+ uint8_t Binding;
+
// Symbol visibility. This is the computed minimum visibility of all
// observed non-DSO symbols.
unsigned Visibility : 2;
@@ -66,6 +73,8 @@ struct Symbol {
unsigned VersionScriptGlobal : 1;
bool includeInDynsym() const;
+
+ bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
};
// The base class for real symbol classes.
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index faf3d0bb5ba..9ee44dcc55a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -424,7 +424,8 @@ static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc,
// True if non-preemptable symbol always has the same value regardless of where
// the DSO is loaded.
template <class ELFT> static bool isAbsolute(const SymbolBody &Body) {
- if (Body.isUndefined() && Body.isWeak())
+ Symbol *Sym = Body.Backref;
+ if (Body.isUndefined() && Sym->isWeak())
return true; // always 0
if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(&Body))
return DR->Section == nullptr; // Absolute symbol.
@@ -521,7 +522,8 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
const RelTy &RI = *I;
uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
SymbolBody &OrigBody = File.getSymbolBody(SymIndex);
- SymbolBody &Body = OrigBody.repl();
+ Symbol *Sym = OrigBody.Backref;
+ SymbolBody &Body = Sym ? *Sym->Body : OrigBody;
uint32_t Type = RI.getType(Config->Mips64EL);
// Ignore "hint" relocation because it is for optional code optimization.
@@ -533,7 +535,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
continue;
// Set "used" bit for --as-needed.
- if (OrigBody.isUndefined() && !OrigBody.isWeak())
+ if (OrigBody.isUndefined() && Sym && !Sym->isWeak())
if (auto *S = dyn_cast<SharedSymbol<ELFT>>(&Body))
S->File->IsUsed = true;
@@ -1342,7 +1344,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
std::vector<DefinedCommon *> CommonSymbols;
for (Symbol *S : Symtab.getSymbols()) {
SymbolBody *Body = S->Body;
- if (Body->isUndefined() && !Body->isWeak()) {
+ if (Body->isUndefined() && !S->isWeak()) {
auto *U = dyn_cast<UndefinedElf<ELFT>>(Body);
if (!U || !U->canKeepUndefined())
reportUndefined<ELFT>(Symtab, Body);
diff --git a/lld/test/ELF/relocation-copy-alias.s b/lld/test/ELF/relocation-copy-alias.s
index d3256d24b53..b7758f75c31 100644
--- a/lld/test/ELF/relocation-copy-alias.s
+++ b/lld/test/ELF/relocation-copy-alias.s
@@ -37,7 +37,7 @@ movl $5, b2
// CHECK: Name: b1
// CHECK-NEXT: Value: [[B:.*]]
// CHECK-NEXT: Size: 1
-// CHECK-NEXT: Binding: Weak (0x2)
+// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object (0x1)
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss
@@ -45,7 +45,7 @@ movl $5, b2
// CHECK: Name: b2
// CHECK-NEXT: Value: [[B]]
// CHECK-NEXT: Size: 1
-// CHECK-NEXT: Binding: Weak (0x2)
+// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object (0x1)
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss
@@ -53,7 +53,7 @@ movl $5, b2
// CHECK: Name: a2
// CHECK-NEXT: Value: [[A]]
// CHECK-NEXT: Size: 1
-// CHECK-NEXT: Binding: Weak (0x2)
+// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object (0x1)
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss
diff --git a/lld/test/ELF/weak-undef-shared.s b/lld/test/ELF/weak-undef-shared.s
new file mode 100644
index 00000000000..862a08632e2
--- /dev/null
+++ b/lld/test/ELF/weak-undef-shared.s
@@ -0,0 +1,19 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/shared.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe
+// RUN: llvm-readobj -t %t.exe | FileCheck %s
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x11020
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+.global _start
+_start:
+ .weak bar
+ .quad bar
OpenPOWER on IntegriCloud