summaryrefslogtreecommitdiffstats
path: root/lld/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2019-09-06 13:23:42 +0000
committerNico Weber <nicolasweber@gmx.de>2019-09-06 13:23:42 +0000
commit8455294f2ac13d587b13d728038a9bffa7185f2b (patch)
treef8ed35e9a3264b360cf099ba195d3ee53b52f9bd /lld/ELF/LinkerScript.cpp
parentedfd276cbc609051143d113f5e0d6b9248aebe47 (diff)
downloadbcm5719-llvm-8455294f2ac13d587b13d728038a9bffa7185f2b.tar.gz
bcm5719-llvm-8455294f2ac13d587b13d728038a9bffa7185f2b.zip
Revert r370635, it caused PR43241.
llvm-svn: 371202
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
-rw-r--r--lld/ELF/LinkerScript.cpp82
1 files changed, 45 insertions, 37 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index dbf705dc7f0..2fc9b0b091d 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -48,22 +48,24 @@ using namespace lld::elf;
LinkerScript *elf::script;
-static uint64_t getOutputSectionVA(SectionBase *sec) {
- OutputSection *os = sec->getOutputSection();
- assert(os && "input section has no output section assigned");
- return os ? os->addr : 0;
+static uint64_t getOutputSectionVA(SectionBase *inputSec, StringRef loc) {
+ if (OutputSection *os = inputSec->getOutputSection())
+ return os->addr;
+ error(loc + ": unable to evaluate expression: input section " +
+ inputSec->name + " has no output section assigned");
+ return 0;
}
uint64_t ExprValue::getValue() const {
if (sec)
- return alignTo(sec->getOffset(val) + getOutputSectionVA(sec),
+ return alignTo(sec->getOffset(val) + getOutputSectionVA(sec, loc),
alignment);
return alignTo(val, alignment);
}
uint64_t ExprValue::getSecAddr() const {
if (sec)
- return sec->getOffset(0) + getOutputSectionVA(sec);
+ return sec->getOffset(0) + getOutputSectionVA(sec, loc);
return 0;
}
@@ -71,7 +73,7 @@ uint64_t ExprValue::getSectionOffset() const {
// If the alignment is trivial, we don't have to compute the full
// value to know the offset. This allows this function to succeed in
// cases where the output section is not yet known.
- if (alignment == 1 && !sec)
+ if (alignment == 1 && (!sec || !sec->getOutputSection()))
return val;
return getValue() - getSecAddr();
}
@@ -155,8 +157,8 @@ static bool shouldDefineSym(SymbolAssignment *cmd) {
return false;
}
-// Called by processSymbolAssignments() to assign definitions to
-// linker-script-defined symbols.
+// This function is called from processSectionCommands,
+// while we are fixing the output section layout.
void LinkerScript::addSymbol(SymbolAssignment *cmd) {
if (!shouldDefineSym(cmd))
return;
@@ -476,10 +478,36 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) {
return ret;
}
-// Create output sections described by SECTIONS commands.
void LinkerScript::processSectionCommands() {
+ // A symbol can be assigned before any section is mentioned in the linker
+ // script. In an DSO, the symbol values are addresses, so the only important
+ // section values are:
+ // * SHN_UNDEF
+ // * SHN_ABS
+ // * Any value meaning a regular section.
+ // To handle that, create a dummy aether section that fills the void before
+ // the linker scripts switches to another section. It has an index of one
+ // which will map to whatever the first actual section is.
+ aether = make<OutputSection>("", 0, SHF_ALLOC);
+ aether->sectionIndex = 1;
+
+ // Ctx captures the local AddressState and makes it accessible deliberately.
+ // This is needed as there are some cases where we cannot just
+ // thread the current state through to a lambda function created by the
+ // script parser.
+ auto deleter = std::make_unique<AddressState>();
+ ctx = deleter.get();
+ ctx->outSec = aether;
+
size_t i = 0;
+ // Add input sections to output sections.
for (BaseCommand *base : sectionCommands) {
+ // Handle symbol assignments outside of any output section.
+ if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
+ addSymbol(cmd);
+ continue;
+ }
+
if (auto *sec = dyn_cast<OutputSection>(base)) {
std::vector<InputSection *> v = createInputSectionList(*sec);
@@ -505,6 +533,12 @@ void LinkerScript::processSectionCommands() {
continue;
}
+ // A directive may contain symbol definitions like this:
+ // ".foo : { ...; bar = .; }". Handle them.
+ for (BaseCommand *base : sec->sectionCommands)
+ if (auto *outCmd = dyn_cast<SymbolAssignment>(base))
+ addSymbol(outCmd);
+
// 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.
@@ -514,7 +548,7 @@ void LinkerScript::processSectionCommands() {
s->alignment = subalign;
}
- // Some input sections may be removed from the list after ICF.
+ // Add input sections to an output section.
for (InputSection *s : v)
sec->addSection(s);
@@ -525,32 +559,6 @@ void LinkerScript::processSectionCommands() {
sec->flags &= ~(uint64_t)SHF_ALLOC;
}
}
-}
-
-void LinkerScript::processSymbolAssignments() {
- // Dot outside an output section still represents a relative address, whose
- // sh_shndx should not be SHN_UNDEF or SHN_ABS. Create a dummy aether section
- // that fills the void outside a section. It has an index of one, which is
- // indistinguishable from any other regular section index.
- aether = make<OutputSection>("", 0, SHF_ALLOC);
- aether->sectionIndex = 1;
-
- // ctx captures the local AddressState and makes it accessible deliberately.
- // This is needed as there are some cases where we cannot just thread the
- // current state through to a lambda function created by the script parser.
- AddressState state;
- ctx = &state;
- ctx->outSec = aether;
-
- for (BaseCommand *base : sectionCommands) {
- if (auto *cmd = dyn_cast<SymbolAssignment>(base))
- addSymbol(cmd);
- else
- for (BaseCommand *sub_base : cast<OutputSection>(base)->sectionCommands)
- if (auto *cmd = dyn_cast<SymbolAssignment>(sub_base))
- addSymbol(cmd);
- }
-
ctx = nullptr;
}
OpenPOWER on IntegriCloud