for (OutputSection *os : outputSections) {
if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
continue;
- for (BaseCommand *bc : os->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(bc)) {
+ for (SectionCommand *cmd : os->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
std::vector<Patch843419Section *> patches =
patchInputSectionDescription(*isd);
if (!patches.empty()) {
for (OutputSection *os : outputSections) {
if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
continue;
- for (BaseCommand *bc : os->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(bc)) {
+ for (SectionCommand *cmd : os->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
std::vector<Patch657417Section *> patches =
patchInputSectionDescription(*isd);
if (!patches.empty()) {
// merging MergeInputSections into a single MergeSyntheticSection. From this
// point onwards InputSectionDescription::sections should be used instead of
// sectionBases.
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
sec->finalizeInputSections();
llvm::erase_if(inputSections, [](InputSectionBase *s) {
return isa<MergeInputSection>(s);
// InputSectionDescription::sections is populated by processSectionCommands().
// ICF may fold some input sections assigned to output sections. Remove them.
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
- for (BaseCommand *sub_base : sec->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(sub_base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
+ for (SectionCommand *subCmd : sec->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(subCmd))
llvm::erase_if(isd->sections,
[](InputSection *isec) { return !isec->isLive(); });
}
// Collect section/value pairs of linker-script-defined symbols. This is used to
// check whether symbol values converge.
-static SymbolAssignmentMap
-getSymbolAssignmentValues(const std::vector<BaseCommand *> §ionCommands) {
+static SymbolAssignmentMap getSymbolAssignmentValues(
+ const std::vector<SectionCommand *> §ionCommands) {
SymbolAssignmentMap ret;
- for (BaseCommand *base : sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- if (cmd->sym) // sym is nullptr for dot.
- ret.try_emplace(cmd->sym,
- std::make_pair(cmd->sym->section, cmd->sym->value));
+ for (SectionCommand *cmd : sectionCommands) {
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+ if (assign->sym) // sym is nullptr for dot.
+ ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
+ assign->sym->value));
continue;
}
- for (BaseCommand *sub_base : cast<OutputSection>(base)->commands)
- if (auto *cmd = dyn_cast<SymbolAssignment>(sub_base))
- if (cmd->sym)
- ret.try_emplace(cmd->sym,
- std::make_pair(cmd->sym->section, cmd->sym->value));
+ for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
+ if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
+ if (assign->sym)
+ ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
+ assign->sym->value));
}
return ret;
}
for (StringRef name : cmd.names) {
// If base is empty, it may have been discarded by
// adjustSectionsBeforeSorting(). We do not handle such output sections.
- auto from = llvm::find_if(sectionCommands, [&](BaseCommand *base) {
- return isa<OutputSection>(base) &&
- cast<OutputSection>(base)->name == name;
+ auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) {
+ return isa<OutputSection>(subCmd) &&
+ cast<OutputSection>(subCmd)->name == name;
});
if (from == sectionCommands.end())
continue;
sectionCommands.erase(from);
}
- auto insertPos = llvm::find_if(sectionCommands, [&cmd](BaseCommand *base) {
- auto *to = dyn_cast<OutputSection>(base);
- return to != nullptr && to->name == cmd.where;
- });
+ auto insertPos =
+ llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) {
+ auto *to = dyn_cast<OutputSection>(subCmd);
+ return to != nullptr && to->name == cmd.where;
+ });
if (insertPos == sectionCommands.end()) {
error("unable to insert " + cmd.names[0] +
(cmd.isAfter ? " after " : " before ") + cmd.where);
// over symbol assignment commands and create placeholder symbols if needed.
void LinkerScript::declareSymbols() {
assert(!ctx);
- for (BaseCommand *base : sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- declareSymbol(cmd);
+ for (SectionCommand *cmd : sectionCommands) {
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+ declareSymbol(assign);
continue;
}
// 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<OutputSection>(base);
+ auto *sec = cast<OutputSection>(cmd);
if (sec->constraint != ConstraintKind::NoConstraint)
continue;
- for (BaseCommand *base2 : sec->commands)
- if (auto *cmd = dyn_cast<SymbolAssignment>(base2))
- declareSymbol(cmd);
+ for (SectionCommand *cmd : sec->commands)
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+ declareSymbol(assign);
}
}
continue;
std::vector<InputSectionBase *> secs(part.armExidx->exidxSections.begin(),
part.armExidx->exidxSections.end());
- for (BaseCommand *base : outCmd.commands)
- if (auto *cmd = dyn_cast<InputSectionDescription>(base)) {
+ for (SectionCommand *cmd : outCmd.commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
std::vector<InputSectionBase *> matches =
- computeInputSections(cmd, secs);
+ computeInputSections(isd, secs);
for (InputSectionBase *s : matches)
discard(s);
}
LinkerScript::createInputSectionList(OutputSection &outCmd) {
std::vector<InputSectionBase *> ret;
- for (BaseCommand *base : outCmd.commands) {
- if (auto *cmd = dyn_cast<InputSectionDescription>(base)) {
- cmd->sectionBases = computeInputSections(cmd, inputSections);
- for (InputSectionBase *s : cmd->sectionBases)
+ for (SectionCommand *cmd : outCmd.commands) {
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
+ isd->sectionBases = computeInputSections(isd, inputSections);
+ for (InputSectionBase *s : isd->sectionBases)
s->parent = &outCmd;
- ret.insert(ret.end(), cmd->sectionBases.begin(), cmd->sectionBases.end());
+ ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end());
}
}
return ret;
for (OutputSection *osec : overwriteSections)
if (process(osec) && !map.try_emplace(osec->name, osec).second)
warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name);
- for (BaseCommand *&base : sectionCommands)
+ for (SectionCommand *&base : sectionCommands)
if (auto *osec = dyn_cast<OutputSection>(base)) {
if (OutputSection *overwrite = map.lookup(osec->name)) {
log(overwrite->location + " overwrites " + osec->name);
ctx = &state;
ctx->outSec = aether;
- for (BaseCommand *base : sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base))
- addSymbol(cmd);
+ for (SectionCommand *cmd : sectionCommands) {
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+ addSymbol(assign);
else
- for (BaseCommand *sub_base : cast<OutputSection>(base)->commands)
- if (auto *cmd = dyn_cast<SymbolAssignment>(sub_base))
- addSymbol(cmd);
+ for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
+ if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
+ addSymbol(assign);
}
ctx = nullptr;
}
-static OutputSection *findByName(ArrayRef<BaseCommand *> vec,
+static OutputSection *findByName(ArrayRef<SectionCommand *> vec,
StringRef name) {
- for (BaseCommand *base : vec)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : vec)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
if (sec->name == name)
return sec;
return nullptr;
// We visited SectionsCommands from processSectionCommands to
// layout sections. Now, we visit SectionsCommands again to fix
// section offsets.
- for (BaseCommand *base : sec->commands) {
+ for (SectionCommand *cmd : sec->commands) {
// This handles the assignments to symbol or to the dot.
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- cmd->addr = dot;
- assignSymbol(cmd, true);
- cmd->size = dot - cmd->addr;
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+ assign->addr = dot;
+ assignSymbol(assign, true);
+ assign->size = dot - assign->addr;
continue;
}
// Handle BYTE(), SHORT(), LONG(), or QUAD().
- if (auto *cmd = dyn_cast<ByteCommand>(base)) {
- cmd->offset = dot - ctx->outSec->addr;
- dot += cmd->size;
- expandOutputSection(cmd->size);
+ if (auto *data = dyn_cast<ByteCommand>(cmd)) {
+ data->offset = dot - ctx->outSec->addr;
+ dot += data->size;
+ expandOutputSection(data->size);
continue;
}
// Handle a single input section description command.
// It calculates and assigns the offsets for each section and also
// updates the output section size.
- for (InputSection *sec : cast<InputSectionDescription>(base)->sections)
+ for (InputSection *sec : cast<InputSectionDescription>(cmd)->sections)
output(sec);
}
if (sec.usedInExpression)
return false;
- for (BaseCommand *base : sec.commands) {
- if (auto cmd = dyn_cast<SymbolAssignment>(base))
+ for (SectionCommand *cmd : sec.commands) {
+ if (auto assign = dyn_cast<SymbolAssignment>(cmd))
// Don't create empty output sections just for unreferenced PROVIDE
// symbols.
- if (cmd->name != "." && !cmd->sym)
+ if (assign->name != "." && !assign->sym)
continue;
- if (!isa<InputSectionDescription>(*base))
+ if (!isa<InputSectionDescription>(*cmd))
return false;
}
return true;
uint64_t flags = SHF_ALLOC;
std::vector<StringRef> defPhdrs;
- for (BaseCommand *&cmd : sectionCommands) {
+ for (SectionCommand *&cmd : sectionCommands) {
auto *sec = dyn_cast<OutputSection>(cmd);
if (!sec)
continue;
// clutter the output.
// We instead remove trivially empty sections. The bfd linker seems even
// more aggressive at removing them.
- llvm::erase_if(sectionCommands, [&](BaseCommand *base) { return !base; });
+ llvm::erase_if(sectionCommands, [&](SectionCommand *cmd) { return !cmd; });
}
void LinkerScript::adjustSectionsAfterSorting() {
// Try and find an appropriate memory region to assign offsets in.
MemoryRegion *hint = nullptr;
- for (BaseCommand *base : sectionCommands) {
- if (auto *sec = dyn_cast<OutputSection>(base)) {
+ for (SectionCommand *cmd : sectionCommands) {
+ if (auto *sec = dyn_cast<OutputSection>(cmd)) {
if (!sec->lmaRegionName.empty()) {
if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
sec->lmaRegion = m;
// Walk the commands and propagate the program headers to commands that don't
// explicitly specify them.
- for (BaseCommand *base : sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
maybePropagatePhdrs(*sec, defPhdrs);
}
switchTo(aether);
SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands);
- for (BaseCommand *base : sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- cmd->addr = dot;
- assignSymbol(cmd, false);
- cmd->size = dot - cmd->addr;
+ for (SectionCommand *cmd : sectionCommands) {
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+ assign->addr = dot;
+ assignSymbol(assign, false);
+ assign->size = dot - assign->addr;
continue;
}
- assignOffsets(cast<OutputSection>(base));
+ assignOffsets(cast<OutputSection>(cmd));
}
ctx = nullptr;
ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr)
};
-struct BaseCommand {
- BaseCommand(int k) : kind(k) {}
+struct SectionCommand {
+ SectionCommand(int k) : kind(k) {}
int kind;
};
// This represents ". = <expr>" or "<symbol> = <expr>".
-struct SymbolAssignment : BaseCommand {
+struct SymbolAssignment : SectionCommand {
SymbolAssignment(StringRef name, Expr e, std::string loc)
- : BaseCommand(AssignmentKind), name(name), expression(e), location(loc) {}
+ : SectionCommand(AssignmentKind), name(name), expression(e),
+ location(loc) {}
- static bool classof(const BaseCommand *c) {
+ static bool classof(const SectionCommand *c) {
return c->kind == AssignmentKind;
}
SortSectionPolicy sortInner;
};
-class InputSectionDescription : public BaseCommand {
+class InputSectionDescription : public SectionCommand {
SingleStringMatcher filePat;
// Cache of the most recent input argument and result of matchesFile().
public:
InputSectionDescription(StringRef filePattern, uint64_t withFlags = 0,
uint64_t withoutFlags = 0)
- : BaseCommand(InputSectionKind), filePat(filePattern),
+ : SectionCommand(InputSectionKind), filePat(filePattern),
withFlags(withFlags), withoutFlags(withoutFlags) {}
- static bool classof(const BaseCommand *c) {
+ static bool classof(const SectionCommand *c) {
return c->kind == InputSectionKind;
}
};
// Represents BYTE(), SHORT(), LONG(), or QUAD().
-struct ByteCommand : BaseCommand {
+struct ByteCommand : SectionCommand {
ByteCommand(Expr e, unsigned size, std::string commandString)
- : BaseCommand(ByteKind), commandString(commandString), expression(e),
+ : SectionCommand(ByteKind), commandString(commandString), expression(e),
size(size) {}
- static bool classof(const BaseCommand *c) { return c->kind == ByteKind; }
+ static bool classof(const SectionCommand *c) { return c->kind == ByteKind; }
// Keeps string representing the command. Used for -Map" is perhaps better.
std::string commandString;
void processInsertCommands();
// SECTIONS command list.
- std::vector<BaseCommand *> sectionCommands;
+ std::vector<SectionCommand *> sectionCommands;
// PHDRS command list.
std::vector<PhdrsCommand> phdrsCommands;
<< " Size Align Out In Symbol\n";
OutputSection* osec = nullptr;
- for (BaseCommand *base : script->sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- if (cmd->provide && !cmd->sym)
+ for (SectionCommand *cmd : script->sectionCommands) {
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+ if (assign->provide && !assign->sym)
continue;
- uint64_t lma = osec ? osec->getLMA() + cmd->addr - osec->getVA(0) : 0;
- writeHeader(os, cmd->addr, lma, cmd->size, 1);
- os << cmd->commandString << '\n';
+ uint64_t lma = osec ? osec->getLMA() + assign->addr - osec->getVA(0) : 0;
+ writeHeader(os, assign->addr, lma, assign->size, 1);
+ os << assign->commandString << '\n';
continue;
}
- osec = cast<OutputSection>(base);
+ osec = cast<OutputSection>(cmd);
writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
os << osec->name << '\n';
// Dump symbols for each input section.
- for (BaseCommand *base : osec->commands) {
- if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
+ for (SectionCommand *subCmd : osec->commands) {
+ if (auto *isd = dyn_cast<InputSectionDescription>(subCmd)) {
for (InputSection *isec : isd->sections) {
if (auto *ehSec = dyn_cast<EhFrameSection>(isec)) {
printEhFrame(os, ehSec);
continue;
}
- if (auto *cmd = dyn_cast<ByteCommand>(base)) {
- writeHeader(os, osec->addr + cmd->offset, osec->getLMA() + cmd->offset,
- cmd->size, 1);
- os << indent8 << cmd->commandString << '\n';
+ if (auto *data = dyn_cast<ByteCommand>(subCmd)) {
+ writeHeader(os, osec->addr + data->offset,
+ osec->getLMA() + data->offset, data->size, 1);
+ os << indent8 << data->commandString << '\n';
continue;
}
- if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
- if (cmd->provide && !cmd->sym)
+ if (auto *assign = dyn_cast<SymbolAssignment>(subCmd)) {
+ if (assign->provide && !assign->sym)
continue;
- writeHeader(os, cmd->addr, osec->getLMA() + cmd->addr - osec->getVA(0),
- cmd->size, 1);
- os << indent8 << cmd->commandString << '\n';
+ writeHeader(os, assign->addr,
+ osec->getLMA() + assign->addr - osec->getVA(0),
+ assign->size, 1);
+ os << indent8 << assign->commandString << '\n';
continue;
}
}
}
OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
- : BaseCommand(OutputSectionKind),
+ : SectionCommand(OutputSectionKind),
SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
/*Info*/ 0, /*Link*/ 0) {}
// to compute an output offset for each piece of each input section.
void OutputSection::finalizeInputSections() {
std::vector<MergeSyntheticSection *> mergeSections;
- for (BaseCommand *base : commands) {
- auto *cmd = dyn_cast<InputSectionDescription>(base);
- if (!cmd)
+ for (SectionCommand *cmd : commands) {
+ auto *isd = dyn_cast<InputSectionDescription>(cmd);
+ if (!isd)
continue;
- cmd->sections.reserve(cmd->sectionBases.size());
- for (InputSectionBase *s : cmd->sectionBases) {
+ isd->sections.reserve(isd->sectionBases.size());
+ for (InputSectionBase *s : isd->sectionBases) {
MergeInputSection *ms = dyn_cast<MergeInputSection>(s);
if (!ms) {
- cmd->sections.push_back(cast<InputSection>(s));
+ isd->sections.push_back(cast<InputSection>(s));
continue;
}
mergeSections.push_back(syn);
i = std::prev(mergeSections.end());
syn->entsize = ms->entsize;
- cmd->sections.push_back(syn);
+ isd->sections.push_back(syn);
}
(*i)->addSection(ms);
}
// sectionBases should not be used from this point onwards. Clear it to
// catch misuses.
- cmd->sectionBases.clear();
+ isd->sectionBases.clear();
// Some input sections may be removed from the list after ICF.
- for (InputSection *s : cmd->sections)
+ for (InputSection *s : isd->sections)
commitSection(s);
}
for (auto *ms : mergeSections)
return Out::elfHeader->size + Out::programHeaders->size;
}
-bool OutputSection::classof(const BaseCommand *c) {
+bool OutputSection::classof(const SectionCommand *c) {
return c->kind == OutputSectionKind;
}
void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
assert(isLive());
- for (BaseCommand *b : commands)
+ for (SectionCommand *b : commands)
if (auto *isd = dyn_cast<InputSectionDescription>(b))
sortByOrder(isd->sections, order);
}
// Linker scripts may have BYTE()-family commands with which you
// can write arbitrary bytes to the output. Process them if any.
- for (BaseCommand *base : commands)
- if (auto *data = dyn_cast<ByteCommand>(base))
+ for (SectionCommand *cmd : commands)
+ if (auto *data = dyn_cast<ByteCommand>(cmd))
writeInt(buf + data->offset, data->expression().getValue(), data->size);
}
}
InputSection *elf::getFirstInputSection(const OutputSection *os) {
- for (BaseCommand *base : os->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(base))
+ for (SectionCommand *cmd : os->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
if (!isd->sections.empty())
return isd->sections[0];
return nullptr;
std::vector<InputSection *> elf::getInputSections(const OutputSection *os) {
std::vector<InputSection *> ret;
- for (BaseCommand *base : os->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(base))
+ for (SectionCommand *cmd : os->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
ret.insert(ret.end(), isd->sections.begin(), isd->sections.end());
return ret;
}
// 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 BaseCommand, public SectionBase {
+class OutputSection final : public SectionCommand, public SectionBase {
public:
OutputSection(StringRef name, uint32_t type, uint64_t flags);
return s->kind() == SectionBase::Output;
}
- static bool classof(const BaseCommand *c);
+ static bool classof(const SectionCommand *c);
uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
Expr alignExpr;
Expr lmaExpr;
Expr subalignExpr;
- std::vector<BaseCommand *> commands;
+ std::vector<SectionCommand *> commands;
std::vector<StringRef> phdrs;
llvm::Optional<std::array<uint8_t, 4>> filler;
ConstraintKind constraint = ConstraintKind::NoConstraint;
using namespace lld::elf;
static Optional<std::string> getLinkerScriptLocation(const Symbol &sym) {
- for (BaseCommand *base : script->sectionCommands)
- if (auto *cmd = dyn_cast<SymbolAssignment>(base))
- if (cmd->sym == &sym)
- return cmd->location;
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+ if (assign->sym == &sym)
+ return assign->location;
return None;
}
for (OutputSection *os : outputSections) {
if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
continue;
- for (BaseCommand *bc : os->commands)
+ for (SectionCommand *bc : os->commands)
if (auto *isd = dyn_cast<InputSectionDescription>(bc))
fn(os, isd);
}
// Find InputSectionRange within Target Output Section (TOS) that the
// InputSection (IS) that we need to precede is in.
OutputSection *tos = isec->getParent();
- for (BaseCommand *bc : tos->commands) {
+ for (SectionCommand *bc : tos->commands) {
auto *isd = dyn_cast<InputSectionDescription>(bc);
if (!isd || isd->sections.empty())
continue;
void readSectionAddressType(OutputSection *cmd);
OutputSection *readOverlaySectionDescription();
OutputSection *readOutputSectionDescription(StringRef outSec);
- std::vector<BaseCommand *> readOverlay();
+ std::vector<SectionCommand *> readOverlay();
std::vector<StringRef> readOutputSectionPhdrs();
std::pair<uint64_t, uint64_t> readInputSectionFlags();
InputSectionDescription *readInputSectionDescription(StringRef tok);
// sections that use the same virtual memory range and normally would trigger
// linker's sections sanity check failures.
// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
-std::vector<BaseCommand *> ScriptParser::readOverlay() {
+std::vector<SectionCommand *> ScriptParser::readOverlay() {
// VA and LMA expressions are optional, though for simplicity of
// implementation we assume they are not. That is what OVERLAY was designed
// for first of all: to allow sections with overlapping VAs at different LMAs.
Expr lmaExpr = readParenExpr();
expect("{");
- std::vector<BaseCommand *> v;
+ std::vector<SectionCommand *> v;
OutputSection *prev = nullptr;
while (!errorCount() && !consume("}")) {
// VA is the same for all sections. The LMAs are consecutive in memory
// Here we want to create the Dot assignment command to achieve that.
Expr moveDot = [=] {
uint64_t max = 0;
- for (BaseCommand *cmd : v)
+ for (SectionCommand *cmd : v)
max = std::max(max, cast<OutputSection>(cmd)->size);
return addrExpr().getValue() + max;
};
void ScriptParser::readSections() {
expect("{");
- std::vector<BaseCommand *> v;
+ std::vector<SectionCommand *> v;
while (!errorCount() && !consume("}")) {
StringRef tok = next();
if (tok == "OVERLAY") {
- for (BaseCommand *cmd : readOverlay())
+ for (SectionCommand *cmd : readOverlay())
v.push_back(cmd);
continue;
} else if (tok == "INCLUDE") {
continue;
}
- if (BaseCommand *cmd = readAssignment(tok))
+ if (SectionCommand *cmd = readAssignment(tok))
v.push_back(cmd);
else
v.push_back(readOutputSectionDescription(tok));
setError("expected AFTER/BEFORE, but got '" + next() + "'");
StringRef where = next();
std::vector<StringRef> names;
- for (BaseCommand *cmd : v)
+ for (SectionCommand *cmd : v)
if (auto *os = dyn_cast<OutputSection>(cmd))
names.push_back(os->name);
if (!names.empty())
got.pagesMap) {
const OutputSection *os = p.first;
uint64_t secSize = 0;
- for (BaseCommand *cmd : os->commands) {
+ for (SectionCommand *cmd : os->commands) {
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
for (InputSection *isec : isd->sections) {
uint64_t off = alignTo(secSize, isec->alignment);
// late, and we do not know them here. For simplicity, we just always create
// a .symtab_shndx section when the amount of output sections is huge.
size_t size = 0;
- for (BaseCommand *base : script->sectionCommands)
- if (isa<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (isa<OutputSection>(cmd))
++size;
return size >= SHN_LORESERVE;
}
bool PPC32Got2Section::isNeeded() const {
// See the comment below. This is not needed if there is no other
// InputSection.
- for (BaseCommand *base : getParent()->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(base))
+ for (SectionCommand *cmd : getParent()->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
for (InputSection *isec : isd->sections)
if (isec != this)
return true;
// PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is
// to collect input sections named ".got2".
uint32_t offset = 0;
- for (BaseCommand *base : getParent()->commands)
- if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
+ for (SectionCommand *cmd : getParent()->commands)
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
for (InputSection *isec : isd->sections) {
if (isec == this)
continue;
}
static OutputSection *findSection(StringRef name, unsigned partition = 1) {
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
if (sec->name == name && sec->partition == partition)
return sec;
return nullptr;
// referring to a section (that happens if the section is a synthetic one), we
// don't create a section symbol for that section.
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
- for (BaseCommand *base : script->sectionCommands) {
- auto *sec = dyn_cast<OutputSection>(base);
+ for (SectionCommand *cmd : script->sectionCommands) {
+ auto *sec = dyn_cast<OutputSection>(cmd);
if (!sec)
continue;
- auto i = llvm::find_if(sec->commands, [](BaseCommand *base) {
- if (auto *isd = dyn_cast<InputSectionDescription>(base))
+ auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) {
+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
return !isd->sections.empty();
return false;
});
return rank;
}
-static bool compareSections(const BaseCommand *aCmd, const BaseCommand *bCmd) {
+static bool compareSections(const SectionCommand *aCmd,
+ const SectionCommand *bCmd) {
const OutputSection *a = cast<OutputSection>(aCmd);
const OutputSection *b = cast<OutputSection>(bCmd);
return countLeadingZeros(a->sortRank ^ b->sortRank);
}
-static int getRankProximity(OutputSection *a, BaseCommand *b) {
+static int getRankProximity(OutputSection *a, SectionCommand *b) {
auto *sec = dyn_cast<OutputSection>(b);
return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1;
}
// /* The RW PT_LOAD starts here*/
// rw_sec : { *(rw_sec) }
// would mean that the RW PT_LOAD would become unaligned.
-static bool shouldSkip(BaseCommand *cmd) {
+static bool shouldSkip(SectionCommand *cmd) {
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
return assign->name != ".";
return false;
// We want to place orphan sections so that they share as much
// characteristics with their neighbors as possible. For example, if
// both are rw, or both are tls.
-static std::vector<BaseCommand *>::iterator
-findOrphanPos(std::vector<BaseCommand *>::iterator b,
- std::vector<BaseCommand *>::iterator e) {
+static std::vector<SectionCommand *>::iterator
+findOrphanPos(std::vector<SectionCommand *>::iterator b,
+ std::vector<SectionCommand *>::iterator e) {
OutputSection *sec = cast<OutputSection>(*e);
// Find the first element that has as close a rank as possible.
- auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) {
+ auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
return getRankProximity(sec, a) < getRankProximity(sec, b);
});
if (i == e)
break;
}
- auto isOutputSecWithInputSections = [](BaseCommand *cmd) {
+ auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
auto *os = dyn_cast<OutputSection>(cmd);
return os && os->hasInputSections;
};
// digit radix sort. The sections may be sorted stably again by a more
// significant key.
if (!order.empty())
- for (BaseCommand *b : sec->commands)
+ for (SectionCommand *b : sec->commands)
if (auto *isd = dyn_cast<InputSectionDescription>(b))
sortISDBySectionOrder(isd, order);
// Build the order once since it is expensive.
DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
maybeShuffle(order);
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
sortSection(sec, order);
}
sortInputSections();
- for (BaseCommand *base : script->sectionCommands) {
- auto *os = dyn_cast<OutputSection>(base);
+ for (SectionCommand *cmd : script->sectionCommands) {
+ auto *os = dyn_cast<OutputSection>(cmd);
if (!os)
continue;
os->sortRank = getSectionRank(os);
if (!script->hasSectionsCommand) {
// We know that all the OutputSections are contiguous in this case.
- auto isSection = [](BaseCommand *base) { return isa<OutputSection>(base); };
+ auto isSection = [](SectionCommand *cmd) {
+ return isa<OutputSection>(cmd);
+ };
std::stable_sort(
llvm::find_if(script->sectionCommands, isSection),
llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
auto i = script->sectionCommands.begin();
auto e = script->sectionCommands.end();
- auto nonScriptI = std::find_if(i, e, [](BaseCommand *base) {
- if (auto *sec = dyn_cast<OutputSection>(base))
+ auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) {
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
return sec->sectionIndex == UINT32_MAX;
return false;
});
// the script with ". = 0xabcd" and the expectation is that every section is
// after that.
auto firstSectionOrDotAssignment =
- std::find_if(i, e, [](BaseCommand *cmd) { return !shouldSkip(cmd); });
+ std::find_if(i, e, [](SectionCommand *cmd) { return !shouldSkip(cmd); });
if (firstSectionOrDotAssignment != e &&
isa<SymbolAssignment>(**firstSectionOrDotAssignment))
++firstSectionOrDotAssignment;
// 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, [=](BaseCommand *cmd) {
+ auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) {
return cast<OutputSection>(cmd)->sortRank != rank;
});
std::rotate(pos, nonScriptI, end);
// Sorting is performed separately.
std::vector<InputSection **> scriptSections;
std::vector<InputSection *> sections;
- for (BaseCommand *base : sec->commands) {
- auto *isd = dyn_cast<InputSectionDescription>(base);
+ for (SectionCommand *cmd : sec->commands) {
+ auto *isd = dyn_cast<InputSectionDescription>(cmd);
if (!isd)
continue;
bool hasLinkOrder = false;
// If addrExpr is set, the address may not be a multiple of the alignment.
// Warn because this is error-prone.
- for (BaseCommand *cmd : script->sectionCommands)
+ for (SectionCommand *cmd : script->sectionCommands)
if (auto *os = dyn_cast<OutputSection>(cmd))
if (os->addr % os->alignment != 0)
warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " +
// If we reach here, then ss is an unused synthetic section and we want
// to remove it from the corresponding input section description, and
// orphanSections.
- for (BaseCommand *b : os->commands)
+ for (SectionCommand *b : os->commands)
if (auto *isd = dyn_cast<InputSectionDescription>(b))
isdSet.insert(isd);
// addresses of each section by section name. Add such symbols.
if (!config->relocatable) {
addStartEndSymbols();
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
addStartStopSymbols(sec);
}
// Now that we have the final list, create a list of all the
// OutputSections for convenience.
- for (BaseCommand *base : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(base))
+ for (SectionCommand *cmd : script->sectionCommands)
+ if (auto *sec = dyn_cast<OutputSection>(cmd))
outputSections.push_back(sec);
// Prefer command line supplied address over other constraints.