diff --git a/lld/MachO/OutputSection.h b/lld/MachO/OutputSection.h --- a/lld/MachO/OutputSection.h +++ b/lld/MachO/OutputSection.h @@ -36,8 +36,8 @@ // as-is so their file size is the same as their address space size. virtual uint64_t getFileSize() const { return getSize(); } - // Hidden sections omit header content, but body content is still present. - virtual bool isHidden() const { return !this->isNeeded(); } + // Hidden sections omit header content, but body content may still be present. + virtual bool isHidden() const { return false; } // Unneeded sections are omitted entirely (header and body). virtual bool isNeeded() const { return true; } diff --git a/lld/MachO/OutputSegment.h b/lld/MachO/OutputSegment.h --- a/lld/MachO/OutputSegment.h +++ b/lld/MachO/OutputSegment.h @@ -51,6 +51,7 @@ OutputSection *getOrCreateOutputSection(StringRef name); void addOutputSection(OutputSection *os); void sortOutputSections(OutputSegmentComparator *comparator); + void removeUnneededSections(); const SectionMap &getSections() const { return sections; } size_t numNonHiddenSections() const; diff --git a/lld/MachO/OutputSegment.cpp b/lld/MachO/OutputSegment.cpp --- a/lld/MachO/OutputSegment.cpp +++ b/lld/MachO/OutputSegment.cpp @@ -40,7 +40,7 @@ size_t count = 0; for (const OutputSegment::SectionMapEntry &i : sections) { OutputSection *os = i.second; - count += (os->isHidden() ? 0 : 1); + count += (!os->isHidden() ? 1 : 0); } return count; } @@ -70,6 +70,12 @@ llvm::stable_sort(sections, *comparator->sectionComparator(this)); } +void OutputSegment::removeUnneededSections() { + sections.remove_if([](const std::pair &p) { + return !p.second->isNeeded(); + }); +} + OutputSegmentComparator::OutputSegmentComparator() { // This defines the order of segments and the sections within each segment. // Segments that are not mentioned here will end up at defaultPosition; @@ -138,9 +144,8 @@ seg->sortOutputSections(&comparator); for (auto &p : seg->getSections()) { OutputSection *section = p.second; - if (!section->isHidden()) { + if (!section->isHidden()) section->index = ++sectionIndex; - } } } } diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -114,7 +114,7 @@ c->maxprot = seg->maxProt; c->initprot = seg->initProt; - if (!seg->isNeeded()) + if (seg->getSections().empty()) return; c->vmaddr = seg->firstSection()->addr; @@ -126,6 +126,7 @@ StringRef s = p.first; OutputSection *section = p.second; c->filesize += section->getFileSize(); + if (section->isHidden()) continue; @@ -283,10 +284,8 @@ uint8_t segIndex = 0; for (OutputSegment *seg : outputSegments) { - if (seg->isNeeded()) { - headerSection->addLoadCommand(make(seg->name, seg)); - seg->index = segIndex++; - } + headerSection->addLoadCommand(make(seg->name, seg)); + seg->index = segIndex++; } uint64_t dylibOrdinal = 1; @@ -327,6 +326,17 @@ ->getOrCreateOutputSection(isec->name) ->mergeInput(isec); } + + // Remove unneeded segments and sections. + // TODO: Avoid creating unneeded segments in the first place + for (auto it = outputSegments.begin(); it != outputSegments.end();) { + OutputSegment *seg = *it; + seg->removeUnneededSections(); + if (!seg->isNeeded()) + it = outputSegments.erase(it); + else + ++it; + } } void Writer::assignAddresses(OutputSegment *seg) { diff --git a/lld/test/MachO/section-merge.s b/lld/test/MachO/section-merge.s --- a/lld/test/MachO/section-merge.s +++ b/lld/test/MachO/section-merge.s @@ -23,9 +23,9 @@ # DATA: {{0*}}[[#%x,BASE:]] <_some_function>: # DATA-NEXT: [[#BASE]]: 48 c7 c0 01 00 00 00 movq $1, %rax # DATA-NEXT: [[#BASE + 0x7]]: c3 retq -# DATA: {{0*}}[[#BASE + 0x8]] <_main>: -# DATA-NEXT: [[#BASE + 0x8]]: 48 c7 c0 00 00 00 00 movq $0, %rax -# DATA-NEXT: [[#BASE + 0xf]]: c3 retq +# DATA: {{0*}}[[#%x,MAIN:]] <_main>: +# DATA-NEXT: [[#MAIN]]: 48 c7 c0 00 00 00 00 movq $0, %rax +# DATA-NEXT: [[#MAIN + 0x7]]: c3 retq .section __TEXT,__text .global _main