[ELF] - Linkerscript: Implemented SORT command.
When the SORT keyword is used, the linker will sort the files or sections into ascending order by name before placing them in the output file.
It is used in FreeBSD script:
https://svnweb.freebsd.org/base/head/sys/conf/ldscript.amd64?revision=284870&view=markup#l139
This is PR28689.
Differential revision: https://reviews.llvm.org/D22749
llvm-svn: 277153
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 097375a..ed47c74 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -132,11 +132,18 @@
}
template <class ELFT>
+static bool compareByName(InputSectionBase<ELFT> *A,
+ InputSectionBase<ELFT> *B) {
+ return A->getSectionName() < B->getSectionName();
+}
+
+template <class ELFT>
std::vector<OutputSectionBase<ELFT> *>
LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
std::vector<OutputSectionBase<ELFT> *> Ret;
for (auto &P : getSectionMap()) {
+ std::vector<InputSectionBase<ELFT> *> Sections;
StringRef OutputName = P.first;
const InputSectionDescription *I = P.second;
for (InputSectionBase<ELFT> *S : getInputSections(I)) {
@@ -145,8 +152,12 @@
reportDiscarded(S);
continue;
}
- addSection(Factory, Ret, S, OutputName);
+ Sections.push_back(S);
}
+ if (I->Sort)
+ std::stable_sort(Sections.begin(), Sections.end(), compareByName<ELFT>);
+ for (InputSectionBase<ELFT> *S : Sections)
+ addSection(Factory, Ret, S, OutputName);
}
// Add all other input sections, which are not listed in script.
@@ -444,6 +455,7 @@
std::vector<uint8_t> readOutputSectionFiller();
std::vector<StringRef> readOutputSectionPhdrs();
std::unique_ptr<InputSectionDescription> readInputSectionDescription();
+ void readInputFilePattern(InputSectionDescription *InCmd, bool Keep);
void readInputSectionRules(InputSectionDescription *InCmd, bool Keep);
unsigned readPhdrType();
void readProvide(bool Hidden);
@@ -674,7 +686,17 @@
.Default(-1);
}
-void ScriptParser::readInputSectionRules(InputSectionDescription *InCmd, bool Keep) {
+void ScriptParser::readInputFilePattern(InputSectionDescription *InCmd,
+ bool Keep) {
+ while (!Error && !skip(")")) {
+ if (Keep)
+ Opt.KeptSections.push_back(peek());
+ InCmd->SectionPatterns.push_back(next());
+ }
+}
+
+void ScriptParser::readInputSectionRules(InputSectionDescription *InCmd,
+ bool Keep) {
InCmd->FilePattern = next();
expect("(");
@@ -684,11 +706,15 @@
InCmd->ExcludedFiles.push_back(next());
}
- while (!Error && !skip(")")) {
- if (Keep)
- Opt.KeptSections.push_back(peek());
- InCmd->SectionPatterns.push_back(next());
+ if (skip("SORT")) {
+ expect("(");
+ InCmd->Sort = true;
+ readInputFilePattern(InCmd, Keep);
+ expect(")");
+ return;
}
+
+ readInputFilePattern(InCmd, Keep);
}
std::unique_ptr<InputSectionDescription>