diff options
Diffstat (limited to 'lld/ELF')
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 50 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.h | 1 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 40 |
3 files changed, 54 insertions, 37 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ab2ca22e9e1..63eb90456e1 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -413,6 +413,56 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { 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) diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 04a388efb4e..61942b2db35 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -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(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 310b2c08679..e8718c258c7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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>::run() { 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>::fixHeaders() { 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 |

