Skip to content
Open
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
9 changes: 9 additions & 0 deletions docs/userguide/CommandLineOptionsSupplements/sysroot.rst.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ The files specified using the INPUT and GROUP command are searched inside the sy
- The file begins with the ``/`` character, and
- The script containing the INPUT/GROUP command is located within the sysroot directory.

Additionally, paths in INPUT/GROUP commands or on the command line can explicitly
force sysroot expansion by using the ``=`` or ``$SYSROOT`` prefix:

- ``=/path/to/file`` expands to ``<sysroot>/path/to/file``
- ``$SYSROOT/path/to/file`` expands to ``<sysroot>/path/to/file``

This works for both linker script commands and command-line input files.
If no sysroot is configured, the prefix is stripped and the remaining path is used.

:option:`-L` ``<search_directory>``

When ``<search_directory>`` is prefixed with ``=``, then ``=`` is expanded to the sysroot.
2 changes: 2 additions & 0 deletions include/eld/Diagnostics/DiagVerbose.inc
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,5 @@ DIAG(verbose_loaded_plugin_config, DiagnosticEngine::Verbose,
DIAG(verbose_infer_target, DiagnosticEngine::Verbose,
"Inferred target : %0")
DIAG(verbose_sframe_log, DiagnosticEngine::Verbose, "SFrame Handling : %0")
DIAG(verbose_sysroot_expansion, DiagnosticEngine::Verbose,
"Expanded sysroot marker in path. '%0' -> '%1'")
8 changes: 8 additions & 0 deletions include/eld/Input/Input.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ class Input {
/// Return a user-facing text representation of input type.
static llvm::StringRef toString(InputType);

/// Expand '=' or '$SYSROOT' prefix in the path using the configured sysroot.
/// Returns the expanded path, or the original if no marker is present.
/// If a marker is present but no sysroot is configured, the marker is
/// stripped. Emits verbose_sysroot_expansion diagnostic when expansion occurs.
static std::string expandSysrootMarkers(llvm::StringRef Name,
const SearchDirs &PSearchDirs,
DiagnosticEngine &DiagEngine);

/// getFileName returns the FileName passed to the driver otherwise.
const std::string getFileName() const { return FileName; }

Expand Down
30 changes: 27 additions & 3 deletions lib/Input/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,40 @@ bool Input::isPathValid(const std::string &Path) const {
return true;
}

std::string Input::expandSysrootMarkers(llvm::StringRef Name,
const SearchDirs &PSearchDirs,
DiagnosticEngine &DiagEngine) {
llvm::StringRef Suffix;
if (Name.starts_with("="))
Suffix = Name.substr(1);
else if (Name.starts_with("$SYSROOT"))
Suffix = Name.substr(strlen("$SYSROOT"));
else
return Name.str();

std::string ExpandedPath = Suffix.str();
if (PSearchDirs.hasSysRoot())
ExpandedPath = (PSearchDirs.sysroot().native() + Suffix).str();

DiagEngine.raise(Diag::verbose_sysroot_expansion) << Name << ExpandedPath;
return ExpandedPath;
}

/// \return True if path able to be resolved, otherwise false
bool Input::resolvePath(const LinkerConfig &PConfig) {
if (ResolvedPath)
return true;
if (PConfig.options().hasMappingFile() && !isInternal())
return resolvePathMappingFile(PConfig);
auto &PSearchDirs = PConfig.directories();

std::string ExpandedFileName = FileName;
if (Type == Input::InputType::Script || Type == Input::InputType::Default)
ExpandedFileName = expandSysrootMarkers(FileName, PSearchDirs, *DiagEngine);

switch (Type) {
default:
ResolvedPath = eld::sys::fs::Path(FileName);
ResolvedPath = eld::sys::fs::Path(ExpandedFileName);
break;
case Input::Internal:
ResolvedPath = eld::sys::fs::Path(FileName);
Expand All @@ -103,11 +127,11 @@ bool Input::resolvePath(const LinkerConfig &PConfig) {
if (Type == Input::Script) {
if (shouldPrependSysrootToScriptInput(PConfig)) {
ResolvedPath = PSearchDirs.sysroot();
ResolvedPath->append(FileName);
ResolvedPath->append(ExpandedFileName);
}
if (!llvm::sys::fs::exists(ResolvedPath->native())) {
const sys::fs::Path *P =
PSearchDirs.find(FileName, SearchDirs::SearchInputType::Script);
PSearchDirs.find(ExpandedFileName, SearchDirs::SearchInputType::Script);
if (P != nullptr)
ResolvedPath = *P;
}
Expand Down
9 changes: 7 additions & 2 deletions lib/Input/InputAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,15 @@ InputFileAction::InputFileAction(std::string Name,
: InputAction(K, Printer), Name(Name), I(nullptr) {}

bool InputFileAction::activate(InputBuilder &PBuilder) {
const LinkerConfig &Config = PBuilder.getLinkerConfig();
std::string ExpandedName = Input::expandSysrootMarkers(
Name, Config.directories(), *Config.getDiagEngine());

std::ifstream Is;
Is.open(Name.c_str(), std::ifstream::in);
Is.open(ExpandedName.c_str(), std::ifstream::in);
if (!Is.good()) {
PBuilder.getDiagEngine()->raise(Diag::fatal_cannot_read_input) << Name;
PBuilder.getDiagEngine()->raise(Diag::fatal_cannot_read_input)
<< ExpandedName;
return false;
}
Is.close();
Expand Down
3 changes: 2 additions & 1 deletion lib/ScriptParser/ScriptParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,9 +744,10 @@ void ScriptParser::addFile(StringRef Name) {
if (Name.consume_front("-l"))
InputStrTok = ThisScriptFile.createNameSpecToken(Name.str(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does ld for namespec files ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find any difference in interpretation for namespec files with explicit sysroot in GNU ld.

ThisScriptFile.asNeeded());
else
else {
InputStrTok =
ThisScriptFile.createFileToken(Name.str(), ThisScriptFile.asNeeded());
}
ThisScriptFile.getCurrentStringList()->pushBack(InputStrTok);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo() { return 1; }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GROUP(=/lib64/lib1.so)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GROUP($SYSROOT/lib64/lib1.so)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int main() { return 0; }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INPUT(=/lib64/lib1.so)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INPUT($SYSROOT/lib64/lib1.so)
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#---SysrootExpansion.test---------------- Linker Script ----------------#
#BEGIN_COMMENT
# Validate sysroot expansion for "=" and "$SYSROOT" markers in INPUT/GROUP
# script commands and command-line object files.
#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

# Create shared library in sysroot
RUN: %link %linkopts -o %t.dir/lib64/lib1.so -shared %t.1.o

# Test INPUT with = prefix
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

# Test INPUT with $SYSROOT prefix
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

# Test GROUP with = prefix
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_EQUALS

# Test GROUP with $SYSROOT prefix
RUN: %link %linkopts -o %t.out4 --sysroot=%t.dir -T %p/Inputs/group_sysroot.t %t.main.o --verbose 2>&1 | %filecheck %s --check-prefix=GROUP_SYSROOT

# Test = prefix without sysroot set (should fail)
RUN: %not %link %linkopts -o %t.out5 -T %p/Inputs/script_equals.t %t.main.o 2>&1 | %filecheck %s --check-prefix=NOSYSROOT

# Copy object file to sysroot for command-line tests
RUN: cp %t.main.o %t.dir/lib64/main.o

# Test command-line object file with = prefix
RUN: %link %linkopts -o %t.out6 --sysroot=%t.dir %t.1.o =/lib64/main.o --verbose 2>&1 | %filecheck %s --check-prefix=CMDLINE_EQUALS

# Test command-line object file with $SYSROOT prefix
RUN: %link %linkopts -o %t.out7 --sysroot=%t.dir %t.1.o '$SYSROOT/lib64/main.o' --verbose 2>&1 | %filecheck %s --check-prefix=CMDLINE_SYSROOT

# Test verbose diagnostic for sysroot expansion
RUN: %link %linkopts -o %t.out8 --sysroot=%t.dir -T %p/Inputs/script_equals.t %t.main.o --verbose 2>&1 | %filecheck %s --check-prefix=VERBOSE_DIAG
RUN: %link %linkopts -o %t.out9 --sysroot=%t.dir %t.1.o =/lib64/main.o --verbose 2>&1 | %filecheck %s --check-prefix=VERBOSE_CMDLINE

#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_EQUALS: Verbose: Mapping input file '{{.*}}dir/lib64/lib1.so' into memory
GROUP_SYSROOT: Verbose: Mapping input file '{{.*}}dir/lib64/lib1.so' into memory
NOSYSROOT: Fatal: cannot read file /lib64/lib1.so
CMDLINE_EQUALS: Verbose: Mapping input file '{{.*}}dir/lib64/main.o' into memory
CMDLINE_SYSROOT: Verbose: Mapping input file '{{.*}}dir/lib64/main.o' into memory
VERBOSE_DIAG: Verbose: Expanded sysroot marker in path. '=/lib64/lib1.so' -> '{{.*}}dir/lib64/lib1.so'
VERBOSE_CMDLINE: Verbose: Expanded sysroot marker in path. '=/lib64/main.o' -> '{{.*}}dir/lib64/main.o'
Loading