aboutsummaryrefslogtreecommitdiffstats
path: root/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-16 21:04:14 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-16 21:04:14 +0000
commit15f7a1a3796209b21af2817fdf11ca9932165c70 (patch)
treeb27ac12a6f210080b2233100767c839224666505 /ELF/LinkerScript.cpp
parent2079716dfb3fb7e4e24b8b2e85eb6780b981a0af (diff)
downloadsrc-15f7a1a3796209b21af2817fdf11ca9932165c70.tar.gz
src-15f7a1a3796209b21af2817fdf11ca9932165c70.zip
Vendor import of lld trunk r305575:vendor/lld/lld-trunk-r305575
Notes
Notes: svn path=/vendor/lld/dist/; revision=320021 svn path=/vendor/lld/lld-trunk-r305575/; revision=320022; tag=vendor/lld/lld-trunk-r305575
Diffstat (limited to 'ELF/LinkerScript.cpp')
-rw-r--r--ELF/LinkerScript.cpp136
1 files changed, 20 insertions, 116 deletions
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 9dd7ba52be19..f5a59f0c8c4d 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -142,10 +142,7 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) {
Sym->Value = V.getValue();
} else {
Sym->Section = V.Sec;
- if (Sym->Section->Flags & SHF_ALLOC)
- Sym->Value = alignTo(V.Val, V.Alignment);
- else
- Sym->Value = V.getValue();
+ Sym->Value = alignTo(V.Val, V.Alignment);
}
}
@@ -461,7 +458,7 @@ void LinkerScript::fabricateDefaultCommands() {
// For each OutputSection that needs a VA fabricate an OutputSectionCommand
// with an InputSectionDescription describing the InputSections
- for (OutputSection *Sec : *OutputSections) {
+ for (OutputSection *Sec : OutputSections) {
auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>");
OSCmd->Sec = Sec;
SecToCommand[Sec] = OSCmd;
@@ -649,7 +646,9 @@ void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
if (!Sec)
return;
- if (Cmd->AddrExpr && (Sec->Flags & SHF_ALLOC))
+ if (!(Sec->Flags & SHF_ALLOC))
+ Dot = 0;
+ else if (Cmd->AddrExpr)
setDot(Cmd->AddrExpr, Cmd->Location, false);
if (Cmd->LMAExpr) {
@@ -681,8 +680,7 @@ void LinkerScript::removeEmptyCommands() {
auto Pos = std::remove_if(
Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- return std::find(OutputSections->begin(), OutputSections->end(),
- Cmd->Sec) == OutputSections->end();
+ return Cmd->Sec == nullptr;
return false;
});
Opt.Commands.erase(Pos, Opt.Commands.end());
@@ -716,15 +714,12 @@ void LinkerScript::adjustSectionsBeforeSorting() {
auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags);
OutSec->SectionIndex = I;
- OutputSections->push_back(OutSec);
Cmd->Sec = OutSec;
SecToCommand[OutSec] = Cmd;
}
}
void LinkerScript::adjustSectionsAfterSorting() {
- placeOrphanSections();
-
// Try and find an appropriate memory region to assign offsets in.
for (BaseCommand *Base : Opt.Commands) {
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) {
@@ -764,106 +759,18 @@ void LinkerScript::adjustSectionsAfterSorting() {
removeEmptyCommands();
}
-// When placing orphan sections, we want to place them after symbol assignments
-// so that an orphan after
-// begin_foo = .;
-// foo : { *(foo) }
-// end_foo = .;
-// doesn't break the intended meaning of the begin/end symbols.
-// We don't want to go over sections since Writer<ELFT>::sortSections is the
-// one in charge of deciding the order of the sections.
-// We don't want to go over alignments, since doing so in
-// rx_sec : { *(rx_sec) }
-// . = ALIGN(0x1000);
-// /* 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) {
- if (isa<OutputSectionCommand>(Cmd))
- return false;
- if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd))
- return Assign->Name != ".";
- return true;
-}
-
-// Orphan sections are sections present in the input files which are
-// not explicitly placed into the output file by the linker script.
-//
-// When the control reaches this function, Opt.Commands contains
-// output section commands for non-orphan sections only. This function
-// adds new elements for orphan sections so that all sections are
-// explicitly handled by Opt.Commands.
-//
-// Writer<ELFT>::sortSections has already sorted output sections.
-// What we need to do is to scan OutputSections vector and
-// Opt.Commands in parallel to find orphan sections. If there is an
-// output section that doesn't have a corresponding entry in
-// Opt.Commands, we will insert a new entry to Opt.Commands.
-//
-// There is some ambiguity as to where exactly a new entry should be
-// inserted, because Opt.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
-// determine whether a new output command should be added before or
-// after another commands. For the details, look at shouldSkip
-// function.
-void LinkerScript::placeOrphanSections() {
- // The OutputSections are already in the correct order.
- // This loops creates or moves commands as needed so that they are in the
- // correct order.
- int CmdIndex = 0;
-
- // As a horrible special case, skip the first . assignment if it is before any
- // section. We do this because it is common to set a load address by starting
- // the script with ". = 0xabcd" and the expectation is that every section is
- // after that.
- auto FirstSectionOrDotAssignment =
- std::find_if(Opt.Commands.begin(), Opt.Commands.end(),
- [](BaseCommand *Cmd) { return !shouldSkip(Cmd); });
- if (FirstSectionOrDotAssignment != Opt.Commands.end()) {
- CmdIndex = FirstSectionOrDotAssignment - Opt.Commands.begin();
- if (isa<SymbolAssignment>(**FirstSectionOrDotAssignment))
- ++CmdIndex;
- }
-
- for (OutputSection *Sec : *OutputSections) {
- StringRef Name = Sec->Name;
-
- // Find the last spot where we can insert a command and still get the
- // correct result.
- auto CmdIter = Opt.Commands.begin() + CmdIndex;
- auto E = Opt.Commands.end();
- while (CmdIter != E && shouldSkip(*CmdIter)) {
- ++CmdIter;
- ++CmdIndex;
- }
-
- // If there is no command corresponding to this output section,
- // create one and put a InputSectionDescription in it so that both
- // representations agree on which input sections to use.
- OutputSectionCommand *Cmd = getCmd(Sec);
- if (!Cmd) {
- Cmd = createOutputSectionCommand(Name, "<internal>");
- Opt.Commands.insert(CmdIter, Cmd);
- ++CmdIndex;
-
- Cmd->Sec = Sec;
- SecToCommand[Sec] = Cmd;
- auto *ISD = make<InputSectionDescription>("");
- for (InputSection *IS : Sec->Sections)
- ISD->Sections.push_back(IS);
- Cmd->Commands.push_back(ISD);
-
+void LinkerScript::createOrphanCommands() {
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->SectionIndex != INT_MAX)
continue;
- }
-
- // Continue from where we found it.
- while (*CmdIter != Cmd) {
- ++CmdIter;
- ++CmdIndex;
- }
- ++CmdIndex;
+ OutputSectionCommand *Cmd =
+ createOutputSectionCommand(Sec->Name, "<internal>");
+ Cmd->Sec = Sec;
+ SecToCommand[Sec] = Cmd;
+ auto *ISD = make<InputSectionDescription>("");
+ ISD->Sections = Sec->Sections;
+ Cmd->Commands.push_back(ISD);
+ Opt.Commands.push_back(Cmd);
}
}
@@ -922,9 +829,7 @@ allocateHeaders(std::vector<PhdrEntry> &Phdrs,
return false;
}
-void LinkerScript::assignAddresses(
- std::vector<PhdrEntry> &Phdrs,
- ArrayRef<OutputSectionCommand *> OutputSectionCommands) {
+void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
ErrorOnMissingSection = true;
@@ -950,8 +855,6 @@ void LinkerScript::assignAddresses(
OutputSection *Sec = Cmd->Sec;
if (Sec->Flags & SHF_ALLOC)
MinVA = std::min<uint64_t>(MinVA, Sec->Addr);
- else
- Sec->Addr = 0;
}
allocateHeaders(Phdrs, OutputSectionCommands, MinVA);
@@ -979,7 +882,8 @@ std::vector<PhdrEntry> LinkerScript::createPhdrs() {
}
// Add output sections to program headers.
- for (OutputSection *Sec : *OutputSections) {
+ for (OutputSectionCommand *Cmd : OutputSectionCommands) {
+ OutputSection *Sec = Cmd->Sec;
if (!(Sec->Flags & SHF_ALLOC))
break;