[lld] r347854 - [LLD][ELF] Error if _GLOBAL_OFFSET_TABLE_ is defined in input objects

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 29 03:18:07 PST 2018


Author: psmith
Date: Thu Nov 29 03:18:07 2018
New Revision: 347854

URL: http://llvm.org/viewvc/llvm-project?rev=347854&view=rev
Log:
[LLD][ELF] Error if _GLOBAL_OFFSET_TABLE_ is defined in input objects

The _GLOBAL_OFFSET_TABLE_ is a linker defined symbol that is placed at
some location relative to the .got, .got.plt or .toc section. On some
targets such as Arm the correctness of some code sequences using a
relocation to _GLOBAL_OFFSET_TABLE_ depend on the value of the symbol
being in the linker defined place. Follow the ld.gold example and give
a multiple symbol definition error. The ld.bfd behaviour is to ignore the
definition in the input object and redefine it, which seems like it could
be more surprising.

fixes pr39587

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


Added:
    lld/trunk/test/ELF/global-offset-table-position-redef-err.s
Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=347854&r1=347853&r2=347854&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Nov 29 03:18:07 2018
@@ -212,9 +212,20 @@ void elf::addReservedSymbols() {
   // _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32-bit ABI. It is used to
   // represent the TOC base which is offset by 0x8000 bytes from the start of
   // the .got section.
-  ElfSym::GlobalOffsetTable = addOptionalRegular(
-      (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_",
-      Out::ElfHeader, Target->GotBaseSymOff);
+  // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the
+  // correctness of some relocations depends on its value.
+  StringRef GotTableSymName =
+      (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_";
+  if (Symbol *S = Symtab->find(GotTableSymName)) {
+    if (S->isDefined())
+      error(toString(S->File) + " cannot redefine linker defined symbol '" +
+            GotTableSymName + "'");
+    else
+      ElfSym::GlobalOffsetTable = Symtab->addDefined(
+          GotTableSymName, STV_HIDDEN, STT_NOTYPE, Target->GotBaseSymOff,
+          /*Size=*/0, STB_GLOBAL, Out::ElfHeader,
+          /*File=*/nullptr);
+  }
 
   // __ehdr_start is the location of ELF file headers. Note that we define
   // this symbol unconditionally even when using a linker script, which

Added: lld/trunk/test/ELF/global-offset-table-position-redef-err.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position-redef-err.s?rev=347854&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position-redef-err.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position-redef-err.s Thu Nov 29 03:18:07 2018
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
+
+# On some targets the location of the _GLOBAL_OFFSET_TABLE_ symbol table can
+# matter for the correctness of some relocations. Follow the example of ld.gold
+# and give a multiple definition error if input objects attempt to redefine it.
+
+# CHECK: ld.lld: error: {{.*o}} cannot redefine linker defined symbol '_GLOBAL_OFFSET_TABLE_'
+
+.data
+.global _GLOBAL_OFFSET_TABLE_
+_GLOBAL_OFFSET_TABLE_:
+.word 0




More information about the llvm-commits mailing list