Skip to content

[ELF] Add --default-script/-dT #89327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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());
Expand Down Expand Up @@ -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");
}
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/DriverUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down Expand Up @@ -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">;
Expand Down
4 changes: 4 additions & 0 deletions lld/docs/ld.lld.1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 63 additions & 0 deletions lld/test/ELF/linkerscript/default-script.s
Original file line number Diff line number Diff line change
@@ -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 : {}
}
4 changes: 3 additions & 1 deletion lld/test/ELF/reproduce.s
Original file line number Diff line number Diff line change
Expand Up @@ -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' \
Expand All @@ -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
Expand Down