[lld/mac] Print dylib search details with --print-dylib-search or RC_TRACE_DYLIB_SEARCHING
For debugging dylib loading, it's useful to have some insight into what the linker is doing. ld64 has the undocumented RC_TRACE_DYLIB_SEARCHING env var for this printing dylib search candidates. This adds a flag --print-dylib-search to make lld print the seame information. It's useful for users, but also for writing tests. The output is formatted slightly differently than ld64, but we still support RC_TRACE_DYLIB_SEARCHING to offer at least a compatible way to trigger this. ld64 has both `-print_statistics` and `-trace_symbol_output` to enable diagnostics output. I went with "print" since that seems like a more straightforward name. Differential Revision: https://reviews.llvm.org/D103985
This commit is contained in:
parent
91f147792e
commit
e87c095af3
|
@ -96,6 +96,7 @@ struct Configuration {
|
|||
bool headerPadMaxInstallNames = false;
|
||||
bool ltoNewPassManager = LLVM_ENABLE_NEW_PASS_MANAGER;
|
||||
bool markDeadStrippableDylib = false;
|
||||
bool printDylibSearch = false;
|
||||
bool printEachFile = false;
|
||||
bool printWhyLoad = false;
|
||||
bool searchDylibsFirst = false;
|
||||
|
|
|
@ -1020,6 +1020,8 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32);
|
||||
config->headerPadMaxInstallNames =
|
||||
args.hasArg(OPT_headerpad_max_install_names);
|
||||
config->printDylibSearch =
|
||||
args.hasArg(OPT_print_dylib_search) || getenv("RC_TRACE_DYLIB_SEARCHING");
|
||||
config->printEachFile = args.hasArg(OPT_t);
|
||||
config->printWhyLoad = args.hasArg(OPT_why_load);
|
||||
config->outputType = getOutputType(args);
|
||||
|
|
|
@ -81,11 +81,6 @@ public:
|
|||
explicit DependencyTracker(llvm::StringRef path);
|
||||
|
||||
// Adds the given path to the set of not-found files.
|
||||
inline void logFileNotFound(std::string path) {
|
||||
if (active)
|
||||
notFounds.insert(std::move(path));
|
||||
}
|
||||
|
||||
inline void logFileNotFound(const Twine &path) {
|
||||
if (active)
|
||||
notFounds.insert(path.str());
|
||||
|
|
|
@ -176,20 +176,27 @@ std::string macho::createResponseFile(const InputArgList &args) {
|
|||
return std::string(data.str());
|
||||
}
|
||||
|
||||
Optional<std::string> macho::resolveDylibPath(StringRef path) {
|
||||
static void searchedDylib(const Twine &path, bool found) {
|
||||
if (config->printDylibSearch)
|
||||
message("searched " + path + (found ? ", found " : ", not found"));
|
||||
if (!found)
|
||||
depTracker->logFileNotFound(path);
|
||||
}
|
||||
|
||||
Optional<std::string> macho::resolveDylibPath(StringRef dylibPath) {
|
||||
// TODO: if a tbd and dylib are both present, we should check to make sure
|
||||
// they are consistent.
|
||||
if (fs::exists(path))
|
||||
return std::string(path);
|
||||
else
|
||||
depTracker->logFileNotFound(path);
|
||||
bool dylibExists = fs::exists(dylibPath);
|
||||
searchedDylib(dylibPath, dylibExists);
|
||||
if (dylibExists)
|
||||
return std::string(dylibPath);
|
||||
|
||||
SmallString<261> location = path;
|
||||
path::replace_extension(location, ".tbd");
|
||||
if (fs::exists(location))
|
||||
return std::string(location);
|
||||
else
|
||||
depTracker->logFileNotFound(location);
|
||||
SmallString<261> tbdPath = dylibPath;
|
||||
path::replace_extension(tbdPath, ".tbd");
|
||||
bool tbdExists = fs::exists(tbdPath);
|
||||
searchedDylib(tbdPath, tbdExists);
|
||||
if (tbdExists)
|
||||
return std::string(tbdPath);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -249,10 +256,10 @@ macho::findPathCombination(const Twine &name,
|
|||
path::append(base, name);
|
||||
for (StringRef ext : extensions) {
|
||||
Twine location = base + ext;
|
||||
if (fs::exists(location))
|
||||
bool exists = fs::exists(location);
|
||||
searchedDylib(location, exists);
|
||||
if (exists)
|
||||
return saver.save(location.str());
|
||||
else
|
||||
depTracker->logFileNotFound(location);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
|
|
@ -49,8 +49,12 @@ def no_lto_legacy_pass_manager : Flag<["--"], "no-lto-legacy-pass-manager">,
|
|||
def time_trace: Flag<["--"], "time-trace">, HelpText<"Record time trace">;
|
||||
def time_trace_granularity_eq: Joined<["--"], "time-trace-granularity=">,
|
||||
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">;
|
||||
def time_trace_file_eq: Joined<["--"], "time-trace-file=">, HelpText<"Specify time trace output file">;
|
||||
def deduplicate_literals: Flag<["--"], "deduplicate-literals">, HelpText<"Enable literal deduplication">;
|
||||
def time_trace_file_eq: Joined<["--"], "time-trace-file=">,
|
||||
HelpText<"Specify time trace output file">;
|
||||
def deduplicate_literals: Flag<["--"], "deduplicate-literals">,
|
||||
HelpText<"Enable literal deduplication">;
|
||||
def print_dylib_search: Flag<["--"], "print-dylib-search">,
|
||||
HelpText<"Print which paths lld searched when trying to find dylibs">;
|
||||
|
||||
// This is a complete Options.td compiled from Apple's ld(1) manpage
|
||||
// dated 2018-03-07 and cross checked with ld64 source code in repo
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
################ default, which is the same as -search_paths_first
|
||||
# RUN: %lld -L%S/Inputs/MacOSX.sdk/usr/lib -o %t/test -Z \
|
||||
# RUN: -L%tA -L%tD -L%t -lhello -lgoodbye -lSystem %t/test.o
|
||||
# RUN: -L%tA -L%tD -L%t -lhello -lgoodbye -lSystem %t/test.o \
|
||||
# RUN: --print-dylib-search | FileCheck --check-prefix=ARCHIVESEARCH -DPATH=%t %s
|
||||
# RUN: llvm-objdump --macho --dylibs-used %t/test | FileCheck --check-prefix=ARCHIVE %s
|
||||
|
||||
################ Test all permutations of -L%t{A,D} with -search_paths_first
|
||||
|
@ -33,8 +34,9 @@
|
|||
# RUN: llvm-objdump --macho --dylibs-used %t/test | FileCheck --check-prefix=DYLIB %s
|
||||
|
||||
################ Test all permutations of -L%t{A,D} with -search_dylibs_first
|
||||
# RUN: %lld -L%S/Inputs/MacOSX.sdk/usr/lib -o %t/test -Z \
|
||||
# RUN: -L%tA -L%tD -L%t -lhello -lgoodbye -lSystem %t/test.o -search_dylibs_first
|
||||
# RUN: env RC_TRACE_DYLIB_SEARCHING=1 %lld -L%S/Inputs/MacOSX.sdk/usr/lib -o %t/test -Z \
|
||||
# RUN: -L%tA -L%tD -L%t -lhello -lgoodbye -lSystem %t/test.o -search_dylibs_first \
|
||||
# RUN: | FileCheck --check-prefix=DYLIBSEARCH -DPATH=%t %s
|
||||
# RUN: llvm-objdump --macho --dylibs-used %t/test | FileCheck --check-prefix=DYLIB %s
|
||||
# RUN: %lld -L%S/Inputs/MacOSX.sdk/usr/lib -o %t/test -Z \
|
||||
# RUN: -L%tD -L%tA -L%t -lhello -lgoodbye -lSystem %t/test.o -search_dylibs_first
|
||||
|
@ -50,10 +52,26 @@
|
|||
# DYLIB: @executable_path/libgoodbye.dylib
|
||||
# DYLIB: /usr/lib/libSystem.dylib
|
||||
|
||||
# DYLIBSEARCH: searched {{.*}}/MacOSX.sdk/usr/lib{{[/\\]}}libhello.tbd, not found
|
||||
# DYLIBSEARCH-NEXT: searched {{.*}}/MacOSX.sdk/usr/lib{{[/\\]}}libhello.dylib, not found
|
||||
# DYLIBSEARCH-NEXT: searched [[PATH]]A{{[/\\]}}libhello.tbd, not found
|
||||
# DYLIBSEARCH-NEXT: searched [[PATH]]A{{[/\\]}}libhello.dylib, not found
|
||||
# DYLIBSEARCH: searched [[PATH]]{{[/\\]}}libhello.dylib, found
|
||||
# DYLIBSEARCH: searched [[PATH]]D{{[/\\]}}libgoodbye.dylib, found
|
||||
|
||||
# ARCHIVE: @executable_path/libhello.dylib
|
||||
# ARCHIVE-NOT: @executable_path/libgoodbye.dylib
|
||||
# ARCHIVE: /usr/lib/libSystem.dylib
|
||||
|
||||
# ARCHIVESEARCH: searched {{.*}}/MacOSX.sdk/usr/lib{{[/\\]}}libhello.tbd, not found
|
||||
# ARCHIVESEARCH-NEXT: searched {{.*}}/MacOSX.sdk/usr/lib{{[/\\]}}libhello.dylib, not found
|
||||
# ARCHIVESEARCH-NEXT: searched {{.*}}/MacOSX.sdk/usr/lib{{[/\\]}}libhello.a, not found
|
||||
# ARCHIVESEARCH-NEXT: searched [[PATH]]A{{[/\\]}}libhello.tbd, not found
|
||||
# ARCHIVESEARCH-NEXT: searched [[PATH]]A{{[/\\]}}libhello.dylib, not found
|
||||
# ARCHIVESEARCH-NEXT: searched [[PATH]]A{{[/\\]}}libhello.a, not found
|
||||
# ARCHIVESEARCH: searched [[PATH]]{{[/\\]}}libhello.dylib, found
|
||||
# ARCHIVESEARCH: searched [[PATH]]A{{[/\\]}}libgoodbye.a, found
|
||||
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
||||
|
|
Loading…
Reference in New Issue