[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:
parent
2f07534263
commit
7051aeef7a
|
@ -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()) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(); });
|
||||
}
|
||||
|
|
|
@ -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 *> §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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue