diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2658,8 +2658,8 @@ // point onwards InputSectionDescription::sections should be used instead of // sectionBases. for (SectionCommand *cmd : script->sectionCommands) - if (auto *sec = dyn_cast(cmd)) - sec->finalizeInputSections(); + if (auto *osd = dyn_cast(cmd)) + osd->osec->finalizeInputSections(); llvm::erase_if(inputSections, [](InputSectionBase *s) { return isa(s); }); diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -568,8 +568,8 @@ // InputSectionDescription::sections is populated by processSectionCommands(). // ICF may fold some input sections assigned to output sections. Remove them. for (SectionCommand *cmd : script->sectionCommands) - if (auto *sec = dyn_cast(cmd)) - for (SectionCommand *subCmd : sec->commands) + if (auto *osd = dyn_cast(cmd)) + for (SectionCommand *subCmd : osd->osec->commands) if (auto *isd = dyn_cast(subCmd)) llvm::erase_if(isd->sections, [](InputSection *isec) { return !isec->isLive(); }); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -348,7 +348,9 @@ // beginning of the output section. template void writeTo(uint8_t *buf); - OutputSection *getParent() const; + OutputSection *getParent() const { + return reinterpret_cast(parent); + } // This variable has two usages. Initially, it represents an index in the // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -323,10 +323,6 @@ StringRef name) : InputSectionBase(f, header, name, InputSectionBase::Regular) {} -OutputSection *InputSection::getParent() const { - return cast_or_null(parent); -} - // Copy SHT_GROUP section contents. Used only for the -r option. template void InputSection::copyShtGroup(uint8_t *buf) { // ELFT::Word is the 32-bit integral type in the target endianness. diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -32,6 +32,7 @@ class OutputSection; class SectionBase; class ThunkSection; +struct OutputDesc; // This represents an r-value in the linker script. struct ExprValue { @@ -357,7 +358,7 @@ SmallVector insertCommands; // OutputSections specified by OVERWRITE_SECTIONS. - SmallVector overwriteSections; + SmallVector overwriteSections; // Sections that will be warned/errored by --orphan-handling. SmallVector orphanSections; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -279,7 +279,7 @@ assign->sym->value)); continue; } - for (SectionCommand *subCmd : cast(cmd)->commands) + for (SectionCommand *subCmd : cast(cmd)->osec->commands) if (auto *assign = dyn_cast(subCmd)) if (assign->sym) ret.try_emplace(assign->sym, std::make_pair(assign->sym->section, @@ -305,25 +305,25 @@ // Process INSERT [AFTER|BEFORE] commands. For each command, we move the // specified output section to the designated place. void LinkerScript::processInsertCommands() { - SmallVector moves; + SmallVector moves; for (const InsertCommand &cmd : insertCommands) { for (StringRef name : cmd.names) { // If base is empty, it may have been discarded by // adjustOutputSections(). We do not handle such output sections. auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) { - return isa(subCmd) && - cast(subCmd)->name == name; + return isa(subCmd) && + cast(subCmd)->osec->name == name; }); if (from == sectionCommands.end()) continue; - moves.push_back(cast(*from)); + moves.push_back(cast(*from)); sectionCommands.erase(from); } auto insertPos = llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) { - auto *to = dyn_cast(subCmd); - return to != nullptr && to->name == cmd.where; + auto *to = dyn_cast(subCmd); + return to != nullptr && to->osec->name == cmd.where; }); if (insertPos == sectionCommands.end()) { error("unable to insert " + cmd.names[0] + @@ -352,7 +352,7 @@ // we can't say for sure if it is going to be included or not. // Skip such sections for now. Improve the checks if we ever // need symbols from that sections to be declared early. - auto *sec = cast(cmd); + auto *sec = cast(cmd)->osec; if (sec->constraint != ConstraintKind::NoConstraint) continue; for (SectionCommand *cmd : sec->commands) @@ -647,17 +647,20 @@ // or orphans. DenseMap map; size_t i = 0; - for (OutputSection *osec : overwriteSections) + for (OutputDesc *osd : overwriteSections) { + OutputSection *osec = osd->osec; if (process(osec) && !map.try_emplace(CachedHashStringRef(osec->name), osec).second) warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name); - for (SectionCommand *&base : sectionCommands) - if (auto *osec = dyn_cast(base)) { + } + for (SectionCommand *base : sectionCommands) + if (auto *osd = dyn_cast(base)) { + OutputSection *osec = osd->osec; if (OutputSection *overwrite = map.lookup(CachedHashStringRef(osec->name))) { log(overwrite->location + " overwrites " + osec->name); overwrite->sectionIndex = i++; - base = overwrite; + osd->osec = overwrite; } else if (process(osec)) { osec->sectionIndex = i++; } @@ -666,9 +669,9 @@ // If an OVERWRITE_SECTIONS specified output section is not in // sectionCommands, append it to the end. The section will be inserted by // orphan placement. - for (OutputSection *osec : overwriteSections) - if (osec->partition == 1 && osec->sectionIndex == UINT32_MAX) - sectionCommands.push_back(osec); + for (OutputDesc *osd : overwriteSections) + if (osd->osec->partition == 1 && osd->osec->sectionIndex == UINT32_MAX) + sectionCommands.push_back(osd); } void LinkerScript::processSymbolAssignments() { @@ -690,7 +693,7 @@ if (auto *assign = dyn_cast(cmd)) addSymbol(assign); else - for (SectionCommand *subCmd : cast(cmd)->commands) + for (SectionCommand *subCmd : cast(cmd)->osec->commands) if (auto *assign = dyn_cast(subCmd)) addSymbol(assign); } @@ -701,9 +704,9 @@ static OutputSection *findByName(ArrayRef vec, StringRef name) { for (SectionCommand *cmd : vec) - if (auto *sec = dyn_cast(cmd)) - if (sec->name == name) - return sec; + if (auto *osd = dyn_cast(cmd)) + if (osd->osec->name == name) + return osd->osec; return nullptr; } @@ -821,7 +824,7 @@ // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections() { StringMap> map; - SmallVector v; + SmallVector v; auto add = [&](InputSectionBase *s) { if (s->isLive() && !s->parent) { @@ -829,12 +832,12 @@ StringRef name = getOutputSectionName(s); if (config->unique) { - v.push_back(createSection(s, name)); + v.push_back(make(createSection(s, name))); } else if (OutputSection *sec = findByName(sectionCommands, name)) { sec->recordSection(s); } else { if (OutputSection *os = addInputSec(map, s, name)) - v.push_back(os); + v.push_back(make(os)); assert(isa(s) || s->getOutputSection()->sectionIndex == UINT32_MAX); } @@ -1138,9 +1141,9 @@ SmallVector defPhdrs; for (SectionCommand *&cmd : sectionCommands) { - auto *sec = dyn_cast(cmd); - if (!sec) + if (!isa(cmd)) continue; + auto *sec = cast(cmd)->osec; // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (sec->alignExpr) @@ -1192,7 +1195,8 @@ // Try and find an appropriate memory region to assign offsets in. MemoryRegion *hint = nullptr; for (SectionCommand *cmd : sectionCommands) { - if (auto *sec = dyn_cast(cmd)) { + if (auto *osd = dyn_cast(cmd)) { + OutputSection *sec = osd->osec; if (!sec->lmaRegionName.empty()) { if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName)) sec->lmaRegion = m; @@ -1219,8 +1223,8 @@ // Walk the commands and propagate the program headers to commands that don't // explicitly specify them. for (SectionCommand *cmd : sectionCommands) - if (auto *sec = dyn_cast(cmd)) - maybePropagatePhdrs(*sec, defPhdrs); + if (auto *osd = dyn_cast(cmd)) + maybePropagatePhdrs(*osd->osec, defPhdrs); } static uint64_t computeBase(uint64_t min, bool allocateHeaders) { @@ -1315,7 +1319,7 @@ assign->size = dot - assign->addr; continue; } - assignOffsets(cast(cmd)); + assignOffsets(cast(cmd)->osec); } ctx = nullptr; diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -168,7 +168,7 @@ continue; } - osec = cast(cmd); + osec = cast(cmd)->osec; writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment); os << osec->name << '\n'; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -27,11 +27,21 @@ uint64_t uncompressedSize; }; +struct OutputDesc final : SectionCommand { + OutputSection *osec; + OutputDesc(OutputSection *osec) + : SectionCommand(OutputSectionKind), osec(osec) {} + + static bool classof(const SectionCommand *c) { + return c->kind == OutputSectionKind; + } +}; + // This represents a section in an output file. // It is composed of multiple InputSections. // The writer creates multiple OutputSections and assign them unique, // non-overlapping file offsets and VAs. -class OutputSection final : public SectionCommand, public SectionBase { +class OutputSection final : public SectionBase { public: OutputSection(StringRef name, uint32_t type, uint64_t flags); @@ -39,8 +49,6 @@ return s->kind() == SectionBase::Output; } - static bool classof(const SectionCommand *c); - uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; } template void writeHeaderTo(typename ELFT::Shdr *sHdr); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -68,8 +68,7 @@ } OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags) - : SectionCommand(OutputSectionKind), - SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type, + : SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type, /*Info*/ 0, /*Link*/ 0) {} // We allow sections of types listed below to merged into a @@ -251,10 +250,6 @@ return Out::elfHeader->size + Out::programHeaders->size; } -bool OutputSection::classof(const SectionCommand *c) { - return c->kind == OutputSectionKind; -} - void OutputSection::sort(llvm::function_ref order) { assert(isLive()); for (SectionCommand *b : commands) diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -92,7 +92,7 @@ bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2); void readSectionAddressType(OutputSection *cmd); OutputSection *readOverlaySectionDescription(); - OutputSection *readOutputSectionDescription(StringRef outSec); + OutputDesc *readOutputSectionDescription(StringRef outSec); SmallVector readOverlay(); SmallVector readOutputSectionPhdrs(); std::pair readInputSectionFlags(); @@ -540,7 +540,7 @@ os->lmaExpr = [=] { return prev->getLMA() + prev->size; }; else os->lmaExpr = lmaExpr; - v.push_back(os); + v.push_back(make(os)); prev = os; } @@ -551,7 +551,7 @@ Expr moveDot = [=] { uint64_t max = 0; for (SectionCommand *cmd : v) - max = std::max(max, cast(cmd)->size); + max = std::max(max, cast(cmd)->osec->size); return addrExpr().getValue() + max; }; v.push_back(make(".", moveDot, getCurrentLocation())); @@ -599,8 +599,8 @@ StringRef where = next(); SmallVector names; for (SectionCommand *cmd : v) - if (auto *os = dyn_cast(cmd)) - names.push_back(os->name); + if (auto *os = dyn_cast(cmd)) + names.push_back(os->osec->name); if (!names.empty()) script->insertCommands.push_back({std::move(names), isAfter, where}); } @@ -885,7 +885,7 @@ return cmd; } -OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { +OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) { OutputSection *cmd = script->createOutputSection(outSec, getCurrentLocation()); @@ -973,7 +973,7 @@ if (script->referencedSymbols.size() > symbolsReferenced) cmd->expressionsUseSymbols = true; - return cmd; + return make(cmd); } // Reads a `=` expression and returns its value as a big-endian number. diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2319,7 +2319,7 @@ // a .symtab_shndx section when the amount of output sections is huge. size_t size = 0; for (SectionCommand *cmd : script->sectionCommands) - if (isa(cmd)) + if (isa(cmd)) ++size; return size >= SHN_LORESERVE; } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -273,9 +273,9 @@ static OutputSection *findSection(StringRef name, unsigned partition = 1) { for (SectionCommand *cmd : script->sectionCommands) - if (auto *sec = dyn_cast(cmd)) - if (sec->name == name && sec->partition == partition) - return sec; + if (auto *osd = dyn_cast(cmd)) + if (osd->osec->name == name && osd->osec->partition == partition) + return osd->osec; return nullptr; } @@ -708,9 +708,10 @@ // don't create a section symbol for that section. template void Writer::addSectionSymbols() { for (SectionCommand *cmd : script->sectionCommands) { - auto *sec = dyn_cast(cmd); - if (!sec) + auto *osd = dyn_cast(cmd); + if (!osd) continue; + OutputSection *sec = osd->osec; auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) { if (auto *isd = dyn_cast(cmd)) return !isd->sections.empty(); @@ -974,8 +975,8 @@ static bool compareSections(const SectionCommand *aCmd, const SectionCommand *bCmd) { - const OutputSection *a = cast(aCmd); - const OutputSection *b = cast(bCmd); + const OutputSection *a = cast(aCmd)->osec; + const OutputSection *b = cast(bCmd)->osec; if (a->sortRank != b->sortRank) return a->sortRank < b->sortRank; @@ -1111,8 +1112,10 @@ } static int getRankProximity(OutputSection *a, SectionCommand *b) { - auto *sec = dyn_cast(b); - return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1; + auto *osd = dyn_cast(b); + return (osd && osd->osec->hasInputSections) + ? getRankProximityAux(a, osd->osec) + : -1; } // When placing orphan sections, we want to place them after symbol assignments @@ -1141,7 +1144,7 @@ static SmallVectorImpl::iterator findOrphanPos(SmallVectorImpl::iterator b, SmallVectorImpl::iterator e) { - OutputSection *sec = cast(*e); + OutputSection *sec = cast(*e)->osec; // Find the first element that has as close a rank as possible. auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) { @@ -1149,9 +1152,9 @@ }); if (i == e) return e; - auto foundSec = dyn_cast(*i); - if (!foundSec) + if (!isa(*i)) return e; + auto foundSec = cast(*i)->osec; // Consider all existing sections with the same proximity. int proximity = getRankProximity(sec, *i); @@ -1165,17 +1168,17 @@ // resemble the behavior of GNU ld. sortRank = std::max(sortRank, foundSec->sortRank); for (; i != e; ++i) { - auto *curSec = dyn_cast(*i); - if (!curSec || !curSec->hasInputSections) + auto *curSec = dyn_cast(*i); + if (!curSec || !curSec->osec->hasInputSections) continue; if (getRankProximity(sec, curSec) != proximity || - sortRank < curSec->sortRank) + sortRank < curSec->osec->sortRank) break; } auto isOutputSecWithInputSections = [](SectionCommand *cmd) { - auto *os = dyn_cast(cmd); - return os && os->hasInputSections; + auto *osd = dyn_cast(cmd); + return osd && osd->osec->hasInputSections; }; auto j = std::find_if(std::make_reverse_iterator(i), std::make_reverse_iterator(b), @@ -1412,8 +1415,8 @@ DenseMap order = buildSectionOrder(); maybeShuffle(order); for (SectionCommand *cmd : script->sectionCommands) - if (auto *sec = dyn_cast(cmd)) - sortSection(sec, order); + if (auto *osd = dyn_cast(cmd)) + sortSection(osd->osec, order); } template void Writer::sortSections() { @@ -1429,13 +1432,11 @@ sortInputSections(); for (SectionCommand *cmd : script->sectionCommands) - if (auto *osec = dyn_cast(cmd)) - osec->sortRank = getSectionRank(osec); + if (auto *osd = dyn_cast(cmd)) + osd->osec->sortRank = getSectionRank(osd->osec); if (!script->hasSectionsCommand) { // We know that all the OutputSections are contiguous in this case. - auto isSection = [](SectionCommand *cmd) { - return isa(cmd); - }; + auto isSection = [](SectionCommand *cmd) { return isa(cmd); }; std::stable_sort( llvm::find_if(script->sectionCommands, isSection), llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(), @@ -1492,8 +1493,8 @@ auto i = script->sectionCommands.begin(); auto e = script->sectionCommands.end(); auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) { - if (auto *sec = dyn_cast(cmd)) - return sec->sectionIndex == UINT32_MAX; + if (auto *osd = dyn_cast(cmd)) + return osd->osec->sectionIndex == UINT32_MAX; return false; }); @@ -1513,13 +1514,13 @@ while (nonScriptI != e) { auto pos = findOrphanPos(i, nonScriptI); - OutputSection *orphan = cast(*nonScriptI); + OutputSection *orphan = cast(*nonScriptI)->osec; // As an optimization, find all sections with the same sort rank // and insert them with one rotate. unsigned rank = orphan->sortRank; auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) { - return cast(cmd)->sortRank != rank; + return cast(cmd)->osec->sortRank != rank; }); std::rotate(pos, nonScriptI, end); nonScriptI = end; @@ -1668,11 +1669,13 @@ // If addrExpr is set, the address may not be a multiple of the alignment. // Warn because this is error-prone. for (SectionCommand *cmd : script->sectionCommands) - if (auto *os = dyn_cast(cmd)) - if (os->addr % os->alignment != 0) - warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " + - os->name + " is not a multiple of alignment (" + - Twine(os->alignment) + ")"); + if (auto *osd = dyn_cast(cmd)) { + OutputSection *osec = osd->osec; + if (osec->addr % osec->alignment != 0) + warn("address (0x" + Twine::utohexstr(osec->addr) + ") of section " + + osec->name + " is not a multiple of alignment (" + + Twine(osec->alignment) + ")"); + } } // If Input Sections have been shrunk (basic block sections) then @@ -1819,8 +1822,8 @@ if (!config->relocatable) { addStartEndSymbols(); for (SectionCommand *cmd : script->sectionCommands) - if (auto *sec = dyn_cast(cmd)) - addStartStopSymbols(sec); + if (auto *osd = dyn_cast(cmd)) + addStartStopSymbols(osd->osec); } // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. @@ -1988,7 +1991,8 @@ // Create a list of OutputSections, assign sectionIndex, and populate // in.shStrTab. for (SectionCommand *cmd : script->sectionCommands) - if (auto *osec = dyn_cast(cmd)) { + if (auto *osd = dyn_cast(cmd)) { + OutputSection *osec = osd->osec; outputSections.push_back(osec); osec->sectionIndex = outputSections.size(); osec->shName = in.shStrTab->addString(osec->name);