[LLD] [COFF] Don't error out on duplicate absolute symbols with the same value
authorMartin Storsjö <martin@martin.st>
Sun, 29 Dec 2019 22:32:22 +0000 (00:32 +0200)
committerMartin Storsjö <martin@martin.st>
Sat, 4 Jan 2020 10:29:33 +0000 (12:29 +0200)
Both MS link.exe and GNU ld.bfd handle it this way; one can have
multiple object files defining the same absolute symbols, as long
as it defines it to the same value. But if there are multiple absolute
symbols with differing values, it is treated as an error.

Differential Revision: https://reviews.llvm.org/D71981

lld/COFF/SymbolTable.cpp
lld/COFF/Symbols.h
lld/test/COFF/duplicate-absolute-same.s [new file with mode: 0644]
lld/test/COFF/duplicate-absolute.s

index e6f9d70..b6e180f 100644 (file)
@@ -591,7 +591,10 @@ Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
   s->isUsedInRegularObj = true;
   if (wasInserted || isa<Undefined>(s) || s->isLazy())
     replaceSymbol<DefinedAbsolute>(s, n, sym);
-  else if (!isa<DefinedCOFF>(s))
+  else if (auto *da = dyn_cast<DefinedAbsolute>(s)) {
+    if (!da->isEqual(sym))
+      reportDuplicate(s, nullptr);
+  } else if (!isa<DefinedCOFF>(s))
     reportDuplicate(s, nullptr);
   return s;
 }
@@ -603,7 +606,10 @@ Symbol *SymbolTable::addAbsolute(StringRef n, uint64_t va) {
   s->isUsedInRegularObj = true;
   if (wasInserted || isa<Undefined>(s) || s->isLazy())
     replaceSymbol<DefinedAbsolute>(s, n, va);
-  else if (!isa<DefinedCOFF>(s))
+  else if (auto *da = dyn_cast<DefinedAbsolute>(s)) {
+    if (!da->isEqual(va))
+      reportDuplicate(s, nullptr);
+  } else if (!isa<DefinedCOFF>(s))
     reportDuplicate(s, nullptr);
   return s;
 }
index fd79bd5..2d74dea 100644 (file)
@@ -229,6 +229,14 @@ public:
   uint64_t getRVA() { return va - config->imageBase; }
   void setVA(uint64_t v) { va = v; }
 
+  bool isEqual(COFFSymbolRef s) const {
+    return va == s.getValue();
+  }
+
+  bool isEqual(uint64_t otherVa) const {
+    return va == otherVa;
+  }
+
   // Section index relocations against absolute symbols resolve to
   // this 16 bit number, and it is the largest valid section index
   // plus one. This variable keeps it.
diff --git a/lld/test/COFF/duplicate-absolute-same.s b/lld/test/COFF/duplicate-absolute-same.s
new file mode 100644 (file)
index 0000000..e8c807c
--- /dev/null
@@ -0,0 +1,14 @@
+// REQUIRES: x86
+// RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t.obj %s
+// RUN: echo -e ".globl myabsolute\nmyabsolute = 0" > %t.dupl.s
+// RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t.dupl.obj %t.dupl.s
+// RUN: lld-link /out:%t.exe %t.obj %t.dupl.obj -subsystem:console -entry:entry 2>&1 | FileCheck --allow-empty %s
+
+// CHECK-NOT: error: duplicate symbol: myabsolute
+
+.globl myabsolute
+myabsolute = 0
+
+.globl entry
+entry:
+    ret
index 0d7e0d3..54d6285 100644 (file)
@@ -1,6 +1,6 @@
 // REQUIRES: x86
 // RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t.obj %s
-// RUN: echo -e ".globl myabsolute\nmyabsolute = 0" > %t.dupl.s
+// RUN: echo -e ".globl myabsolute\nmyabsolute = 1" > %t.dupl.s
 // RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t.dupl.obj %t.dupl.s
 // RUN: not lld-link /out:%t.exe %t.obj %t.dupl.obj 2>&1 | FileCheck %s