[lld] r300687 - [ELF] Always use Script::assignAddresses()

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 19 05:46:33 PDT 2017


Author: psmith
Date: Wed Apr 19 07:46:32 2017
New Revision: 300687

URL: http://llvm.org/viewvc/llvm-project?rev=300687&view=rev
Log:
[ELF] Always use Script::assignAddresses()
    
This change fabricates linker script commands for the case where there is
no linker script SECTIONS to control address assignment. This permits us
to have a single Script->assignAddresses() function.
    
There is a small change in user-visible-behavior with respect to the
handling of .tbss SHT_NOBITS, SHF_TLS as the Script->assignAddresses()
requires setDot() to be called with monotically increasing addresses.
The tls-offset.s test has been updated so that the script and non-script
results match.

This change should make the non-script behavior of lld closer to an
equivalent linker script.

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


Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/tls-offset.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=300687&r1=300686&r2=300687&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Apr 19 07:46:32 2017
@@ -413,6 +413,56 @@ void LinkerScript::processCommands(Outpu
   CurOutSec = nullptr;
 }
 
+void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) {
+  std::vector<BaseCommand *> Commands;
+
+  // Define start address
+  uint64_t StartAddr = Config->ImageBase;
+  if (AllocateHeader)
+    StartAddr += elf::getHeaderSize();
+
+  // The Sections with -T<section> are sorted in order of ascending address
+  // we must use this if it is lower than StartAddr as calls to setDot() must
+  // be monotonically increasing
+  if (!Config->SectionStartMap.empty()) {
+    uint64_t LowestSecStart = Config->SectionStartMap.begin()->second;
+    StartAddr = std::min(StartAddr, LowestSecStart);
+  }
+  Commands.push_back(
+      make<SymbolAssignment>(".", [=] { return StartAddr; }, ""));
+
+  // For each OutputSection that needs a VA fabricate an OutputSectionCommand
+  // with an InputSectionDescription describing the InputSections
+  for (OutputSection *Sec : *OutputSections) {
+    if (!(Sec->Flags & SHF_ALLOC))
+      continue;
+
+    auto I = Config->SectionStartMap.find(Sec->Name);
+    if (I != Config->SectionStartMap.end())
+      Commands.push_back(
+          make<SymbolAssignment>(".", [=] { return I->second; }, ""));
+
+    auto *OSCmd = make<OutputSectionCommand>(Sec->Name);
+    OSCmd->Sec = Sec;
+    if (Sec->PageAlign)
+      OSCmd->AddrExpr = [=] {
+        return alignTo(Script->getDot(), Config->MaxPageSize);
+      };
+    Commands.push_back(OSCmd);
+    if (Sec->Sections.size()) {
+      auto *ISD = make<InputSectionDescription>("");
+      OSCmd->Commands.push_back(ISD);
+      for (InputSection *ISec : Sec->Sections) {
+        ISD->Sections.push_back(ISec);
+        ISec->Assigned = true;
+      }
+    }
+  }
+  // SECTIONS commands run before other non SECTIONS commands
+  Commands.insert(Commands.end(), Opt.Commands.begin(), Opt.Commands.end());
+  Opt.Commands = std::move(Commands);
+}
+
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
   for (InputSectionBase *S : InputSections)

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=300687&r1=300686&r2=300687&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Apr 19 07:46:32 2017
@@ -256,6 +256,7 @@ public:
   bool isDefined(StringRef S);
 
   std::vector<OutputSection *> *OutputSections;
+  void fabricateDefaultCommands(bool AllocateHeader);
   void addOrphanSections(OutputSectionFactory &Factory);
   void removeEmptyCommands();
   void adjustSectionsBeforeSorting();

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=300687&r1=300686&r2=300687&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Apr 19 07:46:32 2017
@@ -59,7 +59,6 @@ private:
   std::vector<PhdrEntry> createPhdrs();
   void removeEmptyPTLoad();
   void addPtArmExid(std::vector<PhdrEntry> &Phdrs);
-  void assignAddresses();
   void assignFileOffsets();
   void assignFileOffsetsBinary();
   void setPhdrs();
@@ -251,13 +250,11 @@ template <class ELFT> void Writer<ELFT>:
   if (Config->Relocatable) {
     assignFileOffsets();
   } else {
-    if (Script->Opt.HasSections) {
-      Script->assignAddresses(Phdrs);
-    } else {
+    if (!Script->Opt.HasSections) {
       fixSectionAlignments();
-      assignAddresses();
-      Script->processNonSectionCommands();
+      Script->fabricateDefaultCommands(Config->MaxPageSize);
     }
+    Script->assignAddresses(Phdrs);
 
     // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
     // 0 sized region. This has to be done late since only after assignAddresses
@@ -1509,37 +1506,6 @@ template <class ELFT> void Writer<ELFT>:
   AllocateHeader = allocateHeaders(Phdrs, OutputSections, Min);
 }
 
-// Assign VAs (addresses at run-time) to output sections.
-template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  uint64_t VA = Config->ImageBase;
-  uint64_t ThreadBssOffset = 0;
-
-  if (AllocateHeader)
-    VA += getHeaderSize();
-
-  for (OutputSection *Sec : OutputSections) {
-    uint32_t Alignment = Sec->Alignment;
-    if (Sec->PageAlign)
-      Alignment = std::max<uint32_t>(Alignment, Config->MaxPageSize);
-
-    auto I = Config->SectionStartMap.find(Sec->Name);
-    if (I != Config->SectionStartMap.end())
-      VA = I->second;
-
-    // We only assign VAs to allocated sections.
-    if (needsPtLoad(Sec)) {
-      VA = alignTo(VA, Alignment);
-      Sec->Addr = VA;
-      VA += Sec->Size;
-    } else if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) {
-      uint64_t TVA = VA + ThreadBssOffset;
-      TVA = alignTo(TVA, Alignment);
-      Sec->Addr = TVA;
-      ThreadBssOffset = TVA - VA + Sec->Size;
-    }
-  }
-}
-
 // Adjusts the file alignment for a given output section and returns
 // its new file offset. The file offset must be the same with its
 // virtual address (modulo the page size) so that the loader can load

Modified: lld/trunk/test/ELF/tls-offset.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/tls-offset.s?rev=300687&r1=300686&r2=300687&view=diff
==============================================================================
--- lld/trunk/test/ELF/tls-offset.s (original)
+++ lld/trunk/test/ELF/tls-offset.s Wed Apr 19 07:46:32 2017
@@ -2,7 +2,17 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
 // RUN: ld.lld %t -o %tout
 // RUN: llvm-readobj -s %tout | FileCheck %s
-
+// RUN: echo "SECTIONS { \
+// RUN:   . = 0x201000; \
+// RUN:   .text : { *(.text) } \
+// RUN:   . = 0x202000; \
+// RUN:   .tdata : { *(.tdata) } \
+// RUN:   .tbss : { *(.tbss) } \
+// RUN:   .data.rel.ro : { *(.data.rel.ro) } \
+// RUN: }" > %t.script
+        // RUN: ld.lld -T %t.script %t -o %tout2
+// RUN: echo SCRIPT
+// RUN: llvm-readobj -s %tout2 | FileCheck %s
         .global _start
 _start:
         retq
@@ -51,6 +61,6 @@ _start:
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_WRITE
 // CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x202004
-// CHECK-NEXT: Offset: 0x2004
+// CHECK-NEXT: Address: 0x202010
+// CHECK-NEXT: Offset: 0x2010
 // CHECK-NEXT: Size: 4




More information about the llvm-commits mailing list