https://github.com/rchamala updated https://github.com/llvm/llvm-project/pull/127153
>From a4fdb2d54e76aefb771fe8ad8399494bb5fa8b70 Mon Sep 17 00:00:00 2001 From: rchamala <racha...@fb.com> Date: Thu, 13 Feb 2025 15:00:37 -0800 Subject: [PATCH 1/2] Allow option to ignore module load errors in ScriptedProcess --- .../Process/scripted/ScriptedProcess.cpp | 39 ++++++++---- .../TestStackCoreScriptedProcess.py | 15 ++++- .../stack_core_scripted_process.py | 60 ++++++++++++++----- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index d2111ce877ce5..79d0bc51bc18c 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -165,7 +165,7 @@ Status ScriptedProcess::DoLoadCore() { Status ScriptedProcess::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__); - + /* MARK: This doesn't reflect how lldb actually launches a process. In reality, it attaches to debugserver, then resume the process. That's not true in all cases. If debugserver is remote, lldb @@ -422,9 +422,11 @@ bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { lldb_private::StructuredData::ObjectSP ScriptedProcess::GetLoadedDynamicLibrariesInfos() { Status error; - auto error_with_message = [&error](llvm::StringRef message) { - return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, - message.data(), error); + auto handle_error_with_message = [&error](llvm::StringRef message, + bool ignore_error) { + ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, + message.data(), error); + return ignore_error; }; StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); @@ -436,12 +438,13 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { ModuleList module_list; Target &target = GetTarget(); - auto reload_image = [&target, &module_list, &error_with_message]( + auto reload_image = [&target, &module_list, &handle_error_with_message]( StructuredData::Object *obj) -> bool { StructuredData::Dictionary *dict = obj->GetAsDictionary(); if (!dict) - return error_with_message("Couldn't cast image object into dictionary."); + return handle_error_with_message( + "Couldn't cast image object into dictionary.", false); ModuleSpec module_spec; llvm::StringRef value; @@ -449,9 +452,11 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { bool has_path = dict->HasKey("path"); bool has_uuid = dict->HasKey("uuid"); if (!has_path && !has_uuid) - return error_with_message("Dictionary should have key 'path' or 'uuid'"); + return handle_error_with_message( + "Dictionary should have key 'path' or 'uuid'", false); if (!dict->HasKey("load_addr")) - return error_with_message("Dictionary is missing key 'load_addr'"); + return handle_error_with_message("Dictionary is missing key 'load_addr'", + false); if (has_path) { dict->GetValueForKeyAsString("path", value); @@ -467,16 +472,21 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { ModuleSP module_sp = target.GetOrCreateModule(module_spec, true /* notify */); + bool ignore_module_load_error = false; + dict->GetValueForKeyAsBoolean("ignore_module_load_error", + ignore_module_load_error); if (!module_sp) - return error_with_message("Couldn't create or get module."); + return handle_error_with_message("Couldn't create or get module.", + ignore_module_load_error); lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; lldb::offset_t slide = LLDB_INVALID_OFFSET; dict->GetValueForKeyAsInteger("load_addr", load_addr); dict->GetValueForKeyAsInteger("slide", slide); if (load_addr == LLDB_INVALID_ADDRESS) - return error_with_message( - "Couldn't get valid load address or slide offset."); + return handle_error_with_message( + "Couldn't get valid load address or slide offset.", + ignore_module_load_error); if (slide != LLDB_INVALID_OFFSET) load_addr += slide; @@ -486,13 +496,16 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { changed); if (!changed && !module_sp->GetObjectFile()) - return error_with_message("Couldn't set the load address for module."); + return handle_error_with_message( + "Couldn't set the load address for module.", + ignore_module_load_error); dict->GetValueForKeyAsString("path", value); FileSpec objfile(value); module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); - return module_list.AppendIfNeeded(module_sp); + return ignore_module_load_error ? true + : module_list.AppendIfNeeded(module_sp); }; if (!loaded_images_sp->ForEach(reload_image)) diff --git a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py index a5c79378bab50..ca6b0fa5229a3 100644 --- a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py @@ -76,6 +76,10 @@ def cleanup(): ) self.assertTrue(corefile_process, PROCESS_IS_VALID) + # Create a random lib which does not exist in the corefile. + random_dylib = self.get_module_with_name(corefile_target, "random.dylib") + self.assertFalse(random_dylib, "Dynamic library random.dylib should not be found.") + structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( json.dumps( @@ -83,7 +87,16 @@ def cleanup(): "backing_target_idx": self.dbg.GetIndexOfTarget( corefile_process.GetTarget() ), - "libbaz_path": self.getBuildArtifact("libbaz.dylib"), + "custom_modules": [ + { + "path": self.getBuildArtifact("libbaz.dylib"), + }, + { + "path": "/random/path/random.dylib", + "load_addr": 12345678, + "ignore_module_load_error": True + } + ] } ) ) diff --git a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py index 8641d9a7ced35..86e5feb49e6cf 100644 --- a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py @@ -46,22 +46,52 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData if len(self.threads) == 2: self.threads[len(self.threads) - 1].is_stopped = True - corefile_module = self.get_module_with_name( - self.corefile_target, "libbaz.dylib" - ) - if not corefile_module or not corefile_module.IsValid(): - return - module_path = os.path.join( - corefile_module.GetFileSpec().GetDirectory(), - corefile_module.GetFileSpec().GetFilename(), - ) - if not os.path.exists(module_path): - return - module_load_addr = corefile_module.GetObjectFileHeaderAddress().GetLoadAddress( - self.corefile_target - ) + custom_modules = args.GetValueForKey("custom_modules") + if custom_modules.GetType() == lldb.eStructuredDataTypeArray: + for id in range(custom_modules.GetSize()): + + custom_module = custom_modules.GetItemAtIndex(id) + if not custom_module or not custom_module.IsValid() or not custom_module.GetType() == lldb.eStructuredDataTypeDictionary: + continue + + # Get custom module path from args + module_path_arg = custom_module.GetValueForKey("path") + module_path = None + if not module_path_arg or not module_path_arg.IsValid() or not module_path_arg.GetType() == lldb.eStructuredDataTypeString: + return + + module_path = module_path_arg.GetStringValue(100) + module_name = os.path.basename(module_path) + + # Get ignore_module_load_error boolean from args + ignore_module_load_error = False + ignore_module_load_error_arg = custom_module.GetValueForKey("ignore_module_load_error") + if ignore_module_load_error_arg and ignore_module_load_error_arg.IsValid() and ignore_module_load_error_arg.GetType() == lldb.eStructuredDataTypeBoolean: + ignore_module_load_error = ignore_module_load_error_arg.GetBooleanValue() + + if not os.path.exists(module_path) and not ignore_module_load_error: + return + + # Get custom module load address from args + module_load_addr = None + module_load_addr_arg = custom_module.GetValueForKey("load_addr") + if module_load_addr_arg and module_load_addr_arg.IsValid() and module_load_addr_arg.GetType() == lldb.eStructuredDataTypeInteger: + module_load_addr = module_load_addr_arg.GetIntegerValue() + + # If module load address is not specified/valid, try to find it from corefile module + if module_load_addr is None: + corefile_module = self.get_module_with_name( + self.corefile_target, module_name + ) + + if not corefile_module or not corefile_module.IsValid(): + return + + module_load_addr = corefile_module.GetObjectFileHeaderAddress().GetLoadAddress( + self.corefile_target + ) - self.loaded_images.append({"path": module_path, "load_addr": module_load_addr}) + self.loaded_images.append({"path": module_path, "load_addr": module_load_addr, "ignore_module_load_error": ignore_module_load_error}) def get_memory_region_containing_address( self, addr: int >From ba03d9dbcf5d7065d3801c07998ebd1b3837848d Mon Sep 17 00:00:00 2001 From: rchamala <racha...@fb.com> Date: Thu, 13 Feb 2025 18:07:48 -0800 Subject: [PATCH 2/2] Fix code formatting --- .../TestStackCoreScriptedProcess.py | 10 ++-- .../stack_core_scripted_process.py | 54 ++++++++++++++----- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py index ca6b0fa5229a3..fa887390f4c9f 100644 --- a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py @@ -78,7 +78,9 @@ def cleanup(): # Create a random lib which does not exist in the corefile. random_dylib = self.get_module_with_name(corefile_target, "random.dylib") - self.assertFalse(random_dylib, "Dynamic library random.dylib should not be found.") + self.assertFalse( + random_dylib, "Dynamic library random.dylib should not be found." + ) structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( @@ -94,9 +96,9 @@ def cleanup(): { "path": "/random/path/random.dylib", "load_addr": 12345678, - "ignore_module_load_error": True - } - ] + "ignore_module_load_error": True, + }, + ], } ) ) diff --git a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py index 86e5feb49e6cf..841122f2a64be 100644 --- a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py @@ -51,13 +51,21 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData for id in range(custom_modules.GetSize()): custom_module = custom_modules.GetItemAtIndex(id) - if not custom_module or not custom_module.IsValid() or not custom_module.GetType() == lldb.eStructuredDataTypeDictionary: + if ( + not custom_module + or not custom_module.IsValid() + or not custom_module.GetType() == lldb.eStructuredDataTypeDictionary + ): continue # Get custom module path from args module_path_arg = custom_module.GetValueForKey("path") module_path = None - if not module_path_arg or not module_path_arg.IsValid() or not module_path_arg.GetType() == lldb.eStructuredDataTypeString: + if ( + not module_path_arg + or not module_path_arg.IsValid() + or not module_path_arg.GetType() == lldb.eStructuredDataTypeString + ): return module_path = module_path_arg.GetStringValue(100) @@ -65,9 +73,18 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData # Get ignore_module_load_error boolean from args ignore_module_load_error = False - ignore_module_load_error_arg = custom_module.GetValueForKey("ignore_module_load_error") - if ignore_module_load_error_arg and ignore_module_load_error_arg.IsValid() and ignore_module_load_error_arg.GetType() == lldb.eStructuredDataTypeBoolean: - ignore_module_load_error = ignore_module_load_error_arg.GetBooleanValue() + ignore_module_load_error_arg = custom_module.GetValueForKey( + "ignore_module_load_error" + ) + if ( + ignore_module_load_error_arg + and ignore_module_load_error_arg.IsValid() + and ignore_module_load_error_arg.GetType() + == lldb.eStructuredDataTypeBoolean + ): + ignore_module_load_error = ( + ignore_module_load_error_arg.GetBooleanValue() + ) if not os.path.exists(module_path) and not ignore_module_load_error: return @@ -75,7 +92,12 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData # Get custom module load address from args module_load_addr = None module_load_addr_arg = custom_module.GetValueForKey("load_addr") - if module_load_addr_arg and module_load_addr_arg.IsValid() and module_load_addr_arg.GetType() == lldb.eStructuredDataTypeInteger: + if ( + module_load_addr_arg + and module_load_addr_arg.IsValid() + and module_load_addr_arg.GetType() + == lldb.eStructuredDataTypeInteger + ): module_load_addr = module_load_addr_arg.GetIntegerValue() # If module load address is not specified/valid, try to find it from corefile module @@ -87,11 +109,19 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData if not corefile_module or not corefile_module.IsValid(): return - module_load_addr = corefile_module.GetObjectFileHeaderAddress().GetLoadAddress( - self.corefile_target + module_load_addr = ( + corefile_module.GetObjectFileHeaderAddress().GetLoadAddress( + self.corefile_target + ) ) - self.loaded_images.append({"path": module_path, "load_addr": module_load_addr, "ignore_module_load_error": ignore_module_load_error}) + self.loaded_images.append( + { + "path": module_path, + "load_addr": module_load_addr, + "ignore_module_load_error": ignore_module_load_error, + } + ) def get_memory_region_containing_address( self, addr: int @@ -193,9 +223,9 @@ def get_stop_reason(self) -> Dict[str, Any]: if self.is_stopped: if "arm64" in self.scripted_process.arch: stop_reason["type"] = lldb.eStopReasonException - stop_reason["data"][ - "desc" - ] = self.corefile_thread.GetStopDescription(100) + stop_reason["data"]["desc"] = ( + self.corefile_thread.GetStopDescription(100) + ) elif self.scripted_process.arch == "x86_64": stop_reason["type"] = lldb.eStopReasonSignal stop_reason["data"]["signal"] = signal.SIGTRAP _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits