aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2020-02-10 15:58:29 -0800
committerFangrui Song <maskray@google.com>2020-02-12 08:21:52 -0800
commit7c426fb1a6d4b7db2517529ec5d863b380479249 (patch)
treea2429abe1e6aa04bceaf56cc0d60dc29efc871b1 /lld/ELF/LinkerScript.cpp
parentb498d99338f868bcab3384b4e58f8a4d764fa48b (diff)
downloadllvm-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/LinkerScript.cpp')
-rw-r--r--lld/ELF/LinkerScript.cpp42
1 files changed, 20 insertions, 22 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index edb5cac..9643da2 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -246,32 +246,30 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
return changed;
}
-// This method is used to handle INSERT AFTER statement. Here we rebuild
-// the list of script commands to mix sections inserted into.
+// Process INSERT [AFTER|BEFORE] commands. For each command, we move the
+// specified output section to the designated place.
void LinkerScript::processInsertCommands() {
- std::vector<BaseCommand *> v;
- auto insert = [&](std::vector<BaseCommand *> &from) {
- v.insert(v.end(), from.begin(), from.end());
- from.clear();
- };
-
- for (BaseCommand *base : sectionCommands) {
- if (auto *os = dyn_cast<OutputSection>(base)) {
- insert(insertBeforeCommands[os->name]);
- v.push_back(base);
- insert(insertAfterCommands[os->name]);
+ for (const InsertCommand &cmd : insertCommands) {
+ // If cmd.os is empty, it may have been discarded by
+ // adjustSectionsBeforeSorting(). We do not handle such output sections.
+ auto from = llvm::find(sectionCommands, cmd.os);
+ if (from == sectionCommands.end())
continue;
+ sectionCommands.erase(from);
+
+ auto insertPos = llvm::find_if(sectionCommands, [&cmd](BaseCommand *base) {
+ auto *to = dyn_cast<OutputSection>(base);
+ return to != nullptr && to->name == cmd.where;
+ });
+ if (insertPos == sectionCommands.end()) {
+ error("unable to insert " + cmd.os->name +
+ (cmd.isAfter ? " after " : " before ") + cmd.where);
+ } else {
+ if (cmd.isAfter)
+ ++insertPos;
+ sectionCommands.insert(insertPos, cmd.os);
}
- v.push_back(base);
}
-
- for (auto &cmds : {insertBeforeCommands, insertAfterCommands})
- for (const std::pair<StringRef, std::vector<BaseCommand *>> &p : cmds)
- if (!p.second.empty())
- error("unable to INSERT AFTER/BEFORE " + p.first +
- ": section not defined");
-
- sectionCommands = std::move(v);
}
// Symbols defined in script should not be inlined by LTO. At the same time