[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