diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2690,8 +2690,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/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 { @@ -267,8 +268,7 @@ uint64_t tbssAddr = 0; }; - llvm::DenseMap - nameToOutputSection; + llvm::DenseMap nameToOutputSection; void addSymbol(SymbolAssignment *cmd); void assignSymbol(SymbolAssignment *cmd, bool inSec); @@ -304,8 +304,8 @@ uint64_t dot; public: - OutputSection *createOutputSection(StringRef name, StringRef location); - OutputSection *getOrCreateOutputSection(StringRef name); + OutputDesc *createOutputSection(StringRef name, StringRef location); + OutputDesc *getOrCreateOutputSection(StringRef name); bool hasPhdrsCommands() { return !phdrsCommands.empty(); } uint64_t getDot() { return dot; } @@ -357,7 +357,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 @@ -130,26 +130,26 @@ return getValue() - getSecAddr(); } -OutputSection *LinkerScript::createOutputSection(StringRef name, - StringRef location) { - OutputSection *&secRef = nameToOutputSection[CachedHashStringRef(name)]; - OutputSection *sec; - if (secRef && secRef->location.empty()) { +OutputDesc *LinkerScript::createOutputSection(StringRef name, + StringRef location) { + OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)]; + OutputDesc *sec; + if (secRef && secRef->osec.location.empty()) { // There was a forward reference. sec = secRef; } else { - sec = make(name, SHT_PROGBITS, 0); + sec = make(name, SHT_PROGBITS, 0); if (!secRef) secRef = sec; } - sec->location = std::string(location); + sec->osec.location = std::string(location); return sec; } -OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) { - OutputSection *&cmdRef = nameToOutputSection[CachedHashStringRef(name)]; +OutputDesc *LinkerScript::getOrCreateOutputSection(StringRef name) { + OutputDesc *&cmdRef = nameToOutputSection[CachedHashStringRef(name)]; if (!cmdRef) - cmdRef = make(name, SHT_PROGBITS, 0); + cmdRef = make(name, SHT_PROGBITS, 0); return cmdRef; } @@ -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,10 +352,10 @@ // 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); - if (sec->constraint != ConstraintKind::NoConstraint) + const OutputSection &sec = cast(cmd)->osec; + if (sec.constraint != ConstraintKind::NoConstraint) continue; - for (SectionCommand *cmd : sec->commands) + for (SectionCommand *cmd : sec.commands) if (auto *assign = dyn_cast(cmd)) declareSymbol(assign); } @@ -645,18 +645,20 @@ // Process OVERWRITE_SECTIONS first so that it can overwrite the main script // or orphans. - DenseMap map; + 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) + !map.try_emplace(CachedHashStringRef(osec->name), osd).second) warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name); + } for (SectionCommand *&base : sectionCommands) - if (auto *osec = dyn_cast(base)) { - if (OutputSection *overwrite = - map.lookup(CachedHashStringRef(osec->name))) { - log(overwrite->location + " overwrites " + osec->name); - overwrite->sectionIndex = i++; + if (auto *osd = dyn_cast(base)) { + OutputSection *osec = &osd->osec; + if (OutputDesc *overwrite = map.lookup(CachedHashStringRef(osec->name))) { + log(overwrite->osec.location + " overwrites " + osec->name); + overwrite->osec.sectionIndex = i++; base = overwrite; } else if (process(osec)) { osec->sectionIndex = i++; @@ -666,9 +668,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 +692,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,22 +703,20 @@ 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; } -static OutputSection *createSection(InputSectionBase *isec, - StringRef outsecName) { - OutputSection *sec = script->createOutputSection(outsecName, ""); - sec->recordSection(isec); - return sec; +static OutputDesc *createSection(InputSectionBase *isec, StringRef outsecName) { + OutputDesc *osd = script->createOutputSection(outsecName, ""); + osd->osec.recordSection(isec); + return osd; } -static OutputSection * -addInputSec(StringMap> &map, - InputSectionBase *isec, StringRef outsecName) { +static OutputDesc *addInputSec(StringMap> &map, + InputSectionBase *isec, StringRef outsecName) { // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r // option is given. A section with SHT_GROUP defines a "section group", and // its members have SHF_GROUP attribute. Usually these flags have already been @@ -743,8 +743,9 @@ return nullptr; } - out->relocationSection = createSection(isec, outsecName); - return out->relocationSection; + OutputDesc *osd = createSection(isec, outsecName); + out->relocationSection = &osd->osec; + return osd; } // The ELF spec just says @@ -813,15 +814,15 @@ return nullptr; } - OutputSection *sec = createSection(isec, outsecName); - v.push_back(sec); - return sec; + OutputDesc *osd = createSection(isec, outsecName); + v.push_back(&osd->osec); + return osd; } // 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) { @@ -833,8 +834,8 @@ } else if (OutputSection *sec = findByName(sectionCommands, name)) { sec->recordSection(s); } else { - if (OutputSection *os = addInputSec(map, s, name)) - v.push_back(os); + if (OutputDesc *osd = addInputSec(map, s, name)) + v.push_back(osd); assert(isa(s) || s->getOutputSection()->sectionIndex == UINT32_MAX); } @@ -1138,9 +1139,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 +1193,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 +1221,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 +1317,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 @@ -31,7 +31,7 @@ // 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 +39,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); @@ -119,6 +117,16 @@ std::array getFiller(); }; +struct OutputDesc final : SectionCommand { + OutputSection osec; + OutputDesc(StringRef name, uint32_t type, uint64_t flags) + : SectionCommand(OutputSectionKind), osec(name, type, flags) {} + + static bool classof(const SectionCommand *c) { + return c->kind == OutputSectionKind; + } +}; + int getPriority(StringRef s); InputSection *getFirstInputSection(const OutputSection *os); 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 @@ -91,8 +91,8 @@ std::array readFill(); bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2); void readSectionAddressType(OutputSection *cmd); - OutputSection *readOverlaySectionDescription(); - OutputSection *readOutputSectionDescription(StringRef outSec); + OutputDesc *readOverlaySectionDescription(); + OutputDesc *readOutputSectionDescription(StringRef outSec); SmallVector readOverlay(); SmallVector readOutputSectionPhdrs(); std::pair readInputSectionFlags(); @@ -534,14 +534,14 @@ while (!errorCount() && !consume("}")) { // VA is the same for all sections. The LMAs are consecutive in memory // starting from the base load address specified. - OutputSection *os = readOverlaySectionDescription(); - os->addrExpr = addrExpr; + OutputDesc *osd = readOverlaySectionDescription(); + osd->osec.addrExpr = addrExpr; if (prev) - os->lmaExpr = [=] { return prev->getLMA() + prev->size; }; + osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; }; else - os->lmaExpr = lmaExpr; - v.push_back(os); - prev = os; + osd->osec.lmaExpr = lmaExpr; + v.push_back(osd); + prev = &osd->osec; } // According to the specification, at the end of the overlay, the location @@ -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}); } @@ -869,45 +869,44 @@ }; } -OutputSection *ScriptParser::readOverlaySectionDescription() { - OutputSection *cmd = - script->createOutputSection(next(), getCurrentLocation()); - cmd->inOverlay = true; +OutputDesc *ScriptParser::readOverlaySectionDescription() { + OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation()); + osd->osec.inOverlay = true; expect("{"); while (!errorCount() && !consume("}")) { uint64_t withFlags = 0; uint64_t withoutFlags = 0; if (consume("INPUT_SECTION_FLAGS")) std::tie(withFlags, withoutFlags) = readInputSectionFlags(); - cmd->commands.push_back( + osd->osec.commands.push_back( readInputSectionRules(next(), withFlags, withoutFlags)); } - return cmd; + return osd; } -OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { - OutputSection *cmd = - script->createOutputSection(outSec, getCurrentLocation()); +OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) { + OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation()); + OutputSection *osec = &cmd->osec; size_t symbolsReferenced = script->referencedSymbols.size(); if (peek() != ":") - readSectionAddressType(cmd); + readSectionAddressType(osec); expect(":"); std::string location = getCurrentLocation(); if (consume("AT")) - cmd->lmaExpr = readParenExpr(); + osec->lmaExpr = readParenExpr(); if (consume("ALIGN")) - cmd->alignExpr = checkAlignment(readParenExpr(), location); + osec->alignExpr = checkAlignment(readParenExpr(), location); if (consume("SUBALIGN")) - cmd->subalignExpr = checkAlignment(readParenExpr(), location); + osec->subalignExpr = checkAlignment(readParenExpr(), location); // Parse constraints. if (consume("ONLY_IF_RO")) - cmd->constraint = ConstraintKind::ReadOnly; + osec->constraint = ConstraintKind::ReadOnly; if (consume("ONLY_IF_RW")) - cmd->constraint = ConstraintKind::ReadWrite; + osec->constraint = ConstraintKind::ReadWrite; expect("{"); while (!errorCount() && !consume("}")) { @@ -915,9 +914,9 @@ if (tok == ";") { // Empty commands are allowed. Do nothing here. } else if (SymbolAssignment *assign = readAssignment(tok)) { - cmd->commands.push_back(assign); + osec->commands.push_back(assign); } else if (ByteCommand *data = readByteCommand(tok)) { - cmd->commands.push_back(data); + osec->commands.push_back(data); } else if (tok == "CONSTRUCTORS") { // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors // by name. This is for very old file formats such as ECOFF/XCOFF. @@ -928,13 +927,13 @@ // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html if (peek() != "(") setError("( expected, but got " + peek()); - cmd->filler = readFill(); + osec->filler = readFill(); } else if (tok == "SORT") { readSort(); } else if (tok == "INCLUDE") { readInclude(); } else if (peek() == "(") { - cmd->commands.push_back(readInputSectionDescription(tok)); + osec->commands.push_back(readInputSectionDescription(tok)); } else { // We have a file name and no input sections description. It is not a // commonly used syntax, but still acceptable. In that case, all sections @@ -944,27 +943,27 @@ // case above. auto *isd = make(tok); isd->sectionPatterns.push_back({{}, StringMatcher("*")}); - cmd->commands.push_back(isd); + osec->commands.push_back(isd); } } if (consume(">")) - cmd->memoryRegionName = std::string(next()); + osec->memoryRegionName = std::string(next()); if (consume("AT")) { expect(">"); - cmd->lmaRegionName = std::string(next()); + osec->lmaRegionName = std::string(next()); } - if (cmd->lmaExpr && !cmd->lmaRegionName.empty()) + if (osec->lmaExpr && !osec->lmaRegionName.empty()) error("section can't have both LMA and a load region"); - cmd->phdrs = readOutputSectionPhdrs(); + osec->phdrs = readOutputSectionPhdrs(); if (peek() == "=" || peek().startswith("=")) { inExpr = true; consume("="); - cmd->filler = readFill(); + osec->filler = readFill(); inExpr = false; } @@ -972,7 +971,7 @@ consume(","); if (script->referencedSymbols.size() > symbolsReferenced) - cmd->expressionsUseSymbols = true; + osec->expressionsUseSymbols = true; return cmd; } @@ -1318,7 +1317,7 @@ } if (tok == "ADDR") { StringRef name = readParenLiteral(); - OutputSection *osec = script->getOrCreateOutputSection(name); + OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; osec->usedInExpression = true; return [=]() -> ExprValue { checkIfExists(*osec, location); @@ -1343,7 +1342,7 @@ } if (tok == "ALIGNOF") { StringRef name = readParenLiteral(); - OutputSection *osec = script->getOrCreateOutputSection(name); + OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; return [=] { checkIfExists(*osec, location); return osec->alignment; @@ -1398,7 +1397,7 @@ } if (tok == "LOADADDR") { StringRef name = readParenLiteral(); - OutputSection *osec = script->getOrCreateOutputSection(name); + OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; osec->usedInExpression = true; return [=] { checkIfExists(*osec, location); @@ -1442,7 +1441,7 @@ } if (tok == "SIZEOF") { StringRef name = readParenLiteral(); - OutputSection *cmd = script->getOrCreateOutputSection(name); + OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec; // Linker script does not create an output section if its content is empty. // We want to allow SIZEOF(.foo) where .foo is a section which happened to // be empty. 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; @@ -1106,13 +1107,15 @@ // The more branches in getSectionRank that match, the more similar they are. // Since each branch corresponds to a bit flag, we can just use // countLeadingZeros. -static int getRankProximityAux(OutputSection *a, OutputSection *b) { - return countLeadingZeros(a->sortRank ^ b->sortRank); +static int getRankProximityAux(const OutputSection &a, const OutputSection &b) { + return countLeadingZeros(a.sortRank ^ b.sortRank); } 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 *curSecDesc = dyn_cast(*i); + if (!curSecDesc || !curSecDesc->osec.hasInputSections) continue; - if (getRankProximity(sec, curSec) != proximity || - sortRank < curSec->sortRank) + if (getRankProximity(sec, curSecDesc) != proximity || + sortRank < curSecDesc->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);