[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
llvm-svn: 277583
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index c5b19845..656e646 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -131,11 +131,27 @@
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 @@
}
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 @@
InCmd->ExcludedFiles.push_back(next());
}
- if (skip("SORT")) {
+ if (skip("SORT") || skip("SORT_BY_NAME")) {
expect("(");
- InCmd->Sort = true;
- readInputFilePattern(InCmd, Keep);
+ 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("(");
+ 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;
}