forked from OSchip/llvm-project
Add comments.
This patch rearranges code a bit to make it easy to explain. llvm-svn: 287515
This commit is contained in:
parent
e0be2901cd
commit
0b1b695a9e
|
@ -8,12 +8,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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().
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -308,11 +302,14 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
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
|
||||
|
@ -325,11 +322,20 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
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;
|
||||
|
@ -338,25 +344,32 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
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));
|
||||
|
@ -482,6 +495,8 @@ findSections(StringRef Name, const std::vector<OutputSectionBase *> &Sections) {
|
|||
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)
|
||||
|
@ -491,6 +506,7 @@ void LinkerScript<ELFT>::assignOffsets(OutputSectionCommand *Cmd) {
|
|||
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(),
|
||||
|
@ -517,10 +533,9 @@ template <class ELFT> void LinkerScript<ELFT>::removeEmptyCommands() {
|
|||
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());
|
||||
}
|
||||
|
@ -672,10 +687,8 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
|
|||
}
|
||||
|
||||
auto *Cmd = cast<OutputSectionCommand>(Base.get());
|
||||
|
||||
if (Cmd->AddrExpr)
|
||||
Dot = Cmd->AddrExpr(Dot);
|
||||
|
||||
assignOffsets(Cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ public:
|
|||
~LinkerScript();
|
||||
|
||||
void processCommands(OutputSectionFactory<ELFT> &Factory);
|
||||
void createSections(OutputSectionFactory<ELFT> &Factory);
|
||||
void addOrphanSections(OutputSectionFactory<ELFT> &Factory);
|
||||
void removeEmptyCommands();
|
||||
void adjustSectionsBeforeSorting();
|
||||
void adjustSectionsAfterSorting();
|
||||
|
|
|
@ -133,18 +133,34 @@ template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }
|
|||
|
||||
// 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);
|
||||
}
|
||||
|
@ -152,6 +168,10 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
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;
|
||||
|
@ -178,6 +198,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
fixAbsoluteSymbols();
|
||||
}
|
||||
|
||||
// Write the result down to a file.
|
||||
openFile();
|
||||
if (HasError)
|
||||
return;
|
||||
|
@ -187,17 +208,21 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
} 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.
|
||||
|
|
Loading…
Reference in New Issue