Finalize content of synthetic sections prior to Thunk Creation

This change moves the calls to finalizeContent() for each synthetic section
before createThunks(). This will allow us to assign addresses prior to
calling createThunks(). As addition of thunks may add to the static
symbol table and may affect the size of the mips got section we introduce a
couple of additional member functions to update these values.
    
Differential revision: https://reviews.llvm.org/D29983

llvm-svn: 297277
This commit is contained in:
Peter Smith 2017-03-08 14:06:24 +00:00
parent 3fa38a14ac
commit 1ec42d9a76
5 changed files with 56 additions and 27 deletions

View File

@ -895,7 +895,7 @@ static void mergeThunks(OutputSection *OS,
// FIXME: All Thunks are assumed to be in range of the relocation. Range
// extension Thunks are not yet supported.
template <class ELFT>
void createThunks(ArrayRef<OutputSection *> OutputSections) {
bool createThunks(ArrayRef<OutputSection *> OutputSections) {
// Track Symbols that already have a Thunk
DenseMap<SymbolBody *, Thunk<ELFT> *> ThunkedSymbols;
// Track InputSections that have a ThunkSection placed in front
@ -977,6 +977,7 @@ void createThunks(ArrayRef<OutputSection *> OutputSections) {
// Merge all created synthetic ThunkSections back into OutputSection
for (auto &KV : ThunkSections)
mergeThunks<ELFT>(KV.first, KV.second);
return !ThunkSections.empty();
}
template void scanRelocations<ELF32LE>(InputSectionBase &);
@ -984,9 +985,9 @@ template void scanRelocations<ELF32BE>(InputSectionBase &);
template void scanRelocations<ELF64LE>(InputSectionBase &);
template void scanRelocations<ELF64BE>(InputSectionBase &);
template void createThunks<ELF32LE>(ArrayRef<OutputSection *>);
template void createThunks<ELF32BE>(ArrayRef<OutputSection *>);
template void createThunks<ELF64LE>(ArrayRef<OutputSection *>);
template void createThunks<ELF64BE>(ArrayRef<OutputSection *>);
template bool createThunks<ELF32LE>(ArrayRef<OutputSection *>);
template bool createThunks<ELF32BE>(ArrayRef<OutputSection *>);
template bool createThunks<ELF64LE>(ArrayRef<OutputSection *>);
template bool createThunks<ELF64BE>(ArrayRef<OutputSection *>);
}
}

View File

@ -112,7 +112,7 @@ struct Relocation {
template <class ELFT> void scanRelocations(InputSectionBase &);
template <class ELFT>
void createThunks(ArrayRef<OutputSection *> OutputSections);
bool createThunks(ArrayRef<OutputSection *> OutputSections);
// Return a int64_t to make sure we get the sign extension out of the way as
// early as possible.

View File

@ -844,6 +844,10 @@ unsigned MipsGotSection<ELFT>::getLocalEntriesNum() const {
}
template <class ELFT> void MipsGotSection<ELFT>::finalizeContents() {
updateAllocSize();
}
template <class ELFT> void MipsGotSection<ELFT>::updateAllocSize() {
PageEntriesNum = 0;
for (std::pair<const OutputSection *, size_t> &P : PageIndexMap) {
// For each output section referenced by GOT page relocations calculate
@ -1330,8 +1334,12 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalizeContents() {
S.Symbol->DynsymIndex = ++I;
return;
}
}
// If it is a .symtab, move all local symbols before global symbols.
template <class ELFT> void SymbolTableSection<ELFT>::postThunkContents() {
if (this->Type == SHT_DYNSYM)
return;
// move all local symbols before global symbols.
auto It = std::stable_partition(
Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
return S.Symbol->isLocal() ||

View File

@ -43,6 +43,11 @@ public:
virtual void writeTo(uint8_t *Buf) = 0;
virtual size_t getSize() const = 0;
virtual void finalizeContents() {}
// If the section has the SHF_ALLOC flag and the size may be changed if
// thunks are added, update the section size.
virtual void updateAllocSize() {}
// If any additional finalization of contents are needed post thunk creation.
virtual void postThunkContents() {}
virtual bool empty() const { return false; }
uint64_t getVA() const;
@ -168,6 +173,7 @@ public:
MipsGotSection();
void writeTo(uint8_t *Buf) override;
size_t getSize() const override { return Size; }
void updateAllocSize() override;
void finalizeContents() override;
bool empty() const override;
void addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr);
@ -366,8 +372,6 @@ template <class ELFT> class DynamicSection final : public SyntheticSection {
};
// finalizeContents() fills this vector with the section contents.
// finalizeContents()cannot directly create final section contents because
// when the function is called, symbol or section addresses are not fixed yet.
std::vector<Entry> Entries;
public:
@ -416,6 +420,7 @@ public:
SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
void finalizeContents() override;
void postThunkContents() override;
void writeTo(uint8_t *Buf) override;
size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
void addSymbol(SymbolBody *Body);

View File

@ -1022,10 +1022,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
}
template <class ELFT>
static void finalizeSynthetic(const std::vector<SyntheticSection *> &Sections) {
static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
std::function<void(SyntheticSection *)> Fn) {
for (SyntheticSection *SS : Sections)
if (SS && SS->OutSec && !SS->empty()) {
SS->finalizeContents();
Fn(SS);
SS->OutSec->template assignOffsets<ELFT>();
}
}
@ -1082,9 +1083,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
addRelIpltSymbols();
// This responsible for splitting up .eh_frame section into
// pieces. The relocation scan uses those peaces, so this has to be
// pieces. The relocation scan uses those pieces, so this has to be
// earlier.
finalizeSynthetic<ELFT>({In<ELFT>::EhFrame});
applySynthetic<ELFT>({In<ELFT>::EhFrame},
[](SyntheticSection *SS) { SS->finalizeContents(); });
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
@ -1145,21 +1147,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
fixHeaders();
}
// Some architectures use small displacements for jump instructions.
// It is linker's responsibility to create thunks containing long
// jump instructions if jump targets are too far. Create thunks.
if (Target->NeedsThunks)
createThunks<ELFT>(OutputSections);
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
for (OutputSection *Sec : OutputSections)
Sec->finalize<ELFT>();
// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
finalizeSynthetic<ELFT>(
applySynthetic<ELFT>(
{In<ELFT>::DynSymTab, In<ELFT>::Bss, In<ELFT>::BssRelRo,
In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab,
In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef,
@ -1168,7 +1158,32 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::Plt,
In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
In<ELFT>::Dynamic});
In<ELFT>::Dynamic},
[](SyntheticSection *SS) { SS->finalizeContents(); });
// Some architectures use small displacements for jump instructions.
// It is linker's responsibility to create thunks containing long
// jump instructions if jump targets are too far. Create thunks.
if (Target->NeedsThunks) {
// FIXME: only ARM Interworking and Mips LA25 Thunks are implemented,
// these
// do not require address information. To support range extension Thunks
// we need to assign addresses so that we can tell if jump instructions
// are out of range. This will need to turn into a loop that converges
// when no more Thunks are added
if (createThunks<ELFT>(OutputSections))
applySynthetic<ELFT>({In<ELFT>::MipsGot},
[](SyntheticSection *SS) { SS->updateAllocSize(); });
}
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
for (OutputSection *Sec : OutputSections)
Sec->finalize<ELFT>();
// createThunks may have added local symbols to the static symbol table
applySynthetic<ELFT>({In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab},
[](SyntheticSection *SS) { SS->postThunkContents(); });
}
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {