From c91146ea007a7ecbe99504a382c65452511f34c2 Mon Sep 17 00:00:00 2001 From: Parth Arora Date: Wed, 18 Mar 2026 02:01:15 -0700 Subject: [PATCH] Expand =/$SYSROOT for INPUT/GROUP script commands This commit improves the script parser to expand the = and $SYSROOT prefix in INPUT/GROUP inputs. Resolves #927 Signed-off-by: Parth Arora --- include/eld/ScriptParser/ScriptParser.h | 5 ++++ lib/ScriptParser/ScriptParser.cpp | 21 +++++++++++++++-- .../linkerscript/SysrootExpansion/Inputs/1.c | 1 + .../SysrootExpansion/Inputs/group_equals.t | 1 + .../SysrootExpansion/Inputs/main.c | 1 + .../SysrootExpansion/Inputs/script_equals.t | 1 + .../SysrootExpansion/Inputs/script_sysroot.t | 1 + .../SysrootExpansion/SysrootExpansion.test | 23 +++++++++++++++++++ 8 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/Inputs/1.c create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/Inputs/group_equals.t create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/Inputs/main.c create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_equals.t create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_sysroot.t create mode 100644 test/Common/standalone/linkerscript/SysrootExpansion/SysrootExpansion.test diff --git a/include/eld/ScriptParser/ScriptParser.h b/include/eld/ScriptParser/ScriptParser.h index a90ffc624..558bbb026 100644 --- a/include/eld/ScriptParser/ScriptParser.h +++ b/include/eld/ScriptParser/ScriptParser.h @@ -122,6 +122,11 @@ class ScriptParser final : ScriptLexer { void addFile(llvm::StringRef Name); + /// Expand "=" or "$SYSROOT" prefix in Name to sysroot path. + /// If sysroot is not set, the marker is stripped and the remaining path is + /// used. + std::string expandSysrootMarkers(llvm::StringRef Name) const; + /// Reads AS_NEEDED(...) subcommand. void readAsNeeded(); diff --git a/lib/ScriptParser/ScriptParser.cpp b/lib/ScriptParser/ScriptParser.cpp index e35d8cc17..bcf09067a 100644 --- a/lib/ScriptParser/ScriptParser.cpp +++ b/lib/ScriptParser/ScriptParser.cpp @@ -739,14 +739,31 @@ void ScriptParser::readAsNeeded() { ThisScriptFile.setAsNeeded(false); } +std::string ScriptParser::expandSysrootMarkers(StringRef Name) const { + StringRef Suffix; + if (Name.starts_with("=")) + Suffix = Name.substr(1); + else if (Name.starts_with("$SYSROOT")) + Suffix = Name.substr(8); // strlen("$SYSROOT") == 8 + else + return Name.str(); + + auto &SearchDirs = ThisConfig.directories(); + if (SearchDirs.hasSysRoot()) + return (SearchDirs.sysroot().native() + Suffix).str(); + return Suffix.str(); +} + void ScriptParser::addFile(StringRef Name) { StrToken *InputStrTok = nullptr; if (Name.consume_front("-l")) InputStrTok = ThisScriptFile.createNameSpecToken(Name.str(), ThisScriptFile.asNeeded()); - else + else { + std::string ExpandedName = expandSysrootMarkers(Name); InputStrTok = - ThisScriptFile.createFileToken(Name.str(), ThisScriptFile.asNeeded()); + ThisScriptFile.createFileToken(ExpandedName, ThisScriptFile.asNeeded()); + } ThisScriptFile.getCurrentStringList()->pushBack(InputStrTok); } diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/1.c b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/1.c new file mode 100644 index 000000000..a60f28c10 --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/1.c @@ -0,0 +1 @@ +int foo() { return 1; } diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/group_equals.t b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/group_equals.t new file mode 100644 index 000000000..8718c221c --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/group_equals.t @@ -0,0 +1 @@ +GROUP(=/lib64/lib1.so) diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/main.c b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_equals.t b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_equals.t new file mode 100644 index 000000000..7ba279c9e --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_equals.t @@ -0,0 +1 @@ +INPUT(=/lib64/lib1.so) diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_sysroot.t b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_sysroot.t new file mode 100644 index 000000000..d95da50af --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/Inputs/script_sysroot.t @@ -0,0 +1 @@ +INPUT($SYSROOT/lib64/lib1.so) diff --git a/test/Common/standalone/linkerscript/SysrootExpansion/SysrootExpansion.test b/test/Common/standalone/linkerscript/SysrootExpansion/SysrootExpansion.test new file mode 100644 index 000000000..d74698d77 --- /dev/null +++ b/test/Common/standalone/linkerscript/SysrootExpansion/SysrootExpansion.test @@ -0,0 +1,23 @@ +#---SysrootExpansion.test---------------- Linker Script ----------------# +#BEGIN_COMMENT +# Validate sysroot expansion for "=" and "$SYSROOT" markers in INPUT/GROUP +# script commands. +# When a path starts with "=" or "$SYSROOT", it should be expanded to the +# sysroot path regardless of where the linker script is located. +#END_COMMENT +#START_TEST + +RUN: rm -rf %t.dir && mkdir -p %t.dir/lib64 +RUN: %clang %clangopts -o %t.1.o %p/Inputs/1.c -c -fPIC +RUN: %clang %clangopts -o %t.main.o %p/Inputs/main.c -c +RUN: %link %linkopts -o %t.dir/lib64/lib1.so -shared %t.1.o +RUN: %link %linkopts -o %t.out1 --sysroot=%t.dir -T %p/Inputs/script_equals.t %t.main.o --verbose 2>&1 | %filecheck %s --check-prefix=EQUALS +RUN: %link %linkopts -o %t.out2 --sysroot=%t.dir -T %p/Inputs/script_sysroot.t %t.main.o --verbose 2>&1 | %filecheck %s --check-prefix=SYSROOT +RUN: %link %linkopts -o %t.out3 --sysroot=%t.dir -T %p/Inputs/group_equals.t %t.main.o --verbose 2>&1 | %filecheck %s --check-prefix=GROUP +RUN: %not %link %linkopts -o %t.out4 -T %p/Inputs/script_equals.t %t.main.o 2>&1 | %filecheck %s --check-prefix=NOSYSROOT +#END_TEST + +EQUALS: Verbose: Mapping input file '{{.*}}dir/lib64/lib1.so' into memory +SYSROOT: Verbose: Mapping input file '{{.*}}dir/lib64/lib1.so' into memory +GROUP: Verbose: Mapping input file '{{.*}}dir/lib64/lib1.so' into memory +NOSYSROOT: Fatal: cannot read file /lib64/lib1.so