-
Notifications
You must be signed in to change notification settings - Fork 18k
[lldb][Module] Make eLoadScriptFromSymFileWarn behave as a "dry-run" #189943
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,8 +36,10 @@ | |
| #endif | ||
|
|
||
| #include "clang/Driver/Driver.h" | ||
| #include "llvm/ADT/StringExtras.h" | ||
| #include "llvm/ADT/StringRef.h" | ||
| #include "llvm/Support/FileSystem.h" | ||
| #include "llvm/Support/FormatVariadic.h" | ||
| #include "llvm/Support/Threading.h" | ||
| #include "llvm/Support/raw_ostream.h" | ||
|
|
||
|
|
@@ -1330,6 +1332,33 @@ bool ModuleList::RemoveSharedModuleIfOrphaned(const ModuleWP module_wp) { | |
| return GetSharedModuleList().RemoveIfOrphaned(module_wp); | ||
| } | ||
|
|
||
| static void | ||
| ReportScriptLoading(Debugger &debugger, | ||
| llvm::ArrayRef<std::string> warned_script_paths) { | ||
| if (warned_script_paths.empty()) | ||
| return; | ||
|
|
||
| static std::once_flag s_warn_once; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems (very) wrong. Shouldn't the once_flag be a member for the module it belongs to?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My idea was to only report the first warning once per debugger session. (note there are 2 |
||
|
|
||
| // clang-format off | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please move this right before the string to keep its coverage as small as possible. |
||
| debugger.ReportWarning( | ||
| R"(Found executable debug scripts. To run a script in this debug session: | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to find a good way of threading the |
||
|
|
||
| command script import "/path/to/script.py" | ||
|
|
||
| To run all discovered debug scripts in this session: | ||
|
|
||
| settings set target.load-script-from-symbol-file true | ||
| )", debugger.GetID(), &s_warn_once); | ||
|
|
||
| debugger.ReportWarning(llvm::formatv( | ||
| R"(The following debug scripts were detected but not loaded: | ||
|
|
||
| - {0} | ||
| )", llvm::join(warned_script_paths, "\n - ")), debugger.GetID()); | ||
| // clang-format on | ||
| } | ||
|
|
||
| static bool LoadScriptingModule(const FileSpec &scripting_fspec, | ||
| ScriptInterpreter &script_interpreter, | ||
| Target &target, Status &error) { | ||
|
|
@@ -1343,9 +1372,9 @@ static bool LoadScriptingModule(const FileSpec &scripting_fspec, | |
| /*module_sp*/ nullptr, /*extra_path*/ {}, target.shared_from_this()); | ||
| } | ||
|
|
||
| bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module, | ||
| Target &target, | ||
| Status &error) { | ||
| bool ModuleList::LoadScriptingResourceInTargetForModule( | ||
| Module &module, Target &target, Status &error, | ||
| std::vector<std::string> &warned_script_paths) { | ||
| Log *log = GetLog(LLDBLog::Modules); | ||
|
|
||
| Debugger &debugger = target.GetDebugger(); | ||
|
|
@@ -1392,23 +1421,7 @@ bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module, | |
| break; | ||
| LLVM_FALLTHROUGH; | ||
| case eLoadScriptFromSymFileWarn: | ||
| debugger.ReportWarning( | ||
| llvm::formatv( | ||
| // clang-format off | ||
| R"('{0}' contains {1} debug script. To run this script in this debug session: | ||
|
|
||
| command script import "{2}" | ||
|
|
||
| To run all discovered debug scripts in this session: | ||
|
|
||
| settings set target.load-script-from-symbol-file true | ||
| )", | ||
| // clang-format on | ||
| module.GetFileSpec().GetFileNameStrippingExtension(), | ||
| trusted ? "a trusted" : "an untrusted", | ||
| scripting_fspec.GetPath()), | ||
| debugger.GetID()); | ||
|
|
||
| warned_script_paths.emplace_back(scripting_fspec.GetPath()); | ||
| continue; | ||
| } | ||
|
|
||
|
|
@@ -1437,10 +1450,13 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target, | |
| const ModuleList tmp_module_list(*this); | ||
| m_modules_mutex.unlock(); | ||
|
|
||
| std::vector<std::string> warned_script_paths; | ||
|
|
||
| for (auto module : tmp_module_list.ModulesNoLocking()) { | ||
| if (module) { | ||
| Status error; | ||
| if (!LoadScriptingResourceInTargetForModule(*module, *target, error)) { | ||
| if (!LoadScriptingResourceInTargetForModule(*module, *target, error, | ||
| warned_script_paths)) { | ||
| if (error.Fail() && error.AsCString()) { | ||
| error = Status::FromErrorStringWithFormat( | ||
| "unable to load scripting data for " | ||
|
|
@@ -1456,6 +1472,9 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target, | |
| } | ||
| } | ||
| } | ||
|
|
||
| ReportScriptLoading(target->GetDebugger(), warned_script_paths); | ||
|
|
||
| return errors.empty(); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # REQUIRES: python, system-darwin | ||
| # | ||
| # Test that when load-script-from-symbol-file is set to 'warn' and multiple | ||
| # dependent modules with dSYM scripts are loaded in a single batch (via | ||
| # target create), LLDB emits a single warning listing all detected scripts. | ||
|
|
||
| # RUN: split-file %s %t | ||
| # RUN: %clang_host -g -shared %t/lib.c -o %t/libTestLib1.dylib | ||
| # RUN: %clang_host -g -shared %t/lib.c -o %t/libTestLib2.dylib | ||
| # RUN: %clang_host -g %t/main.c -o %t/main.out %t/libTestLib1.dylib %t/libTestLib2.dylib | ||
| # RUN: mkdir -p %t/libTestLib1.dylib.dSYM/Contents/Resources/Python | ||
| # RUN: mkdir -p %t/libTestLib2.dylib.dSYM/Contents/Resources/Python | ||
| # RUN: cp %t/dsym_script1.py %t/libTestLib1.dylib.dSYM/Contents/Resources/Python/libTestLib1.py | ||
| # RUN: cp %t/dsym_script2.py %t/libTestLib2.dylib.dSYM/Contents/Resources/Python/libTestLib2.py | ||
| # RUN: %lldb -b \ | ||
| # RUN: -o 'settings set target.load-script-from-symbol-file warn' \ | ||
| # RUN: -o 'target create %t/main.out' 2>&1 \ | ||
| # RUN: | FileCheck %s --strict-whitespace \ | ||
| # RUN: --implicit-check-not=DSYM_SCRIPT1 --implicit-check-not=DSYM_SCRIPT2 | ||
|
|
||
| # Both dependent libraries should appear in a single warning. | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-DAG:{{^}} - {{.*}}/libTestLib1.dylib.dSYM/Contents/Resources/Python/libTestLib1.py | ||
| # CHECK-DAG:{{^}} - {{.*}}/libTestLib2.dylib.dSYM/Contents/Resources/Python/libTestLib2.py | ||
|
|
||
| #--- main.c | ||
| extern int lib_func(void); | ||
| int main() { return lib_func(); } | ||
|
|
||
| #--- lib.c | ||
| int lib_func(void) { return 0; } | ||
|
|
||
| #--- dsym_script1.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("DSYM_SCRIPT1", file=sys.stderr) | ||
|
|
||
| #--- dsym_script2.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("DSYM_SCRIPT2", file=sys.stderr) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # REQUIRES: python, system-darwin | ||
| # | ||
| # Test that when load-script-from-symbol-file is set to 'warn', LLDB emits a | ||
| # warning for each dSYM script without executing them. Verify that warnings | ||
| # are emitted for all modules, not just the first. | ||
|
|
||
| # RUN: split-file %s %t | ||
| # RUN: %clang_host -g %t/main.c -o %t/TestModule.out | ||
| # RUN: %clang_host -g %t/main.c -o %t/TestModule2.out | ||
| # RUN: %clang_host -g %t/main.c -o %t/TestModule3.out | ||
| # RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python | ||
| # RUN: mkdir -p %t/TestModule2.out.dSYM/Contents/Resources/Python | ||
| # RUN: mkdir -p %t/TestModule3.out.dSYM/Contents/Resources/Python | ||
|
|
||
| # RUN: cp %t/dsym_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py | ||
| # RUN: cp %t/dsym_script2.py %t/TestModule2.out.dSYM/Contents/Resources/Python/TestModule2.py | ||
| # RUN: cp %t/dsym_script3.py %t/TestModule3.out.dSYM/Contents/Resources/Python/TestModule3.py | ||
| # RUN: %lldb -b \ | ||
| # RUN: -o 'settings set target.load-script-from-symbol-file warn' \ | ||
| # RUN: -o 'target create %t/TestModule.out' \ | ||
| # RUN: -o 'target modules add %t/TestModule2.out %t/TestModule3.out' 2>&1 \ | ||
| # RUN: | FileCheck %s --strict-whitespace \ | ||
| # RUN: --implicit-check-not=DSYM_SCRIPT --implicit-check-not=DSYM_SCRIPT2 --implicit-check-not=DSYM_SCRIPT3 | ||
|
|
||
| # CHECK: (lldb) target create | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py | ||
|
|
||
| # CHECK: (lldb) target modules add | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/TestModule2.out.dSYM/Contents/Resources/Python/TestModule2.py | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/TestModule3.out.dSYM/Contents/Resources/Python/TestModule3.py | ||
|
|
||
| #--- main.c | ||
| int main() { return 0; } | ||
|
|
||
| #--- dsym_script.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("DSYM_SCRIPT", file=sys.stderr) | ||
|
|
||
| #--- dsym_script2.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("DSYM_SCRIPT2", file=sys.stderr) | ||
|
|
||
| #--- dsym_script3.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("DSYM_SCRIPT3", file=sys.stderr) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # REQUIRES: python, asserts, !system-windows | ||
| # | ||
| # Test that when load-script-from-symbol-file is set to 'warn' and multiple | ||
| # dependent modules with safe-path scripts are loaded in a single batch (via | ||
| # target create), LLDB emits a single warning listing all detected scripts. | ||
|
|
||
| # RUN: split-file %s %t | ||
| # RUN: %clang_host -shared -fPIC %t/lib.c -o %t/libTestLib1.so | ||
| # RUN: %clang_host -shared -fPIC %t/lib.c -o %t/libTestLib2.so | ||
| # RUN: %clang_host %t/main.c -o %t/main.out %t/libTestLib1.so %t/libTestLib2.so \ | ||
| # RUN: -Wl,-rpath,%t | ||
| # RUN: mkdir -p %t/safe-path/libTestLib1 | ||
| # RUN: mkdir -p %t/safe-path/libTestLib2 | ||
| # RUN: cp %t/script1.py %t/safe-path/libTestLib1/libTestLib1.py | ||
| # RUN: cp %t/script2.py %t/safe-path/libTestLib2/libTestLib2.py | ||
| # RUN: %lldb -b \ | ||
| # RUN: -o 'settings set target.load-script-from-symbol-file warn' \ | ||
| # RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ | ||
| # RUN: -o 'target create %t/main.out' 2>&1 \ | ||
| # RUN: | FileCheck %s --strict-whitespace \ | ||
| # RUN: --implicit-check-not=SCRIPT_LOADED1 --implicit-check-not=SCRIPT_LOADED2 | ||
|
|
||
| # Both dependent libraries should appear in a single warning. | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-DAG:{{^}} - {{.*}}/safe-path/libTestLib1/libTestLib1.py | ||
| # CHECK-DAG:{{^}} - {{.*}}/safe-path/libTestLib2/libTestLib2.py | ||
|
|
||
| #--- main.c | ||
| extern int lib_func(void); | ||
| int main() { return lib_func(); } | ||
|
|
||
| #--- lib.c | ||
| int lib_func(void) { return 0; } | ||
|
|
||
| #--- script1.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("SCRIPT_LOADED1", file=sys.stderr) | ||
|
|
||
| #--- script2.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("SCRIPT_LOADED2", file=sys.stderr) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # REQUIRES: python, asserts, !system-windows | ||
| # | ||
| # Test that when load-script-from-symbol-file is set to 'warn', LLDB emits a | ||
| # warning for each safe-path script without executing them. Verify that warnings | ||
| # are emitted for all modules, not just the first. | ||
|
|
||
| # RUN: split-file %s %t | ||
| # RUN: %clang_host %t/main.c -o %t/TestModule.out | ||
| # RUN: %clang_host %t/main.c -o %t/TestModule2.out | ||
| # RUN: %clang_host %t/main.c -o %t/TestModule3.out | ||
| # RUN: mkdir -p %t/safe-path/TestModule | ||
| # RUN: mkdir -p %t/safe-path/TestModule2 | ||
| # RUN: mkdir -p %t/safe-path/TestModule3 | ||
|
|
||
| # RUN: cp %t/script.py %t/safe-path/TestModule/TestModule.py | ||
| # RUN: cp %t/script2.py %t/safe-path/TestModule2/TestModule2.py | ||
| # RUN: cp %t/script3.py %t/safe-path/TestModule3/TestModule3.py | ||
| # RUN: %lldb -b \ | ||
| # RUN: -o 'settings set target.load-script-from-symbol-file warn' \ | ||
| # RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ | ||
| # RUN: -o 'target create %t/TestModule.out' \ | ||
| # RUN: -o 'target modules add %t/TestModule2.out %t/TestModule3.out' 2>&1 \ | ||
| # RUN: | FileCheck %s --strict-whitespace \ | ||
| # RUN: --implicit-check-not=SCRIPT_LOADED --implicit-check-not=SCRIPT2_LOADED --implicit-check-not=SCRIPT3_LOADED | ||
|
|
||
| # CHECK: (lldb) target create | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/safe-path/TestModule/TestModule.py | ||
|
|
||
| # CHECK: (lldb) target modules add | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/safe-path/TestModule2/TestModule2.py | ||
| # CHECK: warning: {{.*}}The following debug scripts were detected but not loaded: | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:{{^}} - {{.*}}/safe-path/TestModule3/TestModule3.py | ||
|
|
||
| #--- main.c | ||
| int main() { return 0; } | ||
|
|
||
| #--- script.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("SCRIPT_LOADED", file=sys.stderr) | ||
|
|
||
| #--- script2.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("SCRIPT2_LOADED", file=sys.stderr) | ||
|
|
||
| #--- script3.py | ||
| import sys | ||
| def __lldb_init_module(debugger, internal_dict): | ||
| print("SCRIPT3_LOADED", file=sys.stderr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, what I had in mind for this in #190407 is a little table for the given module. Something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue is that this will get printed on every module script load attempt. If there's a lot of them then printing the instructions
To run all discovered debug scripts...feels noisy.But will have a think of how to best present it. I do like the table