[lld] r282118 - Once more unto the strict weak ordering, once more.
Eugene Leviant via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 22 01:44:39 PDT 2016
This breaks things for me (I'm getting extra PT_LOAD, because RO
orphans are placed in the beginning of the section list), so I wonder
why don't you simply put RO orphans after RO sections, RW after RW and
so on?
2016-09-22 1:36 GMT+03:00 Rafael Espindola via llvm-commits
<llvm-commits at lists.llvm.org>:
> Author: rafael
> Date: Wed Sep 21 17:36:19 2016
> New Revision: 282118
>
> URL: http://llvm.org/viewvc/llvm-project?rev=282118&view=rev
> Log:
> Once more unto the strict weak ordering, once more.
>
> This should finally give a stable sorting over all implementations.
>
> Added:
> lld/trunk/test/ELF/linkerscript/sections-sort.s
> Modified:
> lld/trunk/ELF/Writer.cpp
> lld/trunk/test/ELF/linkerscript/sections.s
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=282118&r1=282117&r2=282118&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Wed Sep 21 17:36:19 2016
> @@ -51,6 +51,7 @@ private:
> void forEachRelSec(
> std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
> Fn);
> + void sortSections();
> void finalizeSections();
> void addPredefinedSections();
> bool needsGot();
> @@ -435,12 +436,10 @@ template <class ELFT> bool elf::isRelroS
> S == ".eh_frame";
> }
>
> -// Output section ordering is determined by this function.
> template <class ELFT>
> -static bool compareSections(OutputSectionBase<ELFT> *A,
> - OutputSectionBase<ELFT> *B) {
> +static bool compareSectionsNonScript(OutputSectionBase<ELFT> *A,
> + OutputSectionBase<ELFT> *B) {
> typedef typename ELFT::uint uintX_t;
> -
> uintX_t AFlags = A->getFlags();
> uintX_t BFlags = B->getFlags();
>
> @@ -451,19 +450,10 @@ static bool compareSections(OutputSectio
> if (AIsAlloc != BIsAlloc)
> return AIsAlloc;
>
> - // If A and B are mentioned in linker script, use that order.
> - int AIndex = Script<ELFT>::X->getSectionIndex(A->getName());
> - int BIndex = Script<ELFT>::X->getSectionIndex(B->getName());
> - bool AInScript = AIndex != INT_MAX;
> - bool BInScript = BIndex != INT_MAX;
> - if (AInScript && BInScript)
> - return AIndex < BIndex;
> -
> // We don't have any special requirements for the relative order of two non
> // allocatable sections.
> - // Just put linker script sections first to satisfy strict weak ordering.
> if (!AIsAlloc)
> - return AInScript;
> + return false;
>
> // We want the read only sections first so that they go in the PT_LOAD
> // covering the program headers at the start of the file.
> @@ -512,8 +502,25 @@ static bool compareSections(OutputSectio
> return getPPC64SectionRank(A->getName()) <
> getPPC64SectionRank(B->getName());
>
> - // Just put linker script sections first to satisfy strict weak ordering.
> - return AInScript;
> + return false;
> +}
> +
> +// Output section ordering is determined by this function.
> +template <class ELFT>
> +static bool compareSections(OutputSectionBase<ELFT> *A,
> + OutputSectionBase<ELFT> *B) {
> + // For now, put sections mentioned in a linker script first.
> + int AIndex = Script<ELFT>::X->getSectionIndex(A->getName());
> + int BIndex = Script<ELFT>::X->getSectionIndex(B->getName());
> + bool AInScript = AIndex != INT_MAX;
> + bool BInScript = BIndex != INT_MAX;
> + if (AInScript != BInScript)
> + return AInScript;
> + // If both are in the script, use that order.
> + if (AInScript)
> + return AIndex < BIndex;
> +
> + return compareSectionsNonScript(A, B);
> }
>
> template <class ELFT> static bool isDiscarded(InputSectionBase<ELFT> *S) {
> @@ -710,6 +717,55 @@ template <class ELFT> void Writer<ELFT>:
> Sec->assignOffsets();
> }
>
> +template <class ELFT> void Writer<ELFT>::sortSections() {
> + if (!ScriptConfig->HasSections) {
> + std::stable_sort(OutputSections.begin(), OutputSections.end(),
> + compareSectionsNonScript<ELFT>);
> + return;
> + }
> +
> + // The order of the sections in the script is arbitrary and may not agree with
> + // compareSectionsNonScript. This means that we cannot easily define a
> + // strict weak ordering. To see why, consider a comparison of a section in the
> + // script and one not in the script. We have a two simple options:
> + // * Make them equivalent (a is not less than b, and b is not less than a).
> + // The problem is then that equivalence has to be transitive and we can
> + // have sections a, b and c with only b in a script and a less than c
> + // which breaks this property.
> + // * Use compareSectionsNonScript. Given that the script order doesn't have
> + // to match, we can end up with sections a, b, c, d where b and c are in the
> + // script and c is compareSectionsNonScript less than b. In which case d
> + // can be equivalent to c, a to b and d < a. As a concrete example:
> + // .a (rx) # not in script
> + // .b (rx) # in script
> + // .c (ro) # in script
> + // .d (ro) # not in script
> + //
> + // The way we define an order then is:
> + // * First put script sections at the start and sort the script and
> + // non-script sections independently.
> + // * Move each non-script section to the first position where it
> + // compareSectionsNonScript less than the successor.
> +
> + std::stable_sort(OutputSections.begin(), OutputSections.end(),
> + compareSections<ELFT>);
> +
> + auto I = OutputSections.begin();
> + auto E = OutputSections.end();
> + auto NonScriptI = std::find_if(I, E, [](OutputSectionBase<ELFT> *S) {
> + return Script<ELFT>::X->getSectionIndex(S->getName()) == INT_MAX;
> + });
> + while (NonScriptI != E) {
> + auto FirstGreater =
> + std::find_if(I, NonScriptI, [&](OutputSectionBase<ELFT> *S) {
> + return compareSectionsNonScript<ELFT>(*NonScriptI, S);
> + });
> + std::rotate(FirstGreater, NonScriptI, NonScriptI + 1);
> + ++NonScriptI;
> + ++I;
> + }
> +}
> +
> // Create output section objects and add them to OutputSections.
> template <class ELFT> void Writer<ELFT>::finalizeSections() {
> Out<ELFT>::PreinitArray = findSection(".preinit_array");
> @@ -783,8 +839,7 @@ template <class ELFT> void Writer<ELFT>:
> // This function adds linker-created Out<ELFT>::* sections.
> addPredefinedSections();
>
> - std::stable_sort(OutputSections.begin(), OutputSections.end(),
> - compareSections<ELFT>);
> + sortSections();
>
> unsigned I = 1;
> for (OutputSectionBase<ELFT> *Sec : OutputSections) {
>
> Added: lld/trunk/test/ELF/linkerscript/sections-sort.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sections-sort.s?rev=282118&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/linkerscript/sections-sort.s (added)
> +++ lld/trunk/test/ELF/linkerscript/sections-sort.s Wed Sep 21 17:36:19 2016
> @@ -0,0 +1,29 @@
> +# REQUIRES: x86
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> +
> +# RUN: echo "SECTIONS { \
> +# RUN: .text : { *(.text) } \
> +# RUN: foo : { *(foo) } \
> +# RUN: } " > %t.script
> +# RUN: ld.lld -o %t --script %t.script %t.o -shared
> +# RUN: llvm-objdump --section-headers %t | FileCheck %s
> +
> +# Test the section order. This is a case where at least with libstdc++'s
> +# stable_sort we used to get a different result.
> +
> +nop
> +
> +.section foo, "a"
> +.byte 0
> +
> +# CHECK: Id
> +# CHECK-NEXT: 0
> +# CHECK-NEXT: 1 .dynsym
> +# CHECK-NEXT: 2 .hash
> +# CHECK-NEXT: 3 .dynstr
> +# CHECK-NEXT: 4 .text
> +# CHECK-NEXT: 5 foo
> +# CHECK-NEXT: 6 .dynamic
> +# CHECK-NEXT: 7 .symtab
> +# CHECK-NEXT: 8 .shstrtab
> +# CHECK-NEXT: 9 .strtab
>
> Modified: lld/trunk/test/ELF/linkerscript/sections.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sections.s?rev=282118&r1=282117&r2=282118&view=diff
> ==============================================================================
> --- lld/trunk/test/ELF/linkerscript/sections.s (original)
> +++ lld/trunk/test/ELF/linkerscript/sections.s Wed Sep 21 17:36:19 2016
> @@ -42,12 +42,12 @@
> # Idx Name Size
> # SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
> # SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
> -# SEC-ORDER: 3 .data 00000020 {{[0-9a-f]*}} DATA
> -# SEC-ORDER: 4 .text 0000000e {{[0-9a-f]*}} TEXT DATA
> -# SEC-ORDER: 5 .shstrtab 00000002 {{[0-9a-f]*}}
> -# SEC-ORDER: 6 .shstrtab 00000032 {{[0-9a-f]*}}
> -# SEC-ORDER: 7 .symtab 00000030 {{[0-9a-f]*}}
> -# SEC-ORDER: 8 .strtab 00000008 {{[0-9a-f]*}}
> +# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
> +# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
> +# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
> +# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
> +# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
> +# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT DATA
>
> # .text and .data have swapped names but proper sizes and types.
> # RUN: echo "SECTIONS { \
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list