#ifndef LLD_ELF_CONFIG_H
#define LLD_ELF_CONFIG_H
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ELF.h"
struct Configuration {
InputFile *FirstElf = nullptr;
uint8_t OSABI = 0;
+ llvm::DenseMap<llvm::CachedHashStringRef, unsigned> SymbolOrderingFile;
llvm::StringMap<uint64_t> SectionStartMap;
llvm::StringRef DynamicLinker;
llvm::StringRef Entry;
return SortSectionPolicy::Default;
}
+// Parse the --symbol-ordering-file argument. File has form:
+// symbolName1
+// [...]
+// symbolNameN
+static void parseSymbolOrderingList(MemoryBufferRef MB) {
+ unsigned I = 0;
+ SmallVector<StringRef, 0> Arr;
+ MB.getBuffer().split(Arr, '\n');
+ for (StringRef S : Arr)
+ Config->SymbolOrderingFile.insert({CachedHashStringRef(S.trim()), I++});
+}
+
// Initializes Config members by the command line options.
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_L))
if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
parseDynamicList(*Buffer);
+ if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ parseSymbolOrderingList(*Buffer);
+
for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
Config->DynamicList.push_back(Arg->getValue());
def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
+def symbol_ordering_file: S<"symbol-ordering-file">,
+ HelpText<"Layout sections in the order specified by symbol file">;
+
def sysroot: J<"sysroot=">, HelpText<"Set the system root">;
def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
#include "LinkerScript.h"
#include "Memory.h"
#include "Strings.h"
+#include "SymbolListFile.h"
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "Target.h"
this->Size = Off;
}
-// Sorts input sections by section name suffixes, so that .foo.N comes
-// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
-// We want to keep the original order if the priorities are the same
-// because the compiler keeps the original initialization order in a
-// translation unit and we need to respect that.
-// For more detail, read the section of the GCC's manual about init_priority.
-template <class ELFT> void OutputSection<ELFT>::sortInitFini() {
- // Sort sections by priority.
- typedef std::pair<int, InputSection<ELFT> *> Pair;
+template <class ELFT>
+void OutputSection<ELFT>::sort(
+ std::function<unsigned(InputSection<ELFT> *S)> Order) {
+ typedef std::pair<unsigned, InputSection<ELFT> *> Pair;
auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
std::vector<Pair> V;
for (InputSection<ELFT> *S : Sections)
- V.push_back({getPriority(S->Name), S});
+ V.push_back({Order(S), S});
std::stable_sort(V.begin(), V.end(), Comp);
Sections.clear();
for (Pair &P : V)
Sections.push_back(P.second);
}
+// Sorts input sections by section name suffixes, so that .foo.N comes
+// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
+// We want to keep the original order if the priorities are the same
+// because the compiler keeps the original initialization order in a
+// translation unit and we need to respect that.
+// For more detail, read the section of the GCC's manual about init_priority.
+template <class ELFT> void OutputSection<ELFT>::sortInitFini() {
+ // Sort sections by priority.
+ sort([](InputSection<ELFT> *S) { return getPriority(S->Name); });
+}
+
// Returns true if S matches /Filename.?\.o$/.
static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
if (!S.endswith(".o"))
typedef typename ELFT::uint uintX_t;
OutputSection(StringRef Name, uint32_t Type, uintX_t Flags);
void addSection(InputSectionData *C) override;
+ void sort(std::function<unsigned(InputSection<ELFT> *S)> Order);
void sortInitFini();
void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
{Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0});
}
-template <class ELFT>
-static StringRef getSymbolName(const elf::ObjectFile<ELFT> &File,
- SymbolBody &Body) {
- if (Body.isLocal() && Body.getNameOffset())
- return File.getStringTable().data() + Body.getNameOffset();
- if (!Body.isLocal())
- return Body.getName();
- return "";
-}
-
template <class ELFT>
static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body,
bool IsWrite, RelExpr Expr, uint32_t Type,
// only memory. We can hack around it if we are producing an executable and
// the refered symbol can be preemepted to refer to the executable.
if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
- StringRef Name = getSymbolName(File, Body);
+ StringRef Name = getSymbolName(File.getStringTable(), Body);
error("can't create dynamic relocation " + getRelName(Type) + " against " +
(Name.empty() ? "readonly segment" : "symbol " + Name));
return Expr;
// Find a symbol at a given location.
DefinedRegular<ELFT> *Encl = getSymbolAt(&S, Offset);
if (Encl && Encl->Type == STT_FUNC) {
- StringRef Func = getSymbolName(*File, *Encl);
+ StringRef Func = getSymbolName(File->getStringTable(), *Encl);
return SrcFile + " (function " + maybeDemangle(Func) + ")";
}
outs() << B->getName() << "\n";
}
+StringRef elf::getSymbolName(StringRef SymTab, SymbolBody &Body) {
+ if (Body.isLocal() && Body.getNameOffset())
+ return SymTab.data() + Body.getNameOffset();
+ if (!Body.isLocal())
+ return Body.getName();
+ return "";
+}
+
template bool SymbolBody::hasThunk<ELF32LE>() const;
template bool SymbolBody::hasThunk<ELF32BE>() const;
template bool SymbolBody::hasThunk<ELF64LE>() const;
offsetof(Symbol, Body));
}
+StringRef getSymbolName(StringRef SymTab, SymbolBody &Body);
+
} // namespace elf
} // namespace lld
reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
}
+// Sort input sections using the list provided by --symbol-ordering-file.
+template <class ELFT>
+static void sortBySymbolsOrder(ArrayRef<OutputSectionBase *> V) {
+ if (Config->SymbolOrderingFile.empty())
+ return;
+
+ // Build sections order map from symbols list.
+ DenseMap<InputSectionBase<ELFT> *, unsigned> SectionsOrder;
+ for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
+ for (SymbolBody *Body : File->getSymbols()) {
+ auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
+ if (!D || !D->Section)
+ continue;
+ StringRef SymName = getSymbolName(File->getStringTable(), *Body);
+ auto It = Config->SymbolOrderingFile.find(CachedHashString(SymName));
+ if (It == Config->SymbolOrderingFile.end())
+ continue;
+
+ auto It2 = SectionsOrder.insert({D->Section, It->second});
+ if (!It2.second)
+ It2.first->second = std::min(It->second, It2.first->second);
+ }
+ }
+
+ for (OutputSectionBase *Base : V)
+ if (OutputSection<ELFT> *Sec = dyn_cast<OutputSection<ELFT>>(Base))
+ Sec->sort([&](InputSection<ELFT> *S) {
+ auto It = SectionsOrder.find(S);
+ return It == SectionsOrder.end() ? UINT32_MAX : It->second;
+ });
+}
+
template <class ELFT>
void Writer<ELFT>::forEachRelSec(
std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
for (InputSectionBase<ELFT> *IS : Symtab<ELFT>::X->Sections)
addInputSec(IS);
+ sortBySymbolsOrder<ELFT>(OutputSections);
sortInitFini<ELFT>(findSection(".init_array"));
sortInitFini<ELFT>(findSection(".fini_array"));
sortCtorsDtors<ELFT>(findSection(".ctors"));
--- /dev/null
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.out
+# RUN: llvm-objdump -s %t.out| FileCheck %s --check-prefix=BEFORE
+
+# BEFORE: Contents of section .foo:
+# BEFORE-NEXT: 11000 11223344 5566
+
+# RUN: echo "_foo4 " > %t_order.txt
+# RUN: echo " _foo3" >> %t_order.txt
+# RUN: echo "_foo5" >> %t_order.txt
+# RUN: echo "_foo2" >> %t_order.txt
+# RUN: echo " " >> %t_order.txt
+# RUN: echo "_foo4" >> %t_order.txt
+# RUN: echo "_bar1" >> %t_order.txt
+# RUN: echo "_foo1" >> %t_order.txt
+
+# RUN: ld.lld --symbol-ordering-file %t_order.txt %t.o -o %t2.out
+# RUN: llvm-objdump -s %t2.out| FileCheck %s --check-prefix=AFTER
+
+# AFTER: Contents of section .foo:
+# AFTER-NEXT: 11000 44335566 2211
+
+.section .foo,"ax",@progbits,unique,1
+_foo1:
+ .byte 0x11
+
+.section .foo,"ax",@progbits,unique,2
+_foo2:
+ .byte 0x22
+
+.section .foo,"ax",@progbits,unique,3
+_foo3:
+ .byte 0x33
+
+.section .foo,"ax",@progbits,unique,4
+_foo4:
+ .byte 0x44
+
+.section .foo,"ax",@progbits,unique,5
+_foo5:
+ .byte 0x55
+_bar1:
+ .byte 0x66