mib updated this revision to Diff 376508.
mib added a comment.

Use `ScriptedInterface::ErrorWithMessage` helper function.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108953/new/

https://reviews.llvm.org/D108953

Files:
  lldb/bindings/interface/SBMemoryRegionInfo.i
  lldb/bindings/interface/SBMemoryRegionInfoList.i
  lldb/bindings/python/python-wrapper.swig
  lldb/examples/python/scripted_process/main.stack-dump
  lldb/examples/python/scripted_process/my_scripted_process.py
  lldb/include/lldb/API/SBMemoryRegionInfo.h
  lldb/include/lldb/API/SBMemoryRegionInfoList.h
  lldb/include/lldb/Interpreter/ScriptInterpreter.h
  lldb/source/API/SBMemoryRegionInfo.cpp
  lldb/source/API/SBMemoryRegionInfoList.cpp
  lldb/source/Interpreter/ScriptInterpreter.cpp
  lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
  
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
  lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
  lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
  lldb/test/API/functionalities/scripted_process/main.c
  lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Index: lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -166,6 +166,10 @@
   return nullptr;
 }
 
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(void *data) {
+  return nullptr;
+}
+
 extern lldb::ValueObjectSP
 LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data) {
   return nullptr;
Index: lldb/test/API/functionalities/scripted_process/main.c
===================================================================
--- lldb/test/API/functionalities/scripted_process/main.c
+++ lldb/test/API/functionalities/scripted_process/main.c
@@ -1,5 +1,8 @@
-#include <stdlib.h>
-
-int main() {
-  return 0; // break here
+int bar(int i) {
+  int j = i * i;
+  return j; // break here
 }
+
+int foo(int i) { return bar(i); }
+
+int main() { return foo(42); }
Index: lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -0,0 +1,90 @@
+import os,struct, signal
+
+from typing import Any, Dict
+
+import lldb
+from lldb.plugins.scripted_process import ScriptedProcess
+from lldb.plugins.scripted_process import ScriptedThread
+
+class DummyScriptedProcess(ScriptedProcess):
+    def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
+        super().__init__(target, args)
+
+    def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
+        return self.memory_regions[0]
+
+    def get_thread_with_id(self, tid: int):
+        return {}
+
+    def get_registers_for_thread(self, tid: int):
+        return {}
+
+    def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
+        data = lldb.SBData().CreateDataFromCString(
+                                    self.target.GetByteOrder(),
+                                    self.target.GetCodeByteSize(),
+                                    "Hello, world!")
+        return data
+
+    def get_loaded_images(self):
+        return self.loaded_images
+
+    def get_process_id(self) -> int:
+        return 42
+
+    def should_stop(self) -> bool:
+        return True
+
+    def is_alive(self) -> bool:
+        return True
+
+    def get_scripted_thread_plugin(self):
+        return DummyScriptedThread.__module__ + "." + DummyScriptedThread.__name__
+
+
+class DummyScriptedThread(ScriptedThread):
+    def __init__(self, target):
+        super().__init__(target)
+
+    def get_thread_id(self) -> int:
+        return 0x19
+
+    def get_name(self) -> str:
+        return DummyScriptedThread.__name__ + ".thread-1"
+
+    def get_state(self) -> int:
+        return lldb.eStateStopped
+
+    def get_stop_reason(self) -> Dict[str, Any]:
+        return { "type": lldb.eStopReasonSignal, "data": {
+            "signal": signal.SIGINT
+        } }
+
+    def get_stackframes(self):
+        class ScriptedStackFrame:
+            def __init__(idx, cfa, pc, symbol_ctx):
+                self.idx = idx
+                self.cfa = cfa
+                self.pc = pc
+                self.symbol_ctx = symbol_ctx
+
+
+        symbol_ctx = lldb.SBSymbolContext()
+        frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
+        self.frames.append(frame_zero)
+
+        return self.frame_zero[0:0]
+
+    def get_register_context(self) -> str:
+        return struct.pack(
+                '21Q', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
+
+
+def __lldb_init_module(debugger, dict):
+    if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ:
+        debugger.HandleCommand(
+            "process launch -C %s.%s" % (__name__,
+                                     DummyScriptedProcess.__name__))
+    else:
+        print("Name of the class that will manage the scripted process: '%s.%s'"
+                % (__name__, DummyScriptedProcess.__name__))
\ No newline at end of file
Index: lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
+++ lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
@@ -43,41 +43,35 @@
         self.expect('script dir(ScriptedProcess)',
                     substrs=["launch"])
 
-    def test_launch_scripted_process_sbapi(self):
+    def test_scripted_process_and_scripted_thread(self):
         """Test that we can launch an lldb scripted process using the SBAPI,
-        check its process ID and read string from memory."""
+        check its process ID, read string from memory, check scripted thread
+        id, name stop reason and register context.
+        """
         self.build()
         target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
         self.assertTrue(target, VALID_TARGET)
 
-        scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py']
+        scripted_process_example_relpath = 'dummy_scripted_process.py'
         os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
         self.runCmd("command script import " + os.path.join(self.getSourceDir(),
-                                                            *scripted_process_example_relpath))
+                                                            scripted_process_example_relpath))
 
         launch_info = lldb.SBLaunchInfo(None)
         launch_info.SetProcessPluginName("ScriptedProcess")
-        launch_info.SetScriptedProcessClassName("my_scripted_process.MyScriptedProcess")
+        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
 
         error = lldb.SBError()
         process = target.Launch(launch_info, error)
         self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
         self.assertEqual(process.GetProcessID(), 42)
 
-        hello_world = "Hello, world!"
-        memory_read = process.ReadCStringFromMemory(0x50000000000,
-                                                    len(hello_world) + 1, # NULL byte
-                                                    error)
-
-        self.assertTrue(error.Success(), "Failed to read memory from scripted process.")
-        self.assertEqual(hello_world, memory_read)
-
         self.assertEqual(process.GetNumThreads(), 1)
 
         thread = process.GetSelectedThread()
         self.assertTrue(thread, "Invalid thread.")
         self.assertEqual(thread.GetThreadID(), 0x19)
-        self.assertEqual(thread.GetName(), "MyScriptedThread.thread-1")
+        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
 
         self.assertGreater(thread.GetNumFrames(), 0)
@@ -94,13 +88,21 @@
         for idx, reg in enumerate(registers, start=1):
             self.assertEqual(idx, int(reg.value, 16))
 
-    def test_launch_scripted_process_cli(self):
+    def test_launch_scripted_process_stack_frames(self):
         """Test that we can launch an lldb scripted process from the command
         line, check its process ID and read string from memory."""
         self.build()
         target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
         self.assertTrue(target, VALID_TARGET)
 
+        for module in target.modules:
+            if 'a.out' in module.GetFileSpec().GetFilename():
+                main_module = module
+
+        self.assertTrue(main_module, "Invalid main module.")
+        error = target.SetModuleLoadAddress(main_module, 0)
+        self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.")
+
         scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py']
         self.runCmd("command script import " + os.path.join(self.getSourceDir(),
                                                             *scripted_process_example_relpath))
@@ -108,12 +110,21 @@
         process = target.GetProcess()
         self.assertTrue(process, PROCESS_IS_VALID)
         self.assertEqual(process.GetProcessID(), 42)
+        self.assertEqual(process.GetNumThreads(), 1)
 
         error = lldb.SBError()
         hello_world = "Hello, world!"
         memory_read = process.ReadCStringFromMemory(0x50000000000,
                                                     len(hello_world) + 1, # NULL byte
                                                     error)
+        thread = process.GetSelectedThread()
+        self.assertTrue(thread, "Invalid thread.")
+        self.assertEqual(thread.GetThreadID(), 0x19)
+        self.assertEqual(thread.GetName(), "MyScriptedThread.thread-1")
 
-        self.assertTrue(error.Success(), "Failed to read memory from scripted process.")
-        self.assertEqual(hello_world, memory_read)
+        self.assertEqual(thread.GetNumFrames(), 4)
+        frame = thread.GetSelectedFrame()
+        self.assertTrue(frame, "Invalid frame.")
+        self.assertEqual(frame.GetFunctionName(), "bar")
+        self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42)
+        self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
@@ -140,6 +140,11 @@
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
     python::PythonObject &p, Status &error);
 
+template <>
+lldb::MemoryRegionInfoSP
+ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::MemoryRegionInfoSP>(
+    python::PythonObject &p, Status &error);
+
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
@@ -63,11 +63,30 @@
       LLDBSWIGPython_CastPyObjectToSBData(p.get()));
 
   if (!sb_data) {
-    error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status.");
+    error.SetErrorString(
+        "Couldn't cast lldb::SBData to lldb::DataExtractorSP.");
     return nullptr;
   }
 
   return m_interpreter.GetDataExtractorFromSBData(*sb_data);
 }
 
+template <>
+lldb::MemoryRegionInfoSP
+ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::MemoryRegionInfoSP>(
+    python::PythonObject &p, Status &error) {
+
+  lldb::SBMemoryRegionInfo *sb_mem_reg_info =
+      reinterpret_cast<lldb::SBMemoryRegionInfo *>(
+          LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get()));
+
+  if (!sb_mem_reg_info) {
+    error.SetErrorString(
+        "Couldn't cast lldb::SBMemoryRegionInfo to lldb::MemoryRegionInfoSP.");
+    return nullptr;
+  }
+
+  return m_interpreter.GetOpaquePtrFromSBMemoryRegionInfo(*sb_mem_reg_info);
+}
+
 #endif
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -85,8 +85,20 @@
 lldb::MemoryRegionInfoSP
 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
     lldb::addr_t address) {
-  // TODO: Implement
-  return {};
+  Status error;
+  lldb::MemoryRegionInfoSP mem_region_sp = Dispatch<lldb::MemoryRegionInfoSP>(
+      "get_memory_region_containing_address", error, address);
+
+  if (!mem_region_sp || error.Fail()) {
+    return ErrorWithMessage<lldb::MemoryRegionInfoSP>(
+        __PRETTY_FUNCTION__,
+        llvm::Twine("Null or invalid object (" +
+                    llvm::Twine(error.AsCString()) + llvm::Twine(")."))
+            .str(),
+        error);
+  }
+
+  return mem_region_sp;
 }
 
 StructuredData::DictionarySP
Index: lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -53,6 +53,7 @@
 extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data);
 extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data);
 extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(void *data);
 
 } // namespace lldb_private
 
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -239,7 +239,7 @@
   lldb::DataExtractorSP data_extractor_sp =
       GetInterface().ReadMemoryAtAddress(addr, size, error);
 
-  if (!data_extractor_sp || error.Fail())
+  if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
     return 0;
 
   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
Index: lldb/source/Interpreter/ScriptInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/ScriptInterpreter.cpp
+++ lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -83,6 +83,11 @@
   return Status();
 }
 
+lldb::MemoryRegionInfoSP ScriptInterpreter::GetOpaquePtrFromSBMemoryRegionInfo(
+    const lldb::SBMemoryRegionInfo &mem_region) const {
+  return mem_region.m_opaque_sp;
+}
+
 lldb::ScriptLanguage
 ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
   if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
Index: lldb/source/API/SBMemoryRegionInfoList.cpp
===================================================================
--- lldb/source/API/SBMemoryRegionInfoList.cpp
+++ lldb/source/API/SBMemoryRegionInfoList.cpp
@@ -48,6 +48,17 @@
 
   void Clear() { m_regions.clear(); }
 
+  bool GetMemoryRegionContainingAddress(lldb::addr_t addr,
+                                        MemoryRegionInfo &region_info) {
+    for (auto &region : m_regions) {
+      if (region.GetRange().Contains(addr)) {
+        region_info = region;
+        return true;
+      }
+    }
+    return false;
+  }
+
   bool GetMemoryRegionInfoAtIndex(size_t index,
                                   MemoryRegionInfo &region_info) {
     if (index >= GetSize())
@@ -103,6 +114,15 @@
   return m_opaque_up->GetSize();
 }
 
+bool SBMemoryRegionInfoList::GetMemoryRegionContainingAddress(
+    lldb::addr_t addr, SBMemoryRegionInfo &region_info) {
+  LLDB_RECORD_METHOD(
+      bool, SBMemoryRegionInfoList, GetMemoryRegionContainingAddress,
+      (lldb::addr_t, lldb::SBMemoryRegionInfo &), addr, region_info);
+
+  return m_opaque_up->GetMemoryRegionContainingAddress(addr, region_info.ref());
+}
+
 bool SBMemoryRegionInfoList::GetMemoryRegionAtIndex(
     uint32_t idx, SBMemoryRegionInfo &region_info) {
   LLDB_RECORD_METHOD(bool, SBMemoryRegionInfoList, GetMemoryRegionAtIndex,
@@ -153,6 +173,9 @@
       SBMemoryRegionInfoList, operator=,(
                                   const lldb::SBMemoryRegionInfoList &));
   LLDB_REGISTER_METHOD_CONST(uint32_t, SBMemoryRegionInfoList, GetSize, ());
+  LLDB_REGISTER_METHOD(bool, SBMemoryRegionInfoList,
+                       GetMemoryRegionContainingAddress,
+                       (lldb::addr_t, lldb::SBMemoryRegionInfo &));
   LLDB_REGISTER_METHOD(bool, SBMemoryRegionInfoList, GetMemoryRegionAtIndex,
                        (uint32_t, lldb::SBMemoryRegionInfo &));
   LLDB_REGISTER_METHOD(void, SBMemoryRegionInfoList, Clear, ());
Index: lldb/source/API/SBMemoryRegionInfo.cpp
===================================================================
--- lldb/source/API/SBMemoryRegionInfo.cpp
+++ lldb/source/API/SBMemoryRegionInfo.cpp
@@ -18,21 +18,39 @@
 using namespace lldb;
 using namespace lldb_private;
 
-SBMemoryRegionInfo::SBMemoryRegionInfo() : m_opaque_up(new MemoryRegionInfo()) {
+SBMemoryRegionInfo::SBMemoryRegionInfo() : m_opaque_sp(new MemoryRegionInfo()) {
   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBMemoryRegionInfo);
 }
 
+SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin,
+                                       lldb::addr_t end, uint32_t permissions,
+                                       bool mapped, bool stack_memory)
+    : SBMemoryRegionInfo() {
+  LLDB_RECORD_CONSTRUCTOR(
+      SBMemoryRegionInfo,
+      (const char *, lldb::addr_t, lldb::addr_t, uint32_t, bool, bool), name,
+      begin, end, permissions, mapped, stack_memory);
+  m_opaque_sp->SetName(name);
+  m_opaque_sp->GetRange().SetRangeBase(begin);
+  m_opaque_sp->GetRange().SetRangeEnd(end);
+  m_opaque_sp->SetLLDBPermissions(permissions);
+  m_opaque_sp->SetMapped(mapped ? MemoryRegionInfo::eYes
+                                : MemoryRegionInfo::eNo);
+  m_opaque_sp->SetIsStackMemory(stack_memory ? MemoryRegionInfo::eYes
+                                             : MemoryRegionInfo::eNo);
+}
+
 SBMemoryRegionInfo::SBMemoryRegionInfo(const MemoryRegionInfo *lldb_object_ptr)
-    : m_opaque_up(new MemoryRegionInfo()) {
+    : m_opaque_sp(new MemoryRegionInfo()) {
   if (lldb_object_ptr)
     ref() = *lldb_object_ptr;
 }
 
 SBMemoryRegionInfo::SBMemoryRegionInfo(const SBMemoryRegionInfo &rhs)
-    : m_opaque_up() {
+    : m_opaque_sp() {
   LLDB_RECORD_CONSTRUCTOR(SBMemoryRegionInfo,
                           (const lldb::SBMemoryRegionInfo &), rhs);
-  m_opaque_up = clone(rhs.m_opaque_up);
+  m_opaque_sp = clone(rhs.m_opaque_sp);
 }
 
 const SBMemoryRegionInfo &SBMemoryRegionInfo::
@@ -42,7 +60,7 @@
       SBMemoryRegionInfo, operator=,(const lldb::SBMemoryRegionInfo &), rhs);
 
   if (this != &rhs)
-    m_opaque_up = clone(rhs.m_opaque_up);
+    m_opaque_sp = clone(rhs.m_opaque_sp);
   return LLDB_RECORD_RESULT(*this);
 }
 
@@ -51,7 +69,7 @@
 void SBMemoryRegionInfo::Clear() {
   LLDB_RECORD_METHOD_NO_ARGS(void, SBMemoryRegionInfo, Clear);
 
-  m_opaque_up->Clear();
+  m_opaque_sp->Clear();
 }
 
 bool SBMemoryRegionInfo::operator==(const SBMemoryRegionInfo &rhs) const {
@@ -70,56 +88,56 @@
   return ref() != rhs.ref();
 }
 
-MemoryRegionInfo &SBMemoryRegionInfo::ref() { return *m_opaque_up; }
+MemoryRegionInfo &SBMemoryRegionInfo::ref() { return *m_opaque_sp; }
 
-const MemoryRegionInfo &SBMemoryRegionInfo::ref() const { return *m_opaque_up; }
+const MemoryRegionInfo &SBMemoryRegionInfo::ref() const { return *m_opaque_sp; }
 
 lldb::addr_t SBMemoryRegionInfo::GetRegionBase() {
   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBMemoryRegionInfo, GetRegionBase);
 
-  return m_opaque_up->GetRange().GetRangeBase();
+  return m_opaque_sp->GetRange().GetRangeBase();
 }
 
 lldb::addr_t SBMemoryRegionInfo::GetRegionEnd() {
   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBMemoryRegionInfo, GetRegionEnd);
 
-  return m_opaque_up->GetRange().GetRangeEnd();
+  return m_opaque_sp->GetRange().GetRangeEnd();
 }
 
 bool SBMemoryRegionInfo::IsReadable() {
   LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsReadable);
 
-  return m_opaque_up->GetReadable() == MemoryRegionInfo::eYes;
+  return m_opaque_sp->GetReadable() == MemoryRegionInfo::eYes;
 }
 
 bool SBMemoryRegionInfo::IsWritable() {
   LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsWritable);
 
-  return m_opaque_up->GetWritable() == MemoryRegionInfo::eYes;
+  return m_opaque_sp->GetWritable() == MemoryRegionInfo::eYes;
 }
 
 bool SBMemoryRegionInfo::IsExecutable() {
   LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsExecutable);
 
-  return m_opaque_up->GetExecutable() == MemoryRegionInfo::eYes;
+  return m_opaque_sp->GetExecutable() == MemoryRegionInfo::eYes;
 }
 
 bool SBMemoryRegionInfo::IsMapped() {
   LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsMapped);
 
-  return m_opaque_up->GetMapped() == MemoryRegionInfo::eYes;
+  return m_opaque_sp->GetMapped() == MemoryRegionInfo::eYes;
 }
 
 const char *SBMemoryRegionInfo::GetName() {
   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBMemoryRegionInfo, GetName);
 
-  return m_opaque_up->GetName().AsCString();
+  return m_opaque_sp->GetName().AsCString();
 }
 
 bool SBMemoryRegionInfo::HasDirtyMemoryPageList() {
   LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, HasDirtyMemoryPageList);
 
-  return m_opaque_up->GetDirtyPageList().hasValue();
+  return m_opaque_sp->GetDirtyPageList().hasValue();
 }
 
 uint32_t SBMemoryRegionInfo::GetNumDirtyPages() {
@@ -127,7 +145,7 @@
 
   uint32_t num_dirty_pages = 0;
   llvm::Optional<std::vector<addr_t>> dirty_page_list =
-      m_opaque_up->GetDirtyPageList();
+      m_opaque_sp->GetDirtyPageList();
   if (dirty_page_list.hasValue())
     num_dirty_pages = dirty_page_list.getValue().size();
 
@@ -140,7 +158,7 @@
 
   addr_t dirty_page_addr = LLDB_INVALID_ADDRESS;
   const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
-      m_opaque_up->GetDirtyPageList();
+      m_opaque_sp->GetDirtyPageList();
   if (dirty_page_list.hasValue() && idx < dirty_page_list.getValue().size())
     dirty_page_addr = dirty_page_list.getValue()[idx];
 
@@ -150,7 +168,7 @@
 int SBMemoryRegionInfo::GetPageSize() {
   LLDB_RECORD_METHOD_NO_ARGS(int, SBMemoryRegionInfo, GetPageSize);
 
-  return m_opaque_up->GetPageSize();
+  return m_opaque_sp->GetPageSize();
 }
 
 bool SBMemoryRegionInfo::GetDescription(SBStream &description) {
@@ -158,13 +176,13 @@
                      (lldb::SBStream &), description);
 
   Stream &strm = description.ref();
-  const addr_t load_addr = m_opaque_up->GetRange().base;
+  const addr_t load_addr = m_opaque_sp->GetRange().base;
 
   strm.Printf("[0x%16.16" PRIx64 "-0x%16.16" PRIx64 " ", load_addr,
-              load_addr + m_opaque_up->GetRange().size);
-  strm.Printf(m_opaque_up->GetReadable() ? "R" : "-");
-  strm.Printf(m_opaque_up->GetWritable() ? "W" : "-");
-  strm.Printf(m_opaque_up->GetExecutable() ? "X" : "-");
+              load_addr + m_opaque_sp->GetRange().size);
+  strm.Printf(m_opaque_sp->GetReadable() ? "R" : "-");
+  strm.Printf(m_opaque_sp->GetWritable() ? "W" : "-");
+  strm.Printf(m_opaque_sp->GetExecutable() ? "X" : "-");
   strm.Printf("]");
 
   return true;
@@ -178,6 +196,9 @@
   LLDB_REGISTER_CONSTRUCTOR(SBMemoryRegionInfo, ());
   LLDB_REGISTER_CONSTRUCTOR(SBMemoryRegionInfo,
                             (const lldb::SBMemoryRegionInfo &));
+  LLDB_REGISTER_CONSTRUCTOR(
+      SBMemoryRegionInfo,
+      (const char *, lldb::addr_t, lldb::addr_t, uint32_t, bool, bool));
   LLDB_REGISTER_METHOD(
       const lldb::SBMemoryRegionInfo &,
       SBMemoryRegionInfo, operator=,(const lldb::SBMemoryRegionInfo &));
Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -11,6 +11,7 @@
 
 #include "lldb/API/SBData.h"
 #include "lldb/API/SBError.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
 #include "lldb/Breakpoint/BreakpointOptions.h"
 #include "lldb/Core/Communication.h"
 #include "lldb/Core/PluginInterface.h"
@@ -564,6 +565,9 @@
 
   Status GetStatusFromSBError(const lldb::SBError &error) const;
 
+  lldb::MemoryRegionInfoSP GetOpaquePtrFromSBMemoryRegionInfo(
+      const lldb::SBMemoryRegionInfo &mem_region) const;
+
 protected:
   Debugger &m_debugger;
   lldb::ScriptLanguage m_script_lang;
Index: lldb/include/lldb/API/SBMemoryRegionInfoList.h
===================================================================
--- lldb/include/lldb/API/SBMemoryRegionInfoList.h
+++ lldb/include/lldb/API/SBMemoryRegionInfoList.h
@@ -27,6 +27,9 @@
 
   uint32_t GetSize() const;
 
+  bool GetMemoryRegionContainingAddress(lldb::addr_t addr,
+                                        SBMemoryRegionInfo &region_info);
+
   bool GetMemoryRegionAtIndex(uint32_t idx, SBMemoryRegionInfo &region_info);
 
   void Append(lldb::SBMemoryRegionInfo &region);
Index: lldb/include/lldb/API/SBMemoryRegionInfo.h
===================================================================
--- lldb/include/lldb/API/SBMemoryRegionInfo.h
+++ lldb/include/lldb/API/SBMemoryRegionInfo.h
@@ -20,6 +20,10 @@
 
   SBMemoryRegionInfo(const lldb::SBMemoryRegionInfo &rhs);
 
+  SBMemoryRegionInfo(const char *name, lldb::addr_t begin, lldb::addr_t end,
+                     uint32_t permissions, bool mapped,
+                     bool stack_memory = false);
+
   ~SBMemoryRegionInfo();
 
   const lldb::SBMemoryRegionInfo &
@@ -117,6 +121,8 @@
   friend class SBProcess;
   friend class SBMemoryRegionInfoList;
 
+  friend class lldb_private::ScriptInterpreter;
+
   lldb_private::MemoryRegionInfo &ref();
 
   const lldb_private::MemoryRegionInfo &ref() const;
@@ -124,7 +130,7 @@
   // Unused.
   SBMemoryRegionInfo(const lldb_private::MemoryRegionInfo *lldb_object_ptr);
 
-  lldb::MemoryRegionInfoUP m_opaque_up;
+  lldb::MemoryRegionInfoSP m_opaque_sp;
 };
 
 } // namespace lldb
Index: lldb/examples/python/scripted_process/my_scripted_process.py
===================================================================
--- lldb/examples/python/scripted_process/my_scripted_process.py
+++ lldb/examples/python/scripted_process/my_scripted_process.py
@@ -7,11 +7,22 @@
 from lldb.plugins.scripted_process import ScriptedThread
 
 class MyScriptedProcess(ScriptedProcess):
+    memory_regions = [
+        lldb.SBMemoryRegionInfo("stack", 0x1040b2000, 0x1040b4000, 0b110, True,
+                                True)
+    ]
+
+    stack_memory_dump = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                                     'main.stack-dump')
+
     def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
         super().__init__(target, args)
 
     def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
-        return self.memory_regions[0]
+        for region in self.memory_regions:
+            if region.GetRegionBase() <= addr < region.GetRegionEnd():
+                return region
+        return None
 
     def get_thread_with_id(self, tid: int):
         return {}
@@ -20,10 +31,25 @@
         return {}
 
     def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
-        data = lldb.SBData().CreateDataFromCString(
+        data = lldb.SBData()
+
+        with open(self.stack_memory_dump, 'rb') as f:
+            stack_mem = f.read(-1)
+            if not stack_mem:
+                return data
+
+            mem_region = self.get_memory_region_containing_address(addr)
+
+            if not mem_region or addr + size > mem_region.GetRegionEnd():
+                return data
+
+            offset = addr - mem_region.GetRegionBase()
+            shrunk_stack_mem = stack_mem[offset:offset + size]
+
+            error = lldb.SBError()
+            data.SetData(error, shrunk_stack_mem,
                                     self.target.GetByteOrder(),
-                                    self.target.GetCodeByteSize(),
-                                    "Hello, world!")
+                                    self.target.GetAddressByteSize())
         return data
 
     def get_loaded_images(self):
@@ -43,6 +69,30 @@
 
 
 class MyScriptedThread(ScriptedThread):
+    registers = {
+        "rax":0x00000000000006e4,
+        "rbx":0x00000001040b6060,
+        "rcx":0x00000001040b2e00,
+        "rdx":0x00000001040b2ba8,
+        "rdi":0x000000000000002a,
+        "rsi":0x00000001040b2b98,
+        "rbp":0x00000001040b2a20,
+        "rsp":0x00000001040b2a20,
+        "r8":0x00000000003e131e,
+        "r9":0xffffffff00000000,
+        "r10":0x0000000000000000,
+        "r11":0x0000000000000246,
+        "r12":0x000000010007c3a0,
+        "r13":0x00000001040b2b18,
+        "r14":0x0000000100003f90,
+        "r15":0x00000001040b2b88,
+        "rip":0x0000000100003f61,
+        "rflags":0x0000000000000206,
+        "cs":0x000000000000002b,
+        "fs":0x0000000000000000,
+        "gs":0x0000000000000000,
+    }
+
     def __init__(self, target):
         super().__init__(target)
 
@@ -73,8 +123,7 @@
         return self.frame_zero[0:0]
 
     def get_register_context(self) -> str:
-        return struct.pack(
-                '21Q', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
+        return struct.pack(f"{len(self.registers)}Q", *self.registers.values())
 
 
 def __lldb_init_module(debugger, dict):
Index: lldb/bindings/python/python-wrapper.swig
===================================================================
--- lldb/bindings/python/python-wrapper.swig
+++ lldb/bindings/python/python-wrapper.swig
@@ -974,6 +974,22 @@
     return sb_ptr;
 }
 
+SWIGEXPORT void*
+LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo
+(
+    PyObject* data
+)
+{
+    lldb::SBMemoryRegionInfo* sb_ptr = NULL;
+
+    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0);
+
+    if (valid_cast == -1)
+        return NULL;
+
+    return sb_ptr;
+}
+
 SWIGEXPORT bool
 LLDBSwigPythonCallCommand
 (
Index: lldb/bindings/interface/SBMemoryRegionInfoList.i
===================================================================
--- lldb/bindings/interface/SBMemoryRegionInfoList.i
+++ lldb/bindings/interface/SBMemoryRegionInfoList.i
@@ -24,6 +24,9 @@
     uint32_t
     GetSize () const;
 
+    bool
+    GetMemoryRegionContainingAddress (lldb::addr_t addr, SBMemoryRegionInfo &region_info);
+
     bool
     GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo &region_info);
 
Index: lldb/bindings/interface/SBMemoryRegionInfo.i
===================================================================
--- lldb/bindings/interface/SBMemoryRegionInfo.i
+++ lldb/bindings/interface/SBMemoryRegionInfo.i
@@ -20,6 +20,9 @@
 
     SBMemoryRegionInfo (const lldb::SBMemoryRegionInfo &rhs);
 
+    SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin,
+    lldb::addr_t end, uint32_t permissions, bool mapped, bool stack_memory);
+
     ~SBMemoryRegionInfo ();
 
     void
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to