diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -134,7 +134,9 @@ int getPriority(StringRef s); InputSection *getFirstInputSection(const OutputSection *os); -SmallVector getInputSections(const OutputSection &os); +llvm::ArrayRef +getInputSections(const OutputSection &os, + SmallVector &storage); // All output sections that are handled by the linker specially are // globally accessible. Writer initializes them, so don't use them diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -419,7 +419,8 @@ } // Write leading padding. - SmallVector sections = getInputSections(*this); + SmallVector storage; + ArrayRef sections = getInputSections(*this, storage); std::array filler = getFiller(); bool nonZeroFiller = read32(filler.data()) != 0; if (nonZeroFiller) @@ -592,12 +593,24 @@ return nullptr; } -SmallVector elf::getInputSections(const OutputSection &os) { - SmallVector ret; - for (SectionCommand *cmd : os.commands) - if (auto *isd = dyn_cast(cmd)) - ret.insert(ret.end(), isd->sections.begin(), isd->sections.end()); - return ret; +ArrayRef +elf::getInputSections(const OutputSection &os, + SmallVector &storage) { + ArrayRef ret; + storage.clear(); + for (SectionCommand *cmd : os.commands) { + auto *isd = dyn_cast(cmd); + if (!isd) + continue; + if (ret.empty()) { + ret = isd->sections; + } else { + if (storage.empty()) + storage.assign(ret.begin(), ret.end()); + storage.insert(storage.end(), isd->sections.begin(), isd->sections.end()); + } + } + return storage.empty() ? ret : makeArrayRef(storage); } // Sorts input sections by section name suffixes, so that .foo.N comes @@ -622,7 +635,8 @@ void OutputSection::checkDynRelAddends(const uint8_t *bufStart) { assert(config->writeAddends && config->checkDynamicRelocs); assert(type == SHT_REL || type == SHT_RELA); - SmallVector sections = getInputSections(*this); + SmallVector storage; + ArrayRef sections = getInputSections(*this, storage); parallelFor(0, sections.size(), [&](size_t i) { // When linking with -r or --emit-relocs we might also call this function // for input .rel[a]. sections which we simply pass through to the diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1741,6 +1741,7 @@ // option is used. template void Writer::optimizeBasicBlockJumps() { assert(config->optimizeBBJumps); + SmallVector storage; script->assignAddresses(); // For every output section that has executable input sections, this @@ -1752,7 +1753,7 @@ for (OutputSection *osec : outputSections) { if (!(osec->flags & SHF_EXECINSTR)) continue; - SmallVector sections = getInputSections(*osec); + ArrayRef sections = getInputSections(*osec, storage); size_t numDeleted = 0; // Delete all fall through jump instructions. Also, check if two // consecutive jump instructions can be flipped so that a fall @@ -1772,7 +1773,7 @@ fixSymbolsAfterShrinking(); for (OutputSection *osec : outputSections) - for (InputSection *is : getInputSections(*osec)) + for (InputSection *is : getInputSections(*osec, storage)) is->trim(); } @@ -2165,9 +2166,10 @@ if (!config->executeOnly) return; + SmallVector storage; for (OutputSection *osec : outputSections) if (osec->flags & SHF_EXECINSTR) - for (InputSection *isec : getInputSections(*osec)) + for (InputSection *isec : getInputSections(*osec, storage)) if (!(isec->flags & SHF_EXECINSTR)) error("cannot place " + toString(isec) + " into " + toString(osec->name) +