[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:07:56 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/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 <rachamal at 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



More information about the lldb-commits mailing list