diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 12 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 62 | ||||
-rw-r--r-- | lld/ELF/Writer.h | 4 |
3 files changed, 38 insertions, 40 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index b06d8cd36ce..a96a20ce21a 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -733,17 +733,7 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry> &Phdrs) { Sec->Addr = 0; } - uintX_t HeaderSize = getHeaderSize(); - // If the linker script doesn't have PHDRS, add ElfHeader and ProgramHeaders - // now that we know we have space. - if (HeaderSize <= MinVA && !hasPhdrsCommands()) - allocateHeaders<ELFT>(Phdrs, *OutputSections); - - // ELF and Program headers need to be right before the first section in - // memory. Set their addresses accordingly. - MinVA = alignDown(MinVA - HeaderSize, Config->MaxPageSize); - Out<ELFT>::ElfHeader->Addr = MinVA; - Out<ELFT>::ProgramHeaders->Addr = Out<ELFT>::ElfHeader->Size + MinVA; + allocateHeaders<ELFT>(Phdrs, *OutputSections, MinVA); } // Creates program headers as instructed by PHDRS linker script command. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index deab1356573..30ba84868f7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1330,13 +1330,29 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { } template <class ELFT> -void elf::allocateHeaders(MutableArrayRef<PhdrEntry> Phdrs, - ArrayRef<OutputSectionBase *> OutputSections) { +bool elf::allocateHeaders(MutableArrayRef<PhdrEntry> Phdrs, + ArrayRef<OutputSectionBase *> 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; + return false; + + uint64_t HeaderSize = getHeaderSize<ELFT>(); + if (HeaderSize > Min) + return false; + Min = alignDown(Min - HeaderSize, Config->MaxPageSize); + + if (!ScriptConfig->HasSections) + Config->ImageBase = Min = std::min(Min, Config->ImageBase); + + Out<ELFT>::ElfHeader->Addr = Min; + Out<ELFT>::ProgramHeaders->Addr = Min + Out<ELFT>::ElfHeader->Size; + + if (Script<ELFT>::X->hasPhdrsCommands()) + return true; + if (FirstPTLoad->First) for (OutputSectionBase *Sec : OutputSections) if (Sec->FirstInPtLoad == FirstPTLoad->First) @@ -1344,6 +1360,7 @@ void elf::allocateHeaders(MutableArrayRef<PhdrEntry> Phdrs, FirstPTLoad->First = Out<ELFT>::ElfHeader; if (!FirstPTLoad->Last) FirstPTLoad->Last = Out<ELFT>::ProgramHeaders; + return true; } // We should set file offsets and VAs for elf header and program headers @@ -1355,27 +1372,14 @@ template <class ELFT> void Writer<ELFT>::fixHeaders() { if (ScriptConfig->HasSections) return; - uintX_t HeaderSize = getHeaderSize<ELFT>(); // When -T<section> option is specified, lower the base to make room for those // sections. - if (!Config->SectionStartMap.empty()) { - uint64_t Min = -1; + uint64_t Min = -1; + if (!Config->SectionStartMap.empty()) for (const auto &P : Config->SectionStartMap) Min = std::min(Min, P.second); - if (HeaderSize < Min) - Min -= HeaderSize; - else - AllocateHeader = false; - if (Min < Config->ImageBase) - Config->ImageBase = alignDown(Min, Config->MaxPageSize); - } - - if (AllocateHeader) - allocateHeaders<ELFT>(Phdrs, OutputSections); - uintX_t BaseVA = Config->ImageBase; - Out<ELFT>::ElfHeader->Addr = BaseVA; - Out<ELFT>::ProgramHeaders->Addr = BaseVA + Out<ELFT>::ElfHeader->Size; + AllocateHeader = allocateHeaders<ELFT>(Phdrs, OutputSections, Min); } // Assign VAs (addresses at run-time) to output sections. @@ -1740,14 +1744,18 @@ template void elf::writeResult<ELF32BE>(); template void elf::writeResult<ELF64LE>(); template void elf::writeResult<ELF64BE>(); -template void elf::allocateHeaders<ELF32LE>(MutableArrayRef<PhdrEntry>, - ArrayRef<OutputSectionBase *>); -template void elf::allocateHeaders<ELF32BE>(MutableArrayRef<PhdrEntry>, - ArrayRef<OutputSectionBase *>); -template void elf::allocateHeaders<ELF64LE>(MutableArrayRef<PhdrEntry>, - ArrayRef<OutputSectionBase *>); -template void elf::allocateHeaders<ELF64BE>(MutableArrayRef<PhdrEntry>, - ArrayRef<OutputSectionBase *>); +template bool elf::allocateHeaders<ELF32LE>(MutableArrayRef<PhdrEntry>, + ArrayRef<OutputSectionBase *>, + uint64_t); +template bool elf::allocateHeaders<ELF32BE>(MutableArrayRef<PhdrEntry>, + ArrayRef<OutputSectionBase *>, + uint64_t); +template bool elf::allocateHeaders<ELF64LE>(MutableArrayRef<PhdrEntry>, + ArrayRef<OutputSectionBase *>, + uint64_t); +template bool elf::allocateHeaders<ELF64BE>(MutableArrayRef<PhdrEntry>, + ArrayRef<OutputSectionBase *>, + uint64_t); template bool elf::isRelroSection<ELF32LE>(const OutputSectionBase *); template bool elf::isRelroSection<ELF32BE>(const OutputSectionBase *); diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index 718e3139a80..7942fa2cc9b 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -50,8 +50,8 @@ struct PhdrEntry { llvm::StringRef getOutputSectionName(llvm::StringRef Name); template <class ELFT> -void allocateHeaders(llvm::MutableArrayRef<PhdrEntry>, - llvm::ArrayRef<OutputSectionBase *>); +bool allocateHeaders(llvm::MutableArrayRef<PhdrEntry>, + llvm::ArrayRef<OutputSectionBase *>, uint64_t Min); template <class ELFT> void reportDiscarded(InputSectionBase<ELFT> *IS); template <class ELFT> uint32_t getMipsEFlags(); |