[lld] f02a27d - [ELF] Add --default-script/-dT
via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 19 09:09:45 PDT 2024
Author: Fangrui Song
Date: 2024-04-19T09:09:41-07:00
New Revision: f02a27df2f133503b39bad38d0e2b3e95d3f8a23
URL: https://github.com/llvm/llvm-project/commit/f02a27df2f133503b39bad38d0e2b3e95d3f8a23
DIFF: https://github.com/llvm/llvm-project/commit/f02a27df2f133503b39bad38d0e2b3e95d3f8a23.diff
LOG: [ELF] Add --default-script/-dT
GNU ld added --default-script (alias: -dT) in 2007. The option specifies
a default script that is processed if --script/-T is not specified. -dT
can be used to override GNU ld's internal linker script, but only when
the application does not specify -T.
In addition, dynamorio's CMakeLists.txt may use -dT.
The implementation is simple and the feature can be useful to dabble
with different section layouts.
Pull Request: https://github.com/llvm/llvm-project/pull/89327
Added:
lld/test/ELF/linkerscript/default-script.s
Modified:
lld/ELF/Driver.cpp
lld/ELF/DriverUtils.cpp
lld/ELF/Options.td
lld/docs/ld.lld.1
lld/test/ELF/reproduce.s
Removed:
################################################################################
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 5fffdc51f34ddf..a5b47f020f8726 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1856,8 +1856,9 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
std::vector<std::tuple<bool, bool, bool>> stack;
// Iterate over argv to process input files and positional arguments.
+ std::optional<MemoryBufferRef> defaultScript;
InputFile::isInGroup = false;
- bool hasInput = false;
+ bool hasInput = false, hasScript = false;
for (auto *arg : args) {
switch (arg->getOption().getID()) {
case OPT_library:
@@ -1879,9 +1880,16 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
break;
}
case OPT_script:
+ case OPT_default_script:
if (std::optional<std::string> path = searchScript(arg->getValue())) {
- if (std::optional<MemoryBufferRef> mb = readFile(*path))
- readLinkerScript(*mb);
+ if (std::optional<MemoryBufferRef> mb = readFile(*path)) {
+ if (arg->getOption().matches(OPT_default_script)) {
+ defaultScript = mb;
+ } else {
+ readLinkerScript(*mb);
+ hasScript = true;
+ }
+ }
break;
}
error(Twine("cannot find linker script ") + arg->getValue());
@@ -1961,6 +1969,8 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
}
}
+ if (defaultScript && !hasScript)
+ readLinkerScript(*defaultScript);
if (files.empty() && !hasInput && errorCount() == 0)
error("no input files");
}
diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp
index de8ffab0e21249..ac74604408152d 100644
--- a/lld/ELF/DriverUtils.cpp
+++ b/lld/ELF/DriverUtils.cpp
@@ -186,6 +186,7 @@ std::string elf::createResponseFile(const opt::InputArgList &args) {
os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";
break;
case OPT_call_graph_ordering_file:
+ case OPT_default_script:
case OPT_dynamic_list:
case OPT_export_dynamic_symbol_list:
case OPT_just_symbols:
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index d470646ed0eeef..72eaf157a181cf 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -157,6 +157,8 @@ defm debug_names: BB<"debug-names",
"Generate a merged .debug_names section",
"Do not generate a merged .debug_names section (default)">;
+defm default_script: EEq<"default-script", "In the absence of --script, read this default linker script">;
+
defm demangle: B<"demangle",
"Demangle symbol names (default)",
"Do not demangle symbol names">;
@@ -555,6 +557,7 @@ HelpText<"Format diagnostics for Visual Studio compatibility">;
def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">;
// Aliases
+def: Separate<["-"], "dT">, Alias<default_script>, HelpText<"Alias for --default-script">;
def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;
def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
def: F<"dy">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index ba8ce8f784759a..3861120915e8bc 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -176,6 +176,10 @@ is specified, print to the map file.
Generate a merged
.Li .debug_names
section.
+.It Fl -default-script Ns = Ns Ar file , Fl dT Ar file
+In the absence of
+.Fl -script ,
+read this default linker script.
.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
Define a symbol alias.
.Ar expression
diff --git a/lld/test/ELF/linkerscript/default-script.s b/lld/test/ELF/linkerscript/default-script.s
new file mode 100644
index 00000000000000..bb716a5fe0cddf
--- /dev/null
+++ b/lld/test/ELF/linkerscript/default-script.s
@@ -0,0 +1,63 @@
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: ld.lld --default-script=def.t b.t -T a.t a.o -o out
+# RUN: llvm-readelf -Ss out | FileCheck %s
+
+# CHECK: Name
+# CHECK: .foo2
+# CHECK-NEXT: .foo0
+# CHECK-NEXT: .foo1
+# CHECK: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start
+# CHECK-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b
+# CHECK-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS a
+# CHECK-EMPTY:
+
+## In the absence of --script options, the default linker script is read.
+# RUN: ld.lld --default-script def.t b.t a.o -o out1
+# RUN: llvm-readelf -Ss out1 | FileCheck %s --check-prefix=CHECK1
+# RUN: ld.lld -dT def.t b.t a.o -o out1a && cmp out1 out1a
+## If multiple -dT options are specified, the last -dT wins.
+# RUN: ld.lld -dT a.t -dT def.t b.t a.o -o out1a && cmp out1 out1a
+
+# RUN: mkdir d && cp def.t d/default.t
+# RUN: ld.lld -L d -dT default.t b.t a.o -o out1a && cmp out1 out1a
+
+# CHECK1: Name
+# CHECK1: .foo2
+# CHECK1-NEXT: .foo1
+# CHECK1-NEXT: .foo0
+# CHECK1: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start
+# CHECK1-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b
+# CHECK1-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS def
+# CHECK1-EMPTY:
+
+# RUN: not ld.lld --default-script not-exist.t b.t -T a.t a.o 2>&1 | FileCheck %s --check-prefix=ERR
+# ERR: error: cannot find linker script not-exist.t
+
+#--- a.s
+.globl _start
+_start:
+
+.section .foo0,"a"; .long 0
+.section .foo1,"a"; .long 0
+.section .foo2,"a"; .long 0
+
+#--- a.t
+a = 42;
+SECTIONS {
+ .foo2 : {}
+ .foo0 : {}
+ .foo1 : {}
+}
+
+#--- b.t
+b = 42;
+
+#--- def.t
+def = 42;
+SECTIONS {
+ .foo2 : {}
+ .foo1 : {}
+ .foo0 : {}
+}
diff --git a/lld/test/ELF/reproduce.s b/lld/test/ELF/reproduce.s
index 314c08b4f7cdd5..8818a9e35f4039 100644
--- a/lld/test/ELF/reproduce.s
+++ b/lld/test/ELF/reproduce.s
@@ -34,10 +34,11 @@
# RUN: cp dyn dyn2
# RUN: echo > file
# RUN: echo > file2
+# RUN: echo > file3
# RUN: echo "_start" > order
# RUN: mkdir "sysroot with spaces"
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar'
-# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \
+# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 -dT file3 \
# RUN: --dynamic-list dyn --export-dynamic-symbol-list dyn2 -rpath file --script=file --symbol-ordering-file order \
# RUN: --sysroot "sysroot with spaces" --sysroot="sysroot with spaces" \
# RUN: --version-script ver --dynamic-linker "some unusual/path" -soname 'foo bar' \
@@ -48,6 +49,7 @@
# RSP3-NEXT: -L "[[BASEDIR:.+]]/foo bar"
# RSP3-NEXT: -L [[BASEDIR]]/file
# RSP3-NEXT: --script [[BASEDIR]]/file2
+# RSP3-NEXT: --default-script [[BASEDIR]]/file3
# RSP3-NEXT: --dynamic-list [[BASEDIR]]/dyn
# RSP3-NEXT: --export-dynamic-symbol-list [[BASEDIR]]/dyn2
# RSP3-NEXT: -rpath [[BASEDIR]]/file
More information about the llvm-commits
mailing list