Skip to content

Commit 907d6b0

Browse files
authored
Merge pull request #3535 from medismailben/stable/20210726
[lldb] Add support for ScriptedProcess
2 parents 93bcb83 + a7c4c5f commit 907d6b0

37 files changed

+1843
-262
lines changed

lldb/bindings/interface/SBMemoryRegionInfo.i

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ public:
2020

2121
SBMemoryRegionInfo (const lldb::SBMemoryRegionInfo &rhs);
2222

23+
SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin,
24+
lldb::addr_t end, uint32_t permissions, bool mapped, bool stack_memory);
25+
2326
~SBMemoryRegionInfo ();
2427

2528
void

lldb/bindings/interface/SBMemoryRegionInfoList.i

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public:
2424
uint32_t
2525
GetSize () const;
2626

27+
bool
28+
GetMemoryRegionContainingAddress (lldb::addr_t addr, SBMemoryRegionInfo &region_info);
29+
2730
bool
2831
GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo &region_info);
2932

lldb/bindings/python/python-wrapper.swig

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -322,16 +322,69 @@ LLDBSwigPythonCreateScriptedProcess
322322

323323
PythonObject result = {};
324324
if (arg_info.get().max_positional_args == 2) {
325-
if (args_impl != nullptr) {
326-
error_string.assign("args passed, but __init__ does not take an args dictionary");
327-
Py_RETURN_NONE;
328-
}
329-
result = pfunc(target_arg, dict);
330-
} else if (arg_info.get().max_positional_args >= 3) {
331325
PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl)));
332-
result = pfunc(target_arg, args_arg, dict);
326+
result = pfunc(target_arg, args_arg);
333327
} else {
334-
error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
328+
error_string.assign("wrong number of arguments in __init__, should be 2 (not including self)");
329+
Py_RETURN_NONE;
330+
}
331+
332+
if (result.IsAllocated())
333+
return result.release();
334+
Py_RETURN_NONE;
335+
}
336+
337+
SWIGEXPORT void*
338+
LLDBSwigPythonCreateScriptedThread
339+
(
340+
const char *python_class_name,
341+
const char *session_dictionary_name,
342+
const lldb::ProcessSP& process_sp,
343+
lldb_private::StructuredDataImpl *args_impl,
344+
std::string &error_string
345+
)
346+
{
347+
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
348+
Py_RETURN_NONE;
349+
350+
PyErr_Cleaner py_err_cleaner(true);
351+
352+
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
353+
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
354+
355+
if (!pfunc.IsAllocated()) {
356+
error_string.append("could not find script class: ");
357+
error_string.append(python_class_name);
358+
return nullptr;
359+
}
360+
361+
// I do not want the SBProcess to be deallocated when going out of scope
362+
// because python has ownership of it and will manage memory for this
363+
// object by itself
364+
PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBProcess(process_sp)));
365+
366+
if (!process_arg.IsAllocated())
367+
Py_RETURN_NONE;
368+
369+
llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
370+
if (!arg_info) {
371+
llvm::handleAllErrors(
372+
arg_info.takeError(),
373+
[&](PythonException &E) {
374+
error_string.append(E.ReadBacktrace());
375+
},
376+
[&](const llvm::ErrorInfoBase &E) {
377+
error_string.append(E.message());
378+
});
379+
Py_RETURN_NONE;
380+
}
381+
382+
PythonObject result = {};
383+
if (arg_info.get().max_positional_args == 2) {
384+
PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl)));
385+
result = pfunc(process_arg, args_arg);
386+
} else {
387+
error_string.assign("wrong number of arguments in __init__, should be 2 (not including self)");
335388
Py_RETURN_NONE;
336389
}
337390

@@ -917,6 +970,22 @@ LLDBSWIGPython_CastPyObjectToSBValue
917970
return sb_ptr;
918971
}
919972

973+
SWIGEXPORT void*
974+
LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo
975+
(
976+
PyObject* data
977+
)
978+
{
979+
lldb::SBMemoryRegionInfo* sb_ptr = NULL;
980+
981+
int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0);
982+
983+
if (valid_cast == -1)
984+
return NULL;
985+
986+
return sb_ptr;
987+
}
988+
920989
SWIGEXPORT bool
921990
LLDBSwigPythonCallCommand
922991
(

lldb/bindings/python/static-binding/LLDBWrapPython.cpp

Lines changed: 334 additions & 107 deletions
Large diffs are not rendered by default.

lldb/bindings/python/static-binding/lldb.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7065,6 +7065,7 @@ def __init__(self, *args):
70657065
r"""
70667066
__init__(SBMemoryRegionInfo self) -> SBMemoryRegionInfo
70677067
__init__(SBMemoryRegionInfo self, SBMemoryRegionInfo rhs) -> SBMemoryRegionInfo
7068+
__init__(SBMemoryRegionInfo self, char const * name, lldb::addr_t begin, lldb::addr_t end, uint32_t permissions, bool mapped, bool stack_memory) -> SBMemoryRegionInfo
70687069
"""
70697070
_lldb.SBMemoryRegionInfo_swiginit(self, _lldb.new_SBMemoryRegionInfo(*args))
70707071
__swig_destroy__ = _lldb.delete_SBMemoryRegionInfo
@@ -7182,6 +7183,10 @@ def GetSize(self):
71827183
r"""GetSize(SBMemoryRegionInfoList self) -> uint32_t"""
71837184
return _lldb.SBMemoryRegionInfoList_GetSize(self)
71847185

7186+
def GetMemoryRegionContainingAddress(self, addr, region_info):
7187+
r"""GetMemoryRegionContainingAddress(SBMemoryRegionInfoList self, lldb::addr_t addr, SBMemoryRegionInfo region_info) -> bool"""
7188+
return _lldb.SBMemoryRegionInfoList_GetMemoryRegionContainingAddress(self, addr, region_info)
7189+
71857190
def GetMemoryRegionAtIndex(self, idx, region_info):
71867191
r"""GetMemoryRegionAtIndex(SBMemoryRegionInfoList self, uint32_t idx, SBMemoryRegionInfo region_info) -> bool"""
71877192
return _lldb.SBMemoryRegionInfoList_GetMemoryRegionAtIndex(self, idx, region_info)

lldb/examples/python/scripted_process/my_scripted_process.py

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
import os
1+
import os,struct,signal
2+
3+
from typing import Any, Dict
24

35
import lldb
46
from lldb.plugins.scripted_process import ScriptedProcess
7+
from lldb.plugins.scripted_process import ScriptedThread
58

69
class MyScriptedProcess(ScriptedProcess):
10+
memory_regions = [
11+
lldb.SBMemoryRegionInfo("stack", 0x1040b2000, 0x1040b4000, 0b110, True,
12+
True)
13+
]
14+
15+
stack_memory_dump = os.path.join(os.path.dirname(os.path.abspath(__file__)),
16+
'main.stack-dump')
17+
718
def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
819
super().__init__(target, args)
920

1021
def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
11-
return self.memory_regions[0]
22+
for region in self.memory_regions:
23+
if region.GetRegionBase() <= addr < region.GetRegionEnd():
24+
return region
25+
return None
1226

1327
def get_thread_with_id(self, tid: int):
1428
return {}
@@ -17,10 +31,25 @@ def get_registers_for_thread(self, tid: int):
1731
return {}
1832

1933
def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
20-
data = lldb.SBData().CreateDataFromCString(
34+
data = lldb.SBData()
35+
36+
with open(self.stack_memory_dump, 'rb') as f:
37+
stack_mem = f.read(-1)
38+
if not stack_mem:
39+
return data
40+
41+
mem_region = self.get_memory_region_containing_address(addr)
42+
43+
if not mem_region or addr + size > mem_region.GetRegionEnd():
44+
return data
45+
46+
offset = addr - mem_region.GetRegionBase()
47+
shrunk_stack_mem = stack_mem[offset:offset + size]
48+
49+
error = lldb.SBError()
50+
data.SetData(error, shrunk_stack_mem,
2151
self.target.GetByteOrder(),
22-
self.target.GetCodeByteSize(),
23-
"Hello, world!")
52+
self.target.GetAddressByteSize())
2453
return data
2554

2655
def get_loaded_images(self):
@@ -35,6 +64,68 @@ def should_stop(self) -> bool:
3564
def is_alive(self) -> bool:
3665
return True
3766

67+
def get_scripted_thread_plugin(self):
68+
return MyScriptedThread.__module__ + "." + MyScriptedThread.__name__
69+
70+
71+
class MyScriptedThread(ScriptedThread):
72+
register_ctx = {
73+
"rax":0x00000000000006e4,
74+
"rbx":0x00000001040b6060,
75+
"rcx":0x00000001040b2e00,
76+
"rdx":0x00000001040b2ba8,
77+
"rdi":0x000000000000002a,
78+
"rsi":0x00000001040b2b98,
79+
"rbp":0x00000001040b2a20,
80+
"rsp":0x00000001040b2a20,
81+
"r8":0x00000000003e131e,
82+
"r9":0xffffffff00000000,
83+
"r10":0x0000000000000000,
84+
"r11":0x0000000000000246,
85+
"r12":0x000000010007c3a0,
86+
"r13":0x00000001040b2b18,
87+
"r14":0x0000000100003f90,
88+
"r15":0x00000001040b2b88,
89+
"rip":0x0000000100003f61,
90+
"rflags":0x0000000000000206,
91+
"cs":0x000000000000002b,
92+
"fs":0x0000000000000000,
93+
"gs":0x0000000000000000,
94+
}
95+
96+
def __init__(self, process, args):
97+
super().__init__(process, args)
98+
99+
def get_thread_id(self) -> int:
100+
return 0x19
101+
102+
def get_name(self) -> str:
103+
return MyScriptedThread.__name__ + ".thread-1"
104+
105+
def get_stop_reason(self) -> Dict[str, Any]:
106+
return { "type": lldb.eStopReasonSignal, "data": {
107+
"signal": signal.SIGINT
108+
} }
109+
110+
def get_stackframes(self):
111+
class ScriptedStackFrame:
112+
def __init__(idx, cfa, pc, symbol_ctx):
113+
self.idx = idx
114+
self.cfa = cfa
115+
self.pc = pc
116+
self.symbol_ctx = symbol_ctx
117+
118+
119+
symbol_ctx = lldb.SBSymbolContext()
120+
frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
121+
self.frames.append(frame_zero)
122+
123+
return self.frame_zero[0:0]
124+
125+
def get_register_context(self) -> str:
126+
return struct.pack("{}Q".format(len(self.register_ctx)), *self.register_ctx.values())
127+
128+
38129
def __lldb_init_module(debugger, dict):
39130
if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ:
40131
debugger.HandleCommand(

0 commit comments

Comments
 (0)