Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -112,7 +112,7 @@ template void scanRelocations(InputSectionBase &); template -void createThunks(ArrayRef OutputSections); +bool createThunks(ArrayRef OutputSections); // Return a int64_t to make sure we get the sign extension out of the way as // early as possible. Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -895,7 +895,7 @@ // FIXME: All Thunks are assumed to be in range of the relocation. Range // extension Thunks are not yet supported. template -void createThunks(ArrayRef OutputSections) { +bool createThunks(ArrayRef OutputSections) { // Track Symbols that already have a Thunk DenseMap *> ThunkedSymbols; // Track InputSections that have a ThunkSection placed in front @@ -977,6 +977,7 @@ // Merge all created synthetic ThunkSections back into OutputSection for (auto &KV : ThunkSections) mergeThunks(KV.first, KV.second); + return !ThunkSections.empty(); } template void scanRelocations(InputSectionBase &); @@ -984,9 +985,9 @@ template void scanRelocations(InputSectionBase &); template void scanRelocations(InputSectionBase &); -template void createThunks(ArrayRef); -template void createThunks(ArrayRef); -template void createThunks(ArrayRef); -template void createThunks(ArrayRef); +template bool createThunks(ArrayRef); +template bool createThunks(ArrayRef); +template bool createThunks(ArrayRef); +template bool createThunks(ArrayRef); } } Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -43,6 +43,11 @@ 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 @@ 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 @@ }; // 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 Entries; public: @@ -416,6 +420,7 @@ SymbolTableSection(StringTableSection &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); Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -844,6 +844,10 @@ } template void MipsGotSection::finalizeContents() { + updateAllocSize(); +} + +template void MipsGotSection::updateAllocSize() { PageEntriesNum = 0; for (std::pair &P : PageIndexMap) { // For each output section referenced by GOT page relocations calculate @@ -1330,8 +1334,12 @@ S.Symbol->DynsymIndex = ++I; return; } +} - // If it is a .symtab, move all local symbols before global symbols. +template void SymbolTableSection::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() || Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1022,10 +1022,11 @@ } template -static void finalizeSynthetic(const std::vector &Sections) { +static void applySynthetic(const std::vector &Sections, + std::function Fn) { for (SyntheticSection *SS : Sections) if (SS && SS->OutSec && !SS->empty()) { - SS->finalizeContents(); + Fn(SS); SS->OutSec->template assignOffsets(); } } @@ -1082,9 +1083,10 @@ 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({In::EhFrame}); + applySynthetic({In::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 @@ 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(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(); - // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. - finalizeSynthetic( + applySynthetic( {In::DynSymTab, In::Bss, In::BssRelRo, In::GnuHashTab, In::HashTab, In::SymTab, In::ShStrTab, In::StrTab, In::VerDef, @@ -1168,7 +1158,32 @@ In::RelaDyn, In::RelaIplt, In::RelaPlt, In::Plt, In::Iplt, In::Plt, In::EhFrameHdr, In::VerSym, In::VerNeed, - In::Dynamic}); + In::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(OutputSections)) + applySynthetic({In::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(); + + // createThunks may have added local symbols to the static symbol table + applySynthetic({In::SymTab, In::ShStrTab, In::StrTab}, + [](SyntheticSection *SS) { SS->postThunkContents(); }); } template void Writer::addPredefinedSections() {