summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp1
-rw-r--r--lld/ELF/OutputSections.cpp21
-rw-r--r--lld/ELF/OutputSections.h3
-rw-r--r--lld/ELF/Writer.cpp5
5 files changed, 26 insertions, 5 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index fd7dbc2239b..ade684c1c17 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -88,6 +88,7 @@ struct Configuration {
bool Verbose;
bool VersionScript = false;
bool WarnCommon;
+ bool ZCombreloc;
bool ZExecStack;
bool ZNodelete;
bool ZNow;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 9a6be7dc988..f23db3d5fcc 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -352,6 +352,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
if (Config->LtoJobs == 0)
error("number of threads must be > 0");
+ Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
Config->ZExecStack = hasZOption(Args, "execstack");
Config->ZNodelete = hasZOption(Args, "nodelete");
Config->ZNow = hasZOption(Args, "now");
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 9a44339a5c1..676eb8029ef 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -301,9 +301,10 @@ template <class ELFT> void PltSection<ELFT>::finalize() {
}
template <class ELFT>
-RelocationSection<ELFT>::RelocationSection(StringRef Name)
+RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)
: OutputSectionBase<ELFT>(Name, Config->Rela ? SHT_RELA : SHT_REL,
- SHF_ALLOC) {
+ SHF_ALLOC),
+ Sort(Sort) {
this->Header.sh_entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
this->Header.sh_addralign = sizeof(uintX_t);
}
@@ -313,7 +314,13 @@ void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) {
Relocs.push_back(Reloc);
}
+template <class ELFT, class RelTy>
+static bool compRelocations(const RelTy &A, const RelTy &B) {
+ return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL);
+}
+
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
+ uint8_t *BufBegin = Buf;
for (const DynamicReloc<ELFT> &Rel : Relocs) {
auto *P = reinterpret_cast<Elf_Rela *>(Buf);
Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
@@ -325,6 +332,16 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
uint32_t SymIdx = (!Rel.UseSymVA && Sym) ? Sym->DynsymIndex : 0;
P->setSymbolAndType(SymIdx, Rel.Type, Config->Mips64EL);
}
+
+ if (Sort) {
+ if (Config->Rela)
+ std::stable_sort((Elf_Rela *)BufBegin,
+ (Elf_Rela *)BufBegin + Relocs.size(),
+ compRelocations<ELFT, Elf_Rela>);
+ else
+ std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(),
+ compRelocations<ELFT, Elf_Rel>);
+ }
}
template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index d8c0e5b7484..b94f76588e6 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -274,7 +274,7 @@ class RelocationSection final : public OutputSectionBase<ELFT> {
typedef typename ELFT::uint uintX_t;
public:
- RelocationSection(StringRef Name);
+ RelocationSection(StringRef Name, bool Sort);
void addReloc(const DynamicReloc<ELFT> &Reloc);
unsigned getRelocOffset();
void finalize() override;
@@ -284,6 +284,7 @@ public:
bool Static = false;
private:
+ bool Sort;
std::vector<DynamicReloc<ELFT>> Relocs;
};
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c568d7144e7..4c9be04e42a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -129,7 +129,8 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
GotSection<ELFT> Got;
InterpSection<ELFT> Interp;
PltSection<ELFT> Plt;
- RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn");
+ RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn",
+ Config->ZCombreloc);
StringTableSection<ELFT> DynStrTab(".dynstr", true);
StringTableSection<ELFT> ShStrTab(".shstrtab", false);
SymbolTableSection<ELFT> DynSymTab(*Symtab, DynStrTab);
@@ -165,7 +166,7 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
if (Target->UseLazyBinding) {
StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt";
GotPlt.reset(new GotPltSection<ELFT>);
- RelaPlt.reset(new RelocationSection<ELFT>(S));
+ RelaPlt.reset(new RelocationSection<ELFT>(S, false /*Sort*/));
}
if (!Config->StripAll) {
StrTab.reset(new StringTableSection<ELFT>(".strtab", false));
OpenPOWER on IntegriCloud