1import os,struct,signal
2
3from typing import Any, Dict
4
5import lldb
6from lldb.plugins.scripted_process import ScriptedProcess
7from lldb.plugins.scripted_process import ScriptedThread
8
9class 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
18    def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
19        super().__init__(target, args)
20
21    def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
22        for region in self.memory_regions:
23            if region.GetRegionBase() <= addr < region.GetRegionEnd():
24                return region
25        return None
26
27    def get_thread_with_id(self, tid: int):
28        return {}
29
30    def get_registers_for_thread(self, tid: int):
31        return {}
32
33    def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
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,
51                                    self.target.GetByteOrder(),
52                                    self.target.GetAddressByteSize())
53        return data
54
55    def get_loaded_images(self):
56        return self.loaded_images
57
58    def get_process_id(self) -> int:
59        return 42
60
61    def should_stop(self) -> bool:
62        return True
63
64    def is_alive(self) -> bool:
65        return True
66
67    def get_scripted_thread_plugin(self):
68        return MyScriptedThread.__module__ + "." + MyScriptedThread.__name__
69
70
71class MyScriptedThread(ScriptedThread):
72    registers = {
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, target):
97        super().__init__(target)
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.registers)), *self.registers.values())
127
128
129def __lldb_init_module(debugger, dict):
130    if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ:
131        debugger.HandleCommand(
132            "process launch -C %s.%s" % (__name__,
133                                     MyScriptedProcess.__name__))
134    else:
135        print("Name of the class that will manage the scripted process: '%s.%s'"
136                % (__name__, MyScriptedProcess.__name__))