[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
This commit is contained in:
parent
26a59bf6fc
commit
f02a27df2f
@ -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");
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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">;
|
||||
|
@ -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
|
||||
|
63
lld/test/ELF/linkerscript/default-script.s
Normal file
63
lld/test/ELF/linkerscript/default-script.s
Normal file
@ -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 : {}
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user