[ELF] - Fix "--symbol-ordering-file doesn't work with linker scripts"
This is PR33889,
Patch adds support of combination of linkerscript and
-symbol-ordering-file option.
If no sorting commands are present in script inside section declaration
and no --sort-section option specified, code uses sorting from ordering
file if any exist.
Differential revision: https://reviews.llvm.org/D35843
llvm-svn: 310045
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 2f3cec3..ff084cd5 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -44,6 +44,29 @@
return (toString(Sec->File) + ":(" + Sec->Name + ")").str();
}
+template <class ELFT> DenseMap<SectionBase *, int> elf::buildSectionOrder() {
+ // Build a map from symbols to their priorities. Symbols that didn't
+ // appear in the symbol ordering file have the lowest priority 0.
+ // All explicitly mentioned symbols have negative (higher) priorities.
+ DenseMap<StringRef, int> SymbolOrder;
+ int Priority = -Config->SymbolOrderingFile.size();
+ for (StringRef S : Config->SymbolOrderingFile)
+ SymbolOrder.insert({S, Priority++});
+
+ // Build a map from sections to their priorities.
+ DenseMap<SectionBase *, int> SectionOrder;
+ for (ObjFile<ELFT> *File : ObjFile<ELFT>::Instances) {
+ for (SymbolBody *Body : File->getSymbols()) {
+ auto *D = dyn_cast<DefinedRegular>(Body);
+ if (!D || !D->Section)
+ continue;
+ int &Priority = SectionOrder[D->Section];
+ Priority = std::min(Priority, SymbolOrder.lookup(D->getName()));
+ }
+ }
+ return SectionOrder;
+}
+
template <class ELFT>
static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> *File,
const typename ELFT::Shdr *Hdr) {
@@ -982,6 +1005,11 @@
return Piece.OutputOff + Addend;
}
+template DenseMap<SectionBase *, int> elf::buildSectionOrder<ELF32LE>();
+template DenseMap<SectionBase *, int> elf::buildSectionOrder<ELF32BE>();
+template DenseMap<SectionBase *, int> elf::buildSectionOrder<ELF64LE>();
+template DenseMap<SectionBase *, int> elf::buildSectionOrder<ELF64BE>();
+
template InputSection::InputSection(ObjFile<ELF32LE> *, const ELF32LE::Shdr *,
StringRef);
template InputSection::InputSection(ObjFile<ELF32BE> *, const ELF32BE::Shdr *,
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index b51fa15..19533e7 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -331,6 +331,9 @@
// The list of all input sections.
extern std::vector<InputSectionBase *> InputSections;
+// Builds section order for handling --symbol-ordering-file.
+template <class ELFT> llvm::DenseMap<SectionBase *, int> buildSectionOrder();
+
} // namespace elf
std::string toString(const elf::InputSectionBase *);
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index d7da4a2..71d8f32 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -228,6 +228,29 @@
std::stable_sort(Begin, End, getComparator(K));
}
+static llvm::DenseMap<SectionBase *, int> getSectionOrder() {
+ switch (Config->EKind) {
+ case ELF32LEKind:
+ return buildSectionOrder<ELF32LE>();
+ case ELF32BEKind:
+ return buildSectionOrder<ELF32BE>();
+ case ELF64LEKind:
+ return buildSectionOrder<ELF64LE>();
+ case ELF64BEKind:
+ return buildSectionOrder<ELF64BE>();
+ default:
+ llvm_unreachable("unknown ELF type");
+ }
+}
+
+static void sortBySymbolOrder(InputSection **Begin, InputSection **End) {
+ if (Config->SymbolOrderingFile.empty())
+ return;
+ static llvm::DenseMap<SectionBase *, int> Order = getSectionOrder();
+ MutableArrayRef<InputSection *> In(Begin, End - Begin);
+ sortByOrder(In, [&](InputSectionBase *S) { return Order.lookup(S); });
+}
+
// Compute and remember which sections the InputSectionDescription matches.
std::vector<InputSection *>
LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
@@ -273,8 +296,15 @@
// --sort-section is handled as an inner SORT command.
// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
// 4. If no SORT command is given, sort according to --sort-section.
+ // 5. If no SORT commands are given and --sort-section is not specified,
+ // apply sorting provided by --symbol-ordering-file if any exist.
InputSection **Begin = Ret.data() + SizeBefore;
InputSection **End = Ret.data() + Ret.size();
+ if (Pat.SortOuter == SortSectionPolicy::Default &&
+ Config->SortSection == SortSectionPolicy::Default) {
+ sortBySymbolOrder(Begin, End);
+ continue;
+ }
if (Pat.SortOuter != SortSectionPolicy::None) {
if (Pat.SortInner == SortSectionPolicy::Default)
sortSections(Begin, End, Config->SortSection);
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 581a07c..c4fd7f1 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -184,6 +184,20 @@
Type == SHT_NOTE;
}
+void elf::sortByOrder(MutableArrayRef<InputSection *> In,
+ std::function<int(InputSectionBase *S)> Order) {
+ typedef std::pair<int, InputSection *> Pair;
+ auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
+
+ std::vector<Pair> V;
+ for (InputSection *S : In)
+ V.push_back({Order(S), S});
+ std::stable_sort(V.begin(), V.end(), Comp);
+
+ for (size_t I = 0; I < V.size(); ++I)
+ In[I] = V[I].second;
+}
+
void elf::reportDiscarded(InputSectionBase *IS) {
if (!Config->PrintGcSections)
return;
@@ -291,18 +305,8 @@
}
void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) {
- typedef std::pair<int, InputSection *> Pair;
- auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
-
- std::vector<Pair> V;
assert(Commands.size() == 1);
- auto *ISD = cast<InputSectionDescription>(Commands[0]);
- for (InputSection *S : ISD->Sections)
- V.push_back({Order(S), S});
- std::stable_sort(V.begin(), V.end(), Comp);
- ISD->Sections.clear();
- for (Pair &P : V)
- ISD->Sections.push_back(P.second);
+ sortByOrder(cast<InputSectionDescription>(Commands[0])->Sections, Order);
}
// Fill [Buf, Buf + Size) with Filler.
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 817c943..76adfeb 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -170,6 +170,8 @@
uint64_t getHeaderSize();
void reportDiscarded(InputSectionBase *IS);
+void sortByOrder(llvm::MutableArrayRef<InputSection *> In,
+ std::function<int(InputSectionBase *S)> Order);
extern std::vector<OutputSection *> OutputSections;
} // namespace elf
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 186f4fa..e140e0a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -872,27 +872,8 @@
if (Config->SymbolOrderingFile.empty())
return;
- // Build a map from symbols to their priorities. Symbols that didn't
- // appear in the symbol ordering file have the lowest priority 0.
- // All explicitly mentioned symbols have negative (higher) priorities.
- DenseMap<StringRef, int> SymbolOrder;
- int Priority = -Config->SymbolOrderingFile.size();
- for (StringRef S : Config->SymbolOrderingFile)
- SymbolOrder.insert({S, Priority++});
-
- // Build a map from sections to their priorities.
- DenseMap<SectionBase *, int> SectionOrder;
- for (ObjFile<ELFT> *File : ObjFile<ELFT>::Instances) {
- for (SymbolBody *Body : File->getSymbols()) {
- auto *D = dyn_cast<DefinedRegular>(Body);
- if (!D || !D->Section)
- continue;
- int &Priority = SectionOrder[D->Section];
- Priority = std::min(Priority, SymbolOrder.lookup(D->getName()));
- }
- }
-
// Sort sections by priority.
+ DenseMap<SectionBase *, int> SectionOrder = buildSectionOrder<ELFT>();
for (BaseCommand *Base : Script->Opt.Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
diff --git a/lld/test/ELF/linkerscript/symbol-ordering-file.s b/lld/test/ELF/linkerscript/symbol-ordering-file.s
new file mode 100644
index 0000000..ad6916c
--- /dev/null
+++ b/lld/test/ELF/linkerscript/symbol-ordering-file.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { .foo : { *(.foo) } }" > %t.script
+
+# RUN: ld.lld %t.o --script %t.script -o %t.out
+# RUN: llvm-objdump -s %t.out| FileCheck %s --check-prefix=BEFORE
+# BEFORE: Contents of section .foo:
+# BEFORE-NEXT: 1122
+
+# RUN: echo "_foo2" > %t.ord
+# RUN: echo "_foo1" >> %t.ord
+# RUN: ld.lld --symbol-ordering-file %t.ord %t.o --script %t.script -o %t2.out
+# RUN: llvm-objdump -s %t2.out| FileCheck %s --check-prefix=AFTER
+# AFTER: Contents of section .foo:
+# AFTER-NEXT: 2211
+
+.section .foo,"ax",@progbits,unique,1
+_foo1:
+ .byte 0x11
+
+.section .foo,"ax",@progbits,unique,2
+_foo2:
+ .byte 0x22