diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 48 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 1 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 2 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/Inputs/implicit-program-header.script | 12 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/implicit-program-header.s | 13 |
5 files changed, 58 insertions, 18 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 2cf088e91e2..c8ca74abd86 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -563,6 +563,35 @@ template <class ELFT> void LinkerScript<ELFT>::adjustSectionsBeforeSorting() { auto *OutSec = make<OutputSection<ELFT>>(Cmd->Name, Type, Flags); OutputSections->push_back(OutSec); } +} + +template <class ELFT> void LinkerScript<ELFT>::adjustSectionsAfterSorting() { + placeOrphanSections(); + + // If output section command doesn't specify any segments, + // and we haven't previously assigned any section to segment, + // then we simply assign section to the very first load segment. + // Below is an example of such linker script: + // PHDRS { seg PT_LOAD; } + // SECTIONS { .aaa : { *(.aaa) } } + std::vector<StringRef> DefPhdrs; + auto FirstPtLoad = + std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(), + [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); + if (FirstPtLoad != Opt.PhdrsCommands.end()) + DefPhdrs.push_back(FirstPtLoad->Name); + + // Walk the commands and propagate the program headers to commands that don't + // explicitly specify them. + for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()); + if (!Cmd) + continue; + if (Cmd->Phdrs.empty()) + Cmd->Phdrs = DefPhdrs; + else + DefPhdrs = Cmd->Phdrs; + } removeEmptyCommands(); } @@ -630,8 +659,6 @@ void LinkerScript<ELFT>::placeOrphanSections() { template <class ELFT> void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) { - placeOrphanSections(); - // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; @@ -711,7 +738,6 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() { // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. - std::vector<size_t> DefPhdrIds; for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); PhdrEntry<ELFT> &Phdr = Ret.back(); @@ -725,15 +751,6 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() { Phdr.H.p_paddr = Cmd.LMAExpr(0); Phdr.HasLMA = true; } - - // If output section command doesn't specify any segments, - // and we haven't previously assigned any section to segment, - // then we simply assign section to the very first load segment. - // Below is an example of such linker script: - // PHDRS { seg PT_LOAD; } - // SECTIONS { .aaa : { *(.aaa) } } - if (DefPhdrIds.empty() && Phdr.H.p_type == PT_LOAD) - DefPhdrIds.push_back(Ret.size() - 1); } // Add output sections to program headers. @@ -741,17 +758,12 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() { if (!(Sec->Flags & SHF_ALLOC)) break; - std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName()); - if (PhdrIds.empty()) - PhdrIds = std::move(DefPhdrIds); - // Assign headers specified by linker script - for (size_t Id : PhdrIds) { + for (size_t Id : getPhdrIndices(Sec->getName())) { Ret[Id].add(Sec); if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) Ret[Id].H.p_flags |= Sec->getPhdrFlags(); } - DefPhdrIds = std::move(PhdrIds); } return Ret; } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 6bd02f13c2f..ce645269f77 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -221,6 +221,7 @@ public: void createSections(OutputSectionFactory<ELFT> &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); + void adjustSectionsAfterSorting(); std::vector<PhdrEntry<ELFT>> createPhdrs(); bool ignoreInterpSection(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 9776f62fdb6..2117e47e781 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -856,6 +856,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() { std::rotate(BestPos, NonScriptI, NonScriptI + 1); ++NonScriptI; } + + Script<ELFT>::X->adjustSectionsAfterSorting(); } // Create output section objects and add them to OutputSections. diff --git a/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script b/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script new file mode 100644 index 00000000000..27dbea84c4e --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script @@ -0,0 +1,12 @@ +PHDRS +{ + ph_write PT_LOAD FLAGS(2); + ph_exec PT_LOAD FLAGS(1); +} + +SECTIONS +{ + .bar : { *(.bar) } : ph_exec + .foo : { *(.foo) } + .text : { *(.text) } : ph_write +} diff --git a/lld/test/ELF/linkerscript/implicit-program-header.s b/lld/test/ELF/linkerscript/implicit-program-header.s new file mode 100644 index 00000000000..9598a6abebb --- /dev/null +++ b/lld/test/ELF/linkerscript/implicit-program-header.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld -o %t1 --script %S/Inputs/implicit-program-header.script \ +# RUN: %t.o -shared +# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s + +# CHECK: Segment Sections... +# CHECK-NEXT: 00 .text .dynsym .hash .dynstr .dynamic +# CHECK-NEXT: 01 .foo + +.quad 0 +.section .foo,"ax" +.quad 0 |