diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -282,6 +282,7 @@ ExprValue getSymbolValue(StringRef name, const Twine &loc); void addOrphanSections(); + void processOrphanHandling(); void adjustSectionsBeforeSorting(); void adjustSectionsAfterSorting(); @@ -321,6 +322,9 @@ // to be reordered. std::vector insertCommands; + // Sections that will be warned/errored by --orphan-handling. + std::vector orphanSections; + // Sections whose addresses are not equal to their addrExpr values. std::vector> changedSectionAddresses; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -681,13 +681,9 @@ std::function add; add = [&](InputSectionBase *s) { if (s->isLive() && !s->parent) { + orphanSections.push_back(s); + StringRef name = getOutputSectionName(s); - - if (config->orphanHandling == OrphanHandlingPolicy::Error) - error(toString(s) + " is being placed in '" + name + "'"); - else if (config->orphanHandling == OrphanHandlingPolicy::Warn) - warn(toString(s) + " is being placed in '" + name + "'"); - if (OutputSection *sec = findByName(sectionCommands, name)) { sec->recordSection(s); } else { @@ -732,6 +728,16 @@ sectionCommands.insert(sectionCommands.begin(), v.begin(), v.end()); } +void LinkerScript::processOrphanHandling() { + for (const InputSectionBase *sec : orphanSections) { + StringRef name = getOutputSectionName(sec); + if (config->orphanHandling == OrphanHandlingPolicy::Error) + error(toString(sec) + " is being placed in '" + name + "'"); + else if (config->orphanHandling == OrphanHandlingPolicy::Warn) + warn(toString(sec) + " is being placed in '" + name + "'"); + } +} + uint64_t LinkerScript::advance(uint64_t size, unsigned alignment) { bool isTbss = (ctx->outSec->flags & SHF_TLS) && ctx->outSec->type == SHT_NOBITS; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1679,11 +1679,14 @@ continue; // If we reach here, then SS is an unused synthetic section and we want to - // remove it from corresponding input section description of output section. + // remove it from the corresponding input section description, and + // orphanSections. for (BaseCommand *b : os->sectionCommands) if (auto *isd = dyn_cast(b)) llvm::erase_if(isd->sections, [=](InputSection *isec) { return isec == ss; }); + llvm::erase_if(script->orphanSections, + [=](const InputSectionBase *isec) { return isec == ss; }); } } @@ -1830,6 +1833,7 @@ in.mipsGot->build(); removeUnusedSyntheticSections(); + script->processOrphanHandling(); sortSections(); diff --git a/lld/test/ELF/linkerscript/orphan-report.s b/lld/test/ELF/linkerscript/orphan-report.s --- a/lld/test/ELF/linkerscript/orphan-report.s +++ b/lld/test/ELF/linkerscript/orphan-report.s @@ -12,33 +12,22 @@ # RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=DEFAULT ## Check --orphan-handling=error reports errors about orphans. +# RUN: not ld.lld --orphan-handling=error -o /dev/null --script %t.script \ +# RUN: %t.o 2>&1 | FileCheck %s --check-prefix=REPORT # RUN: not ld.lld -shared --orphan-handling=error -o /dev/null --script %t.script \ -# RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=REPORT +# RUN: %t.o 2>&1 | FileCheck %s --check-prefixes=REPORT,PIC # REPORT: {{.*}}.o:(.text) is being placed in '.text' # REPORT-NEXT: {{.*}}.o:(.text.2) is being placed in '.text' # REPORT-NEXT: :(.comment) is being placed in '.comment' -# REPORT-NEXT: :(.bss) is being placed in '.bss' -# REPORT-NEXT: :(.bss.rel.ro) is being placed in '.bss.rel.ro' -# REPORT-NEXT: :(.dynsym) is being placed in '.dynsym' -# REPORT-NEXT: :(.gnu.version) is being placed in '.gnu.version' -# REPORT-NEXT: :(.gnu.version_r) is being placed in '.gnu.version_r' -# REPORT-NEXT: :(.gnu.hash) is being placed in '.gnu.hash' -# REPORT-NEXT: :(.hash) is being placed in '.hash' -# REPORT-NEXT: :(.dynamic) is being placed in '.dynamic' -# REPORT-NEXT: :(.dynstr) is being placed in '.dynstr' -# REPORT-NEXT: :(.rela.dyn) is being placed in '.rela.dyn' -# REPORT-NEXT: :(.eh_frame) is being placed in '.eh_frame' -# REPORT-NEXT: :(.got) is being placed in '.got' -# REPORT-NEXT: :(.got.plt) is being placed in '.got.plt' -# REPORT-NEXT: :(.got.plt) is being placed in '.got.plt' -# REPORT-NEXT: :(.rela.plt) is being placed in '.rela.plt' -# REPORT-NEXT: :(.rela.dyn) is being placed in '.rela.dyn' -# REPORT-NEXT: :(.plt) is being placed in '.plt' -# REPORT-NEXT: :(.iplt) is being placed in '.iplt' -# REPORT-NEXT: :(.symtab) is being placed in '.symtab' -# REPORT-NEXT: :(.symtab_shndx) is being placed in '.symtab_shndx' +# PIC-NEXT: :(.dynsym) is being placed in '.dynsym' +# PIC-NEXT: :(.gnu.hash) is being placed in '.gnu.hash' +# PIC-NEXT: :(.hash) is being placed in '.hash' +# PIC-NEXT: :(.dynamic) is being placed in '.dynamic' +# PIC-NEXT: :(.dynstr) is being placed in '.dynstr' +# REPORT: :(.symtab) is being placed in '.symtab' # REPORT-NEXT: :(.shstrtab) is being placed in '.shstrtab' # REPORT-NEXT: :(.strtab) is being placed in '.strtab' +# REPORT-NOT: ## Check --orphan-handling=warn reports warnings about orphans. # RUN: ld.lld -shared --orphan-handling=warn -o %t.out --script %t.script \