//===----------------------------------------------------------------------===//
//
// This file contains the parser/evaluator of the linker script.
-// It parses a linker script and write the result to Config or ScriptConfig
-// objects.
-//
-// If SECTIONS command is used, a ScriptConfig contains an AST
-// of the command which will later be consumed by createSections() and
-// assignAddresses().
//
//===----------------------------------------------------------------------===//
for (unsigned I = 0; I < Opt.Commands.size(); ++I) {
auto Iter = Opt.Commands.begin() + I;
const std::unique_ptr<BaseCommand> &Base1 = *Iter;
+
+ // Handle symbol assignments outside of any output section.
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
if (shouldDefine<ELFT>(Cmd))
addSymbol<ELFT>(Cmd);
continue;
}
+
if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
// If we don't have SECTIONS then output sections have already been
// created by Writer<ELFT>. The LinkerScript<ELFT>::assignAddresses
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
+ // The output section name `/DISCARD/' is special.
+ // Any input section assigned to it is discarded.
if (Cmd->Name == "/DISCARD/") {
discard(V);
continue;
}
+ // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive
+ // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input
+ // sections satisfy a given constraint. If not, a directive is handled
+ // as if it wasn't present from the beginning.
+ //
+ // Because we'll iterate over Commands many more times, the easiest
+ // way to "make it as if it wasn't present" is to just remove it.
if (!matchConstraints<ELFT>(V, Cmd->Constraint)) {
for (InputSectionBase<ELFT> *S : V)
S->Assigned = false;
continue;
}
+ // A directive may contain symbol definitions like this:
+ // ".foo : { ...; bar = .; }". Handle them.
for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
if (shouldDefine<ELFT>(OutCmd))
addSymbol<ELFT>(OutCmd);
- for (InputSectionBase<ELFT> *Sec : V) {
- addSection(Factory, Sec, Cmd->Name);
- if (uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0)
- Sec->Alignment = Subalign;
+ // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
+ // is given, input sections are aligned to that value, whether the
+ // given value is larger or smaller than the original section alignment.
+ if (Cmd->SubalignExpr) {
+ uint32_t Subalign = Cmd->SubalignExpr(0);
+ for (InputSectionBase<ELFT> *S : V)
+ S->Alignment = Subalign;
}
+
+ // Add input sections to an output section.
+ for (InputSectionBase<ELFT> *S : V)
+ addSection(Factory, S, Cmd->Name);
}
}
}
+// Add sections that didn't match any sections command.
template <class ELFT>
-void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
- processCommands(Factory);
-
- // Add orphan sections.
+void LinkerScript<ELFT>::addOrphanSections(OutputSectionFactory<ELFT> &Factory) {
for (InputSectionBase<ELFT> *S : Symtab<ELFT>::X->Sections)
if (S->Live && !S->OutSec)
addSection(Factory, S, getOutputSectionName(S->Name));
return Ret;
}
+// This function assigns offsets to input sections and an output section
+// for a single sections command (e.g. ".text { *(.text); }").
template <class ELFT>
void LinkerScript<ELFT>::assignOffsets(OutputSectionCommand *Cmd) {
if (Cmd->LMAExpr)
if (Sections.empty())
return;
switchTo(Sections[0]);
+
// Find the last section output location. We will output orphan sections
// there so that end symbols point to the correct location.
auto E = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
auto Pos = std::remove_if(
Opt.Commands.begin(), Opt.Commands.end(),
[&](const std::unique_ptr<BaseCommand> &Base) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
- if (!Cmd)
- return false;
- return findSections<ELFT>(Cmd->Name, *OutputSections).empty();
+ if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()))
+ return findSections<ELFT>(Cmd->Name, *OutputSections).empty();
+ return false;
});
Opt.Commands.erase(Pos, Opt.Commands.end());
}
}
auto *Cmd = cast<OutputSectionCommand>(Base.get());
-
if (Cmd->AddrExpr)
Dot = Cmd->AddrExpr(Dot);
-
assignOffsets(Cmd);
}
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
+ // Create linker-synthesized sections such as .got or .plt.
+ // Such sections are of type input section.
createSyntheticSections();
+ // We need to create some reserved symbols such as _end. Create them.
if (!Config->Relocatable)
addReservedSymbols();
+ // Some architectures use small displacements for jump instructions.
+ // It is linker's responsibility to create thunks containing long
+ // jump instructions if jump targets are too far. Create thunks.
if (Target->NeedsThunks)
forEachRelSec(createThunks<ELFT>);
+ // Create output sections.
Script<ELFT>::X->OutputSections = &OutputSections;
if (ScriptConfig->HasSections) {
- Script<ELFT>::X->createSections(Factory);
+ // If linker script contains SECTIONS commands, let it create sections.
+ Script<ELFT>::X->processCommands(Factory);
+
+ // Linker scripts may have left some input sections unassigned.
+ // Assign such sections using the default rule.
+ Script<ELFT>::X->addOrphanSections(Factory);
} else {
+ // If linker script does not contain SECTIONS commands, create
+ // output sections by default rules. We still need to give the
+ // linker script a chance to run, because it might contain
+ // non-SECTIONS commands such as ASSERT.
createSections();
Script<ELFT>::X->processCommands(Factory);
}
if (Config->Discard != DiscardPolicy::All)
copyLocalSymbols();
+ // Now that we have a complete set of output sections. This function
+ // completes section contents. For example, we need to add strings
+ // to the string table, and add entries to .got and .plt.
+ // finalizeSections does that.
finalizeSections();
if (HasError)
return;
fixAbsoluteSymbols();
}
+ // Write the result down to a file.
openFile();
if (HasError)
return;
} else {
writeSectionsBinary();
}
+
+ // Backfill .note.gnu.build-id section content. This is done at last
+ // because the content is usually a hash value of the entire output file.
writeBuildId();
if (HasError)
return;
+
if (auto EC = Buffer->commit())
error(EC, "failed to write to the output file");
- if (Config->ExitEarly) {
- // Flush the output streams and exit immediately. A full shutdown is a good
- // test that we are keeping track of all allocated memory, but actually
- // freeing it is a waste of time in a regular linker run.
+
+ // Flush the output streams and exit immediately. A full shutdown
+ // is a good test that we are keeping track of all allocated memory,
+ // but actually freeing it is a waste of time in a regular linker run.
+ if (Config->ExitEarly)
exitLld(0);
- }
}
// Initialize Out<ELFT> members.