[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
This commit is contained in:
George Rimar
2017-08-04 10:25:29 +00:00
parent 1c17001235
commit d6bcde389a
7 changed files with 102 additions and 31 deletions

View File

@@ -44,6 +44,29 @@ std::string lld::toString(const InputSectionBase *Sec) {
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 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
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 *,

View File

@@ -331,6 +331,9 @@ private:
// 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 *);

View File

@@ -228,6 +228,29 @@ static void sortSections(InputSection **Begin, InputSection **End,
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 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
// --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);

View File

@@ -184,6 +184,20 @@ static bool canMergeToProgbits(unsigned Type) {
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 @@ bool OutputSection::classof(const BaseCommand *C) {
}
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.

View File

@@ -170,6 +170,8 @@ private:
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

View File

@@ -872,27 +872,8 @@ template <class ELFT> static void sortBySymbolsOrder() {
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); });

View File

@@ -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