[lld] 03051f7 - [ELF] Preserve section order within an INSERT AFTER command
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 30 11:35:57 PDT 2021
Author: Fangrui Song
Date: 2021-06-30T11:35:50-07:00
New Revision: 03051f7ac8a3e2eda44b8280290c90863a064f0e
URL: https://github.com/llvm/llvm-project/commit/03051f7ac8a3e2eda44b8280290c90863a064f0e
DIFF: https://github.com/llvm/llvm-project/commit/03051f7ac8a3e2eda44b8280290c90863a064f0e.diff
LOG: [ELF] Preserve section order within an INSERT AFTER command
For
```
SECTIONS {
text.0 : {}
text.1 : {}
text.2 : {}
} INSERT AFTER .data;
```
the current order is `.data text.2 text.1 text.0`. It makes more sense to
preserve the specified order and thus improve compatibility with GNU ld.
For
```
SECTIONS { text.0 : {} } INSERT AFTER .data;
SECTIONS { text.3 : {} } INSERT AFTER .data;
```
GNU ld somehow collects sections with `INSERT AFTER .data` together (IMO
inconsistent) but I think it makes more sense to execute the commands in order
and get `.data text.3 text.0` instead.
Reviewed By: peter.smith
Differential Revision: https://reviews.llvm.org/D105158
Added:
lld/test/ELF/linkerscript/insert-multi.test
Modified:
lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/ELF/ScriptParser.cpp
Removed:
################################################################################
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 6deb9a98cc4bb..a938984ad945e 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -251,30 +251,34 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
// Process INSERT [AFTER|BEFORE] commands. For each command, we move the
// specified output section to the designated place.
void LinkerScript::processInsertCommands() {
+ std::vector<OutputSection *> moves;
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_if(sectionCommands, [&](BaseCommand *base) {
- return isa<OutputSection>(base) &&
- cast<OutputSection>(base)->name == cmd.name;
- });
- if (from == sectionCommands.end())
- continue;
- OutputSection *osec = cast<OutputSection>(*from);
- sectionCommands.erase(from);
+ for (StringRef name : cmd.names) {
+ // If base is empty, it may have been discarded by
+ // adjustSectionsBeforeSorting(). We do not handle such output sections.
+ auto from = llvm::find_if(sectionCommands, [&](BaseCommand *base) {
+ return isa<OutputSection>(base) &&
+ cast<OutputSection>(base)->name == name;
+ });
+ if (from == sectionCommands.end())
+ continue;
+ moves.push_back(cast<OutputSection>(*from));
+ 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 " + osec->name +
+ error("unable to insert " + cmd.names[0] +
(cmd.isAfter ? " after " : " before ") + cmd.where);
} else {
if (cmd.isAfter)
++insertPos;
- sectionCommands.insert(insertPos, osec);
+ sectionCommands.insert(insertPos, moves.begin(), moves.end());
}
+ moves.clear();
}
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 14cd145af5613..0592c52acb84d 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -227,7 +227,7 @@ struct ByteCommand : BaseCommand {
};
struct InsertCommand {
- StringRef name;
+ std::vector<StringRef> names;
bool isAfter;
StringRef where;
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 3d0d720014f25..4726dd1c6a2c9 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -596,9 +596,12 @@ void ScriptParser::readSections() {
else if (!consume("BEFORE"))
setError("expected AFTER/BEFORE, but got '" + next() + "'");
StringRef where = next();
+ std::vector<StringRef> names;
for (BaseCommand *cmd : v)
if (auto *os = dyn_cast<OutputSection>(cmd))
- script->insertCommands.push_back({os->name, isAfter, where});
+ names.push_back(os->name);
+ if (!names.empty())
+ script->insertCommands.push_back({std::move(names), isAfter, where});
}
void ScriptParser::readTarget() {
diff --git a/lld/test/ELF/linkerscript/insert-multi.test b/lld/test/ELF/linkerscript/insert-multi.test
new file mode 100644
index 0000000000000..88c065371de0e
--- /dev/null
+++ b/lld/test/ELF/linkerscript/insert-multi.test
@@ -0,0 +1,53 @@
+# REQUIRES: x86
+## Sections in an INSERT command are in a unit. Their order is preserved.
+
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
+# RUN: ld.lld -T %t/a.lds %t/a.o -o %t1
+# RUN: llvm-readelf -S -l %t1 | FileCheck %s
+
+# CHECK: Name
+# CHECK-NEXT: NULL
+# CHECK-NEXT: text.3
+# CHECK-NEXT: text.4
+# CHECK-NEXT: text.5
+# CHECK-NEXT: .text
+# CHECK-NEXT: .data
+# CHECK-NEXT: text.6
+# CHECK-NEXT: text.7
+# CHECK-NEXT: text.8
+# CHECK-NEXT: text.0
+# CHECK-NEXT: text.1
+# CHECK-NEXT: text.2
+
+#--- a.lds
+SECTIONS {
+ text.0 : {}
+ text.1 : {}
+ text.2 : {}
+} INSERT AFTER .data;
+
+SECTIONS {
+ text.3 : {}
+ text.4 : {}
+ text.5 : {}
+} INSERT BEFORE .text;
+
+SECTIONS {
+ text.6 : {}
+ text.7 : {}
+ text.8 : {}
+} INSERT AFTER .data;
+
+#--- a.s
+.text; nop
+.section text.0,"ax"; nop
+.section text.1,"ax"; nop
+.section text.2,"ax"; nop
+.section text.3,"ax"; nop
+.section text.4,"ax"; nop
+.section text.5,"ax"; nop
+.section text.6,"ax"; nop
+.section text.7,"ax"; nop
+.section text.8,"ax"; nop
+.data; .byte 0
More information about the llvm-commits
mailing list