diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index c94f6e84ff889..001ff7e112909 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -1091,6 +1091,13 @@ class Platform : public PluginInterface { const ScriptInterpreter::SanitizedScriptingModuleName &sanitized_name, const FileSpec &original_fspec, const FileSpec &fspec); + /// Returns the \c LoadScriptFromSymFile of scripting resource associated + /// with the specified module \c FileSpec. If the load style wasn't explicitly + /// set for a module, returns the target-wide default. + static LoadScriptFromSymFile + GetScriptLoadStyleForModule(const FileSpec &module_fspec, + const Target &target); + private: typedef std::function ModuleResolver; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 2e9ee1de3c456..16f21ad9d8271 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -239,6 +239,11 @@ class TargetProperties : public Properties { LoadScriptFromSymFile GetLoadScriptFromSymbolFile() const; + /// Set the target-wide target.load-script-from-symbol-file setting. + /// See \c SetAutoLoadScriptsForModule for overriding this setting + /// per-module. + void SetLoadScriptFromSymbolFile(LoadScriptFromSymFile load_style); + LoadCWDlldbinitFile GetLoadCWDlldbinitFile() const; Disassembler::HexImmediateStyle GetHexImmediateStyle() const; @@ -279,6 +284,16 @@ class TargetProperties : public Properties { bool GetDebugUtilityExpression() const; + std::optional + GetAutoLoadScriptsForModule(llvm::StringRef module_name) const; + + /// Set the \c LoadScriptFromSymFile for a module called \c module_name + /// (excluding file extension). LLDB will prefer this over the target-wide + /// target.load-script-from-symbol-file setting + /// (see \c SetLoadScriptFromSymbolFile). + void SetAutoLoadScriptsForModule(llvm::StringRef module_name, + LoadScriptFromSymFile load_style); + private: std::optional GetExperimentalPropertyValue(size_t prop_idx, diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index cc1e00562e4a0..6d6aa68a2462f 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -236,8 +236,9 @@ PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM( orig_script_fspec, script_fspec); if (FileSystem::Instance().Exists(script_fspec)) { - file_specs.try_emplace(std::move(script_fspec), - target.GetLoadScriptFromSymbolFile()); + LoadScriptFromSymFile load_style = + Platform::GetScriptLoadStyleForModule(script_fspec, target); + file_specs.try_emplace(std::move(script_fspec), load_style); break; } diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 57c30f2c95eb2..c92a71d2c3baa 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -24,6 +24,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Interpreter/OptionValueFileSpec.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" @@ -40,6 +41,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" @@ -159,6 +161,17 @@ Status Platform::GetFileWithUUID(const FileSpec &platform_file, bool Platform::IsSymbolFileTrusted(Module &module) { return false; } +LoadScriptFromSymFile +Platform::GetScriptLoadStyleForModule(const FileSpec &module_fspec, + const Target &target) { + LoadScriptFromSymFile default_load_style = + target.GetLoadScriptFromSymbolFile(); + + return target + .GetAutoLoadScriptsForModule(module_fspec.GetFileNameStrippingExtension()) + .value_or(default_load_style); +} + llvm::SmallDenseMap Platform::LocateExecutableScriptingResourcesFromSafePaths( Stream &feedback_stream, FileSpec module_spec, const Target &target) { @@ -200,9 +213,11 @@ Platform::LocateExecutableScriptingResourcesFromSafePaths( WarnIfInvalidUnsanitizedScriptExists(feedback_stream, sanitized_name, orig_script_fspec, script_fspec); - if (FileSystem::Instance().Exists(script_fspec)) - file_specs.try_emplace(std::move(script_fspec), - target.GetLoadScriptFromSymbolFile()); + if (FileSystem::Instance().Exists(script_fspec)) { + LoadScriptFromSymFile load_style = + Platform::GetScriptLoadStyleForModule(script_fspec, target); + file_specs.try_emplace(std::move(script_fspec), load_style); + } // If we successfully found a directory in a safe auto-load path // stop looking at any other paths. diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index d802e7b1bf40e..7394bb64a8ed9 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -40,6 +40,7 @@ #include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h" #include "lldb/Interpreter/OptionGroupWatchpoint.h" +#include "lldb/Interpreter/OptionValueEnumeration.h" #include "lldb/Interpreter/OptionValues.h" #include "lldb/Interpreter/Property.h" #include "lldb/Symbol/Function.h" @@ -5105,6 +5106,12 @@ LoadScriptFromSymFile TargetProperties::GetLoadScriptFromSymbolFile() const { g_target_properties[idx].default_uint_value)); } +void TargetProperties::SetLoadScriptFromSymbolFile( + LoadScriptFromSymFile load_style) { + const uint32_t idx = ePropertyLoadScriptFromSymbolFile; + SetPropertyAtIndex(idx, load_style); +} + LoadCWDlldbinitFile TargetProperties::GetLoadCWDlldbinitFile() const { const uint32_t idx = ePropertyLoadCWDlldbinitFile; return GetPropertyAtIndexAs( @@ -5275,6 +5282,33 @@ void TargetProperties::SetDebugUtilityExpression(bool debug) { SetPropertyAtIndex(idx, debug); } +std::optional +TargetProperties::GetAutoLoadScriptsForModule( + llvm::StringRef module_name) const { + auto *dict = m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary( + ePropertyAutoLoadScriptsForModules); + if (!dict) + return std::nullopt; + + OptionValueSP value_sp = dict->GetValueForKey(module_name); + if (!value_sp) + return std::nullopt; + + return value_sp->GetValueAs(); +} + +void TargetProperties::SetAutoLoadScriptsForModule( + llvm::StringRef module_name, LoadScriptFromSymFile load_style) { + auto *dict = m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary( + ePropertyAutoLoadScriptsForModules); + if (!dict) + return; + + dict->SetValueForKey(module_name, + std::make_shared( + g_load_script_from_sym_file_values, load_style)); +} + // Target::TargetEventData Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp) diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index f8b51ad8558b9..e36d233fc2469 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -222,6 +222,12 @@ let Definition = "target", Path = "target" in { def ParallelModuleLoad: Property<"parallel-module-load", "Boolean">, DefaultTrue, Desc<"Enable loading of modules in parallel for the dynamic loader.">; + def AutoLoadScriptsForModules + : Property<"auto-load-scripts-for-modules", "Dictionary">, + ElementType<"Enum">, + EnumValues<"OptionEnumValues(g_load_script_from_sym_file_values)">, + Desc<"A list of module/image names and whether LLDB should auto-load scripting " + "resources for it from safe paths.">; } let Definition = "process_experimental", Path = "target.process.experimental" in { diff --git a/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-false.test b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-false.test new file mode 100644 index 0000000000000..9cab60bf8dbfa --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-false.test @@ -0,0 +1,24 @@ +# REQUIRES: python, system-darwin + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'false', +# its scripting resources are NOT loaded even when target.load-script-from-symbol-file +# is true. + +# RUN: split-file %s %t +# RUN: %clang_host -g %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python +# RUN: cp %t/dsym_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py + +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file true' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=false' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 \ +# RUN: | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS --implicit-check-not=warning + +#--- main.c +int main() { return 0; } + +#--- dsym_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-multiple.test b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-multiple.test new file mode 100644 index 0000000000000..c1016ae0fab84 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-multiple.test @@ -0,0 +1,38 @@ +# REQUIRES: python, system-darwin + +# Test that multiple modules listed in target.auto-load-scripts-for-modules are all +# auto-loaded. + +# RUN: split-file %s %t +# RUN: %clang_host -shared %t/lib.c -o %t/libFoo.dylib +# RUN: %clang_host %t/main.c -o %t/TestModule.out %t/libFoo.dylib +# RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python +# RUN: mkdir -p %t/libFoo.out.dSYM/Contents/Resources/Python +# +# RUN: cp %t/main_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py +# RUN: cp %t/lib_script.py %t/libFoo.out.dSYM/Contents/Resources/Python/libFoo.py + +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file false' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=true libFoo=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s + +# CHECK-DAG: MAIN_AUTOLOAD_SUCCESS +# CHECK-DAG: LIB_AUTOLOAD_SUCCESS + +#--- main.c +extern int foo(void); +int main() { return foo(); } + +#--- lib.c +int foo(void) { return 0; } + +#--- main_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("MAIN_AUTOLOAD_SUCCESS", file=sys.stderr) + +#--- lib_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("LIB_AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-not-in-dict.test b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-not-in-dict.test new file mode 100644 index 0000000000000..1ca595b9ec067 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-not-in-dict.test @@ -0,0 +1,27 @@ +# REQUIRES: python, system-darwin + +# Test that when a module is NOT in target.auto-load-scripts-for-modules, the existing +# target.load-script-from-symbol-file setting controls whether scripts load. +# With load-script-from-symbol-file=true and no dictionary entry, scripts +# should still load normally. + +# RUN: split-file %s %t +# RUN: %clang_host -g %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python +# RUN: cp %t/dsym_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py + +## A different module is in the dictionary; TestModule is not. +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file warn' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules SomeOtherModule=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS + +# CHECK: warning: 'TestModule' contains an untrusted debug script. To run this script in this debug session + +#--- main.c +int main() { return 0; } + +#--- dsym_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-true.test b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-true.test new file mode 100644 index 0000000000000..31aa3d4101b81 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-true.test @@ -0,0 +1,25 @@ +# REQUIRES: python, system-darwin + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'true', +# its scripting resources are loaded even when target.load-script-from-symbol-file +# is false. + +# RUN: split-file %s %t +# RUN: %clang_host -g %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python +# RUN: cp %t/dsym_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py + +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file false' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s + +# CHECK: AUTOLOAD_SUCCESS + +#--- main.c +int main() { return 0; } + +#--- dsym_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-warn.test b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-warn.test new file mode 100644 index 0000000000000..df5b57ae2c5e4 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/Darwin/dsym-auto-load-modules-warn.test @@ -0,0 +1,26 @@ +# REQUIRES: python, system-darwin + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'warn', +# its scripting resources are NOT loaded even when target.load-script-from-symbol-file +# is true but we still print a warning. + +# RUN: split-file %s %t +# RUN: %clang_host -g %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/TestModule.out.dSYM/Contents/Resources/Python +# RUN: cp %t/dsym_script.py %t/TestModule.out.dSYM/Contents/Resources/Python/TestModule.py + +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file true' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=warn' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 \ +# RUN: | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS + +# CHECK-WARN: warning: 'TestModule' contains an untrusted debug script. To run this script in this debug session: + +#--- main.c +int main() { return 0; } + +#--- dsym_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-false.test b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-false.test new file mode 100644 index 0000000000000..7154d52e8f6a2 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-false.test @@ -0,0 +1,25 @@ +# REQUIRES: python, asserts, !system-windows + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'false', +# its scripting resources are NOT loaded even when target.load-script-from-symbol-file +# is true. + +# RUN: split-file %s %t +# RUN: %clang_host %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/safe-path/TestModule + +# RUN: cp %t/script.py %t/safe-path/TestModule/TestModule.py +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file true' \ +# RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=false' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 \ +# RUN: | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS --implicit-check-not=warning + +#--- main.c +int main() { return 0; } + +#--- script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-multiple.test b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-multiple.test new file mode 100644 index 0000000000000..d26c574ff2d5c --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-multiple.test @@ -0,0 +1,38 @@ +# REQUIRES: python, asserts, !system-windows + +# Test that multiple modules listed in target.auto-load-scripts-for-modules are all +# auto-loaded. + +# RUN: split-file %s %t +# RUN: %clang_host -shared %t/lib.c -o %t/libFoo.dylib +# RUN: %clang_host %t/main.c -o %t/TestModule.out %t/libFoo.dylib +# RUN: mkdir -p %t/safe-path/TestModule +# RUN: mkdir -p %t/safe-path/libFoo + +# RUN: cp %t/main_script.py %t/safe-path/TestModule/TestModule.py +# RUN: cp %t/lib_script.py %t/safe-path/libFoo/libFoo.py +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file false' \ +# RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=true libFoo=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s + +# CHECK-DAG: MAIN_AUTOLOAD_SUCCESS +# CHECK-DAG: LIB_AUTOLOAD_SUCCESS + +#--- main.c +extern int foo(void); +int main() { return foo(); } + +#--- lib.c +int foo(void) { return 0; } + +#--- main_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("MAIN_AUTOLOAD_SUCCESS", file=sys.stderr) + +#--- lib_script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("LIB_AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-not-in-dict.test b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-not-in-dict.test new file mode 100644 index 0000000000000..802f49c12f0e6 --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-not-in-dict.test @@ -0,0 +1,29 @@ +# REQUIRES: python, asserts, !system-windows + +# Test that when a module is NOT in target.auto-load-scripts-for-modules, the existing +# target.load-script-from-symbol-file setting controls whether scripts load. +# With load-script-from-symbol-file=true and no dictionary entry, scripts +# should still load normally. + +# RUN: split-file %s %t +# RUN: %clang_host %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/safe-path/TestModule + +# RUN: cp %t/script.py %t/safe-path/TestModule/TestModule.py + +## A different module is in the dictionary; TestModule is not. +# 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 'settings set target.auto-load-scripts-for-modules SomeOtherModule=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS + +# CHECK: warning: 'TestModule' contains an untrusted debug script. To run this script in this debug session + +#--- main.c +int main() { return 0; } + +#--- script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-true.test b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-true.test new file mode 100644 index 0000000000000..f1f2932cac55b --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-true.test @@ -0,0 +1,26 @@ +# REQUIRES: python, asserts, !system-windows + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'true', +# its scripting resources are loaded even when target.load-script-from-symbol-file +# is false. + +# RUN: split-file %s %t +# RUN: %clang_host %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/safe-path/TestModule + +# RUN: cp %t/script.py %t/safe-path/TestModule/TestModule.py +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file false' \ +# RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=true' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 | FileCheck %s + +# CHECK: AUTOLOAD_SUCCESS + +#--- main.c +int main() { return 0; } + +#--- script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-warn.test b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-warn.test new file mode 100644 index 0000000000000..48a9a8483ef7b --- /dev/null +++ b/lldb/test/Shell/Platform/AutoLoad/UNIX/auto-load-modules-warn.test @@ -0,0 +1,27 @@ +# REQUIRES: python, asserts, !system-windows + +# Test that when a module is listed in target.auto-load-scripts-for-modules with 'warn', +# its scripting resources are NOT loaded even when target.load-script-from-symbol-file +# is true but we print a warning. + +# RUN: split-file %s %t +# RUN: %clang_host %t/main.c -o %t/TestModule.out +# RUN: mkdir -p %t/safe-path/TestModule + +# RUN: cp %t/script.py %t/safe-path/TestModule/TestModule.py +# RUN: %lldb -b \ +# RUN: -o 'settings set target.load-script-from-symbol-file true' \ +# RUN: -o 'settings append testing.safe-auto-load-paths %t/safe-path' \ +# RUN: -o 'settings set target.auto-load-scripts-for-modules TestModule=warn' \ +# RUN: -o 'target create %t/TestModule.out' 2>&1 \ +# RUN: | FileCheck %s --implicit-check-not=AUTOLOAD_SUCCESS + +# CHECK-WARN: warning: 'TestModule' contains an untrusted debug script. To run this script in this debug session: + +#--- main.c +int main() { return 0; } + +#--- script.py +import sys +def __lldb_init_module(debugger, internal_dict): + print("AUTOLOAD_SUCCESS", file=sys.stderr) diff --git a/lldb/unittests/Platform/PlatformDarwinTest.cpp b/lldb/unittests/Platform/PlatformDarwinTest.cpp index 70986bf3e0199..803bbc558c552 100644 --- a/lldb/unittests/Platform/PlatformDarwinTest.cpp +++ b/lldb/unittests/Platform/PlatformDarwinTest.cpp @@ -545,6 +545,135 @@ TEST_F( EXPECT_TRUE(ss.Empty()); } +TEST_F(PlatformDarwinLocateTest, + LocateExecutableScriptingResourcesFromDSYM_AutoLoadScriptsForModule) { + // Test that the LocateExecutableScriptingResourcesFromDSYM API respects the + // target.auto-load-scripts-for-modules setting. + + m_target_sp->SetLoadScriptFromSymbolFile(eLoadScriptFromSymFileTrusted); + TestingProperties::GetGlobalTestingProperties().AppendSafeAutoLoadPaths( + FileSpec(m_tmp_root_dir)); + + auto setup_module = [this](llvm::StringRef module_name) { + FileSpec module_fspec( + CreateFile(llvm::formatv("{0}.o", module_name).str(), m_tmp_root_dir)); + EXPECT_TRUE(module_fspec); + + FileSpec dsym_module_fpec(CreateFile( + llvm::formatv("{0}.o", module_name).str(), m_tmp_dsym_dwarf_dir)); + EXPECT_TRUE(dsym_module_fpec); + + FileSpec script_fspec(CreateFile(llvm::formatv("{0}.py", module_name).str(), + m_tmp_dsym_python_dir)); + + return std::pair{script_fspec, dsym_module_fpec}; + }; + + auto [script_false_fspec, dsym_module_false_fspec] = + setup_module("ModuleFalse"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleFalse", + eLoadScriptFromSymFileFalse); + + auto [script_true_fspec, dsym_module_true_fspec] = setup_module("ModuleTrue"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleTrue", + eLoadScriptFromSymFileTrue); + + auto [script_warn_fspec, dsym_module_warn_fspec] = setup_module("ModuleWarn"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleWarn", + eLoadScriptFromSymFileWarn); + + auto [script_trusted_fspec, dsym_module_trusted_fspec] = + setup_module("ModuleTrusted"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleTrusted", + eLoadScriptFromSymFileTrusted); + + auto [script_another_true_fspec, dsym_module_another_true_fspec] = + setup_module("ModuleAnotherTrue"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleAnotherTrue", + eLoadScriptFromSymFileTrue); + + auto [script_default_fspec, dsym_module_default_fspec] = + setup_module("ModuleDefault"); + + { + StreamString ss; + auto fspecs = + std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_false_fspec, *m_target_sp, dsym_module_false_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_false_fspec)); + + EXPECT_EQ(fspecs[script_false_fspec], eLoadScriptFromSymFileFalse); + } + + { + StreamString ss; + auto fspecs = + std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_true_fspec, *m_target_sp, dsym_module_true_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_true_fspec)); + + EXPECT_EQ(fspecs[script_true_fspec], eLoadScriptFromSymFileTrue); + } + + { + StreamString ss; + auto fspecs = + std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_warn_fspec, *m_target_sp, dsym_module_warn_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_warn_fspec)); + + EXPECT_EQ(fspecs[script_warn_fspec], eLoadScriptFromSymFileWarn); + } + + { + StreamString ss; + auto fspecs = std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_trusted_fspec, *m_target_sp, + dsym_module_trusted_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_trusted_fspec)); + + EXPECT_EQ(fspecs[script_trusted_fspec], eLoadScriptFromSymFileTrusted); + } + + { + StreamString ss; + auto fspecs = std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_another_true_fspec, *m_target_sp, + dsym_module_another_true_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_another_true_fspec)); + + EXPECT_EQ(fspecs[script_another_true_fspec], eLoadScriptFromSymFileTrue); + } + + { + StreamString ss; + auto fspecs = std::static_pointer_cast(m_platform_sp) + ->LocateExecutableScriptingResourcesFromDSYM( + ss, script_default_fspec, *m_target_sp, + dsym_module_default_fspec); + + ASSERT_EQ(fspecs.size(), 1u); + ASSERT_TRUE(fspecs.contains(script_default_fspec)); + + EXPECT_EQ(fspecs[script_default_fspec], eLoadScriptFromSymFileTrusted); + } +} + struct SpecialCharTestCase { char special_char; char replacement; diff --git a/lldb/unittests/Platform/PlatformTest.cpp b/lldb/unittests/Platform/PlatformTest.cpp index 1769282459eee..73899d6046f33 100644 --- a/lldb/unittests/Platform/PlatformTest.cpp +++ b/lldb/unittests/Platform/PlatformTest.cpp @@ -672,4 +672,116 @@ TEST_F(PlatformLocateSafePathTest, EXPECT_EQ(file_specs.size(), 1u); EXPECT_TRUE(ss.GetString().empty()); } + +TEST_F(PlatformLocateSafePathTest, + LocateScriptingResourcesFromSafePaths_AutoLoadScriptsForModule) { + // Test that the LocateScriptingResourcesFromSafePaths API respects the + // target.auto-load-scripts-for-modules setting. + + m_target_sp->SetLoadScriptFromSymbolFile(eLoadScriptFromSymFileTrusted); + TestingProperties::GetGlobalTestingProperties().AppendSafeAutoLoadPaths( + FileSpec(m_tmp_root_dir)); + + auto setup_module = [this](llvm::StringRef module_name) { + FileSpec module_fspec( + CreateFile(llvm::formatv("{0}.o", module_name).str(), m_tmp_root_dir)); + EXPECT_TRUE(module_fspec); + + llvm::SmallString<128> module_dir(m_tmp_root_dir); + llvm::sys::path::append(module_dir, module_name); + EXPECT_FALSE(llvm::sys::fs::create_directory(module_dir)); + + return FileSpec( + CreateFile(llvm::formatv("{0}.py", module_name).str(), module_dir)); + }; + + FileSpec script_false_fspec = setup_module("ModuleFalse"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleFalse", + eLoadScriptFromSymFileFalse); + + FileSpec script_true_fspec = setup_module("ModuleTrue"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleTrue", + eLoadScriptFromSymFileTrue); + + FileSpec script_warn_fspec = setup_module("ModuleWarn"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleWarn", + eLoadScriptFromSymFileWarn); + + FileSpec script_trusted_fspec = setup_module("ModuleTrusted"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleTrusted", + eLoadScriptFromSymFileTrusted); + + FileSpec script_another_true_fspec = setup_module("ModuleAnotherTrue"); + m_target_sp->SetAutoLoadScriptsForModule("ModuleAnotherTrue", + eLoadScriptFromSymFileTrue); + + FileSpec script_default_fspec = setup_module("ModuleDefault"); + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_false_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_false_fspec)); + + EXPECT_EQ(file_specs[script_false_fspec], eLoadScriptFromSymFileFalse); + } + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_true_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_true_fspec)); + + EXPECT_EQ(file_specs[script_true_fspec], eLoadScriptFromSymFileTrue); + } + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_warn_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_warn_fspec)); + + EXPECT_EQ(file_specs[script_warn_fspec], eLoadScriptFromSymFileWarn); + } + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_trusted_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_trusted_fspec)); + + EXPECT_EQ(file_specs[script_trusted_fspec], eLoadScriptFromSymFileTrusted); + } + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_another_true_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_another_true_fspec)); + + EXPECT_EQ(file_specs[script_another_true_fspec], + eLoadScriptFromSymFileTrue); + } + + { + StreamString ss; + auto file_specs = Platform::LocateExecutableScriptingResourcesFromSafePaths( + ss, script_default_fspec, *m_target_sp); + + ASSERT_EQ(file_specs.size(), 1u); + ASSERT_TRUE(file_specs.contains(script_default_fspec)); + + EXPECT_EQ(file_specs[script_default_fspec], eLoadScriptFromSymFileTrusted); + } +} #endif // NDEBUG