Skip to content

Commit f4758d8

Browse files
committed
[lldb/Plugins] Add memory writing capabilities to Scripted Process
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]>
1 parent 026c6be commit f4758d8

File tree

13 files changed

+107
-8
lines changed

13 files changed

+107
-8
lines changed

lldb/bindings/python/python-swigsafecast.swig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp) {
9999
SWIGTYPE_p_lldb__SBAttachInfo);
100100
}
101101

102+
PythonObject ToSWIGWrapper(lldb::DataExtractorSP data_sp) {
103+
return ToSWIGHelper(new lldb::DataExtractorSP(std::move(data_sp)),
104+
SWIGTYPE_p_lldb__SBData);
105+
}
106+
102107
ScopedPythonObject<lldb::SBCommandReturnObject>
103108
ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
104109
return ScopedPythonObject<lldb::SBCommandReturnObject>(

lldb/examples/python/scripted_process/scripted_process.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,21 @@ def read_memory_at_address(self, addr, size, error):
9898
"""
9999
pass
100100

101+
def write_memory_at_address(self, addr, data, error):
102+
""" Write a buffer to the scripted process memory.
103+
104+
Args:
105+
addr (int): Address from which we should start reading.
106+
data (lldb.SBData): An `lldb.SBData` buffer to write to the
107+
process memory.
108+
error (lldb.SBError): Error object.
109+
110+
Returns:
111+
size (int): Size of the memory to read.
112+
"""
113+
error.SetErrorString("%s doesn't support memory writes." % self.__class__.__name__)
114+
return 0
115+
101116
def get_loaded_images(self):
102117
""" Get the list of loaded images for the scripted process.
103118

lldb/include/lldb/Interpreter/ScriptedProcessInterface.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ class ScriptedProcessInterface : virtual public ScriptedInterface {
5454
return {};
5555
}
5656

57+
virtual size_t WriteMemoryAtAddress(lldb::addr_t addr,
58+
lldb::DataExtractorSP data_sp,
59+
Status &error) {
60+
return LLDB_INVALID_OFFSET;
61+
};
62+
5763
virtual StructuredData::ArraySP GetLoadedImages() { return {}; }
5864

5965
virtual lldb::pid_t GetProcessID() { return LLDB_INVALID_PROCESS_ID; }

lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,31 @@ size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
255255
return ScriptedInterface::ErrorWithMessage<size_t>(
256256
LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
257257

258-
return size;
258+
// FIXME: We should use the diagnostic system to report a warning if the
259+
// `bytes_copied` is different from `size`.
260+
261+
return bytes_copied;
262+
}
263+
264+
size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
265+
size_t size, Status &error) {
266+
lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
267+
buf, size, GetByteOrder(), GetAddressByteSize());
268+
269+
if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
270+
return 0;
271+
272+
size_t bytes_written =
273+
GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
274+
275+
if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
276+
return ScriptedInterface::ErrorWithMessage<size_t>(
277+
LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
278+
279+
// FIXME: We should use the diagnostic system to report a warning if the
280+
// `bytes_written` is different from `size`.
281+
282+
return bytes_written;
259283
}
260284

261285
ArchSpec ScriptedProcess::GetArchitecture() {

lldb/source/Plugins/Process/scripted/ScriptedProcess.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class ScriptedProcess : public Process {
6969
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
7070
Status &error) override;
7171

72+
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
73+
Status &error) override;
74+
7275
ArchSpec GetArchitecture();
7376

7477
Status

lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx);
7878

7979
PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp);
8080
PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp);
81+
PythonObject ToSWIGWrapper(lldb::DataExtractorSP data_extractor_sp);
8182

8283
PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb);
8384
PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb);

lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,22 @@ lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
134134
return data_sp;
135135
}
136136

137+
size_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(
138+
lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
139+
Status py_error;
140+
StructuredData::ObjectSP obj =
141+
Dispatch("write_memory_at_address", py_error, addr, data_sp, error);
142+
143+
if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
144+
return LLDB_INVALID_OFFSET;
145+
146+
// If there was an error on the python call, surface it to the user.
147+
if (py_error.Fail())
148+
error = py_error;
149+
150+
return obj->GetIntegerValue(LLDB_INVALID_OFFSET);
151+
}
152+
137153
StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
138154
Status error;
139155
StructuredData::ArraySP array =

lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
4848

4949
lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size,
5050
Status &error) override;
51-
51+
52+
size_t WriteMemoryAtAddress(lldb::addr_t addr, lldb::DataExtractorSP data_sp,
53+
Status &error) override;
5254

5355
StructuredData::ArraySP GetLoadedImages() override;
5456

lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
124124
return python::ToSWIGWrapper(arg);
125125
}
126126

127+
python::PythonObject Transform(lldb::DataExtractorSP arg) {
128+
return python::ToSWIGWrapper(arg);
129+
}
130+
127131
template <typename T, typename U>
128132
void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
129133
// If U is not a PythonObject, don't touch it!

lldb/source/Target/Memory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,11 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
234234
return dst_len - bytes_left;
235235

236236
if (process_bytes_read != cache_line_byte_size) {
237+
data_buffer_heap_up->SetByteSize(process_bytes_read);
237238
if (process_bytes_read < data_buffer_heap_up->GetByteSize()) {
238239
dst_len -= data_buffer_heap_up->GetByteSize() - process_bytes_read;
239240
bytes_left = process_bytes_read;
240241
}
241-
data_buffer_heap_up->SetByteSize(process_bytes_read);
242242
}
243243
m_L2_cache[curr_addr] = DataBufferSP(data_buffer_heap_up.release());
244244
// We have read data and put it into the cache, continue through the

0 commit comments

Comments
 (0)