mib created this revision.
mib added reviewers: bulbazord, JDevlieghere.
mib added a project: LLDB.
Herald added a project: All.
mib requested review of this revision.
Herald added a subscriber: lldb-commits.
This patch adds memory writing capabilities to the Scripted Process plugin.
This allows to user to get a target address and a memory buffer on the
python scripted process implementation that the user can make processing
on before performing the actual write.
This will also be used to write trap instruction to a real process
memory to set a breakpoint.
Signed-off-by: Med Ismail Bennani <[email protected]>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D144237
Files:
lldb/examples/python/scripted_process/scripted_process.py
lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
lldb/source/Plugins/Process/scripted/ScriptedProcess.h
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
Index: lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
+++ lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -7,20 +7,29 @@
from lldb.plugins.scripted_process import ScriptedThread
class DummyScriptedProcess(ScriptedProcess):
+ memory = None
+
def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData):
super().__init__(exe_ctx, args)
self.threads[0] = DummyScriptedThread(self, None)
-
- def read_memory_at_address(self, addr: int, size: int, error: lldb.SBError) -> lldb.SBData:
+ self.memory = {}
+ addr = 0x500000000
debugger = self.target.GetDebugger()
index = debugger.GetIndexOfTarget(self.target)
+ self.memory[addr] = "Hello, target " + str(index)
+
+ def read_memory_at_address(self, addr: int, size: int, error: lldb.SBError) -> lldb.SBData:
data = lldb.SBData().CreateDataFromCString(
self.target.GetByteOrder(),
self.target.GetCodeByteSize(),
- "Hello, target " + str(index))
+ self.memory[addr])
return data
+ def write_memory_at_address(self, addr, data, error):
+ self.memory[addr] = data.GetString(error, 0)
+ return len(self.memory[addr])
+
def get_loaded_images(self):
return self.loaded_images
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
@@ -150,7 +150,6 @@
self.assertEqual(process_1.GetNumThreads(), 1)
# ... then try reading from target #1 process ...
- addr = 0x500000000
message = "Hello, target 1"
buff = process_1.ReadCStringFromMemory(addr, len(message) + 1, error)
self.assertSuccess(error)
@@ -158,12 +157,22 @@
# ... now, reading again from target #0 process to make sure the call
# gets dispatched to the right target.
- addr = 0x500000000
message = "Hello, target 0"
buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)
self.assertSuccess(error)
self.assertEqual(buff, message)
+ # Let's write some memory.
+ message = "Hello, world!"
+ bytes_written = process_0.WriteCStringToMemory(addr, message, error)
+ self.assertSuccess(error)
+ self.assertEqual(bytes_written, len(message) + 1)
+
+ # ... and check if that memory was saved properly.
+ buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)
+ self.assertSuccess(error)
+ self.assertEqual(buff, message)
+
thread = process_0.GetSelectedThread()
self.assertTrue(thread, "Invalid thread.")
self.assertEqual(thread.GetThreadID(), 0x19)
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
@@ -50,6 +50,7 @@
lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size,
Status &error) override;
+ size_t WriteMemoryAtAddress(lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) override;
StructuredData::ArraySP GetLoadedImages() override;
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -131,6 +131,20 @@
return data_sp;
}
+size_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
+ Status py_error;
+ StructuredData::ObjectSP obj = Dispatch("write_memory_at_address", py_error, addr, data_sp, error);
+
+ if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+ return LLDB_INVALID_OFFSET;
+
+ // If there was an error on the python call, surface it to the user.
+ if (py_error.Fail())
+ error = py_error;
+
+ return obj->GetIntegerValue(LLDB_INVALID_OFFSET);
+}
+
StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
Status error;
StructuredData::ArraySP array =
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.h
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.h
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -68,6 +68,9 @@
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
+
+ size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
+ size_t size, Status &error) override;
ArchSpec GetArchitecture();
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -307,6 +307,22 @@
return size;
}
+size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
+ size_t size, Status &error) {
+ lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(buf, size, GetByteOrder(), GetAddressByteSize());
+
+ if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
+ return 0;
+
+ size_t bytes_written = GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
+
+ if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
+ return ScriptedInterface::ErrorWithMessage<size_t>(
+ LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
+
+ return size;
+}
+
ArchSpec ScriptedProcess::GetArchitecture() {
return GetTarget().GetArchitecture();
}
Index: lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
+++ lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
@@ -52,6 +52,11 @@
ReadMemoryAtAddress(lldb::addr_t address, size_t size, Status &error) {
return {};
}
+
+ virtual size_t
+ WriteMemoryAtAddress(lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
+ return LLDB_INVALID_OFFSET;
+ };
virtual StructuredData::ArraySP GetLoadedImages() { return {}; }
Index: lldb/examples/python/scripted_process/scripted_process.py
===================================================================
--- lldb/examples/python/scripted_process/scripted_process.py
+++ lldb/examples/python/scripted_process/scripted_process.py
@@ -98,6 +98,21 @@
"""
pass
+ def write_memory_at_address(self, addr, data, error):
+ """ Write a buffer to the scripted process memory.
+
+ Args:
+ addr (int): Address from which we should start reading.
+ data (lldb.SBData): An `lldb.SBData` buffer to write to the
+ process memory.
+ error (lldb.SBError): Error object.
+
+ Returns:
+ size (int): Size of the memory to read.
+ """
+ error.SetErrorString("$s doesn't support memory writting." % self.__class__.__name__)
+ return 0
+
def get_loaded_images(self):
""" Get the list of loaded images for the scripted process.
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits