[lld] r281771 - [ELF] - Implemented --sort-section cmd line option and SORT_NONE script command.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 16 13:21:56 PDT 2016


Author: grimar
Date: Fri Sep 16 15:21:55 2016
New Revision: 281771

URL: http://llvm.org/viewvc/llvm-project?rev=281771&view=rev
Log:
[ELF] - Implemented --sort-section cmd line option and SORT_NONE script command.

This fixes Bug 30385 - SORT_NONE not implemented,

`SORT_NONE' disables section sorting by ignoring the command line
section sorting option.

That is why this patch also implements --sort-section option.

Description of sorting rules
available at https://sourceware.org/binutils/docs/ld/Input-Section-Wildcards.html 

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

Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/Options.td
    lld/trunk/test/ELF/linkerscript/sort-nested.s
    lld/trunk/test/ELF/linkerscript/sort.s

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Sep 16 15:21:55 2016
@@ -42,6 +42,9 @@ enum class StripPolicy { None, All, Debu
 // For --unresolved-symbols.
 enum class UnresolvedPolicy { NoUndef, ReportError, Warn, Ignore };
 
+// For --sort-section and linkerscript sorting rules.
+enum class SortSectionPolicy { None, IgnoreConfig, Alignment, Name, Priority };
+
 struct SymbolVersion {
   llvm::StringRef Name;
   bool IsExternCpp;
@@ -124,6 +127,7 @@ struct Configuration {
   bool ZOrigin;
   bool ZRelro;
   DiscardPolicy Discard;
+  SortSectionPolicy SortSection;
   StripPolicy Strip = StripPolicy::None;
   UnresolvedPolicy UnresolvedSymbols;
   BuildIdKind BuildId = BuildIdKind::None;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Sep 16 15:21:55 2016
@@ -407,6 +407,17 @@ static StringMap<uint64_t> getSectionSta
   return Ret;
 }
 
+static SortSectionPolicy getSortKind(opt::InputArgList &Args) {
+  StringRef S = getString(Args, OPT_sort_section);
+  if (S == "alignment")
+    return SortSectionPolicy::Alignment;
+  if (S == "name")
+    return SortSectionPolicy::Name;
+  if (!S.empty())
+    error("unknown --sort-section rule: " + S);
+  return SortSectionPolicy::None;
+}
+
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   for (auto *Arg : Args.filtered(OPT_L))
@@ -530,6 +541,8 @@ void LinkerDriver::readConfigs(opt::Inpu
   for (auto *Arg : Args.filtered(OPT_undefined))
     Config->Undefined.push_back(Arg->getValue());
 
+  Config->SortSection = getSortKind(Args);
+
   Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
 
   if (auto *Arg = Args.getLastArg(OPT_dynamic_list))

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Sep 16 15:21:55 2016
@@ -131,12 +131,17 @@ static bool compareAlignment(InputSectio
 }
 
 static std::function<bool(InputSectionData *, InputSectionData *)>
-getComparator(SortKind K) {
-  if (K == SortByPriority)
-    return comparePriority;
-  if (K == SortByName)
+getComparator(SortSectionPolicy K) {
+  switch (K) {
+  case SortSectionPolicy::Alignment:
+    return compareAlignment;
+  case SortSectionPolicy::Name:
     return compareName;
-  return compareAlignment;
+  case SortSectionPolicy::Priority:
+    return comparePriority;
+  default:
+    llvm_unreachable("unknown sort policy");
+  }
 }
 
 static bool checkConstraint(uint64_t Flags, ConstraintKind Kind) {
@@ -180,10 +185,10 @@ void LinkerScript<ELFT>::computeInputSec
     return;
   }
 
-  if (I->SortInner)
+  if (I->SortInner != SortSectionPolicy::None)
     std::stable_sort(I->Sections.begin(), I->Sections.end(),
                      getComparator(I->SortInner));
-  if (I->SortOuter)
+  if (I->SortOuter != SortSectionPolicy::None)
     std::stable_sort(I->Sections.begin(), I->Sections.end(),
                      getComparator(I->SortOuter));
 
@@ -704,7 +709,7 @@ private:
   void readSectionExcludes(InputSectionDescription *Cmd);
   InputSectionDescription *readInputSectionRules(StringRef FilePattern);
   unsigned readPhdrType();
-  SortKind readSortKind();
+  SortSectionPolicy readSortKind();
   SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
   SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
   void readSort();
@@ -985,14 +990,39 @@ Regex ScriptParser::readFilePatterns() {
   return compileGlobPatterns(V);
 }
 
-SortKind ScriptParser::readSortKind() {
+SortSectionPolicy ScriptParser::readSortKind() {
   if (skip("SORT") || skip("SORT_BY_NAME"))
-    return SortByName;
+    return SortSectionPolicy::Name;
   if (skip("SORT_BY_ALIGNMENT"))
-    return SortByAlignment;
+    return SortSectionPolicy::Alignment;
   if (skip("SORT_BY_INIT_PRIORITY"))
-    return SortByPriority;
-  return SortNone;
+    return SortSectionPolicy::Priority;
+  // `SORT_NONE' disables section sorting by ignoring the command line
+  // section sorting option.
+  if (skip("SORT_NONE"))
+    return SortSectionPolicy::IgnoreConfig;
+  return SortSectionPolicy::None;
+}
+
+static void selectSortKind(InputSectionDescription *Cmd) {
+  if (Cmd->SortOuter == SortSectionPolicy::IgnoreConfig) {
+    Cmd->SortOuter = SortSectionPolicy::None;
+    return;
+  }
+
+  if (Cmd->SortOuter != SortSectionPolicy::None) {
+    // If the section sorting command in linker script is nested, the command
+    // line option will be ignored.
+    if (Cmd->SortInner != SortSectionPolicy::None)
+      return;
+    // If the section sorting command in linker script isn't nested, the
+    // command line option will make the section sorting command to be treated
+    // as nested sorting command.
+    Cmd->SortInner = Config->SortSection;
+    return;
+  }
+  // If sorting rule not specified, use command line option.
+  Cmd->SortOuter = Config->SortSection;
 }
 
 // Method reads a list of sequence of excluded files and section globs given in
@@ -1031,10 +1061,12 @@ ScriptParser::readInputSectionRules(Stri
   expect("(");
 
   // Read SORT().
-  if (SortKind K1 = readSortKind()) {
+  SortSectionPolicy K1 = readSortKind();
+  if (K1 != SortSectionPolicy::None) {
     Cmd->SortOuter = K1;
     expect("(");
-    if (SortKind K2 = readSortKind()) {
+    SortSectionPolicy K2 = readSortKind();
+    if (K2 != SortSectionPolicy::None) {
       Cmd->SortInner = K2;
       expect("(");
       Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()});
@@ -1043,9 +1075,11 @@ ScriptParser::readInputSectionRules(Stri
       Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()});
     }
     expect(")");
+    selectSortKind(Cmd);
     return Cmd;
   }
 
+  selectSortKind(Cmd);
   readSectionExcludes(Cmd);
   return Cmd;
 }

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Sep 16 15:21:55 2016
@@ -10,6 +10,7 @@
 #ifndef LLD_ELF_LINKER_SCRIPT_H
 #define LLD_ELF_LINKER_SCRIPT_H
 
+#include "Config.h"
 #include "Strings.h"
 #include "Writer.h"
 #include "lld/Core/LLVM.h"
@@ -97,16 +98,14 @@ struct OutputSectionCommand : BaseComman
   ConstraintKind Constraint = ConstraintKind::NoConstraint;
 };
 
-enum SortKind { SortNone, SortByPriority, SortByName, SortByAlignment };
-
 struct InputSectionDescription : BaseCommand {
   InputSectionDescription(StringRef FilePattern)
       : BaseCommand(InputSectionKind),
         FileRe(compileGlobPatterns({FilePattern})) {}
   static bool classof(const BaseCommand *C);
   llvm::Regex FileRe;
-  SortKind SortOuter = SortNone;
-  SortKind SortInner = SortNone;
+  SortSectionPolicy SortOuter = SortSectionPolicy::None;
+  SortSectionPolicy SortInner = SortSectionPolicy::None;
   // Pairs of section regex and files excluded.
   std::list<std::pair<llvm::Regex, llvm::Regex>> SectionsVec;
   std::vector<InputSectionData *> Sections;

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Fri Sep 16 15:21:55 2016
@@ -160,6 +160,8 @@ def shared: F<"shared">, HelpText<"Build
 
 def soname: J<"soname=">, HelpText<"Set DT_SONAME">;
 
+def sort_section: S<"sort-section">, HelpText<"Specifies sections sorting rule when linkerscript is used">;
+
 def start_lib: F<"start-lib">,
   HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">;
 

Modified: lld/trunk/test/ELF/linkerscript/sort-nested.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sort-nested.s?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/sort-nested.s (original)
+++ lld/trunk/test/ELF/linkerscript/sort-nested.s Fri Sep 16 15:21:55 2016
@@ -23,6 +23,16 @@
 # SORTED_NA:   02000000 00000000 00000000 00000000
 # SORTED_NA:   55000000 00000000
 
+## If the section sorting command in linker script isn't nested, the
+## command line option will make the section sorting command to be treated
+## as nested sorting command.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(.aaa.*)) } }" > %t3.script
+# RUN: ld.lld --sort-section name -o %t3 --script %t3.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_AN %s
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(.aaa.*)) } }" > %t4.script
+# RUN: ld.lld --sort-section alignment -o %t4 --script %t4.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SORTED_NA %s
+
 .global _start
 _start:
  nop

Modified: lld/trunk/test/ELF/linkerscript/sort.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sort.s?rev=281771&r1=281770&r2=281771&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/sort.s (original)
+++ lld/trunk/test/ELF/linkerscript/sort.s Fri Sep 16 15:21:55 2016
@@ -66,6 +66,27 @@
 # SORTED_ALIGNMENT-NEXT:  0180 44000000 00000000 01000000 00000000
 # SORTED_ALIGNMENT-NEXT:  0190 55000000 00000000
 
+## SORT_NONE itself does not sort anything.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_NONE(.aaa.*)) } }" > %t6.script
+# RUN: ld.lld -o %t7 --script %t6.script %t2.o %t1.o
+# RUN: llvm-objdump -s %t7 | FileCheck -check-prefix=UNSORTED %s
+
+## Check --sort-section alignment option.
+# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t7.script
+# RUN: ld.lld --sort-section alignment -o %t8 --script %t7.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t8 | FileCheck -check-prefix=SORTED_ALIGNMENT %s
+
+## Check --sort-section name option.
+# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t8.script
+# RUN: ld.lld --sort-section name -o %t9 --script %t8.script %t1.o %t2.o
+# RUN: llvm-objdump -s %t9 | FileCheck -check-prefix=SORTED_B %s
+
+## SORT_NONE disables the --sort-section.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_NONE(.aaa.*)) } }" > %t9.script
+# RUN: ld.lld --sort-section name -o %t10 --script %t9.script %t2.o %t1.o
+# RUN: llvm-objdump -s %t10 | FileCheck -check-prefix=UNSORTED %s
+
+
 .global _start
 _start:
  nop




More information about the llvm-commits mailing list