This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2e7ec447cc7e: [lldb] Add AllocateMemory/DeallocateMemory to 
the SBProcess API (authored by housel, committed by teemperor).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D105389

Files:
  lldb/bindings/interface/SBProcess.i
  lldb/include/lldb/API/SBProcess.h
  lldb/source/API/SBProcess.cpp
  lldb/test/API/python_api/process/TestProcessAPI.py
  lldb/test/API/python_api/process/main.cpp

Index: lldb/test/API/python_api/process/main.cpp
===================================================================
--- lldb/test/API/python_api/process/main.cpp
+++ lldb/test/API/python_api/process/main.cpp
@@ -21,3 +21,13 @@
     return 0; // Set break point at this line and check variable 'my_char'.
               // Use lldb Python API to set memory content for my_int and check the result.
 }
+
+char test_read (char *ptr)
+{
+    return *ptr;
+}
+
+void test_write (char *ptr, char c)
+{
+    *ptr = c;
+}
Index: lldb/test/API/python_api/process/TestProcessAPI.py
===================================================================
--- lldb/test/API/python_api/process/TestProcessAPI.py
+++ lldb/test/API/python_api/process/TestProcessAPI.py
@@ -398,3 +398,58 @@
                 "Process effective group ID is invalid")
 
         process_info.GetParentProcessID()
+
+    def test_allocate_deallocate_memory(self):
+        """Test Python SBProcess.AllocateMemory() and SBProcess.DeallocateMemory() APIs."""
+        self.build()
+        (target, process, main_thread, main_breakpoint) = lldbutil.run_to_source_breakpoint(
+            self, "// Set break point at this line", lldb.SBFileSpec("main.cpp"))
+
+        # Allocate a block of memory in the target process
+        error = lldb.SBError()
+        addr = process.AllocateMemory(16384, lldb.ePermissionsReadable, error)
+        if not error.Success() or addr == lldb.LLDB_INVALID_ADDRESS:
+            self.fail("SBProcess.AllocateMemory() failed")
+
+        # Now use WriteMemory() API to write 'a' into the allocated
+        # memory. Note that the debugger can do this even though the
+        # block is not set writable.
+        result = process.WriteMemory(addr, 'a', error)
+        if not error.Success() or result != 1:
+            self.fail("SBProcess.WriteMemory() failed")
+
+        # Read from the memory location.  This time it should be 'a'.
+        # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
+        # expect to get a Python string as the result object!
+        content = process.ReadMemory(addr, 1, error)
+        if not error.Success():
+            self.fail("SBProcess.ReadMemory() failed")
+        if self.TraceOn():
+            print("memory content:", content)
+
+        self.expect(
+            content,
+            "Result from SBProcess.ReadMemory() matches our expected output: 'a'",
+            exe=False,
+            startstr=b'a')
+
+        # Verify that the process itself can read the allocated memory
+        frame = main_thread.GetFrameAtIndex(0)
+        val = frame.EvaluateExpression(
+            "test_read(reinterpret_cast<char *>({:#x}))".format(addr))
+        self.expect(val.GetValue(),
+                    "Result of test_read() matches expected output 'a'",
+                    exe=False,
+                    startstr="'a'")
+
+        # Verify that the process cannot write into the block
+        val = frame.EvaluateExpression(
+            "test_write(reinterpret_cast<char *>({:#x}), 'b')".format(addr))
+        if val.GetError().Success():
+            self.fail(
+                "test_write() to allocated memory without write permission unexpectedly succeeded")
+
+        # Deallocate the memory
+        error = process.DeallocateMemory(addr)
+        if not error.Success():
+            self.fail("SBProcess.DeallocateMemory() failed")
Index: lldb/source/API/SBProcess.cpp
===================================================================
--- lldb/source/API/SBProcess.cpp
+++ lldb/source/API/SBProcess.cpp
@@ -1288,6 +1288,51 @@
   return LLDB_RECORD_RESULT(sb_proc_info);
 }
 
+lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions,
+                                       lldb::SBError &sb_error) {
+  LLDB_RECORD_METHOD(lldb::addr_t, SBProcess, AllocateMemory,
+                     (size_t, uint32_t, lldb::SBError &), size, permissions,
+                     sb_error);
+
+  lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+  ProcessSP process_sp(GetSP());
+  if (process_sp) {
+    Process::StopLocker stop_locker;
+    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+      std::lock_guard<std::recursive_mutex> guard(
+          process_sp->GetTarget().GetAPIMutex());
+      addr = process_sp->AllocateMemory(size, permissions, sb_error.ref());
+    } else {
+      sb_error.SetErrorString("process is running");
+    }
+  } else {
+    sb_error.SetErrorString("SBProcess is invalid");
+  }
+  return addr;
+}
+
+lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
+  LLDB_RECORD_METHOD(lldb::SBError, SBProcess, DeallocateMemory, (lldb::addr_t),
+                     ptr);
+
+  lldb::SBError sb_error;
+  ProcessSP process_sp(GetSP());
+  if (process_sp) {
+    Process::StopLocker stop_locker;
+    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+      std::lock_guard<std::recursive_mutex> guard(
+          process_sp->GetTarget().GetAPIMutex());
+      Status error = process_sp->DeallocateMemory(ptr);
+      sb_error.SetError(error);
+    } else {
+      sb_error.SetErrorString("process is running");
+    }
+  } else {
+    sb_error.SetErrorString("SBProcess is invalid");
+  }
+  return sb_error;
+}
+
 namespace lldb_private {
 namespace repro {
 
@@ -1417,6 +1462,10 @@
   LLDB_REGISTER_METHOD(lldb::SBMemoryRegionInfoList, SBProcess,
                        GetMemoryRegions, ());
   LLDB_REGISTER_METHOD(lldb::SBProcessInfo, SBProcess, GetProcessInfo, ());
+  LLDB_REGISTER_METHOD(lldb::addr_t, SBProcess, AllocateMemory,
+                       (size_t, uint32_t, lldb::SBError &));
+  LLDB_REGISTER_METHOD(lldb::SBError, SBProcess, DeallocateMemory,
+                       (lldb::addr_t));
 
   LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDOUT);
   LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDERR);
Index: lldb/include/lldb/API/SBProcess.h
===================================================================
--- lldb/include/lldb/API/SBProcess.h
+++ lldb/include/lldb/API/SBProcess.h
@@ -370,6 +370,45 @@
   /// valid.
   lldb::SBProcessInfo GetProcessInfo();
 
+  /// Allocate memory within the process.
+  ///
+  /// This function will allocate memory in the process's address space.
+  ///
+  /// \param[in] size
+  ///     The size of the allocation requested.
+  ///
+  /// \param[in] permissions
+  ///     Or together any of the lldb::Permissions bits.  The
+  ///     permissions on a given memory allocation can't be changed
+  ///     after allocation.  Note that a block that isn't set writable
+  ///     can still be written from lldb, just not by the process
+  ///     itself.
+  ///
+  /// \param[out] error
+  ///     An error object that gets filled in with any errors that
+  ///     might occur when trying allocate.
+  ///
+  /// \return
+  ///     The address of the allocated buffer in the process, or
+  ///     LLDB_INVALID_ADDRESS if the allocation failed.
+  lldb::addr_t AllocateMemory(size_t size, uint32_t permissions,
+                              lldb::SBError &error);
+
+  /// Deallocate memory in the process.
+  ///
+  /// This function will deallocate memory in the process's address
+  /// space that was allocated with AllocateMemory.
+  ///
+  /// \param[in] ptr
+  ///     A return value from AllocateMemory, pointing to the memory you
+  ///     want to deallocate.
+  ///
+  /// \return
+  ///     An error object describes any errors that occurred while
+  ///     deallocating.
+  ///
+  lldb::SBError DeallocateMemory(lldb::addr_t ptr);
+
 protected:
   friend class SBAddress;
   friend class SBBreakpoint;
Index: lldb/bindings/interface/SBProcess.i
===================================================================
--- lldb/bindings/interface/SBProcess.i
+++ lldb/bindings/interface/SBProcess.i
@@ -417,6 +417,25 @@
     lldb::SBProcessInfo
     GetProcessInfo();
 
+    %feature("autodoc", "
+    Allocates a block of memory within the process, with size and
+    access permissions specified in the arguments. The permisssions
+    argument is an or-combination of zero or more of
+    lldb.ePermissionsWritable, lldb.ePermissionsReadable, and
+    lldb.ePermissionsExecutable. Returns the address
+    of the allocated buffer in the process, or
+    lldb.LLDB_INVALID_ADDRESS if the allocation failed.") AllocateMemory;
+
+    lldb::addr_t
+    AllocateMemory(size_t size, uint32_t permissions, lldb::SBError &error);
+
+    %feature("autodoc", "
+    Deallocates the block of memory (previously allocated using
+    AllocateMemory) given in the argument.") DeallocateMemory;
+
+    lldb::SBError
+    DeallocateMemory(lldb::addr_t ptr);
+
     STRING_EXTENSION(SBProcess)
 
 #ifdef SWIGPYTHON
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to