[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)

via lldb-commits lldb-commits at lists.llvm.org
Sun Feb 23 00:45:08 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/5] 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/5] 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/5] 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

>From c14b6dfc6c9fe6581f9324423a2c46f5870c4191 Mon Sep 17 00:00:00 2001
From: Rahul Reddy Chamala <rachamal at fb.com>
Date: Sat, 22 Feb 2025 15:50:54 -0800
Subject: [PATCH 4/5] Ignore module load errors by default and create
 placeholder modules for missing modules

---
 .../Process/scripted/ScriptedProcess.cpp      | 91 +++++++++++--------
 .../TestStackCoreScriptedProcess.py           |  1 -
 .../stack_core_scripted_process.py            | 21 +----
 3 files changed, 54 insertions(+), 59 deletions(-)

diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index 79d0bc51bc18c..6071e29d20669 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -25,6 +25,8 @@
 #include "lldb/Utility/ScriptedMetadata.h"
 #include "lldb/Utility/State.h"
 
+#include "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h"
+
 #include <mutex>
 
 LLDB_PLUGIN_DEFINE(ScriptedProcess)
@@ -422,11 +424,9 @@ bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
 lldb_private::StructuredData::ObjectSP
 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
   Status 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;
+  auto error_with_message = [&error](llvm::StringRef message) {
+    return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
+                                                     message.data(), error);
   };
 
   StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
@@ -438,13 +438,12 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
   ModuleList module_list;
   Target &target = GetTarget();
 
-  auto reload_image = [&target, &module_list, &handle_error_with_message](
+  auto reload_image = [&target, &module_list, &error_with_message](
                           StructuredData::Object *obj) -> bool {
     StructuredData::Dictionary *dict = obj->GetAsDictionary();
 
     if (!dict)
-      return handle_error_with_message(
-          "Couldn't cast image object into dictionary.", false);
+      return error_with_message("Couldn't cast image object into dictionary.");
 
     ModuleSpec module_spec;
     llvm::StringRef value;
@@ -452,65 +451,81 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
     bool has_path = dict->HasKey("path");
     bool has_uuid = dict->HasKey("uuid");
     if (!has_path && !has_uuid)
-      return handle_error_with_message(
-          "Dictionary should have key 'path' or 'uuid'", false);
+      return error_with_message("Dictionary should have key 'path' or 'uuid'");
     if (!dict->HasKey("load_addr"))
-      return handle_error_with_message("Dictionary is missing key 'load_addr'",
-                                       false);
+      return error_with_message("Dictionary is missing key 'load_addr'");
 
+    llvm::StringRef path = "";
     if (has_path) {
-      dict->GetValueForKeyAsString("path", value);
-      module_spec.GetFileSpec().SetPath(value);
+      dict->GetValueForKeyAsString("path", path);
+      module_spec.GetFileSpec().SetPath(path);
     }
 
     if (has_uuid) {
       dict->GetValueForKeyAsString("uuid", value);
       module_spec.GetUUID().SetFromStringRef(value);
     }
-    module_spec.GetArchitecture() = target.GetArchitecture();
-
-    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 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 handle_error_with_message(
-          "Couldn't get valid load address or slide offset.",
-          ignore_module_load_error);
+      return error_with_message(
+          "Couldn't get valid load address or slide offset.");
 
     if (slide != LLDB_INVALID_OFFSET)
       load_addr += slide;
 
+    module_spec.GetArchitecture() = target.GetArchitecture();
+
+    ModuleSP module_sp =
+        target.GetOrCreateModule(module_spec, true /* notify */);
+
+    bool is_placeholder_module = false;
+
+    if (!module_sp) {
+      // Create a placeholder module
+      LLDB_LOGF(
+          GetLog(LLDBLog::Process),
+          "ScriptedProcess::%s unable to locate the matching "
+          "object file path %s, creating a placeholder module at 0x%" PRIx64,
+          __FUNCTION__, path.str().c_str(), load_addr);
+
+      module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>(
+          module_spec, load_addr, module_spec.GetFileSpec().MemorySize());
+
+      is_placeholder_module = true;
+    }
+
     bool changed = false;
     module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
                               changed);
 
     if (!changed && !module_sp->GetObjectFile())
-      return handle_error_with_message(
-          "Couldn't set the load address for module.",
-          ignore_module_load_error);
+      return error_with_message("Couldn't set the load address for module.");
 
-    dict->GetValueForKeyAsString("path", value);
-    FileSpec objfile(value);
+    FileSpec objfile(path);
     module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
 
-    return ignore_module_load_error ? true
-                                    : module_list.AppendIfNeeded(module_sp);
+    if (is_placeholder_module) {
+      target.GetImages().AppendIfNeeded(module_sp, true /*notify=*/);
+      return true;
+    }
+
+    return module_list.AppendIfNeeded(module_sp);
   };
 
-  if (!loaded_images_sp->ForEach(reload_image))
-    return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
-        LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
+  size_t loaded_images_size = loaded_images_sp->GetSize();
+  bool print_error = true;
+  for (size_t idx = 0; idx < loaded_images_size; idx++) {
+    const auto &loaded_image = loaded_images_sp->GetItemAtIndex(idx);
+    if (!reload_image(loaded_image.get()) && print_error) {
+      print_error = false;
+      ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
+          LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
+    }
+  }
 
   target.ModulesDidLoad(module_list);
 
diff --git a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
index fa887390f4c9f..22b0d01c2c173 100644
--- a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
+++ b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
@@ -96,7 +96,6 @@ def cleanup():
                         {
                             "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 6f3124e64d3ce..2b7aec7c87a47 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
@@ -69,25 +69,6 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
                     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
@@ -102,6 +83,7 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
 
                 # If module load address is not specified/valid, try to find it from corefile module
                 if module_load_addr is None:
+                    module_name = os.path.basename(module_path)
                     corefile_module = self.get_module_with_name(
                         self.corefile_target, module_name
                     )
@@ -119,7 +101,6 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
                     {
                         "path": module_path,
                         "load_addr": module_load_addr,
-                        "ignore_module_load_error": ignore_module_load_error,
                     }
                 )
 

>From 3d3c48b55bb8d05ad9fa2578dfbdb24f99748b77 Mon Sep 17 00:00:00 2001
From: rchamala <rachamal at fb.com>
Date: Sat, 22 Feb 2025 23:52:51 -0800
Subject: [PATCH 5/5] Fix nit

---
 lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp    | 6 +++---
 .../scripted_process/stack_core_scripted_process.py         | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index 6071e29d20669..6b371a151668d 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -446,7 +446,6 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
       return error_with_message("Couldn't cast image object into dictionary.");
 
     ModuleSpec module_spec;
-    llvm::StringRef value;
 
     bool has_path = dict->HasKey("path");
     bool has_uuid = dict->HasKey("uuid");
@@ -461,9 +460,10 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
       module_spec.GetFileSpec().SetPath(path);
     }
 
+    llvm::StringRef uuid = "";
     if (has_uuid) {
-      dict->GetValueForKeyAsString("uuid", value);
-      module_spec.GetUUID().SetFromStringRef(value);
+      dict->GetValueForKeyAsString("uuid", uuid);
+      module_spec.GetUUID().SetFromStringRef(uuid);
     }
 
     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
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 2b7aec7c87a47..736bb69397f9b 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
@@ -66,7 +66,7 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
                     or not module_path_arg.IsValid()
                     or not module_path_arg.GetType() == lldb.eStructuredDataTypeString
                 ):
-                    return
+                    continue
 
                 module_path = module_path_arg.GetStringValue(100)
 
@@ -89,7 +89,7 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
                     )
 
                     if not corefile_module or not corefile_module.IsValid():
-                        return
+                        continue
 
                     module_load_addr = (
                         corefile_module.GetObjectFileHeaderAddress().GetLoadAddress(



More information about the lldb-commits mailing list