diff options
author | Fangrui Song <maskray@google.com> | 2020-02-10 15:58:29 -0800 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2020-02-12 08:21:52 -0800 |
commit | 7c426fb1a6d4b7db2517529ec5d863b380479249 (patch) | |
tree | a2429abe1e6aa04bceaf56cc0d60dc29efc871b1 /lld/ELF/ScriptParser.cpp | |
parent | b498d99338f868bcab3384b4e58f8a4d764fa48b (diff) | |
download | llvm-7c426fb1a6d4b7db2517529ec5d863b380479249.zip llvm-7c426fb1a6d4b7db2517529ec5d863b380479249.tar.gz llvm-7c426fb1a6d4b7db2517529ec5d863b380479249.tar.bz2 |
[ELF] Support INSERT [AFTER|BEFORE] for orphan sections
D43468+D44380 added INSERT [AFTER|BEFORE] for non-orphan sections. This patch
makes INSERT work for orphan sections as well.
`SECTIONS {...} INSERT [AFTER|BEFORE] .foo` does not set `hasSectionCommands`, so the result
will be similar to a regular link without a linker script. The differences when `hasSectionCommands` is set include:
* image base is different
* -z noseparate-code/-z noseparate-loadable-segments are unavailable
* some special symbols such as `_end _etext _edata` are not defined
The behavior is similar to GNU ld:
INSERT is not considered an external linker script.
This feature makes the section layout more flexible. It can be used to:
* Place .nv_fatbin before other readonly SHT_PROGBITS sections to mitigate relocation overflows.
* Disturb the layout to expose address sensitive application bugs.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D74375
Diffstat (limited to 'lld/ELF/ScriptParser.cpp')
-rw-r--r-- | lld/ELF/ScriptParser.cpp | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 635d281..8186420 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -523,13 +523,6 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() { } void ScriptParser::readSections() { - script->hasSectionsCommand = 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 - // script. See comment for computeFlags(). - config->singleRoRx = true; - expect("{"); std::vector<BaseCommand *> v; while (!errorCount() && !consume("}")) { @@ -548,22 +541,29 @@ void ScriptParser::readSections() { else v.push_back(readOutputSectionDescription(tok)); } + script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), + v.end()); - if (!atEOF() && consume("INSERT")) { - std::vector<BaseCommand *> *dest = nullptr; - if (consume("AFTER")) - dest = &script->insertAfterCommands[next()]; - else if (consume("BEFORE")) - dest = &script->insertBeforeCommands[next()]; - else - setError("expected AFTER/BEFORE, but got '" + next() + "'"); - if (dest) - dest->insert(dest->end(), v.begin(), v.end()); + if (atEOF() || !consume("INSERT")) { + // --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 script. See comment for computeFlags(). + // TODO This rule will be dropped in the future. + config->singleRoRx = true; + + script->hasSectionsCommand = true; return; } - script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), - v.end()); + bool isAfter = false; + if (consume("AFTER")) + isAfter = true; + else if (!consume("BEFORE")) + setError("expected AFTER/BEFORE, but got '" + next() + "'"); + StringRef where = next(); + for (BaseCommand *cmd : v) + if (auto *os = dyn_cast<OutputSection>(cmd)) + script->insertCommands.push_back({os, isAfter, where}); } void ScriptParser::readTarget() { |