[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