[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
llvm-svn: 300687
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index ab2ca22..63eb904 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -413,6 +413,56 @@
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)