Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1085,9 +1085,17 @@ template void SymbolTableSection::finalize() { this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex; - this->OutSec->Info = this->Info = NumLocals + 1; this->OutSec->Entsize = this->Entsize; + if (!StrTabSec.isDynamic()) { + // All explictly added STB_LOCAL symbols without a Symbol are first + auto It = std::stable_partition( + Symbols.begin(), Symbols.end(), + [](const SymbolTableEntry &S) { return S.Symbol->isLocal(); }); + NumLocals = It - Symbols.begin(); + } + this->OutSec->Info = this->Info = 1 + NumLocals; + if (Config->Relocatable) return; @@ -1122,7 +1130,6 @@ template void SymbolTableSection::addLocal(SymbolBody *B) { assert(!StrTabSec.isDynamic()); - ++NumLocals; Symbols.push_back({B, StrTabSec.addString(B->getName())}); } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1112,13 +1112,7 @@ if (In::Iplt && !In::Iplt->empty()) In::Iplt->addSymbols(); - // 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); - - // Now that we have defined all possible symbols including linker- + // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. for (Symbol *S : Symtab::X->getSymbols()) { SymbolBody *Body = S->body(); @@ -1168,6 +1162,12 @@ 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.