[lld] r291459 - [ELF] Allow defined symbols to be assigned from linker script

Meador Inge via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 9 10:36:57 PST 2017


Author: meadori
Date: Mon Jan  9 12:36:57 2017
New Revision: 291459

URL: http://llvm.org/viewvc/llvm-project?rev=291459&view=rev
Log:
[ELF] Allow defined symbols to be assigned from linker script

This patch allows for linker scripts to assign a new value
to a symbol that is already defined (either in an object file
or the linker script itself).

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/test/ELF/linkerscript/symbol-assignexpr.s
    lld/trunk/test/ELF/mips-gp-ext.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=291459&r1=291458&r2=291459&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Mon Jan  9 12:36:57 2017
@@ -56,29 +56,30 @@ using namespace lld::elf;
 LinkerScriptBase *elf::ScriptBase;
 ScriptConfiguration *elf::ScriptConfig;
 
-template <class ELFT> static void addRegular(SymbolAssignment *Cmd) {
+template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) {
   uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
-  Symbol *Sym = Symtab<ELFT>::X->addRegular(Cmd->Name, Visibility, STT_NOTYPE,
-                                            0, 0, STB_GLOBAL, nullptr, nullptr);
-  Cmd->Sym = Sym->body();
-
-  // If we have no SECTIONS then we don't have '.' and don't call
-  // assignAddresses(). We calculate symbol value immediately in this case.
-  if (!ScriptConfig->HasSections)
-    cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(0);
+  Symbol *Sym = Symtab<ELFT>::X->addUndefined(
+      Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
+      /*Type*/ 0,
+      /*CanOmitFromDynSym*/ false, /*File*/ nullptr);
+
+  replaceBody<DefinedRegular<ELFT>>(Sym, Cmd->Name, /*IsLocal=*/false,
+                                    Visibility, STT_NOTYPE, 0, 0, nullptr,
+                                    nullptr);
+  return Sym->body();
 }
 
-template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
-  // If we have SECTIONS block then output sections haven't been created yet.
+template <class ELFT> static SymbolBody *addSynthetic(SymbolAssignment *Cmd) {
+  uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
   const OutputSectionBase *Sec =
       ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
-  Symbol *Sym = Symtab<ELFT>::X->addSynthetic(
-      Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
-  Cmd->Sym = Sym->body();
-
-  // If we already know section then we can calculate symbol value immediately.
-  if (Sec)
-    cast<DefinedSynthetic>(Cmd->Sym)->Value = Cmd->Expression(0) - Sec->Addr;
+  Symbol *Sym = Symtab<ELFT>::X->addUndefined(
+      Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
+      /*Type*/ 0,
+      /*CanOmitFromDynSym*/ false, /*File*/ nullptr);
+
+  replaceBody<DefinedSynthetic>(Sym, Cmd->Name, 0, Sec);
+  return Sym->body();
 }
 
 static bool isUnderSysroot(StringRef Path) {
@@ -90,21 +91,39 @@ static bool isUnderSysroot(StringRef Pat
   return false;
 }
 
-template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
-  if (Cmd->Expression.IsAbsolute())
-    addRegular<ELFT>(Cmd);
-  else
-    addSynthetic<ELFT>(Cmd);
+template <class ELFT> static void assignSymbol(SymbolAssignment *Cmd) {
+  // If there are sections, then let the value be assigned later in
+  // `assignAddresses`.
+  if (ScriptConfig->HasSections)
+    return;
+
+  uint64_t Value = Cmd->Expression(0);
+  if (Cmd->Expression.IsAbsolute()) {
+    cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Value;
+  } else {
+    const OutputSectionBase *Sec = Cmd->Expression.Section();
+    if (Sec)
+      cast<DefinedSynthetic>(Cmd->Sym)->Value = Value - Sec->Addr;
+  }
 }
-// If a symbol was in PROVIDE(), we need to define it only when
-// it is an undefined symbol.
-template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
+
+template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
   if (Cmd->Name == ".")
-    return false;
-  if (!Cmd->Provide)
-    return true;
+    return;
+
+  // If a symbol was in PROVIDE(), we need to define it only when
+  // it is a referenced undefined symbol.
   SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
-  return B && B->isUndefined();
+  if (Cmd->Provide && (!B || B->isDefined()))
+    return;
+
+  // Otherwise, create a new symbol if one does not exist or an
+  // undefined one does exist.
+  if (Cmd->Expression.IsAbsolute())
+    Cmd->Sym = addRegular<ELFT>(Cmd);
+  else
+    Cmd->Sym = addSynthetic<ELFT>(Cmd);
+  assignSymbol<ELFT>(Cmd);
 }
 
 bool SymbolAssignment::classof(const BaseCommand *C) {
@@ -283,8 +302,7 @@ void LinkerScript<ELFT>::processCommands
 
     // Handle symbol assignments outside of any output section.
     if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
-      if (shouldDefine<ELFT>(Cmd))
-        addSymbol<ELFT>(Cmd);
+      addSymbol<ELFT>(Cmd);
       continue;
     }
 
@@ -326,8 +344,7 @@ void LinkerScript<ELFT>::processCommands
       // ".foo : { ...; bar = .; }". Handle them.
       for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
         if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
-          if (shouldDefine<ELFT>(OutCmd))
-            addSymbol<ELFT>(OutCmd);
+          addSymbol<ELFT>(OutCmd);
 
       // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
       // is given, input sections are aligned to that value, whether the

Modified: lld/trunk/test/ELF/linkerscript/symbol-assignexpr.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbol-assignexpr.s?rev=291459&r1=291458&r2=291459&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbol-assignexpr.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbol-assignexpr.s Mon Jan  9 12:36:57 2017
@@ -13,14 +13,20 @@
 # RUN:         symbol9 = - 4; \
 # RUN:         symbol10 = 0xfedcba9876543210; \
 # RUN:         symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \
+# RUN:         symbol12 = 0x1234; \
+# RUN:         symbol12 += 1; \
+# RUN:         bar = 0x5678; \
+# RUN:         baz = 0x9abc; \
 # RUN:       }" > %t.script
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-objdump -t %t1 | FileCheck %s
 
 # CHECK:      SYMBOL TABLE:
 # CHECK-NEXT: 0000000000000000 *UND* 00000000
-# CHECK-NEXT:                  .text 00000000 _start
-# CHECK-NEXT:                  .text 00000000 foo
+# CHECK-NEXT: 0000000000000000 .text 00000000 _start
+# CHECK-NEXT: 0000000000005678 *ABS* 00000000 bar
+# CHECK-NEXT: 0000000000009abc *ABS* 00000000 baz
+# CHECK-NEXT: 0000000000000001 .text 00000000 foo
 # CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol
 # CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2
 # CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3
@@ -32,6 +38,7 @@
 # CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9
 # CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10
 # CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11
+# CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12
 
 # RUN: echo "SECTIONS { \
 # RUN:         symbol2 = symbol; \
@@ -46,3 +53,9 @@ _start:
 
 .global foo
 foo:
+ nop
+
+.global bar
+bar = 0x1234
+
+.comm baz,8,8

Modified: lld/trunk/test/ELF/mips-gp-ext.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-ext.s?rev=291459&r1=291458&r2=291459&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-gp-ext.s (original)
+++ lld/trunk/test/ELF/mips-gp-ext.s Mon Jan  9 12:36:57 2017
@@ -1,8 +1,10 @@
 # Check that the linker use a value of _gp symbol defined
 # in a linker script to calculate GOT relocations.
 
-# FIXME: This test is xfailed because it depends on D27276 patch
-# that enables absolute symbols redefinition by a linker's script.
+# FIXME: This test is xfailed because there is currently a bug
+# that causes symbols defined by linker scripts to be put in the
+# wrong sections.  In particular, `_gp = . + 0x100` ends up in
+# `.text` when it should be in `*ABS*`.
 # XFAIL: *
 
 # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o




More information about the llvm-commits mailing list