[ELF] Rename BaseCommand to SectionCommand. NFC

BaseCommand was picked when PHDRS/INSERT/etc were not implemented. Rename it to
SectionCommand to match `sectionCommands` and make it clear that the commands
are used in SECTIONS (except a special case for SymbolAssignment).

Also, improve naming of some BaseCommand variables (base -> cmd).
This commit is contained in:
Fangrui Song 2021-11-25 20:24:23 -08:00
parent 2f07534263
commit 7051aeef7a
13 changed files with 190 additions and 184 deletions

View File

@ -630,8 +630,8 @@ bool AArch64Err843419Patcher::createFixes() {
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()) {

View File

@ -525,8 +525,8 @@ bool ARMErr657417Patcher::createFixes() {
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()) {

View File

@ -2476,8 +2476,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// 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);

View File

@ -552,10 +552,10 @@ template <class ELFT> void ICF<ELFT>::run() {
// 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(); });
}

View File

@ -275,21 +275,21 @@ using SymbolAssignmentMap =
// 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 *> &sectionCommands) {
static SymbolAssignmentMap getSymbolAssignmentValues(
const std::vector<SectionCommand *> &sectionCommands) {
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;
}
@ -316,9 +316,9 @@ void LinkerScript::processInsertCommands() {
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;
@ -326,10 +326,11 @@ void LinkerScript::processInsertCommands() {
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);
@ -347,9 +348,9 @@ void LinkerScript::processInsertCommands() {
// 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;
}
@ -357,12 +358,12 @@ void LinkerScript::declareSymbols() {
// 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);
}
}
@ -588,10 +589,10 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) {
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);
}
@ -602,12 +603,12 @@ std::vector<InputSectionBase *>
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;
@ -665,7 +666,7 @@ void LinkerScript::processSectionCommands() {
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);
@ -699,22 +700,22 @@ void LinkerScript::processSymbolAssignments() {
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;
@ -1058,27 +1059,27 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
// 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);
}
@ -1109,14 +1110,14 @@ static bool isDiscardable(const OutputSection &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;
@ -1163,7 +1164,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
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;
@ -1209,14 +1210,14 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// 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;
@ -1242,8 +1243,8 @@ void LinkerScript::adjustSectionsAfterSorting() {
// 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);
}
@ -1332,14 +1333,14 @@ const Defined *LinkerScript::assignAddresses() {
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;

View File

@ -82,17 +82,18 @@ enum SectionsCommandKind {
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;
}
@ -182,7 +183,7 @@ public:
SortSectionPolicy sortInner;
};
class InputSectionDescription : public BaseCommand {
class InputSectionDescription : public SectionCommand {
SingleStringMatcher filePat;
// Cache of the most recent input argument and result of matchesFile().
@ -191,10 +192,10 @@ class InputSectionDescription : public BaseCommand {
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;
}
@ -223,12 +224,12 @@ public:
};
// 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;
@ -340,7 +341,7 @@ public:
void processInsertCommands();
// SECTIONS command list.
std::vector<BaseCommand *> sectionCommands;
std::vector<SectionCommand *> sectionCommands;
// PHDRS command list.
std::vector<PhdrsCommand> phdrsCommands;

View File

@ -164,23 +164,23 @@ void elf::writeMapFile() {
<< " 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);
@ -196,19 +196,20 @@ void elf::writeMapFile() {
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;
}
}

View File

@ -69,7 +69,7 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {
}
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) {}
@ -165,15 +165,15 @@ void OutputSection::commitSection(InputSection *isec) {
// 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;
}
@ -202,17 +202,17 @@ void OutputSection::finalizeInputSections() {
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)
@ -236,13 +236,13 @@ uint64_t elf::getHeaderSize() {
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);
}
@ -366,8 +366,8 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
// 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);
}
@ -504,8 +504,8 @@ int elf::getPriority(StringRef s) {
}
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;
@ -513,8 +513,8 @@ InputSection *elf::getFirstInputSection(const OutputSection *os) {
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;
}

View File

@ -29,7 +29,7 @@ class InputSectionBase;
// 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);
@ -37,7 +37,7 @@ public:
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);
@ -82,7 +82,7 @@ public:
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;

View File

@ -66,10 +66,10 @@ using namespace lld;
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;
}
@ -1640,7 +1640,7 @@ static void forEachInputSectionDescription(
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);
}
@ -1817,7 +1817,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *isec) {
// 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;

View File

@ -93,7 +93,7 @@ private:
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);
@ -519,7 +519,7 @@ void ScriptParser::readSearchDir() {
// 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.
@ -529,7 +529,7 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
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
@ -550,7 +550,7 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
// 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;
};
@ -566,11 +566,11 @@ void ScriptParser::readOverwriteSections() {
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") {
@ -578,7 +578,7 @@ void ScriptParser::readSections() {
continue;
}
if (BaseCommand *cmd = readAssignment(tok))
if (SectionCommand *cmd = readAssignment(tok))
v.push_back(cmd);
else
v.push_back(readOutputSectionDescription(tok));
@ -598,7 +598,7 @@ void ScriptParser::readSections() {
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())

View File

@ -900,7 +900,7 @@ void MipsGotSection::build() {
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);
@ -2300,8 +2300,8 @@ bool SymtabShndxSection::isNeeded() const {
// 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;
}
@ -3604,8 +3604,8 @@ PPC32Got2Section::PPC32Got2Section()
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;
@ -3618,8 +3618,8 @@ void PPC32Got2Section::finalizeContents() {
// 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;

View File

@ -271,8 +271,8 @@ void elf::addReservedSymbols() {
}
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;
@ -725,12 +725,12 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
// 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;
});
@ -991,7 +991,8 @@ static unsigned getSectionRank(const OutputSection *sec) {
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);
@ -1148,7 +1149,7 @@ static int getRankProximityAux(OutputSection *a, OutputSection *b) {
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;
}
@ -1167,7 +1168,7 @@ static int getRankProximity(OutputSection *a, BaseCommand *b) {
// /* 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;
@ -1176,13 +1177,13 @@ static bool shouldSkip(BaseCommand *cmd) {
// 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)
@ -1211,7 +1212,7 @@ findOrphanPos(std::vector<BaseCommand *>::iterator b,
break;
}
auto isOutputSecWithInputSections = [](BaseCommand *cmd) {
auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
auto *os = dyn_cast<OutputSection>(cmd);
return os && os->hasInputSections;
};
@ -1420,7 +1421,7 @@ static void sortSection(OutputSection *sec,
// 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);
@ -1453,8 +1454,8 @@ template <class ELFT> void Writer<ELFT>::sortInputSections() {
// 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);
}
@ -1469,8 +1470,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
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);
@ -1485,7 +1486,9 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
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(),
@ -1540,8 +1543,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
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;
});
@ -1554,7 +1557,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// 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;
@ -1567,7 +1570,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// 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);
@ -1608,8 +1611,8 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
// 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;
@ -1712,7 +1715,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
// 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 " +
@ -1842,7 +1845,7 @@ static void removeUnusedSyntheticSections() {
// 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);
@ -1873,8 +1876,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// 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);
}
@ -2027,8 +2030,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// 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.