forked from OSchip/llvm-project
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:
parent
b920f85d8e
commit
ac27de9dc7
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 +
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue