diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 48 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 69 | ||||
-rw-r--r-- | lld/ELF/Writer.h | 3 |
4 files changed, 52 insertions, 70 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 35b88254304..2620e699053 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -420,13 +420,11 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { CurOutSec = nullptr; } -void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) { +void LinkerScript::fabricateDefaultCommands() { std::vector<BaseCommand *> Commands; // Define start address - uint64_t StartAddr = Config->ImageBase; - if (AllocateHeader) - StartAddr += elf::getHeaderSize(); + uint64_t StartAddr = Config->ImageBase + elf::getHeaderSize(); // The Sections with -T<section> have been sorted in order of ascending // address. We must lower StartAddr if the lowest -T<section address> as @@ -892,6 +890,48 @@ void LinkerScript::synchronize() { } } +static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs, + ArrayRef<OutputSection *> OutputSections, + uint64_t Min) { + auto FirstPTLoad = + std::find_if(Phdrs.begin(), Phdrs.end(), + [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); + if (FirstPTLoad == Phdrs.end()) + return false; + + uint64_t HeaderSize = getHeaderSize(); + if (HeaderSize <= Min || Script->hasPhdrsCommands()) { + Min = alignDown(Min - HeaderSize, Config->MaxPageSize); + Out::ElfHeader->Addr = Min; + Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; + return true; + } + + assert(FirstPTLoad->First == Out::ElfHeader); + OutputSection *ActualFirst = nullptr; + for (OutputSection *Sec : OutputSections) { + if (Sec->FirstInPtLoad == Out::ElfHeader) { + ActualFirst = Sec; + break; + } + } + if (ActualFirst) { + for (OutputSection *Sec : OutputSections) + if (Sec->FirstInPtLoad == Out::ElfHeader) + Sec->FirstInPtLoad = ActualFirst; + FirstPTLoad->First = ActualFirst; + } else { + Phdrs.erase(FirstPTLoad); + } + + auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { + return E.p_type == PT_PHDR; + }); + if (PhdrI != Phdrs.end()) + Phdrs.erase(PhdrI); + return false; +} + void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index b4ca6535891..9404f49a2b0 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -253,7 +253,7 @@ public: bool isDefined(StringRef S); std::vector<OutputSection *> *OutputSections; - void fabricateDefaultCommands(bool AllocateHeader); + void fabricateDefaultCommands(); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3de2596af27..d78705ae522 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -62,7 +62,6 @@ private: void assignFileOffsets(); void assignFileOffsetsBinary(); void setPhdrs(); - void fixHeaders(); void fixSectionAlignments(); void fixPredefinedSymbols(); void openFile(); @@ -86,7 +85,6 @@ private: uint64_t FileSize; uint64_t SectionHeaderOff; - bool AllocateHeader = true; }; } // anonymous namespace @@ -252,7 +250,7 @@ template <class ELFT> void Writer<ELFT>::run() { } else { if (!Script->Opt.HasSections) { fixSectionAlignments(); - Script->fabricateDefaultCommands(AllocateHeader); + Script->fabricateDefaultCommands(); } Script->synchronize(); Script->assignAddresses(Phdrs); @@ -1176,7 +1174,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (!Config->Relocatable && !Config->OFormatBinary) { Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs(); addPtArmExid(Phdrs); - fixHeaders(); + Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } // Dynamic section must be the last one in this list and dynamic @@ -1321,6 +1319,11 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { // Add the first PT_LOAD segment for regular output sections. uint64_t Flags = computeFlags(PF_R); PhdrEntry *Load = AddHdr(PT_LOAD, Flags); + + // Add the headers. We will remove them if they don't fit. + Load->add(Out::ElfHeader); + Load->add(Out::ProgramHeaders); + for (OutputSection *Sec : OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; @@ -1447,64 +1450,6 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { } } -bool elf::allocateHeaders(std::vector<PhdrEntry> &Phdrs, - ArrayRef<OutputSection *> OutputSections, - uint64_t Min) { - auto FirstPTLoad = - std::find_if(Phdrs.begin(), Phdrs.end(), - [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); - if (FirstPTLoad == Phdrs.end()) - return false; - - uint64_t HeaderSize = getHeaderSize(); - if (HeaderSize > Min) { - auto PhdrI = - std::find_if(Phdrs.begin(), Phdrs.end(), - [](const PhdrEntry &E) { return E.p_type == PT_PHDR; }); - if (PhdrI != Phdrs.end()) - Phdrs.erase(PhdrI); - return false; - } - Min = alignDown(Min - HeaderSize, Config->MaxPageSize); - - if (!Script->Opt.HasSections) - Config->ImageBase = Min = std::min(Min, Config->ImageBase); - - Out::ElfHeader->Addr = Min; - Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; - - if (Script->hasPhdrsCommands()) - return true; - - if (FirstPTLoad->First) - for (OutputSection *Sec : OutputSections) - if (Sec->FirstInPtLoad == FirstPTLoad->First) - Sec->FirstInPtLoad = Out::ElfHeader; - FirstPTLoad->First = Out::ElfHeader; - if (!FirstPTLoad->Last) - FirstPTLoad->Last = Out::ProgramHeaders; - return true; -} - -// We should set file offsets and VAs for elf header and program headers -// sections. These are special, we do not include them into output sections -// list, but have them to simplify the code. -template <class ELFT> void Writer<ELFT>::fixHeaders() { - Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); - // If the script has SECTIONS, assignAddresses will compute the values. - if (Script->Opt.HasSections) - return; - - // When -T<section> option is specified, lower the base to make room for those - // sections. - uint64_t Min = -1; - if (!Config->SectionStartMap.empty()) - for (const auto &P : Config->SectionStartMap) - Min = std::min(Min, P.second); - - AllocateHeader = allocateHeaders(Phdrs, OutputSections, Min); -} - // 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 diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index a669e42ef20..8b965f7bedd 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -49,9 +49,6 @@ struct PhdrEntry { llvm::StringRef getOutputSectionName(llvm::StringRef Name); -bool allocateHeaders(std::vector<PhdrEntry> &, llvm::ArrayRef<OutputSection *>, - uint64_t Min); - template <class ELFT> uint32_t getMipsEFlags(); uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, |