Skip to content

Commit f02a27d

Browse files
authored
[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: #89327
1 parent 26a59bf commit f02a27d

File tree

6 files changed

+87
-4
lines changed

6 files changed

+87
-4
lines changed

lld/ELF/Driver.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,8 +1856,9 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
18561856
std::vector<std::tuple<bool, bool, bool>> stack;
18571857

18581858
// Iterate over argv to process input files and positional arguments.
1859+
std::optional<MemoryBufferRef> defaultScript;
18591860
InputFile::isInGroup = false;
1860-
bool hasInput = false;
1861+
bool hasInput = false, hasScript = false;
18611862
for (auto *arg : args) {
18621863
switch (arg->getOption().getID()) {
18631864
case OPT_library:
@@ -1879,9 +1880,16 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
18791880
break;
18801881
}
18811882
case OPT_script:
1883+
case OPT_default_script:
18821884
if (std::optional<std::string> path = searchScript(arg->getValue())) {
1883-
if (std::optional<MemoryBufferRef> mb = readFile(*path))
1884-
readLinkerScript(*mb);
1885+
if (std::optional<MemoryBufferRef> mb = readFile(*path)) {
1886+
if (arg->getOption().matches(OPT_default_script)) {
1887+
defaultScript = mb;
1888+
} else {
1889+
readLinkerScript(*mb);
1890+
hasScript = true;
1891+
}
1892+
}
18851893
break;
18861894
}
18871895
error(Twine("cannot find linker script ") + arg->getValue());
@@ -1961,6 +1969,8 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
19611969
}
19621970
}
19631971

1972+
if (defaultScript && !hasScript)
1973+
readLinkerScript(*defaultScript);
19641974
if (files.empty() && !hasInput && errorCount() == 0)
19651975
error("no input files");
19661976
}

lld/ELF/DriverUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ std::string elf::createResponseFile(const opt::InputArgList &args) {
186186
os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";
187187
break;
188188
case OPT_call_graph_ordering_file:
189+
case OPT_default_script:
189190
case OPT_dynamic_list:
190191
case OPT_export_dynamic_symbol_list:
191192
case OPT_just_symbols:

lld/ELF/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ defm debug_names: BB<"debug-names",
157157
"Generate a merged .debug_names section",
158158
"Do not generate a merged .debug_names section (default)">;
159159

160+
defm default_script: EEq<"default-script", "In the absence of --script, read this default linker script">;
161+
160162
defm demangle: B<"demangle",
161163
"Demangle symbol names (default)",
162164
"Do not demangle symbol names">;
@@ -555,6 +557,7 @@ HelpText<"Format diagnostics for Visual Studio compatibility">;
555557
def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">;
556558

557559
// Aliases
560+
def: Separate<["-"], "dT">, Alias<default_script>, HelpText<"Alias for --default-script">;
558561
def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;
559562
def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
560563
def: F<"dy">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;

lld/docs/ld.lld.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ is specified, print to the map file.
176176
Generate a merged
177177
.Li .debug_names
178178
section.
179+
.It Fl -default-script Ns = Ns Ar file , Fl dT Ar file
180+
In the absence of
181+
.Fl -script ,
182+
read this default linker script.
179183
.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
180184
Define a symbol alias.
181185
.Ar expression
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# REQUIRES: x86
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
4+
# RUN: ld.lld --default-script=def.t b.t -T a.t a.o -o out
5+
# RUN: llvm-readelf -Ss out | FileCheck %s
6+
7+
# CHECK: Name
8+
# CHECK: .foo2
9+
# CHECK-NEXT: .foo0
10+
# CHECK-NEXT: .foo1
11+
# CHECK: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start
12+
# CHECK-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b
13+
# CHECK-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS a
14+
# CHECK-EMPTY:
15+
16+
## In the absence of --script options, the default linker script is read.
17+
# RUN: ld.lld --default-script def.t b.t a.o -o out1
18+
# RUN: llvm-readelf -Ss out1 | FileCheck %s --check-prefix=CHECK1
19+
# RUN: ld.lld -dT def.t b.t a.o -o out1a && cmp out1 out1a
20+
## If multiple -dT options are specified, the last -dT wins.
21+
# RUN: ld.lld -dT a.t -dT def.t b.t a.o -o out1a && cmp out1 out1a
22+
23+
# RUN: mkdir d && cp def.t d/default.t
24+
# RUN: ld.lld -L d -dT default.t b.t a.o -o out1a && cmp out1 out1a
25+
26+
# CHECK1: Name
27+
# CHECK1: .foo2
28+
# CHECK1-NEXT: .foo1
29+
# CHECK1-NEXT: .foo0
30+
# CHECK1: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start
31+
# CHECK1-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b
32+
# CHECK1-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS def
33+
# CHECK1-EMPTY:
34+
35+
# RUN: not ld.lld --default-script not-exist.t b.t -T a.t a.o 2>&1 | FileCheck %s --check-prefix=ERR
36+
# ERR: error: cannot find linker script not-exist.t
37+
38+
#--- a.s
39+
.globl _start
40+
_start:
41+
42+
.section .foo0,"a"; .long 0
43+
.section .foo1,"a"; .long 0
44+
.section .foo2,"a"; .long 0
45+
46+
#--- a.t
47+
a = 42;
48+
SECTIONS {
49+
.foo2 : {}
50+
.foo0 : {}
51+
.foo1 : {}
52+
}
53+
54+
#--- b.t
55+
b = 42;
56+
57+
#--- def.t
58+
def = 42;
59+
SECTIONS {
60+
.foo2 : {}
61+
.foo1 : {}
62+
.foo0 : {}
63+
}

lld/test/ELF/reproduce.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
# RUN: cp dyn dyn2
3535
# RUN: echo > file
3636
# RUN: echo > file2
37+
# RUN: echo > file3
3738
# RUN: echo "_start" > order
3839
# RUN: mkdir "sysroot with spaces"
3940
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar'
40-
# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \
41+
# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 -dT file3 \
4142
# RUN: --dynamic-list dyn --export-dynamic-symbol-list dyn2 -rpath file --script=file --symbol-ordering-file order \
4243
# RUN: --sysroot "sysroot with spaces" --sysroot="sysroot with spaces" \
4344
# RUN: --version-script ver --dynamic-linker "some unusual/path" -soname 'foo bar' \
@@ -48,6 +49,7 @@
4849
# RSP3-NEXT: -L "[[BASEDIR:.+]]/foo bar"
4950
# RSP3-NEXT: -L [[BASEDIR]]/file
5051
# RSP3-NEXT: --script [[BASEDIR]]/file2
52+
# RSP3-NEXT: --default-script [[BASEDIR]]/file3
5153
# RSP3-NEXT: --dynamic-list [[BASEDIR]]/dyn
5254
# RSP3-NEXT: --export-dynamic-symbol-list [[BASEDIR]]/dyn2
5355
# RSP3-NEXT: -rpath [[BASEDIR]]/file

0 commit comments

Comments
 (0)