diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 25 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 8 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/no-space.s | 16 |
4 files changed, 36 insertions, 15 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); diff --git a/lld/test/ELF/linkerscript/no-space.s b/lld/test/ELF/linkerscript/no-space.s index f24a72aa616..e8b6be7e790 100644 --- a/lld/test/ELF/linkerscript/no-space.s +++ b/lld/test/ELF/linkerscript/no-space.s @@ -2,9 +2,21 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: echo "SECTIONS {foo 0 : {*(foo*)} }" > %t.script -# RUN: not ld.lld -o %t --script %t.script %t.o -shared 2>&1 | FileCheck %s +# RUN: ld.lld -o %t --script %t.script %t.o -shared +# RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s -# CHECK: Not enough space for ELF and program headers +# There is not enough address space available for the header, so just start the PT_LOAD +# after it. + +# CHECK: Program Headers: +# CHECK-NEXT: Type Offset VirtAddr PhysAddr +# CHECK-NEXT: PHDR +# CHECK-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 + +# CHECK: Section to Segment mapping: +# CHECK-NEXT: Segment Sections... +# CHECK-NEXT: 00 +# CHECK-NEXT: 01 foo .dynsym .hash .dynstr .section foo, "a" .quad 0 |