mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 16:50:51 +08:00
[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:
@@ -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 *,
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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); });
|
||||
|
||||
23
lld/test/ELF/linkerscript/symbol-ordering-file.s
Normal file
23
lld/test/ELF/linkerscript/symbol-ordering-file.s
Normal 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
|
||||
Reference in New Issue
Block a user