diff options
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 25 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 8 |
3 files changed, 22 insertions, 13 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index e9885d46a9f..b979d06b927 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -553,7 +553,8 @@ static bool shouldSkip(const BaseCommand &Cmd) { return Assign->Name != "."; } -template <class ELFT> void LinkerScript<ELFT>::assignAddresses() { +template <class ELFT> +void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) { // Orphan sections are sections present in the input files which // are not explicitly placed into the output file by the linker script. // We place orphan sections at end of file. @@ -628,14 +629,20 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() { } uintX_t HeaderSize = getHeaderSize(); - if (HeaderSize > MinVA) - fatal("Not enough space for ELF and program headers"); - - // ELF and Program headers need to be right before the first section in - // memory. Set their addresses accordingly. - MinVA = alignDown(MinVA - HeaderSize, Target->PageSize); - Out<ELFT>::ElfHeader->setVA(MinVA); - Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA); + auto FirstPTLoad = + std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry<ELFT> &E) { + return E.H.p_type == PT_LOAD; + }); + if (HeaderSize <= MinVA && FirstPTLoad != Phdrs.end()) { + // ELF and Program headers need to be right before the first section in + // memory. Set their addresses accordingly. + MinVA = alignDown(MinVA - HeaderSize, Target->PageSize); + Out<ELFT>::ElfHeader->setVA(MinVA); + Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA); + FirstPTLoad->First = Out<ELFT>::ElfHeader; + if (!FirstPTLoad->Last) + FirstPTLoad->Last = Out<ELFT>::ProgramHeaders; + } } // Creates program headers as instructed by PHDRS linker script command. diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 59f47d69b95..47b7b683a34 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -208,7 +208,7 @@ public: Expr getLma(StringRef Name); bool shouldKeep(InputSectionBase<ELFT> *S); void assignOffsets(OutputSectionCommand *Cmd); - void assignAddresses(); + void assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs); bool hasPhdrsCommands(); uint64_t getOutputSectionAddress(StringRef Name) override; uint64_t getOutputSectionSize(StringRef Name) override; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ac1d159219d..9f1346c090b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -275,7 +275,7 @@ template <class ELFT> void Writer<ELFT>::run() { : createPhdrs(); fixHeaders(); if (ScriptConfig->HasSections) { - Script<ELFT>::X->assignAddresses(); + Script<ELFT>::X->assignAddresses(Phdrs); } else { fixSectionAlignments(); assignAddresses(); @@ -1047,8 +1047,10 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() { // Add the first PT_LOAD segment for regular output sections. uintX_t Flags = computeFlags<ELFT>(PF_R); Phdr *Load = AddHdr(PT_LOAD, Flags); - Load->add(Out<ELFT>::ElfHeader); - Load->add(Out<ELFT>::ProgramHeaders); + if (!ScriptConfig->HasSections) { + Load->add(Out<ELFT>::ElfHeader); + Load->add(Out<ELFT>::ProgramHeaders); + } Phdr TlsHdr(PT_TLS, PF_R); Phdr RelRo(PT_GNU_RELRO, PF_R); |