[PATCH] D43571: [ELF] - Do not remove empty output sections that are explicitly assigned to phdr in script.
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 22 14:22:56 PST 2018
This is a very interesting idea.
It looks like most "very generic" scripts are based on "ld.bfd
--verbose", and that doesn't use explicit phdr assignments.
So it does look like we can keep more output sections and simplify the
code.
LGTM
Cheers,
Rafael
George Rimar via Phabricator <reviews at reviews.llvm.org> writes:
> grimar created this revision.
> grimar added reviewers: ruiu, espindola.
> Herald added subscribers: arichardson, emaste.
>
> This continues direction shown in https://reviews.llvm.org/D43069.
>
> I suggest to keep sections that are explicitly assigned to segment in script.
> With that code can be simplified (as shown in diff).
>
> Also with that it might be possible to get rid of `Live` flag of output section (if we want).
>
>
> https://reviews.llvm.org/D43571
>
> Files:
> ELF/LinkerScript.cpp
> ELF/LinkerScript.h
> ELF/Writer.cpp
> test/ELF/linkerscript/implicit-program-header.s
> test/ELF/linkerscript/orphan-phdrs.s
>
> Index: test/ELF/linkerscript/orphan-phdrs.s
> ===================================================================
> --- test/ELF/linkerscript/orphan-phdrs.s
> +++ test/ELF/linkerscript/orphan-phdrs.s
> @@ -18,6 +18,7 @@
> # CHECK: Section Headers
> # CHECK: .text
> # CHECK-NEXT: .orphan
> +# CHECK-NEXT: .empty
> # CHECK-NEXT: .rw
>
> # CHECK: Segment Sections
> Index: test/ELF/linkerscript/implicit-program-header.s
> ===================================================================
> --- test/ELF/linkerscript/implicit-program-header.s
> +++ test/ELF/linkerscript/implicit-program-header.s
> @@ -15,7 +15,7 @@
>
> # CHECK: Segment Sections...
> # CHECK-NEXT: 00 .text .dynsym .hash .dynstr .dynamic
> -# CHECK-NEXT: 01 .foo
> +# CHECK-NEXT: 01 .bar .foo
>
> .quad 0
> .section .foo,"ax"
> Index: ELF/Writer.cpp
> ===================================================================
> --- ELF/Writer.cpp
> +++ ELF/Writer.cpp
> @@ -937,8 +937,7 @@
>
> static int getRankProximity(OutputSection *A, BaseCommand *B) {
> if (auto *Sec = dyn_cast<OutputSection>(B))
> - if (Sec->Live)
> - return getRankProximityAux(A, Sec);
> + return getRankProximityAux(A, Sec);
> return -1;
> }
>
> @@ -984,28 +983,24 @@
> int Proximity = getRankProximity(Sec, *I);
> for (; I != E; ++I) {
> auto *CurSec = dyn_cast<OutputSection>(*I);
> - if (!CurSec || !CurSec->Live)
> + if (!CurSec)
> continue;
> if (getRankProximity(Sec, CurSec) != Proximity ||
> Sec->SortRank < CurSec->SortRank)
> break;
> }
>
> - auto IsLiveSection = [](BaseCommand *Cmd) {
> - auto *OS = dyn_cast<OutputSection>(Cmd);
> - return OS && OS->Live;
> - };
> -
> + auto IsOutputSec = [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); };
> auto J = std::find_if(llvm::make_reverse_iterator(I),
> - llvm::make_reverse_iterator(B), IsLiveSection);
> + llvm::make_reverse_iterator(B), IsOutputSec);
> I = J.base();
>
> // As a special case, if the orphan section is the last section, put
> // it at the very end, past any other commands.
> // This matches bfd's behavior and is convenient when the linker script fully
> // specifies the start of the file, but doesn't care about the end (the non
> // alloc sections for example).
> - auto NextSec = std::find_if(I, E, IsLiveSection);
> + auto NextSec = std::find_if(I, E, IsOutputSec);
> if (NextSec == E)
> return E;
>
> @@ -1077,8 +1072,6 @@
>
> static void sortSection(OutputSection *Sec,
> const DenseMap<const InputSectionBase *, int> &Order) {
> - if (!Sec->Live)
> - return;
> StringRef Name = Sec->Name;
>
> // Sort input sections by section name suffixes for
> @@ -1186,7 +1179,7 @@
> auto E = Script->SectionCommands.end();
> auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
> if (auto *Sec = dyn_cast<OutputSection>(Base))
> - return Sec->Live && Sec->SectionIndex == INT_MAX;
> + return Sec->SectionIndex == INT_MAX;
> return false;
> });
>
> @@ -1505,7 +1498,6 @@
> removeUnusedSyntheticSections();
>
> sortSections();
> - Script->removeEmptyCommands();
>
> // Now that we have the final list, create a list of all the
> // OutputSections for convenience.
> Index: ELF/LinkerScript.h
> ===================================================================
> --- ELF/LinkerScript.h
> +++ ELF/LinkerScript.h
> @@ -254,7 +254,6 @@
> ExprValue getSymbolValue(StringRef Name, const Twine &Loc);
>
> void addOrphanSections();
> - void removeEmptyCommands();
> void adjustSectionsBeforeSorting();
> void adjustSectionsAfterSorting();
>
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -752,21 +752,12 @@
> }
> }
>
> -void LinkerScript::removeEmptyCommands() {
> - // It is common practice to use very generic linker scripts. So for any
> - // given run some of the output sections in the script will be empty.
> - // We could create corresponding empty output sections, but that would
> - // clutter the output.
> - // We instead remove trivially empty sections. The bfd linker seems even
> - // more aggressive at removing them.
> - llvm::erase_if(SectionCommands, [&](BaseCommand *Base) {
> - if (auto *Sec = dyn_cast<OutputSection>(Base))
> - return !Sec->Live;
> +static bool isAllSectionDescription(const OutputSection &Cmd) {
> + // We do not remove empty sections that are explicitly
> + // assigned to any segment.
> + if (!Cmd.Phdrs.empty())
> return false;
> - });
> -}
>
> -static bool isAllSectionDescription(const OutputSection &Cmd) {
> for (BaseCommand *Base : Cmd.SectionCommands)
> if (!isa<InputSectionDescription>(*Base))
> return false;
> @@ -796,29 +787,34 @@
> // the previous sections. Only a few flags are needed to keep the impact low.
> uint64_t Flags = SHF_ALLOC;
>
> - for (BaseCommand *Cmd : SectionCommands) {
> + for (BaseCommand *&Cmd : SectionCommands) {
> auto *Sec = dyn_cast<OutputSection>(Cmd);
> if (!Sec)
> continue;
> if (Sec->Live) {
> Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
> continue;
> }
>
> - if (isAllSectionDescription(*Sec))
> - continue;
> -
> - Sec->Live = true;
> - Sec->Flags = Flags;
> + if (!isAllSectionDescription(*Sec))
> + Sec->Flags = Flags;
> + else
> + Cmd = nullptr;
> }
> +
> + // It is common practice to use very generic linker scripts. So for any
> + // given run some of the output sections in the script will be empty.
> + // We could create corresponding empty output sections, but that would
> + // clutter the output.
> + // We instead remove trivially empty sections. The bfd linker seems even
> + // more aggressive at removing them.
> + llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; });
> }
>
> void LinkerScript::adjustSectionsAfterSorting() {
> // Try and find an appropriate memory region to assign offsets in.
> for (BaseCommand *Base : SectionCommands) {
> if (auto *Sec = dyn_cast<OutputSection>(Base)) {
> - if (!Sec->Live)
> - continue;
> if (!Sec->LMARegionName.empty()) {
> if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName))
> Sec->LMARegion = M;
More information about the llvm-commits
mailing list