forked from OSchip/llvm-project
[lld-macho] Re-root absolute input file paths if -syslibroot is specified
Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D100147
This commit is contained in:
parent
eb5b7d4497
commit
db7a413e51
|
@ -76,16 +76,19 @@ static HeaderFileType getOutputType(const InputArgList &args) {
|
|||
}
|
||||
}
|
||||
|
||||
static Optional<std::string>
|
||||
findAlongPathsWithExtensions(StringRef name, ArrayRef<StringRef> extensions) {
|
||||
// Search for all possible combinations of `{root}/{name}.{extension}`.
|
||||
// If \p extensions are not specified, then just search for `{root}/{name}`.
|
||||
static Optional<StringRef>
|
||||
findPathCombination(const Twine &name, const std::vector<StringRef> &roots,
|
||||
ArrayRef<StringRef> extensions = {""}) {
|
||||
SmallString<261> base;
|
||||
for (StringRef dir : config->librarySearchPaths) {
|
||||
for (StringRef dir : roots) {
|
||||
base = dir;
|
||||
path::append(base, Twine("lib") + name);
|
||||
path::append(base, name);
|
||||
for (StringRef ext : extensions) {
|
||||
Twine location = base + ext;
|
||||
if (fs::exists(location))
|
||||
return location.str();
|
||||
return saver.save(location.str());
|
||||
else
|
||||
depTracker->logFileNotFound(location);
|
||||
}
|
||||
|
@ -93,14 +96,29 @@ findAlongPathsWithExtensions(StringRef name, ArrayRef<StringRef> extensions) {
|
|||
return {};
|
||||
}
|
||||
|
||||
static Optional<std::string> findLibrary(StringRef name) {
|
||||
static Optional<StringRef> findLibrary(StringRef name) {
|
||||
if (config->searchDylibsFirst) {
|
||||
if (Optional<std::string> path =
|
||||
findAlongPathsWithExtensions(name, {".tbd", ".dylib"}))
|
||||
if (Optional<StringRef> path = findPathCombination(
|
||||
"lib" + name, config->librarySearchPaths, {".tbd", ".dylib"}))
|
||||
return path;
|
||||
return findAlongPathsWithExtensions(name, {".a"});
|
||||
return findPathCombination("lib" + name, config->librarySearchPaths,
|
||||
{".a"});
|
||||
}
|
||||
return findAlongPathsWithExtensions(name, {".tbd", ".dylib", ".a"});
|
||||
return findPathCombination("lib" + name, config->librarySearchPaths,
|
||||
{".tbd", ".dylib", ".a"});
|
||||
}
|
||||
|
||||
// If -syslibroot is specified, absolute paths to non-object files may be
|
||||
// rerooted.
|
||||
static StringRef rerootPath(StringRef path) {
|
||||
if (!path::is_absolute(path, path::Style::posix) || path.endswith(".o"))
|
||||
return path;
|
||||
|
||||
if (Optional<StringRef> rerootedPath =
|
||||
findPathCombination(path, config->systemLibraryRoots))
|
||||
return *rerootedPath;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static Optional<std::string> findFramework(StringRef name) {
|
||||
|
@ -337,7 +355,7 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive,
|
|||
}
|
||||
|
||||
static void addLibrary(StringRef name, bool isWeak) {
|
||||
if (Optional<std::string> path = findLibrary(name)) {
|
||||
if (Optional<StringRef> path = findLibrary(name)) {
|
||||
auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path, false));
|
||||
if (isWeak && dylibFile)
|
||||
dylibFile->forceWeakImport = true;
|
||||
|
@ -396,7 +414,7 @@ static void addFileList(StringRef path) {
|
|||
return;
|
||||
MemoryBufferRef mbref = *buffer;
|
||||
for (StringRef path : args::getLines(mbref))
|
||||
addFile(path, false);
|
||||
addFile(rerootPath(path), false);
|
||||
}
|
||||
|
||||
// An order file has one entry per line, in the following format:
|
||||
|
@ -814,18 +832,18 @@ void createFiles(const InputArgList &args) {
|
|||
|
||||
switch (opt.getID()) {
|
||||
case OPT_INPUT:
|
||||
addFile(arg->getValue(), false);
|
||||
addFile(rerootPath(arg->getValue()), false);
|
||||
break;
|
||||
case OPT_weak_library:
|
||||
if (auto *dylibFile =
|
||||
dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
|
||||
if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
|
||||
addFile(rerootPath(arg->getValue()), false)))
|
||||
dylibFile->forceWeakImport = true;
|
||||
break;
|
||||
case OPT_filelist:
|
||||
addFileList(arg->getValue());
|
||||
break;
|
||||
case OPT_force_load:
|
||||
addFile(arg->getValue(), true);
|
||||
addFile(rerootPath(arg->getValue()), true);
|
||||
break;
|
||||
case OPT_l:
|
||||
case OPT_weak_l:
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# CHECK-DAG: input-file: {{.*}}{{[/\]}}main.o
|
||||
# CHECK-DAG: input-file: {{.*}}bar.o
|
||||
|
||||
# CHECK-NEXT: not-found: {{.*}}{{[/\]}}libdyld.{{.*}}
|
||||
# CHECK: not-found: {{.*}}{{[/\]}}libdyld.{{.*}}
|
||||
## There could be more not-found here but we are not checking those because it's brittle.
|
||||
|
||||
# CHECK: output-file: {{.*}}{{[/\]}}test.out
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
# REQUIRES: x86
|
||||
# UNSUPPORTED: system-windows
|
||||
## FIXME: In principle this test should pass on Windows
|
||||
# RUN: rm -rf %t; split-file %s %t
|
||||
|
||||
## This test verifies that we attempt to re-root absolute paths if -syslibroot
|
||||
## is specified. Therefore we would like to be able to specify an absolute path
|
||||
## without worrying that it may match an actual file on the system outside the
|
||||
## syslibroot. `chroot` would do the job but isn't cross-platform, so I've used
|
||||
## this %t/%:t hack instead.
|
||||
# RUN: mkdir -p %t/%:t
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/bar.s -o %t/bar.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
|
||||
|
||||
## bar.a is under %t/%:t, and so verifies that rerooting happens. foo.a isn't,
|
||||
## and therefore verifies that we still fall back to the original path if no
|
||||
## file exists at the rerooted path.
|
||||
# RUN: llvm-ar rcs %t/foo.a %t/foo.o
|
||||
# RUN: %lld -dylib %t/foo.o -o %t/libfoo.dylib
|
||||
# RUN: llvm-ar rcs %t/%:t/bar.a %t/bar.o
|
||||
# RUN: %lld -dylib %t/bar.o -o %t/%:t/libbar.dylib
|
||||
|
||||
## Test our various file-loading flags to make sure all bases are covered.
|
||||
# RUN: %lld -lSystem -syslibroot %t %t/foo.a %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
|
||||
# RUN: %lld -lSystem -syslibroot %t -force_load %t/foo.a -force_load %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
|
||||
# RUN: %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
|
||||
# RUN: %lld -lSystem -syslibroot %t -weak_library %t/libfoo.dylib -weak_library %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
|
||||
# RUN: echo "%t/libfoo.dylib" > %t/filelist
|
||||
# RUN: echo "%t/libbar.dylib" >> %t/filelist
|
||||
# RUN: %lld -lSystem -syslibroot %t -filelist %t/filelist %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
|
||||
# CHECK: [[DIR]]/{{(lib)?}}bar
|
||||
|
||||
## Paths to object files don't get rerooted.
|
||||
# RUN: mv %t/bar.o %t/%:t/bar.o
|
||||
# RUN: not %lld -lSystem -syslibroot %t %t/foo.o %t/bar.o %t/test.o -o \
|
||||
# RUN: /dev/null 2>&1 | FileCheck %s --check-prefix=OBJ
|
||||
# OBJ: error: cannot open {{.*[\\/]}}bar.o: {{[Nn]}}o such file or directory
|
||||
|
||||
## Now create a "decoy" libfoo.dylib under %t/%:t to demonstrate that the
|
||||
## rerooted path takes precedence over the original path. We will get an
|
||||
## undefined symbol error since we aren't loading %t/libfoo.dylib.
|
||||
# RUN: cp %t/%:t/libbar.dylib %t/%:t/libfoo.dylib
|
||||
# RUN: not %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF
|
||||
# UNDEF: error: undefined symbol: _foo
|
||||
|
||||
#--- foo.s
|
||||
.globl _foo
|
||||
_foo:
|
||||
|
||||
#--- bar.s
|
||||
.globl _bar
|
||||
_bar:
|
||||
|
||||
#--- test.s
|
||||
.text
|
||||
.globl _main
|
||||
|
||||
_main:
|
||||
callq _foo
|
||||
callq _bar
|
||||
ret
|
Loading…
Reference in New Issue