[lldb/API] Expose Module::IsLoadedInTarget() to SB API (NFC)

This patch adds an `SBTarget::IsLoaded(const SBModule&) const` endpoint
to lldb's Scripting Bridge API. As the name suggests, it will allow the
user to know if the module is loaded in a specific target.

rdar://37957625

Differential Review: https://reviews.llvm.org/D95686

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
GitOrigin-RevId: b8923c002207da449ec462ade468e27a651b1f91
diff --git a/bindings/interface/SBTarget.i b/bindings/interface/SBTarget.i
index f874726..772ee1a 100644
--- a/bindings/interface/SBTarget.i
+++ b/bindings/interface/SBTarget.i
@@ -938,6 +938,16 @@
     lldb::addr_t
     GetStackRedZoneSize();
 
+    %feature("docstring", "
+    Returns true if the module has been loaded in this `SBTarget`.
+    A module can be loaded either by the dynamic loader or by being manually
+    added to the target (see `SBTarget.AddModule` and the `target module add` command).
+
+    :rtype: bool
+    ") IsLoaded;
+    bool
+    IsLoaded (const lldb::SBModule &module) const;
+
     lldb::SBLaunchInfo
     GetLaunchInfo () const;
 
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 30f4005..f427404 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -834,6 +834,8 @@
 
   lldb::addr_t GetStackRedZoneSize();
 
+  bool IsLoaded(const lldb::SBModule &module) const;
+
   lldb::SBLaunchInfo GetLaunchInfo() const;
 
   void SetLaunchInfo(const lldb::SBLaunchInfo &launch_info);
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 6128c04..72702b9 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -2410,6 +2410,21 @@
   return 0;
 }
 
+bool SBTarget::IsLoaded(const SBModule &module) const {
+  LLDB_RECORD_METHOD_CONST(bool, SBTarget, IsLoaded, (const lldb::SBModule &),
+                           module);
+
+  TargetSP target_sp(GetSP());
+  if (!target_sp)
+    return LLDB_RECORD_RESULT(false);
+
+  ModuleSP module_sp(module.GetSP());
+  if (!module_sp)
+    return LLDB_RECORD_RESULT(false);
+
+  return LLDB_RECORD_RESULT(module_sp->IsLoadedInTarget(target_sp.get()));
+}
+
 lldb::SBLaunchInfo SBTarget::GetLaunchInfo() const {
   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBLaunchInfo, SBTarget, GetLaunchInfo);
 
@@ -2682,6 +2697,8 @@
   LLDB_REGISTER_METHOD(lldb::SBValue, SBTarget, EvaluateExpression,
                        (const char *, const lldb::SBExpressionOptions &));
   LLDB_REGISTER_METHOD(lldb::addr_t, SBTarget, GetStackRedZoneSize, ());
+  LLDB_REGISTER_METHOD_CONST(bool, SBTarget, IsLoaded,
+                             (const lldb::SBModule &));
   LLDB_REGISTER_METHOD_CONST(lldb::SBLaunchInfo, SBTarget, GetLaunchInfo, ());
   LLDB_REGISTER_METHOD(void, SBTarget, SetLaunchInfo,
                        (const lldb::SBLaunchInfo &));
diff --git a/test/API/python_api/target/TestTargetAPI.py b/test/API/python_api/target/TestTargetAPI.py
index 12c9d9d..c444b44 100644
--- a/test/API/python_api/target/TestTargetAPI.py
+++ b/test/API/python_api/target/TestTargetAPI.py
@@ -489,3 +489,27 @@
         target3 = self.dbg.CreateTargetWithFileAndTargetTriple(exe, target.GetTriple())
         self.assertTrue(target3.IsValid())
 
+
+    @add_test_categories(['pyapi'])
+    def test_is_loaded(self):
+        """Exercise SBTarget.IsLoaded(SBModule&) API."""
+        d = {'EXE': 'b.out'}
+        self.build(dictionary=d)
+        self.setTearDownCleanup(dictionary=d)
+        target = self.create_simple_target('b.out')
+
+        self.assertFalse(target.IsLoaded(lldb.SBModule()))
+
+        num_modules = target.GetNumModules()
+        for i in range(num_modules):
+            module = target.GetModuleAtIndex(i)
+            self.assertFalse(target.IsLoaded(module), "Target that isn't "
+                             "running shouldn't have any module loaded.")
+
+        process = target.LaunchSimple(None, None,
+                                      self.get_process_working_directory())
+
+        for i in range(num_modules):
+            module = target.GetModuleAtIndex(i)
+            self.assertTrue(target.IsLoaded(module), "Running the target should "
+                            "have loaded its modules.")