forked from OSchip/llvm-project
[ELF] Heuristic for placing orphan section
Differential revision: https://reviews.llvm.org/D25325 llvm-svn: 286225
This commit is contained in:
parent
9e83e22ddf
commit
bae1c656bb
|
@ -701,6 +701,22 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||||
Sec->assignOffsets();
|
Sec->assignOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
static bool canSharePtLoad(const OutputSectionBase<ELFT> &S1,
|
||||||
|
const OutputSectionBase<ELFT> &S2) {
|
||||||
|
if (!(S1.getFlags() & SHF_ALLOC) || !(S2.getFlags() & SHF_ALLOC))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool S1IsWrite = S1.getFlags() & SHF_WRITE;
|
||||||
|
bool S2IsWrite = S2.getFlags() & SHF_WRITE;
|
||||||
|
if (S1IsWrite != S2IsWrite)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!S1IsWrite)
|
||||||
|
return true; // RO and RX share a PT_LOAD with linker scripts.
|
||||||
|
return (S1.getFlags() & SHF_EXECINSTR) == (S2.getFlags() & SHF_EXECINSTR);
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT> void Writer<ELFT>::sortSections() {
|
template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
if (!ScriptConfig->HasSections) {
|
if (!ScriptConfig->HasSections) {
|
||||||
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
||||||
|
@ -729,25 +745,46 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
// The way we define an order then is:
|
// The way we define an order then is:
|
||||||
// * First put script sections at the start and sort the script and
|
// * First put script sections at the start and sort the script and
|
||||||
// non-script sections independently.
|
// non-script sections independently.
|
||||||
// * Move each non-script section to the first position where it
|
// * Move each non-script section to its preferred position. We try
|
||||||
// compareSectionsNonScript less than the successor.
|
// to put each section in the last position where it it can share
|
||||||
|
// a PT_LOAD.
|
||||||
|
|
||||||
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
||||||
compareSections<ELFT>);
|
compareSections<ELFT>);
|
||||||
|
|
||||||
auto I = OutputSections.begin();
|
auto I = OutputSections.begin();
|
||||||
auto E = OutputSections.end();
|
auto E = OutputSections.end();
|
||||||
auto NonScriptI = std::find_if(I, E, [](OutputSectionBase<ELFT> *S) {
|
auto NonScriptI =
|
||||||
return Script<ELFT>::X->getSectionIndex(S->getName()) == INT_MAX;
|
std::find_if(OutputSections.begin(), E, [](OutputSectionBase<ELFT> *S) {
|
||||||
});
|
return Script<ELFT>::X->getSectionIndex(S->getName()) == INT_MAX;
|
||||||
|
});
|
||||||
while (NonScriptI != E) {
|
while (NonScriptI != E) {
|
||||||
auto FirstGreater =
|
auto BestPos =
|
||||||
std::find_if(I, NonScriptI, [&](OutputSectionBase<ELFT> *S) {
|
std::max_element(I, NonScriptI, [&](OutputSectionBase<ELFT> *&A,
|
||||||
return compareSectionsNonScript<ELFT>(*NonScriptI, S);
|
OutputSectionBase<ELFT> *&B) {
|
||||||
|
bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A);
|
||||||
|
bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B);
|
||||||
|
if (ACanSharePtLoad != BCanSharePtLoad)
|
||||||
|
return BCanSharePtLoad;
|
||||||
|
|
||||||
|
bool ACmp = compareSectionsNonScript<ELFT>(*NonScriptI, A);
|
||||||
|
bool BCmp = compareSectionsNonScript<ELFT>(*NonScriptI, B);
|
||||||
|
if (ACmp != BCmp)
|
||||||
|
return BCmp; // FIXME: missing test
|
||||||
|
|
||||||
|
size_t PosA = &A - &OutputSections[0];
|
||||||
|
size_t PosB = &B - &OutputSections[0];
|
||||||
|
return ACmp ? PosA > PosB : PosA < PosB;
|
||||||
});
|
});
|
||||||
std::rotate(FirstGreater, NonScriptI, NonScriptI + 1);
|
|
||||||
|
// max_element only returns NonScriptI if the range is empty. If the range
|
||||||
|
// is not empty we should consider moving the the element forward one
|
||||||
|
// position.
|
||||||
|
if (BestPos != NonScriptI &&
|
||||||
|
!compareSectionsNonScript<ELFT>(*NonScriptI, *BestPos))
|
||||||
|
++BestPos;
|
||||||
|
std::rotate(BestPos, NonScriptI, NonScriptI + 1);
|
||||||
++NonScriptI;
|
++NonScriptI;
|
||||||
++I;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# REQUIRES: x86
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||||
|
# RUN: echo "SECTIONS { \
|
||||||
|
# RUN: .text : { *(.text) } \
|
||||||
|
# RUN: .rw1 : { *(.rw1) } \
|
||||||
|
# RUN: .rw2 : { *(.rw2) } \
|
||||||
|
# RUN: .rw3 : { *(.rw3) } \
|
||||||
|
# RUN: }" > %t.script
|
||||||
|
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||||
|
# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
|
||||||
|
|
||||||
|
# CHECK: 0 00000000 0000000000000000
|
||||||
|
# CHECK-NEXT: 1 .text 00000000 0000000000000000 TEXT DATA
|
||||||
|
# CHECK-NEXT: 2 .jcr 00000008 0000000000000000 DATA
|
||||||
|
# CHECK-NEXT: 3 .rw1 00000008 0000000000000008 DATA
|
||||||
|
# CHECK-NEXT: 4 .rw2 00000008 0000000000000010 DATA
|
||||||
|
# CHECK-NEXT: 5 .rw3 00000008 0000000000000018 DATA
|
||||||
|
|
||||||
|
.section .rw1, "aw"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .rw2, "aw"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .rw3, "aw"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .jcr, "aw"
|
||||||
|
.quad 0
|
|
@ -23,9 +23,9 @@
|
||||||
# NO1-NEXT: Idx Name Size
|
# NO1-NEXT: Idx Name Size
|
||||||
# NO1-NEXT: 0 00000000
|
# NO1-NEXT: 0 00000000
|
||||||
# NO1: .writable 00000004
|
# NO1: .writable 00000004
|
||||||
|
# NO1: .foo.2 00000004
|
||||||
# NO1: .readable 00000004
|
# NO1: .readable 00000004
|
||||||
# NO1: .foo.1 00000004
|
# NO1: .foo.1 00000004
|
||||||
# NO1: .foo.2 00000004
|
|
||||||
|
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
|
|
Loading…
Reference in New Issue