[lld] r277583 - [ELF] - Linkerscript: support all kinds of sorting (including nested).

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 3 01:36:00 PDT 2016


Author: grimar
Date: Wed Aug  3 03:35:59 2016
New Revision: 277583

URL: http://llvm.org/viewvc/llvm-project?rev=277583&view=rev
Log:
[ELF] - Linkerscript: support all kinds of sorting (including nested).

Previously we supported only sorting by name.

When there are nested section sorting commands in linker script, there can be at most 1
level of nesting for section sorting commands.

SORT_BY_NAME (SORT_BY_ALIGNMENT (wildcard section pattern)). It will sort the input
sections by name first, then by alignment if 2 sections have the same name.

SORT_BY_ALIGNMENT (SORT_BY_NAME (wildcard section pattern)). It will sort the input
sections by alignment first, then by name if 2 sections have the same alignment.

SORT_BY_NAME (SORT_BY_NAME (wildcard section pattern)) is treated the same as SORT_
BY_NAME (wildcard section pattern).

SORT_BY_ALIGNMENT (SORT_BY_ALIGNMENT (wildcard section pattern)) is treated the
same as SORT_BY_ALIGNMENT (wildcard section pattern).

All other nested section sorting commands are invalid.

Patch implements that all above.

Differential revision: https://reviews.llvm.org/D23019

Added:
    lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s
    lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s
    lld/trunk/test/ELF/linkerscript/linkerscript-sort.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=277583&r1=277582&r2=277583&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Aug  3 03:35:59 2016
@@ -131,11 +131,27 @@ static void addSection(OutputSectionFact
   Sec->addSection(C);
 }
 
-template <class ELFT>
-static bool compareByName(InputSectionBase<ELFT> *A,
-                          InputSectionBase<ELFT> *B) {
-  return A->getSectionName() < B->getSectionName();
-}
+template <class ELFT> struct SectionsSorter {
+  SectionsSorter(SortKind Kind) : Kind(Kind) {}
+  bool operator()(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
+    int AlignmentCmp = A->Alignment - B->Alignment;
+    if (Kind == SortKind::Align || (Kind == SortKind::AlignName && AlignmentCmp != 0))
+      return AlignmentCmp < 0;
+
+    int NameCmp = A->getSectionName().compare(B->getSectionName());
+    if (Kind == SortKind::Name || (Kind == SortKind::NameAlign && NameCmp != 0))
+      return NameCmp < 0;
+
+    if (Kind == SortKind::NameAlign)
+      return AlignmentCmp < 0;
+    if (Kind == SortKind::AlignName)
+      return NameCmp < 0;
+
+    llvm_unreachable("unknown section sort kind in predicate");
+    return false;
+  }
+  SortKind Kind;
+};
 
 template <class ELFT>
 void LinkerScript<ELFT>::createSections(
@@ -155,8 +171,9 @@ void LinkerScript<ELFT>::createSections(
       }
       Sections.push_back(S);
     }
-    if (I->Sort)
-      std::stable_sort(Sections.begin(), Sections.end(), compareByName<ELFT>);
+    if (I->Sort != SortKind::None)
+      std::stable_sort(Sections.begin(), Sections.end(),
+                       SectionsSorter<ELFT>(I->Sort));
     for (InputSectionBase<ELFT> *S : Sections)
       addSection(Factory, *Out, S, OutputName);
   }
@@ -715,10 +732,32 @@ void ScriptParser::readInputSectionRules
       InCmd->ExcludedFiles.push_back(next());
   }
 
-  if (skip("SORT")) {
+  if (skip("SORT") || skip("SORT_BY_NAME")) {
+    expect("(");
+    if (skip("SORT_BY_ALIGNMENT")) {
+      InCmd->Sort = SortKind::NameAlign;
+      expect("(");
+      readInputFilePattern(InCmd, Keep);
+      expect(")");
+    } else {
+      InCmd->Sort = SortKind::Name;
+      readInputFilePattern(InCmd, Keep);
+    }
+    expect(")");
+    return;
+  }
+
+  if (skip("SORT_BY_ALIGNMENT")) {
     expect("(");
-    InCmd->Sort = true;
-    readInputFilePattern(InCmd, Keep);
+    if (skip("SORT") || skip("SORT_BY_NAME")) {
+      InCmd->Sort = SortKind::AlignName;
+      expect("(");
+      readInputFilePattern(InCmd, Keep);
+      expect(")");
+    } else {
+      InCmd->Sort = SortKind::Align;
+      readInputFilePattern(InCmd, Keep);
+    }
     expect(")");
     return;
   }

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=277583&r1=277582&r2=277583&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Aug  3 03:35:59 2016
@@ -87,11 +87,13 @@ struct OutputSectionCommand : BaseComman
   ConstraintKind Constraint = ConstraintKind::NoConstraint;
 };
 
+enum class SortKind { None, Name, Align, NameAlign, AlignName };
+
 struct InputSectionDescription : BaseCommand {
   InputSectionDescription() : BaseCommand(InputSectionKind) {}
   static bool classof(const BaseCommand *C);
   StringRef FilePattern;
-  bool Sort = false;
+  SortKind Sort = SortKind::None;
   std::vector<StringRef> ExcludedFiles;
   std::vector<StringRef> SectionPatterns;
 };

Added: lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s?rev=277583&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s (added)
+++ lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s Wed Aug  3 03:35:59 2016
@@ -0,0 +1,7 @@
+.section .aaa.1, "a"
+.align 16
+.quad 0x11
+
+.section .aaa.2, "a"
+.align 4
+.quad 0x22

Modified: lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s?rev=277583&r1=277582&r2=277583&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s (original)
+++ lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s Wed Aug  3 03:35:59 2016
@@ -1,14 +1,19 @@
 .section .aaa.5, "a"
+.align 2
 .quad 0x55
 
 .section .aaa.1, "a"
+.align 32
 .quad 0x11
 
 .section .aaa.3, "a"
+.align 8
 .quad 0x33
 
 .section .aaa.2, "a"
+.align 16
 .quad 0x22
 
 .section .aaa.4, "a"
+.align 4
 .quad 0x44

Added: lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s?rev=277583&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s (added)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s Wed Aug  3 03:35:59 2016
@@ -0,0 +1,42 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN:   %p/Inputs/linkerscript-sort-nested.s -o %t2.o
+
+## Check sorting first by alignment and then by name.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.aaa.*))) } }" > %t1.script
+# RUN: ld.lld -o %t1 --script %t1.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=SORTED_AN %s
+# SORTED_AN:      Contents of section .aaa:
+# SORTED_AN-NEXT:  0120 02000000 00000000 22000000 00000000
+# SORTED_AN-NEXT:  0130 11000000 00000000 00000000 00000000
+# SORTED_AN-NEXT:  0140 55000000 00000000 00000000 00000000
+# SORTED_AN-NEXT:  0150 00000000 00000000 00000000 00000000
+# SORTED_AN-NEXT:  0160 01000000 00000000
+
+## Check sorting first by name and then by alignment.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(SORT_BY_ALIGNMENT(.aaa.*))) } }" > %t2.script
+# RUN: ld.lld -o %t2 --script %t2.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SORTED_NA %s
+# SORTED_NA:      Contents of section .aaa:
+# SORTED_NA-NEXT:  0120 11000000 00000000 00000000 00000000
+# SORTED_NA-NEXT:  0130 00000000 00000000 00000000 00000000
+# SORTED_NA-NEXT:  0140 01000000 00000000 02000000 00000000
+# SORTED_NA-NEXT:  0150 22000000 00000000 00000000 00000000
+# SORTED_NA-NEXT:  0160 55000000 00000000
+
+.global _start
+_start:
+ nop
+
+.section .aaa.1, "a"
+.align 32
+.quad 1
+
+.section .aaa.2, "a"
+.align 2
+.quad 2
+
+.section .aaa.5, "a"
+.align 16
+.quad 0x55

Modified: lld/trunk/test/ELF/linkerscript/linkerscript-sort.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sort.s?rev=277583&r1=277582&r2=277583&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-sort.s (original)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-sort.s Wed Aug  3 03:35:59 2016
@@ -6,12 +6,14 @@
 # RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t1.script
 # RUN: ld.lld -o %t1 --script %t1.script %t2.o %t1.o
 # RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=UNSORTED %s
-# UNSORTED:      Contents of section .aaa:
-# UNSORTED-NEXT:   0120 55000000 00000000 11000000 00000000
-# UNSORTED-NEXT:   0130 33000000 00000000 22000000 00000000
-# UNSORTED-NEXT:   0140 44000000 00000000 05000000 00000000
-# UNSORTED-NEXT:   0150 01000000 00000000 03000000 00000000
-# UNSORTED-NEXT:   0160 02000000 00000000 04000000 00000000
+# UNSORTED:       Contents of section .aaa:
+# UNSORTED-NEXT:   0120 55000000 00000000 00000000 00000000
+# UNSORTED-NEXT:   0130 00000000 00000000 00000000 00000000
+# UNSORTED-NEXT:   0140 11000000 00000000 33000000 00000000
+# UNSORTED-NEXT:   0150 22000000 00000000 44000000 00000000
+# UNSORTED-NEXT:   0160 05000000 00000000 01000000 00000000
+# UNSORTED-NEXT:   0170 03000000 00000000 02000000 00000000
+# UNSORTED-NEXT:   0180 04000000 00000000
 
 ## Check that SORT works (sorted by name of section).
 # RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t2.script
@@ -21,8 +23,10 @@
 # SORTED_A-NEXT:  0120 11000000 00000000 01000000 00000000
 # SORTED_A-NEXT:  0130 22000000 00000000 02000000 00000000
 # SORTED_A-NEXT:  0140 33000000 00000000 03000000 00000000
-# SORTED_A-NEXT:  0150 44000000 00000000 04000000 00000000
-# SORTED_A-NEXT:  0160 55000000 00000000 05000000 00000000
+# SORTED_A-NEXT:  0150 44000000 00000000 00000000 00000000
+# SORTED_A-NEXT:  0160 04000000 00000000 55000000 00000000
+# SORTED_A-NEXT:  0170 00000000 00000000 00000000 00000000
+# SORTED_A-NEXT:  0180 05000000 00000000
 
 ## When we switch the order of files, check that sorting by
 ## section names is stable.
@@ -30,32 +34,59 @@
 # RUN: ld.lld -o %t3 --script %t3.script %t1.o %t2.o
 # RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_B %s
 # SORTED_B:      Contents of section .aaa:
-# SORTED_B-NEXT:  0120 01000000 00000000 11000000 00000000
-# SORTED_B-NEXT:  0130 02000000 00000000 22000000 00000000
-# SORTED_B-NEXT:  0140 03000000 00000000 33000000 00000000
-# SORTED_B-NEXT:  0150 04000000 00000000 44000000 00000000
-# SORTED_B-NEXT:  0160 05000000 00000000 55000000 00000000
+# SORTED_B-NEXT:  0120 01000000 00000000 00000000 00000000
+# SORTED_B-NEXT:  0130 00000000 00000000 00000000 00000000
+# SORTED_B-NEXT:  0140 11000000 00000000 02000000 00000000
+# SORTED_B-NEXT:  0150 22000000 00000000 03000000 00000000
+# SORTED_B-NEXT:  0160 33000000 00000000 00000000 00000000
+# SORTED_B-NEXT:  0170 04000000 00000000 44000000 00000000
+# SORTED_B-NEXT:  0180 05000000 00000000 55000000 00000000
 
 ## Check that SORT surrounded with KEEP also works.
 # RUN: echo "SECTIONS { .aaa : { KEEP (*(SORT(.aaa.*))) } }" > %t3.script
 # RUN: ld.lld -o %t3 --script %t3.script %t2.o %t1.o
 # RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_A %s
 
+## Check that SORT_BY_NAME works (SORT is alias).
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(.aaa.*)) } }" > %t4.script
+# RUN: ld.lld -o %t4 --script %t4.script %t2.o %t1.o
+# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SORTED_A %s
+
+## Check that sections ordered by alignment.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(.aaa.*)) } }" > %t5.script
+# RUN: ld.lld -o %t5 --script %t5.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t5 | FileCheck -check-prefix=SORTED_ALIGNMENT %s
+# SORTED_ALIGNMENT:      Contents of section .aaa:
+# SORTED_ALIGNMENT-NEXT:   0120 01000000 00000000 55000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0130 02000000 00000000 44000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0140 03000000 00000000 33000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0150 04000000 00000000 00000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0160 22000000 00000000 00000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0170 00000000 00000000 00000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0180 05000000 00000000 00000000 00000000
+# SORTED_ALIGNMENT-NEXT:   0190 00000000 00000000 00000000 00000000
+# SORTED_ALIGNMENT-NEXT:   01a0 11000000 00000000                  
+
 .global _start
 _start:
  nop
 
 .section .aaa.5, "a"
+.align 32
 .quad 5
 
 .section .aaa.1, "a"
+.align 2
 .quad 1
 
 .section .aaa.3, "a"
+.align 8
 .quad 3
 
 .section .aaa.2, "a"
+.align 4
 .quad 2
 
 .section .aaa.4, "a"
+.align 16
 .quad 4




More information about the llvm-commits mailing list