Remove ScriptConfiguration class and move the members to LinkerScript class.

ScriptConfiguration was a class to contain parsed results of
linker scripts. LinkerScript is a class to interpret it.

That ditinction was needed because we haven't instantiated
LinkerScript early (because, IIRC, LinkerScript class was a
ELFT template function). So, when we parse linker scripts,
we couldn't directly store the result to a LinkerScript instance.

Now, that limitation is gone. We instantiate LinkerScript
at the very beginning of our main function. We can directly
store parse results to a LinkerScript instance.

llvm-svn: 315403
This commit is contained in:
Rui Ueyama 2017-10-11 01:19:33 +00:00
parent b920f85d8e
commit ac27de9dc7
7 changed files with 88 additions and 95 deletions

View File

@ -1035,7 +1035,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// Some symbols (such as __ehdr_start) are defined lazily only when there
// are undefined symbols for them, so we add these to trigger that logic.
for (StringRef Sym : Script->Opt.ReferencedSymbols)
for (StringRef Sym : Script->ReferencedSymbols)
Symtab->addUndefined<ELFT>(Sym);
// Handle the `--undefined <sym>` options.

View File

@ -130,7 +130,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
std::vector<lto::SymbolResolution> Resols(Syms.size());
DenseSet<StringRef> ScriptSymbols;
for (BaseCommand *Base : Script->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base))
ScriptSymbols.insert(Cmd->Name);

View File

@ -201,7 +201,7 @@ static std::string filename(InputFile *File) {
}
bool LinkerScript::shouldKeep(InputSectionBase *S) {
for (InputSectionDescription *ID : Opt.KeptSections) {
for (InputSectionDescription *ID : KeptSections) {
std::string Filename = filename(S->File);
if (ID->FilePat.match(Filename))
for (SectionPattern &P : ID->SectionPatterns)
@ -366,7 +366,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
// which will map to whatever the first actual section is.
Aether = make<OutputSection>("", 0, SHF_ALLOC);
Aether->SectionIndex = 1;
auto State = make_unique<AddressState>(Opt);
auto State = make_unique<AddressState>();
// CurAddressState captures the local AddressState and makes it accessible
// deliberately. This is needed as there are some cases where we cannot just
@ -375,14 +375,14 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
CurAddressState = State.get();
CurAddressState->OutSec = Aether;
for (size_t I = 0; I < Opt.Commands.size(); ++I) {
for (size_t I = 0; I < Commands.size(); ++I) {
// Handle symbol assignments outside of any output section.
if (auto *Cmd = dyn_cast<SymbolAssignment>(Opt.Commands[I])) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Commands[I])) {
addSymbol(Cmd);
continue;
}
if (auto *Sec = dyn_cast<OutputSection>(Opt.Commands[I])) {
if (auto *Sec = dyn_cast<OutputSection>(Commands[I])) {
std::vector<InputSectionBase *> V = createInputSectionList(*Sec);
// The output section name `/DISCARD/' is special.
@ -402,7 +402,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
if (!matchConstraints(V, Sec->Constraint)) {
for (InputSectionBase *S : V)
S->Assigned = false;
Opt.Commands.erase(Opt.Commands.begin() + I);
Commands.erase(Commands.begin() + I);
--I;
continue;
}
@ -448,8 +448,7 @@ void LinkerScript::fabricateDefaultCommands() {
auto Expr = [=] {
return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize());
};
Opt.Commands.insert(Opt.Commands.begin(),
make<SymbolAssignment>(".", Expr, ""));
Commands.insert(Commands.begin(), make<SymbolAssignment>(".", Expr, ""));
}
static OutputSection *findByName(ArrayRef<BaseCommand *> Vec,
@ -463,7 +462,7 @@ static OutputSection *findByName(ArrayRef<BaseCommand *> Vec,
// Add sections that didn't match any sections command.
void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
unsigned End = Opt.Commands.size();
unsigned End = Commands.size();
for (InputSectionBase *S : InputSections) {
if (!S->Live || S->Parent)
@ -472,14 +471,14 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
StringRef Name = getOutputSectionName(S->Name);
log(toString(S) + " is being placed in '" + Name + "'");
if (OutputSection *Sec = findByName(
makeArrayRef(Opt.Commands).slice(0, End), Name)) {
if (OutputSection *Sec =
findByName(makeArrayRef(Commands).slice(0, End), Name)) {
Sec->addSection(cast<InputSection>(S));
continue;
}
if (OutputSection *OS = Factory.addInputSec(S, Name))
Script->Opt.Commands.push_back(OS);
Script->Commands.push_back(OS);
assert(S->getOutputSection()->SectionIndex == INT_MAX);
}
}
@ -588,8 +587,8 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {
// If a memory region name was specified in the output section command,
// then try to find that region first.
if (!Sec->MemoryRegionName.empty()) {
auto It = Opt.MemoryRegions.find(Sec->MemoryRegionName);
if (It != Opt.MemoryRegions.end())
auto It = MemoryRegions.find(Sec->MemoryRegionName);
if (It != MemoryRegions.end())
return It->second;
error("memory region '" + Sec->MemoryRegionName + "' not declared");
return nullptr;
@ -598,11 +597,11 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {
// If at least one memory region is defined, all sections must
// belong to some memory region. Otherwise, we don't need to do
// anything for memory regions.
if (Opt.MemoryRegions.empty())
if (MemoryRegions.empty())
return nullptr;
// See if a region can be found by matching section flags.
for (auto &Pair : Opt.MemoryRegions) {
for (auto &Pair : MemoryRegions) {
MemoryRegion *M = Pair.second;
if ((M->Flags & Sec->Flags) && (M->NegFlags & Sec->Flags) == 0)
return M;
@ -649,7 +648,7 @@ void LinkerScript::removeEmptyCommands() {
// clutter the output.
// We instead remove trivially empty sections. The bfd linker seems even
// more aggressive at removing them.
llvm::erase_if(Opt.Commands, [&](BaseCommand *Base) {
llvm::erase_if(Commands, [&](BaseCommand *Base) {
if (auto *Sec = dyn_cast<OutputSection>(Base))
return !Sec->Live;
return false;
@ -670,7 +669,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// consequeces and gives us a section to put the symbol in.
uint64_t Flags = SHF_ALLOC;
for (BaseCommand * Cmd : Opt.Commands) {
for (BaseCommand *Cmd : Commands) {
auto *Sec = dyn_cast<OutputSection>(Cmd);
if (!Sec)
continue;
@ -689,7 +688,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
void LinkerScript::adjustSectionsAfterSorting() {
// Try and find an appropriate memory region to assign offsets in.
for (BaseCommand *Base : Opt.Commands) {
for (BaseCommand *Base : Commands) {
if (auto *Sec = dyn_cast<OutputSection>(Base)) {
if (!Sec->Live)
continue;
@ -709,14 +708,14 @@ void LinkerScript::adjustSectionsAfterSorting() {
// SECTIONS { .aaa : { *(.aaa) } }
std::vector<StringRef> DefPhdrs;
auto FirstPtLoad =
std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(),
std::find_if(PhdrsCommands.begin(), PhdrsCommands.end(),
[](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; });
if (FirstPtLoad != Opt.PhdrsCommands.end())
if (FirstPtLoad != PhdrsCommands.end())
DefPhdrs.push_back(FirstPtLoad->Name);
// Walk the commands and propagate the program headers to commands that don't
// explicitly specify them.
for (BaseCommand *Base : Opt.Commands) {
for (BaseCommand *Base : Commands) {
auto *Sec = dyn_cast<OutputSection>(Base);
if (!Sec)
continue;
@ -765,7 +764,7 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
uint64_t HeaderSize = getHeaderSize();
// When linker script with SECTIONS is being used, don't output headers
// unless there's a space for them.
uint64_t Base = Opt.HasSections ? alignDown(Min, Config->MaxPageSize) : 0;
uint64_t Base = HasSections ? alignDown(Min, Config->MaxPageSize) : 0;
if (HeaderSize <= Min - Base || Script->hasPhdrsCommands()) {
Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
Out::ElfHeader->Addr = Min;
@ -781,8 +780,8 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
[](const PhdrEntry *E) { return E->p_type == PT_PHDR; });
}
LinkerScript::AddressState::AddressState(const ScriptConfiguration &Opt) {
for (auto &MRI : Opt.MemoryRegions) {
LinkerScript::AddressState::AddressState() {
for (auto &MRI : Script->MemoryRegions) {
const MemoryRegion *MR = MRI.second;
MemRegionOffset[MR] = MR->Origin;
}
@ -793,7 +792,7 @@ void LinkerScript::assignAddresses() {
// By default linker scripts use an initial value of 0 for '.', but prefer
// -image-base if set.
Dot = Config->ImageBase ? *Config->ImageBase : 0;
auto State = make_unique<AddressState>(Opt);
auto State = make_unique<AddressState>();
// CurAddressState captures the local AddressState and makes it accessible
// deliberately. This is needed as there are some cases where we cannot just
@ -803,7 +802,7 @@ void LinkerScript::assignAddresses() {
ErrorOnMissingSection = true;
switchTo(Aether);
for (BaseCommand *Base : Opt.Commands) {
for (BaseCommand *Base : Commands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
assignSymbol(Cmd, false);
continue;
@ -825,7 +824,7 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
// Process PHDRS and FILEHDR keywords because they are not
// real output sections and cannot be added in the following loop.
for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) {
for (const PhdrsCommand &Cmd : PhdrsCommands) {
PhdrEntry *Phdr = make<PhdrEntry>(Cmd.Type, Cmd.Flags ? *Cmd.Flags : PF_R);
if (Cmd.HasFilehdr)
@ -845,7 +844,7 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
// Assign headers specified by linker script
for (size_t Id : getPhdrIndices(Sec)) {
Ret[Id]->add(Sec);
if (!Opt.PhdrsCommands[Id].Flags.hasValue())
if (!PhdrsCommands[Id].Flags.hasValue())
Ret[Id]->p_flags |= Sec->getPhdrFlags();
}
}
@ -858,9 +857,9 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
// no PT_INTERP is there, there's no place to emit an
// .interp, so we don't do that in that case.
bool LinkerScript::needsInterpSection() {
if (Opt.PhdrsCommands.empty())
if (PhdrsCommands.empty())
return true;
for (PhdrsCommand &Cmd : Opt.PhdrsCommands)
for (PhdrsCommand &Cmd : PhdrsCommands)
if (Cmd.Type == PT_INTERP)
return true;
return false;
@ -899,7 +898,7 @@ std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Cmd) {
std::vector<size_t> Ret;
for (StringRef S : Cmd->Phdrs) {
if (Optional<size_t> Idx = getPhdrIndex(Opt.PhdrsCommands, S))
if (Optional<size_t> Idx = getPhdrIndex(PhdrsCommands, S))
Ret.push_back(*Idx);
else if (S != "NONE")
error(Cmd->Location + ": section header '" + S +

View File

@ -181,39 +181,19 @@ struct PhdrsCommand {
Expr LMAExpr = nullptr;
};
// ScriptConfiguration holds linker script parse results.
struct ScriptConfiguration {
// Used to assign addresses to sections.
std::vector<BaseCommand *> Commands;
// Used to assign sections to headers.
std::vector<PhdrsCommand> PhdrsCommands;
bool HasSections = false;
// List of section patterns specified with KEEP commands. They will
// be kept even if they are unused and --gc-sections is specified.
std::vector<InputSectionDescription *> KeptSections;
// A map from memory region name to a memory region descriptor.
llvm::DenseMap<llvm::StringRef, MemoryRegion *> MemoryRegions;
// A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols;
};
class LinkerScript final {
// Temporary state used in processCommands() and assignAddresses()
// that must be reinitialized for each call to the above functions, and must
// not be used outside of the scope of a call to the above functions.
struct AddressState {
AddressState();
uint64_t ThreadBssOffset = 0;
OutputSection *OutSec = nullptr;
MemoryRegion *MemRegion = nullptr;
llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset;
std::function<uint64_t()> LMAOffset;
AddressState(const ScriptConfiguration &Opt);
};
llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection;
void assignSymbol(SymbolAssignment *Cmd, bool InSec);
@ -243,7 +223,7 @@ public:
OutputSection *createOutputSection(StringRef Name, StringRef Location);
OutputSection *getOrCreateOutputSection(StringRef Name);
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
bool hasPhdrsCommands() { return !PhdrsCommands.empty(); }
uint64_t getDot() { return Dot; }
void discard(ArrayRef<InputSectionBase *> V);
@ -265,8 +245,23 @@ public:
void addSymbol(SymbolAssignment *Cmd);
void processCommands(OutputSectionFactory &Factory);
// Parsed linker script configurations are set to this struct.
ScriptConfiguration Opt;
// SECTIONS command list.
std::vector<BaseCommand *> Commands;
// PHDRS command list.
std::vector<PhdrsCommand> PhdrsCommands;
bool HasSections = false;
// List of section patterns specified with KEEP commands. They will
// be kept even if they are unused and --gc-sections is specified.
std::vector<InputSectionDescription *> KeptSections;
// A map from memory region name to a memory region descriptor.
llvm::DenseMap<llvm::StringRef, MemoryRegion *> MemoryRegions;
// A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols;
};
extern LinkerScript *Script;

View File

@ -229,7 +229,7 @@ template <class ELFT> static void doGcSections() {
MarkSymbol(Symtab->find(Config->Fini));
for (StringRef S : Config->Undefined)
MarkSymbol(Symtab->find(S));
for (StringRef S : Script->Opt.ReferencedSymbols)
for (StringRef S : Script->ReferencedSymbols)
MarkSymbol(Symtab->find(S));
// Preserve externally-visible symbols if the symbols defined by this

View File

@ -234,7 +234,7 @@ void ScriptParser::readLinkerScript() {
continue;
if (Tok == "ASSERT") {
Script->Opt.Commands.push_back(readAssert());
Script->Commands.push_back(readAssert());
} else if (Tok == "ENTRY") {
readEntry();
} else if (Tok == "EXTERN") {
@ -262,7 +262,7 @@ void ScriptParser::readLinkerScript() {
} else if (Tok == "VERSION") {
readVersion();
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
Script->Opt.Commands.push_back(Cmd);
Script->Commands.push_back(Cmd);
} else {
setError("unknown directive: " + Tok);
}
@ -407,7 +407,7 @@ void ScriptParser::readPhdrs() {
setError("unexpected header attribute: " + next());
}
Script->Opt.PhdrsCommands.push_back(Cmd);
Script->PhdrsCommands.push_back(Cmd);
}
}
@ -418,11 +418,11 @@ void ScriptParser::readRegionAlias() {
StringRef Name = next();
expect(")");
if (Script->Opt.MemoryRegions.count(Alias))
if (Script->MemoryRegions.count(Alias))
setError("redefinition of memory region '" + Alias + "'");
if (!Script->Opt.MemoryRegions.count(Name))
if (!Script->MemoryRegions.count(Name))
setError("memory region '" + Name + "' is not defined");
Script->Opt.MemoryRegions[Alias] = Script->Opt.MemoryRegions[Name];
Script->MemoryRegions[Alias] = Script->MemoryRegions[Name];
}
void ScriptParser::readSearchDir() {
@ -434,7 +434,7 @@ void ScriptParser::readSearchDir() {
}
void ScriptParser::readSections() {
Script->Opt.HasSections = true;
Script->HasSections = true;
// -no-rosegment is used to avoid placing read only non-executable sections in
// their own segment. We do the same if SECTIONS command is present in linker
@ -451,7 +451,7 @@ void ScriptParser::readSections() {
else
Cmd = readOutputSectionDescription(Tok);
}
Script->Opt.Commands.push_back(Cmd);
Script->Commands.push_back(Cmd);
}
}
@ -572,7 +572,7 @@ ScriptParser::readInputSectionDescription(StringRef Tok) {
StringRef FilePattern = next();
InputSectionDescription *Cmd = readInputSectionRules(FilePattern);
expect(")");
Script->Opt.KeptSections.push_back(Cmd);
Script->KeptSections.push_back(Cmd);
return Cmd;
}
return readInputSectionRules(Tok);
@ -1013,9 +1013,9 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "LENGTH") {
StringRef Name = readParenLiteral();
if (Script->Opt.MemoryRegions.count(Name) == 0)
if (Script->MemoryRegions.count(Name) == 0)
setError("memory region not defined: " + Name);
return [=] { return Script->Opt.MemoryRegions[Name]->Length; };
return [=] { return Script->MemoryRegions[Name]->Length; };
}
if (Tok == "LOADADDR") {
StringRef Name = readParenLiteral();
@ -1027,9 +1027,9 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "ORIGIN") {
StringRef Name = readParenLiteral();
if (Script->Opt.MemoryRegions.count(Name) == 0)
if (Script->MemoryRegions.count(Name) == 0)
setError("memory region not defined: " + Name);
return [=] { return Script->Opt.MemoryRegions[Name]->Origin; };
return [=] { return Script->MemoryRegions[Name]->Origin; };
}
if (Tok == "SEGMENT_START") {
expect("(");
@ -1061,7 +1061,7 @@ Expr ScriptParser::readPrimary() {
// Tok is a symbol name.
if (!isValidCIdentifier(Tok))
setError("malformed number: " + Tok);
Script->Opt.ReferencedSymbols.push_back(Tok);
Script->ReferencedSymbols.push_back(Tok);
return [=] { return Script->getSymbolValue(Location, Tok); };
}
@ -1261,11 +1261,11 @@ void ScriptParser::readMemory() {
uint64_t Length = readMemoryAssignment("LENGTH", "len", "l");
// Add the memory region to the region map.
if (Script->Opt.MemoryRegions.count(Name))
if (Script->MemoryRegions.count(Name))
setError("region '" + Name + "' already defined");
MemoryRegion *MR = make<MemoryRegion>();
*MR = {Name, Origin, Length, Flags, NegFlags};
Script->Opt.MemoryRegions[Name] = MR;
Script->MemoryRegions[Name] = MR;
}
}

View File

@ -161,7 +161,7 @@ template <class ELFT> void Writer<ELFT>::run() {
addReservedSymbols();
// Create output sections.
if (Script->Opt.HasSections) {
if (Script->HasSections) {
// If linker script contains SECTIONS commands, let it create sections.
Script->processCommands(Factory);
@ -466,7 +466,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
// Create one STT_SECTION symbol for each output section we might
// have a relocation with.
for (BaseCommand *Base : Script->Opt.Commands) {
for (BaseCommand *Base : Script->Commands) {
auto *Sec = dyn_cast<OutputSection>(Base);
if (!Sec)
continue;
@ -813,7 +813,7 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
addOptionalRegular<ELFT>(Name, Out::ElfHeader, 0, STV_HIDDEN);
// If linker script do layout we do not need to create any standart symbols.
if (Script->Opt.HasSections)
if (Script->HasSections)
return;
auto Add = [](StringRef S, int64_t Pos) {
@ -849,7 +849,7 @@ static void sortBySymbolsOrder() {
// Sort sections by priority.
DenseMap<SectionBase *, int> SectionOrder = buildSectionOrder();
for (BaseCommand *Base : Script->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
}
@ -876,8 +876,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
Factory.addInputSec(IS, getOutputSectionName(IS->Name)))
Vec.push_back(Sec);
Script->Opt.Commands.insert(Script->Opt.Commands.begin(), Vec.begin(),
Vec.end());
Script->Commands.insert(Script->Commands.begin(), Vec.begin(), Vec.end());
Script->fabricateDefaultCommands();
sortBySymbolsOrder();
@ -1052,15 +1051,15 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
if (Config->Relocatable)
return;
for (BaseCommand *Base : Script->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
Sec->SortRank = getSectionRank(Sec);
if (!Script->Opt.HasSections) {
if (!Script->HasSections) {
// We know that all the OutputSections are contiguous in
// this case.
auto E = Script->Opt.Commands.end();
auto I = Script->Opt.Commands.begin();
auto E = Script->Commands.end();
auto I = Script->Commands.begin();
auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); };
I = std::find_if(I, E, IsSection);
E = std::find_if(llvm::make_reverse_iterator(E),
@ -1101,7 +1100,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// a PT_LOAD.
//
// There is some ambiguity as to where exactly a new entry should be
// inserted, because Opt.Commands contains not only output section
// inserted, because Commands contains not only output section
// commands but also other types of commands such as symbol assignment
// expressions. There's no correct answer here due to the lack of the
// formal specification of the linker script. We use heuristics to
@ -1109,8 +1108,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// after another commands. For the details, look at shouldSkip
// function.
auto I = Script->Opt.Commands.begin();
auto E = Script->Opt.Commands.end();
auto I = Script->Commands.begin();
auto E = Script->Commands.end();
auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
if (auto *Sec = dyn_cast<OutputSection>(Base))
return Sec->Live && Sec->SectionIndex == INT_MAX;
@ -1241,7 +1240,7 @@ 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->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
addStartStopSymbols(Sec);
}
@ -1305,7 +1304,7 @@ 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->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
OutputSections.push_back(Sec);
@ -1356,7 +1355,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
InX::Dynamic},
[](SyntheticSection *SS) { SS->finalizeContents(); });
if (!Script->Opt.HasSections && !Config->Relocatable)
if (!Script->HasSections && !Config->Relocatable)
fixSectionAlignments();
// Some architectures use small displacements for jump instructions.
@ -1441,7 +1440,7 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
}
template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
for (BaseCommand *Base : Script->Opt.Commands)
for (BaseCommand *Base : Script->Commands)
if (auto *Sec = dyn_cast<OutputSection>(Base))
if (Sec->Name == Name)
return Sec;
@ -1682,7 +1681,7 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
for (OutputSection *Sec : OutputSections) {
Off = setOffset(Sec, Off);
if (Script->Opt.HasSections)
if (Script->HasSections)
continue;
// If this is a last section of the last executable segment and that
// segment is the last loadable segment, align the offset of the
@ -1861,7 +1860,7 @@ static void fillTrap(uint8_t *I, uint8_t *End) {
// We'll leave other pages in segments as-is because the rest will be
// overwritten by output sections.
template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
if (Script->Opt.HasSections)
if (Script->HasSections)
return;
// Fill the last page.