diff --git a/lld/MachO/ConcatOutputSection.h b/lld/MachO/ConcatOutputSection.h --- a/lld/MachO/ConcatOutputSection.h +++ b/lld/MachO/ConcatOutputSection.h @@ -31,6 +31,7 @@ const ConcatInputSection *firstSection() const { return inputs.front(); } const ConcatInputSection *lastSection() const { return inputs.back(); } + bool isNeeded() const override { return !inputs.empty(); } // These accessors will only be valid after finalizing the section uint64_t getSize() const override { return size; } @@ -50,6 +51,8 @@ return sec->kind() == ConcatKind; } + static ConcatOutputSection *getOrCreateForInput(const InputSection *); + private: void finalizeFlags(InputSection *input); @@ -79,6 +82,12 @@ uint8_t sequence = 0; // how many thunks created so-far? }; +NamePair maybeRenameSection(NamePair key); + +// Output sections are added to output segments in iteration order +// of ConcatOutputSection, so must have deterministic iteration order. +extern llvm::MapVector concatOutputSections; + extern llvm::DenseMap thunkMap; } // namespace macho diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -24,7 +24,10 @@ using namespace lld; using namespace lld::macho; +MapVector macho::concatOutputSections; + void ConcatOutputSection::addInput(ConcatInputSection *input) { + assert(input->parent == this); if (inputs.empty()) { align = input->align; flags = input->getFlags(); @@ -33,7 +36,6 @@ finalizeFlags(input); } inputs.push_back(input); - input->parent = this; } // Branch-range extension can be implemented in two ways, either through ... @@ -357,3 +359,22 @@ break; } } + +ConcatOutputSection * +ConcatOutputSection::getOrCreateForInput(const InputSection *isec) { + NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()}); + ConcatOutputSection *&osec = concatOutputSections[names]; + if (!osec) + osec = make(names.second); + return osec; +} + +NamePair macho::maybeRenameSection(NamePair key) { + auto newNames = config->sectionRenameMap.find(key); + if (newNames != config->sectionRenameMap.end()) + return newNames->second; + auto newName = config->segmentRenameMap.find(key.first); + if (newName != config->segmentRenameMap.end()) + return std::make_pair(newName->second, key.second); + return key; +} diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -541,6 +541,7 @@ // any CommonSymbols. static void replaceCommonSymbols() { TimeTraceScope timeScope("Replace common symbols"); + ConcatOutputSection *osec = nullptr; for (Symbol *sym : symtab->getSymbols()) { auto *common = dyn_cast(sym); if (common == nullptr) @@ -553,6 +554,9 @@ auto *isec = make( segment_names::data, section_names::common, common->getFile(), data, common->align, S_ZEROFILL); + if (!osec) + osec = ConcatOutputSection::getOrCreateForInput(isec); + isec->parent = osec; inputSections.push_back(isec); // FIXME: CommonSymbol should store isReferencedDynamically, noDeadStrip @@ -989,6 +993,7 @@ int inputOrder = 0; for (const InputFile *file : inputFiles) { for (const SubsectionMap &map : file->subsections) { + ConcatOutputSection *osec = nullptr; for (const SubsectionEntry &entry : map) { if (auto *isec = dyn_cast(entry.isec)) { if (isec->isCoalescedWeak()) @@ -999,6 +1004,9 @@ continue; } isec->outSecOff = inputOrder++; + if (!osec) + osec = ConcatOutputSection::getOrCreateForInput(isec); + isec->parent = osec; inputSections.push_back(isec); } else if (auto *isec = dyn_cast(entry.isec)) { if (in.cStringSection->inputOrder == UnspecifiedInputOrder) diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "InputSection.h" +#include "ConcatOutputSection.h" #include "Config.h" #include "InputFiles.h" #include "OutputSegment.h" diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -15,6 +15,7 @@ #include "OutputSection.h" #include "OutputSegment.h" #include "Target.h" +#include "Writer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -15,7 +15,6 @@ #include "OutputSegment.h" #include "SymbolTable.h" #include "Symbols.h" -#include "Writer.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" @@ -506,6 +505,8 @@ stubBinder->reference(RefState::Strong); in.got->addEntry(stubBinder); + in.imageLoaderCache->parent = + ConcatOutputSection::getOrCreateForInput(in.imageLoaderCache); inputSections.push_back(in.imageLoaderCache); // Since this isn't in the symbol table or in any input file, the noDeadStrip // argument doesn't matter. It's kept alive by ImageLoaderCacheSection() diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -144,6 +144,7 @@ void UnwindInfoSectionImpl::addInput(ConcatInputSection *isec) { assert(isec->getSegName() == segment_names::ld && isec->getName() == section_names::compactUnwind); + isec->parent = compactUnwindSection; compactUnwindSection->addInput(isec); } diff --git a/lld/MachO/Writer.h b/lld/MachO/Writer.h --- a/lld/MachO/Writer.h +++ b/lld/MachO/Writer.h @@ -9,8 +9,6 @@ #ifndef LLD_MACHO_WRITER_H #define LLD_MACHO_WRITER_H -#include "Config.h" - #include namespace lld { @@ -29,8 +27,6 @@ template void writeResult(); -NamePair maybeRenameSection(NamePair key); - void createSyntheticSections(); // Add bindings for symbols that need weak or non-lazy bindings. diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -76,10 +76,6 @@ LCUuid *uuidCommand = nullptr; OutputSegment *linkEditSegment = nullptr; - - // Output sections are added to output segments in iteration order - // of ConcatOutputSection, so must have deterministic iteration order. - MapVector concatOutputSections; }; // LC_DYLD_INFO_ONLY stores the offsets of symbol import/export information. @@ -850,16 +846,6 @@ } } -NamePair macho::maybeRenameSection(NamePair key) { - auto newNames = config->sectionRenameMap.find(key); - if (newNames != config->sectionRenameMap.end()) - return newNames->second; - auto newName = config->segmentRenameMap.find(key.first); - if (newName != config->segmentRenameMap.end()) - return std::make_pair(newName->second, key.second); - return key; -} - template void Writer::createOutputSections() { TimeTraceScope timeScope("Create output sections"); // First, create hidden sections @@ -890,10 +876,7 @@ for (ConcatInputSection *isec : inputSections) { if (isec->shouldOmitFromOutput()) continue; - NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()}); - ConcatOutputSection *&osec = concatOutputSections[names]; - if (!osec) - osec = make(names.second); + ConcatOutputSection *osec = cast(isec->parent); osec->addInput(isec); osec->inputOrder = std::min(osec->inputOrder, static_cast(isec->outSecOff)); @@ -905,7 +888,8 @@ StringRef segname = it.first.first; ConcatOutputSection *osec = it.second; assert(segname != segment_names::ld); - getOrCreateOutputSegment(segname)->addOutputSection(osec); + if (osec->isNeeded()) + getOrCreateOutputSegment(segname)->addOutputSection(osec); } for (SyntheticSection *ssec : syntheticSections) {