housel created this revision.
housel added a reviewer: clayborg.
housel requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
This change adds AllocateMemory and DeallocateMemory methods to the SBProcess
API, so that clients can allocate and deallocate memory blocks within the
process being debugged (for storing JIT-compiled code or other uses).
(I am developing a debugger + REPL using the API; it will need to store
JIT-compiled code within the target.)
Repository:
rG LLVM Github Monorepo
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
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,55 @@
"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()
+ exe = self.getBuildArtifact("a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
+ self.assertTrue(breakpoint, VALID_BREAKPOINT)
+
+ # Launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory())
+
+ thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+ self.assertTrue(
+ thread.IsValid(),
+ "There should be a thread stopped due to breakpoint")
+ frame = thread.GetFrameAtIndex(0)
+
+ # Allocate a block of memory in the target process
+ error = lldb.SBError()
+ addr = process.AllocateMemory(16384, lldb.ePermissionsWritable | 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
+ 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')
+
+ # 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,50 @@
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 +1461,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,44 @@
/// 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,12 @@
lldb::SBProcessInfo
GetProcessInfo();
+ lldb::addr_t
+ AllocateMemory(size_t size, uint32_t permissions, lldb::SBError &error);
+
+ lldb::SBError
+ DeallocateMemory(lldb::addr_t ptr);
+
STRING_EXTENSION(SBProcess)
#ifdef SWIGPYTHON
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits