[lld] r285641 - The expr '.' is not absolute.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 31 14:36:24 PDT 2016


Author: rafael
Date: Mon Oct 31 16:36:23 2016
New Revision: 285641

URL: http://llvm.org/viewvc/llvm-project?rev=285641&view=rev
Log:
The expr '.' is not absolute.

With this patch we keep track of the fact that . is a position in the
file and therefore not absolute. This allow us to compute relative
relocations that involve symbol that are defined in linker scripts
with '.'.

This fixes https://llvm.org/bugs/show_bug.cgi?id=30406

There is still more work to track absoluteness over the various
expressions, but this should unblock linking the EFI bootloader.

Added:
    lld/trunk/test/ELF/linkerscript/dot-is-not-abs.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/test/ELF/linkerscript/symbol-conflict.s
    lld/trunk/test/ELF/linkerscript/symbols.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=285641&r1=285640&r2=285641&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Mon Oct 31 16:36:23 2016
@@ -299,7 +299,7 @@ void LinkerScript<ELFT>::processCommands
     const std::unique_ptr<BaseCommand> &Base1 = *Iter;
     if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
       if (shouldDefine<ELFT>(Cmd))
-        addRegular<ELFT>(Cmd);
+        addSymbol<ELFT>(Cmd);
       continue;
     }
     if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
@@ -621,7 +621,8 @@ void LinkerScript<ELFT>::assignAddresses
       if (Cmd->Name == ".") {
         Dot = Cmd->Expression(Dot);
       } else if (Cmd->Sym) {
-        cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(Dot);
+        assignSectionSymbol(Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0],
+                            Dot);
       }
       continue;
     }
@@ -1186,7 +1187,7 @@ void ScriptParser::readSections() {
   expect("{");
   while (!Error && !consume("}")) {
     StringRef Tok = next();
-    BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
+    BaseCommand *Cmd = readProvideOrAssignment(Tok, false);
     if (!Cmd) {
       if (Tok == "ASSERT")
         Cmd = new AssertCommand(readAssert());
@@ -1636,7 +1637,7 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "CONSTANT") {
     StringRef Name = readParenLiteral();
-    return {[=](uint64_t Dot) { return getConstant(Name); }, true};
+    return [=](uint64_t Dot) { return getConstant(Name); };
   }
   if (Tok == "DEFINED") {
     expect("(");
@@ -1679,23 +1680,20 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "SIZEOF") {
     StringRef Name = readParenLiteral();
-    return {
-        [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); },
-        true};
+    return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); };
   }
   if (Tok == "ALIGNOF") {
     StringRef Name = readParenLiteral();
-    return {
-        [=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); },
-        true};
+    return
+        [=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); };
   }
   if (Tok == "SIZEOF_HEADERS")
-    return {[=](uint64_t Dot) { return ScriptBase->getHeaderSize(); }, true};
+    return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); };
 
   // Tok is a literal number.
   uint64_t V;
   if (readInteger(Tok, V))
-    return {[=](uint64_t Dot) { return V; }, true};
+    return [=](uint64_t Dot) { return V; };
 
   // Tok is a symbol name.
   if (Tok != "." && !isValidCIdentifier(Tok))

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=285641&r1=285640&r2=285641&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Mon Oct 31 16:36:23 2016
@@ -43,13 +43,9 @@ struct Expr {
   uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
   operator bool() const { return (bool)Val; }
 
-  template <typename T>
-  Expr(T Val, std::function<bool()> IsAbsolute)
+  Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute)
       : Val(Val), IsAbsolute(IsAbsolute) {}
-  template <typename T> Expr(T Val, bool IsAbsolute) : Val(Val) {
-    this->IsAbsolute = [=]() { return IsAbsolute; };
-  }
-  template <typename T> Expr(T V) : Expr(V, false) {}
+  template <typename T> Expr(T V) : Expr(V, []() { return true; }) {}
   Expr() : Expr(nullptr) {}
 };
 

Added: lld/trunk/test/ELF/linkerscript/dot-is-not-abs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/dot-is-not-abs.s?rev=285641&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/dot-is-not-abs.s (added)
+++ lld/trunk/test/ELF/linkerscript/dot-is-not-abs.s Mon Oct 31 16:36:23 2016
@@ -0,0 +1,53 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# RUN: echo "SECTIONS { .text : { *(.text) } \
+# RUN:                  foo = .; \
+# RUN:                  .bar : { *(.bar) } }" > %t1.script
+# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared
+# RUN: llvm-readobj -t -s -section-data %t1 | FileCheck %s
+
+.hidden foo
+.long foo - .
+
+.section .bar, "a"
+.long 0
+
+# The symbol foo is defined as a position in the file. This means that it is
+# not absolute and it is possible to compute the distance from foo to some other
+# position in the file. The symbol is not really in any output section, but
+# ELF has no magic constant for not absolute, but not in any section.
+# Fortunately the value of a symbol in a non relocatable file is a virtual
+# address, so the section can be arbitrary.
+
+# CHECK:      Section {
+# CHECK:        Index:
+# CHECK:        Name: .text
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:     SHF_EXECINSTR
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x0
+# CHECK-NEXT:   Offset:
+# CHECK-NEXT:   Size: 4
+# CHECK-NEXT:   Link:
+# CHECK-NEXT:   Info:
+# CHECK-NEXT:   AddressAlignment:
+# CHECK-NEXT:   EntrySize:
+# CHECK-NEXT:   SectionData (
+# CHECK-NEXT:     0000: 04000000 |
+# CHECK-NEXT:   )
+# CHECK-NEXT: }
+
+# CHECK:      Symbol {
+# CHECK:        Name: foo
+# CHECK-NEXT:   Value: 0x4
+# CHECK-NEXT:   Size: 0
+# CHECK-NEXT:   Binding: Local
+# CHECK-NEXT:   Type: None
+# CHECK-NEXT:   Other [
+# CHECK-NEXT:     STV_HIDDEN
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Section: .text
+# CHECK-NEXT: }

Modified: lld/trunk/test/ELF/linkerscript/symbol-conflict.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbol-conflict.s?rev=285641&r1=285640&r2=285641&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbol-conflict.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbol-conflict.s Mon Oct 31 16:36:23 2016
@@ -4,7 +4,7 @@
 # RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : {*(.text.*)} end = .;}" > %t.script
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-objdump -t %t1 | FileCheck %s
-# CHECK: 00000000000000e9         *ABS*    00000000 end
+# CHECK: 00000000000000e9         .text    00000000 end
 
 .global _start
 _start:

Modified: lld/trunk/test/ELF/linkerscript/symbols.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbols.s?rev=285641&r1=285640&r2=285641&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbols.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbols.s Mon Oct 31 16:36:23 2016
@@ -7,7 +7,7 @@
 # RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
-# SIMPLE:                               *ABS*    00000000 text_end
+# SIMPLE:                               .text    00000000 text_end
 
 # The symbol is not referenced. Don't provide it.
 # RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script




More information about the llvm-commits mailing list