diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -130,7 +130,7 @@ template void reportUndefinedSymbols(); -void hexagonTLSSymbolUpdate(ArrayRef outputSections); +bool hexagonTLSSymbolUpdate(ArrayRef outputSections); bool hexagonNeedsTLSSymbol(ArrayRef outputSections); class ThunkSection; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -2195,10 +2195,10 @@ return needTlsSymbol; } -void elf::hexagonTLSSymbolUpdate(ArrayRef outputSections) { +bool elf::hexagonTLSSymbolUpdate(ArrayRef outputSections) { Symbol *sym = symtab->find("__tls_get_addr"); if (!sym) - return; + return false; bool needEntry = true; forEachInputSectionDescription( outputSections, [&](OutputSection *os, InputSectionDescription *isd) { @@ -2214,6 +2214,7 @@ rel.sym = sym; } }); + return true; } template void elf::scanRelocations(InputSectionBase &); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -56,7 +56,7 @@ void copyLocalSymbols(); void addSectionSymbols(); void sortSections(); - void resolveShfLinkOrder(); + bool resolveShfLinkOrder(); void finalizeAddressDependentContent(); void optimizeBasicBlockJumps(); void sortInputSections(); @@ -1557,11 +1557,13 @@ return la->outSecOff < lb->outSecOff; } -template void Writer::resolveShfLinkOrder() { +template bool Writer::resolveShfLinkOrder() { llvm::TimeTraceScope timeScope("Resolve SHF_LINK_ORDER"); + bool changed = false; for (OutputSection *sec : outputSections) { if (!(sec->flags & SHF_LINK_ORDER)) continue; + changed = true; // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated // this processing inside the ARMExidxsyntheticsection::finalizeContents(). @@ -1598,6 +1600,7 @@ } } } + return changed; } static void finalizeSynthetic(SyntheticSection *sec) { @@ -1616,22 +1619,23 @@ ThunkCreator tc; AArch64Err843419Patcher a64p; ARMErr657417Patcher a32p; - script->assignAddresses(); + bool changed = script->assignAddresses() != nullptr; // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they // do require the relative addresses of OutputSections because linker scripts // can assign Virtual Addresses to OutputSections that are not monotonically // increasing. for (Partition &part : partitions) finalizeSynthetic(part.armExidx.get()); - resolveShfLinkOrder(); + changed |= resolveShfLinkOrder(); // Converts call x@GDPLT to call __tls_get_addr if (config->emachine == EM_HEXAGON) - hexagonTLSSymbolUpdate(outputSections); + changed |= hexagonTLSSymbolUpdate(outputSections); + int passes = 0; int assignPasses = 0; for (;;) { - bool changed = target->needsThunks && tc.createThunks(outputSections); + changed |= target->needsThunks && tc.createThunks(outputSections); // With Thunk Size much smaller than branch range we expect to // converge quickly; if we get to 15 something has gone wrong. @@ -1652,7 +1656,7 @@ } if (in.mipsGot) - in.mipsGot->updateAllocSize(); + changed |= in.mipsGot->updateAllocSize(); for (Partition &part : partitions) { changed |= part.relaDyn->updateAllocSize(); @@ -1660,7 +1664,10 @@ changed |= part.relrDyn->updateAllocSize(); } - const Defined *changedSym = script->assignAddresses(); + const Defined *changedSym = nullptr; + if (changed || passes > 0 || script->hasSectionsCommand) + changedSym = script->assignAddresses(); + ++passes; if (!changed) { // Some symbols may be dependent on section addresses. When we break the // loop, the symbol values are finalized because a previous @@ -1673,6 +1680,7 @@ break; } } + changed = false; } if (config->relocatable) diff --git a/lld/test/ELF/linkerscript/symbol-assign-not-converge.test b/lld/test/ELF/linkerscript/symbol-assign-not-converge.test --- a/lld/test/ELF/linkerscript/symbol-assign-not-converge.test +++ b/lld/test/ELF/linkerscript/symbol-assign-not-converge.test @@ -16,5 +16,6 @@ c = d; d = e; e = f; - f = .; + f = g; + g = .; }