llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Greg Clayton (clayborg)

<details>
<summary>Changes</summary>

This patch extends the "target hook" to be able to lazily resolve addresses. It 
does so by allowing the python class that gets specified to the "target hook" 
to have a new 'def resolve_load_addr(self, load_addr, stream) -&gt; 
lldb.SBAddress' method that is optionally implemented. 

JIT loader plug-ins can now be implemented by creating a python class and using 
the "target hook add" and specifying the python class. The script can find and 
load the corresponding module lazily and only when needed. As a backtrace is 
happening, the PC's are resolved through the target and if the PC fails to 
resolve to a section/offset address, the `resolve_load_address` method will be 
called and the address can be resolved.

---

Patch is 31.11 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/212831.diff


19 Files Affected:

- (modified) lldb/bindings/python/python-swigsafecast.swig (+4) 
- (modified) lldb/bindings/python/python-wrapper.swig (+12) 
- (modified) lldb/examples/python/templates/scripted_hook.py (+24) 
- (modified) lldb/include/lldb/API/SBAddress.h (+9) 
- (modified) lldb/include/lldb/Interpreter/Interfaces/ScriptedHookInterface.h 
(+25-2) 
- (modified) lldb/include/lldb/Interpreter/ScriptInterpreter.h (+2) 
- (modified) lldb/include/lldb/Target/Target.h (+13-1) 
- (modified) lldb/source/Commands/CommandObjectTarget.cpp (+4-1) 
- (modified) lldb/source/Interpreter/ScriptInterpreter.cpp (+9) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.cpp
 (+27) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.h
 (+3-2) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 (+14) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
 (+8) 
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h 
(+2) 
- (modified) lldb/source/Target/Target.cpp (+46-2) 
- (added) lldb/test/API/commands/target/module-hook/resolve-addr/Makefile (+2) 
- (added) 
lldb/test/API/commands/target/module-hook/resolve-addr/TestModuleHookResolveAddr.py
 (+128) 
- (added) lldb/test/API/commands/target/module-hook/resolve-addr/addrhook.py 
(+94) 
- (added) lldb/test/API/commands/target/module-hook/resolve-addr/main.cpp (+4) 


``````````diff
diff --git a/lldb/bindings/python/python-swigsafecast.swig 
b/lldb/bindings/python/python-swigsafecast.swig
index a86dc44ce4106..ec3b36a7b1ec7 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -59,6 +59,10 @@ PythonObject SWIGBridge::ToSWIGWrapper(const 
StructuredDataImpl &data_impl) {
   return ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData>(new 
lldb::SBStructuredData(data_impl)));
 }
 
+PythonObject SWIGBridge::ToSWIGWrapper(const Address &addr) {
+  return ToSWIGHelper(new lldb::SBAddress(addr), SWIGTYPE_p_lldb__SBAddress);
+}
+
 PythonObject SWIGBridge::ToSWIGWrapper(lldb::ThreadSP thread_sp) {
   return ToSWIGHelper(new lldb::SBThread(std::move(thread_sp)),
                       SWIGTYPE_p_lldb__SBThread);
diff --git a/lldb/bindings/python/python-wrapper.swig 
b/lldb/bindings/python/python-wrapper.swig
index 2392737402e20..513d04bd3daa2 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -533,6 +533,18 @@ void 
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObjec
   return sb_ptr;
 }
 
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBAddress(PyObject * 
data) {
+  lldb::SBAddress *sb_ptr = nullptr;
+
+  int valid_cast =
+      SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBAddress, 0);
+
+  if (valid_cast == -1)
+    return NULL;
+
+  return sb_ptr;
+}
+
 void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * 
data) {
   lldb::SBValue *sb_ptr = NULL;
 
diff --git a/lldb/examples/python/templates/scripted_hook.py 
b/lldb/examples/python/templates/scripted_hook.py
index 0725c2c9c5d91..a8468aea2ab3d 100644
--- a/lldb/examples/python/templates/scripted_hook.py
+++ b/lldb/examples/python/templates/scripted_hook.py
@@ -65,3 +65,27 @@ def handle_stop(
             returned to the user, `False` if the process should keep running.
         """
         pass
+
+
+    def handle_resolve_addr(
+        self, load_addr: int, stream: lldb.SBStream) -> lldb.SBAddress:
+        """Called whenever the target is not able to resolve a load address to
+        a section offset address.
+
+        Clients can implement a JIT loader plugin using this method. Anytime 
the
+        target fails to resolve an address, this method will be called. The
+        function can find the file for the module that contains the address,
+        load it into the target, and return the resolved address. If the
+        address cannot be resolved, return a default construct lldb.SBAddress.
+
+        Args:
+            load_addr (int): The load address to attempt to resolve.
+            stream (lldb.SBStream): The stream to which the hook can write
+                output that will be reported to the user.
+
+        Returns:
+            lldb.SBAddress: If the address was resolved, return a SBAddress
+            that has been resolved to a section offset address, or return a
+            default constructed SBAddress if the address could not be resolved.
+        """
+        pass
diff --git a/lldb/include/lldb/API/SBAddress.h 
b/lldb/include/lldb/API/SBAddress.h
index 430dad4862dbf..bb490ee9dfedd 100644
--- a/lldb/include/lldb/API/SBAddress.h
+++ b/lldb/include/lldb/API/SBAddress.h
@@ -12,6 +12,12 @@
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBModule.h"
 
+namespace lldb_private {
+namespace python {
+class SWIGBridge;
+}
+} // namespace lldb_private
+
 namespace lldb {
 
 class LLDB_API SBAddress {
@@ -104,6 +110,9 @@ class LLDB_API SBAddress {
   friend class SBValue;
   friend class SBQueueItem;
 
+  friend class lldb_private::ScriptInterpreter;
+  friend class lldb_private::python::SWIGBridge;
+
   lldb_private::Address *operator->();
 
   const lldb_private::Address *operator->() const;
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedHookInterface.h 
b/lldb/include/lldb/Interpreter/Interfaces/ScriptedHookInterface.h
index 54d335122300d..775fc65af87b2 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedHookInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedHookInterface.h
@@ -10,7 +10,7 @@
 #define LLDB_INTERPRETER_INTERFACES_SCRIPTEDHOOKINTERFACE_H
 
 #include "lldb/lldb-private.h"
-
+#include "lldb/Core/Address.h"
 #include "ScriptedInterface.h"
 
 namespace lldb_private {
@@ -21,9 +21,10 @@ class ScriptedHookInterface : public ScriptedInterface {
     bool handle_module_loaded = false;
     bool handle_module_unloaded = false;
     bool handle_stop = false;
+    bool handle_resolve_addr = false;
 
     bool any() const {
-      return handle_module_loaded || handle_module_unloaded || handle_stop;
+      return handle_module_loaded || handle_module_unloaded || handle_stop || 
handle_resolve_addr;
     }
   };
 
@@ -47,6 +48,28 @@ class ScriptedHookInterface : public ScriptedInterface {
                                           lldb::StreamSP &output_sp) {
     return true;
   }
+
+  /// Called when the target tried to resolve an address but wasn't able to 
+  /// resolve it to an object file section. This allows plug-ins to resolve
+  /// an address on demand. JIT plug-ins can be completely implemented using
+  /// ScriptedHookInterface plug-ins and can lazily load the JIT'ed information
+  /// as needed instead of setting breakpoints
+  ///
+  /// \param[in] load_addr
+  ///   The load address to resolve.
+  ///
+  /// \param[out] addr
+  ///   The section offset address that was resolved if \a true is returned.
+  ///
+  /// \param[in] output_sp
+  ///   An output stream to use for logging.
+  ///
+  /// \return
+  ///   True if the address was resolved, false otherwise.
+  virtual std::optional<Address>
+  HandleResolveAddress(lldb::addr_t load_addr, lldb::StreamSP &output_sp) {
+    return std::nullopt;
+  }
 };
 } // namespace lldb_private
 
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h 
b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 0e65cb4b8ac4a..519155cffd360 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -652,6 +652,8 @@ class ScriptInterpreter : public PluginInterface {
   SymbolContext
   GetOpaqueTypeFromSBSymbolContext(const lldb::SBSymbolContext &sym_ctx) const;
 
+  Address GetOpaqueTypeFromSBAddress(const lldb::SBAddress &addr) const;
+
   lldb::BreakpointSP
   GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;
 
diff --git a/lldb/include/lldb/Target/Target.h 
b/lldb/include/lldb/Target/Target.h
index fb43f432a08da..4062c123abb45 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1769,6 +1769,7 @@ class Target : public 
std::enable_shared_from_this<Target>,
       kModulesLoaded = (1u << 0),
       kModulesUnloaded = (1u << 1),
       kProcessStop = (1u << 2),
+      kResolveAddress = (1u << 3)
     };
 
     lldb::TargetSP &GetTarget() { return m_target_sp; }
@@ -1826,6 +1827,11 @@ class Target : public 
std::enable_shared_from_this<Target>,
       return StopHook::StopHookResult::NoPreference;
     }
 
+    virtual std::optional<Address> HandleResolveAddress(lldb::addr_t 
load_addr, 
+                                                        lldb::StreamSP 
&output_sp) {
+      return std::nullopt;
+    }
+
     virtual void GetDescription(Stream &s, lldb::DescriptionLevel level) const;
 
   protected:
@@ -1896,7 +1902,9 @@ class Target : public 
std::enable_shared_from_this<Target>,
     void HandleModuleUnloaded(lldb::StreamSP output) override;
     StopHook::StopHookResult HandleStop(ExecutionContext &exe_ctx,
                                         lldb::StreamSP output) override;
-
+    std::optional<Address> 
+    HandleResolveAddress(lldb::addr_t load_addr, 
+                         lldb::StreamSP &output_sp) override;
     Status SetScriptCallback(const ScriptedMetadata &scripted_metadata);
 
   private:
@@ -1948,6 +1956,10 @@ class Target : public 
std::enable_shared_from_this<Target>,
   // control over the process for the first time.
   bool RunStopHooks(bool at_initial_stop = false);
 
+  /// Runs the resolve address hooks that have been registered with this
+  /// target. Returns true if the address was resolved.
+  std::optional<Address> RunResolveAddressHooks(lldb::addr_t load_addr);
+
   bool SetSuppresStopHooks(bool suppress) {
     bool old_value = m_suppress_stop_hooks;
     m_suppress_stop_hooks = suppress;
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp 
b/lldb/source/Commands/CommandObjectTarget.cpp
index f77e87ad43aa2..cf06f3bb2c8ca 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -5557,7 +5557,8 @@ Python class hooks:
             pass
         def handle_stop(self, exe_ctx, stream):
             return True  # True = should_stop, False = continue
-
+        def handle_resolve_addr(self, load_addr, stream):
+            return lldb.SBAddress()  # Invalid defailt constructed address.
 Filter options:
 ---------------
   Filters (-s, -f, -l, -e, -c, -n, -x, -t, -T, -q) restrict when the hook
@@ -5913,6 +5914,8 @@ Valid trigger names: load, unload, stop.
       return Target::Hook::kModulesUnloaded;
     if (name == "stop")
       return Target::Hook::kProcessStop;
+    if (name == "resolve-addr")
+      return Target::Hook::kResolveAddress;
     return 0;
   }
 
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp 
b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 4f6095d097d10..2be78ad5f1511 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -7,6 +7,8 @@
 
//===----------------------------------------------------------------------===//
 
 #include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/Core/Address.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/Pipe.h"
@@ -152,6 +154,13 @@ SymbolContext 
ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(
   return {};
 }
 
+Address ScriptInterpreter::GetOpaqueTypeFromSBAddress(
+    const lldb::SBAddress &sb_addr) const {
+  if (sb_addr.m_opaque_up)
+    return *sb_addr.m_opaque_up;
+  return {};
+}
+
 std::optional<lldb_private::MemoryRegionInfo>
 ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
     const lldb::SBMemoryRegionInfo &mem_region) const {
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.cpp
index df4146657c53e..3724f65a5ba25 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.cpp
@@ -49,6 +49,8 @@ ScriptedHookPythonInterface::GetSupportedMethods() {
   methods.handle_module_unloaded =
       implementor.HasAttribute("handle_module_unloaded");
   methods.handle_stop = implementor.HasAttribute("handle_stop");
+  methods.handle_resolve_addr =
+      implementor.HasAttribute("handle_resolve_addr");
   return methods;
 }
 
@@ -64,12 +66,20 @@ void ScriptedHookPythonInterface::HandleModuleLoaded(
     lldb::StreamSP &output_sp) {
   Status error;
   Dispatch("handle_module_loaded", error, output_sp);
+  if (error.Fail()) {
+    LLDB_LOG(GetLog(LLDBLog::Script), "handle_module_loaded failed: {0}",
+             error.AsCString());
+  }
 }
 
 void ScriptedHookPythonInterface::HandleModuleUnloaded(
     lldb::StreamSP &output_sp) {
   Status error;
   Dispatch("handle_module_unloaded", error, output_sp);
+  if (error.Fail()) {
+    LLDB_LOG(GetLog(LLDBLog::Script), "handle_module_unloaded failed: {0}",
+             error.AsCString());
+  }
 }
 
 llvm::Expected<bool>
@@ -83,6 +93,8 @@ ScriptedHookPythonInterface::HandleStop(ExecutionContext 
&exe_ctx,
 
   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
                                                     error)) {
+    LLDB_LOG(GetLog(LLDBLog::Script), "handle_stop failed: {0}",
+             error.AsCString());
     if (!obj)
       return true;
     return error.ToError();
@@ -91,6 +103,21 @@ ScriptedHookPythonInterface::HandleStop(ExecutionContext 
&exe_ctx,
   return obj->GetBooleanValue();
 }
 
+std::optional<Address>
+ScriptedHookPythonInterface::HandleResolveAddress(lldb::addr_t load_addr,
+                                                  lldb::StreamSP &output_sp) {
+  Status error;
+  Address addr =
+      Dispatch<Address>("handle_resolve_addr", error, load_addr, output_sp);
+  if (error.Fail()) {
+    LLDB_LOG(GetLog(LLDBLog::Script), "handle_resolve_addr failed: {0}",
+             error.AsCString());
+  }
+  if (addr.IsSectionOffset())
+    return addr;
+  return std::nullopt;
+}
+
 void ScriptedHookPythonInterface::Initialize() {
   const std::vector<llvm::StringRef> ci_usages = {
       "target hook add -P <script-name> [-k key -v value ...]"};
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.h
index da15a4bb287d9..6b6403e3fd1fc 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedHookPythonInterface.h
@@ -33,14 +33,15 @@ class ScriptedHookPythonInterface : public 
ScriptedHookInterface,
     return llvm::SmallVector<AbstractMethodRequirement>({{"handle_stop", 2}});
   }
 
-  /// Check which of the three hook methods the Python class implements.
+  /// Check which of the hook methods the Python class implements.
   SupportedHookMethods GetSupportedMethods() override;
 
   void HandleModuleLoaded(lldb::StreamSP &output_sp) override;
   void HandleModuleUnloaded(lldb::StreamSP &output_sp) override;
   llvm::Expected<bool> HandleStop(ExecutionContext &exe_ctx,
                                   lldb::StreamSP &output_sp) override;
-
+  std::optional<Address> HandleResolveAddress(lldb::addr_t load_addr, 
+                                              lldb::StreamSP &output_sp) 
override;
   static void Initialize();
   static void Terminate();
 
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 61ceb40dd9d32..9a99cf73e3783 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -14,6 +14,8 @@
 
 #include "../ScriptInterpreterPythonImpl.h"
 #include "ScriptedPythonInterface.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/Core/Address.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/ValueObject/ValueObjectList.h"
 #include <optional>
@@ -118,6 +120,18 @@ 
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
   return {};
 }
 
+template <>
+Address ScriptedPythonInterface::ExtractValueFromPythonObject<Address>(
+    python::PythonObject &p, Status &error) {
+  if (lldb::SBAddress *sb_addr = reinterpret_cast<lldb::SBAddress *>(
+          python::LLDBSWIGPython_CastPyObjectToSBAddress(p.get())))
+    return m_interpreter.GetOpaqueTypeFromSBAddress(*sb_addr);
+  error = Status::FromErrorString(
+      "Couldn't cast lldb::SBAddress to lldb_private::Address.");
+
+  return {};
+}
+
 template <>
 lldb::DataExtractorSP
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index aaa0b6a0f7a59..984fcaf6b8989 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -648,6 +648,10 @@ class ScriptedPythonInterface : virtual public 
ScriptedInterface {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
 
+  python::PythonObject Transform(Address &arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+
   python::PythonObject Transform(lldb::StreamSP arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg.get());
   }
@@ -768,6 +772,10 @@ SymbolContext
 ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
     python::PythonObject &p, Status &error);
 
+template <>
+Address ScriptedPythonInterface::ExtractValueFromPythonObject<Address>(
+    python::PythonObject &p, Status &error);
+
 template <>
 lldb::StreamSP
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h 
b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 07e0da1dcf70d..839d421b9e855 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -86,6 +86,7 @@ class SWIGBridge {
   static PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp);
   static PythonObject ToSWIGWrapper(Status &&status);
   static PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl);
+  static PythonObject ToSWIGWrapper(const Address &addr);
   static PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp);
   static PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp);
   static PythonObject ToSWIGWrapper(lldb::StackFrameListSP frames_sp);
@@ -252,6 +253,7 @@ void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBThread(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBFrame(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject *data);
+void *LLDBSWIGPython_CastPyObjectToSBAddress(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBValueList(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 148d7e0b30dbb..ddaba55deb203 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3481,8 +3481,14 @@ Status Target::Install(ProcessLaunchInfo *launch_info) {
 
 bool Target::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
                                 uint32_t stop_id, bool allow_section_end) {
-  return m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr,
-                                                   allow_section_end);
+  if (m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr,
+                                                allow_section_end))
+    return true;
+  if (std::optional<Address> opt_addr = RunResolveAddressHooks(load_addr)) {
+    so_addr = *opt_addr;
+    return true;
+  }
+  return false;
 }
 
 bool Target::ResolveFileAddress(lldb::addr_t file_addr,
@@ -4668,6 +4674,8 @@ Status Target::HookScripted::SetScriptCallback(
     m_trigger_mask |= kModulesUnloaded;
   if (methods.handle_stop)
     m_trigger_mask |= kProcessStop;
+  if (methods.handle_resolve_addr)
+    m_trigger_mask |= kResolveAddress;
 
   return {};
 }
@@ -4709,6 +4717,14 @@ Target::HookScripted::HandleStop(ExecutionContext 
&exc_ctx,
                              : StopHook::StopHookResult::RequestContinue;
 }
 
+std::optional<Address> 
+Target::HookScripted::HandleResolveAddress(lldb::addr_t load_addr, 
+                                           lldb::StreamSP &output_sp) {
+  if (!m_interface_sp)
+    return std::nullopt;
+  return m_interface_sp->HandleResolveAddress(load_addr, output_sp);
+}
+
 llvm::StringRef Target::HookScripted::GetScriptClassName() const {
   if (m_interface_sp && m_interface_sp->GetScriptedMetadata())
     return m_interface_sp->GetScriptedMetadata()->GetClassName();
@@ -4812,6 +4828,34 @@ void Target::SetAllHooksEnabledState(bool enabled) {
     hook->SetIsEnabled(enabled);
 }
 
+std::optional<Address> Target::RunResolveAddressHooks(lldb::addr_t load_addr) {
+  if (m_hooks.empty())
+    return std::nullopt;
+
+  // Copy active hooks into a local vector before iterating, in case a
+  // callback modifies m_hooks (same pattern as RunStopHooks).
+  std::vector<HookSP...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/212831
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to