summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/SymbolTable.cpp21
-rw-r--r--lld/test/ELF/abs-conflict.s16
2 files changed, 31 insertions, 6 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index c7fe4ceea68..6734e54a135 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -291,18 +291,24 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
// We have a new non-common defined symbol with the specified binding. Return 1
// if the new symbol should win, -1 if the new symbol should lose, or 0 if there
// is a conflict. If the new symbol wins, also update the binding.
-static int compareDefinedNonCommon(Symbol *S, bool WasInserted,
- uint8_t Binding) {
+template <typename ELFT>
+static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
+ bool IsAbsolute, typename ELFT::uint Value) {
if (int Cmp = compareDefined(S, WasInserted, Binding)) {
if (Cmp > 0)
S->Binding = Binding;
return Cmp;
}
- if (isa<DefinedCommon>(S->body())) {
+ SymbolBody *B = S->body();
+ if (isa<DefinedCommon>(B)) {
// Non-common symbols take precedence over common symbols.
if (Config->WarnCommon)
warn("common " + S->body()->getName() + " is overridden");
return 1;
+ } else if (auto *R = dyn_cast<DefinedRegular<ELFT>>(B)) {
+ if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute &&
+ R->Value == Value)
+ return -1;
}
return 0;
}
@@ -377,7 +383,8 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther,
bool WasInserted;
std::tie(S, WasInserted) = insert(Name, Type, StOther & 3,
/*CanOmitFromDynSym*/ false, File);
- int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
+ int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
+ Section == nullptr, Value);
if (Cmp > 0)
replaceBody<DefinedRegular<ELFT>>(S, Name, /*IsLocal=*/false, StOther, Type,
Value, Size, Section, File);
@@ -394,7 +401,8 @@ Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
bool WasInserted;
std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3,
/*CanOmitFromDynSym*/ false, nullptr);
- int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL);
+ int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, STB_GLOBAL,
+ /*IsAbsolute*/ false, /*Value*/ 0);
if (Cmp > 0)
replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section);
else if (Cmp == 0)
@@ -431,7 +439,8 @@ Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding,
bool WasInserted;
std::tie(S, WasInserted) =
insert(Name, Type, StOther & 3, CanOmitFromDynSym, F);
- int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
+ int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
+ /*IsAbs*/ false, /*Value*/ 0);
if (Cmp > 0)
replaceBody<DefinedRegular<ELFT>>(S, Name, /*IsLocal=*/false, StOther, Type,
0, 0, nullptr, F);
diff --git a/lld/test/ELF/abs-conflict.s b/lld/test/ELF/abs-conflict.s
new file mode 100644
index 00000000000..7837a6bae50
--- /dev/null
+++ b/lld/test/ELF/abs-conflict.s
@@ -0,0 +1,16 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o %t.o -o %t.so -shared
+// RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x123
+
+.global foo
+foo = 0x123
+
+// RUN: echo ".global foo; foo = 0x124" > %t2.s
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o
+// RUN: not ld.lld %t.o %t2.o -o %t.so -shared 2>&1 | FileCheck --check-prefix=DUP %s
+
+// DUP: duplicate symbol 'foo'
OpenPOWER on IntegriCloud