From: Rafael Espindola Date: Thu, 29 Sep 2016 18:50:34 +0000 (+0000) Subject: Don't error if we can't put the header in a PT_LOAD. X-Git-Tag: llvmorg-4.0.0-rc1~8601 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6d91fce526ee8e36fa24d95dfc0fc379d3662939;p=platform%2Fupstream%2Fllvm.git Don't error if we can't put the header in a PT_LOAD. If there is not sufficient address space, just give up and don't put the header in the PT_LOAD. This matches bfd behaviour and I found at least one script that depends on having a section at address 0. llvm-svn: 282750 --- diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index e9885d4..b979d06 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 void LinkerScript::assignAddresses() { +template +void LinkerScript::assignAddresses(std::vector> &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 void LinkerScript::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::ElfHeader->setVA(MinVA); - Out::ProgramHeaders->setVA(Out::ElfHeader->getSize() + MinVA); + auto FirstPTLoad = + std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &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::ElfHeader->setVA(MinVA); + Out::ProgramHeaders->setVA(Out::ElfHeader->getSize() + MinVA); + FirstPTLoad->First = Out::ElfHeader; + if (!FirstPTLoad->Last) + FirstPTLoad->Last = Out::ProgramHeaders; + } } // Creates program headers as instructed by PHDRS linker script command. diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 59f47d6..47b7b68 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -208,7 +208,7 @@ public: Expr getLma(StringRef Name); bool shouldKeep(InputSectionBase *S); void assignOffsets(OutputSectionCommand *Cmd); - void assignAddresses(); + void assignAddresses(std::vector> &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 ac1d1592..9f1346c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -275,7 +275,7 @@ template void Writer::run() { : createPhdrs(); fixHeaders(); if (ScriptConfig->HasSections) { - Script::X->assignAddresses(); + Script::X->assignAddresses(Phdrs); } else { fixSectionAlignments(); assignAddresses(); @@ -1047,8 +1047,10 @@ std::vector> Writer::createPhdrs() { // Add the first PT_LOAD segment for regular output sections. uintX_t Flags = computeFlags(PF_R); Phdr *Load = AddHdr(PT_LOAD, Flags); - Load->add(Out::ElfHeader); - Load->add(Out::ProgramHeaders); + if (!ScriptConfig->HasSections) { + Load->add(Out::ElfHeader); + Load->add(Out::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 f24a72a..e8b6be7 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