[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Feb 13 18:28:49 PST 2025
https://github.com/rchamala updated https://github.com/llvm/llvm-project/pull/127153
>From a4fdb2d54e76aefb771fe8ad8399494bb5fa8b70 Mon Sep 17 00:00:00 2001
From: rchamala <rachamal at fb.com>
Date: Thu, 13 Feb 2025 15:00:37 -0800
Subject: [PATCH 1/3] 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 <rachamal at fb.com>
Date: Thu, 13 Feb 2025 18:07:48 -0800
Subject: [PATCH 2/3] 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
>From 45b45e0c43eaab3c2ace682836c77302ac1e2761 Mon Sep 17 00:00:00 2001
From: rchamala <rachamal at fb.com>
Date: Thu, 13 Feb 2025 18:24:43 -0800
Subject: [PATCH 3/3] Fix nit formatting
---
.../scripted_process/stack_core_scripted_process.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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 841122f2a64be..6f3124e64d3ce 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
@@ -223,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
More information about the lldb-commits
mailing list