1from abc import ABCMeta, abstractmethod 2import six 3 4import lldb 5 6@six.add_metaclass(ABCMeta) 7class ScriptedProcess: 8 9 """ 10 The base class for a scripted process. 11 12 Most of the base class methods are `@abstractmethod` that need to be 13 overwritten by the inheriting class. 14 15 DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE. 16 THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. 17 """ 18 19 @abstractmethod 20 def __init__(self, target, args): 21 """ Construct a scripted process. 22 23 Args: 24 target (lldb.SBTarget): The target launching the scripted process. 25 args (lldb.SBStructuredData): A Dictionary holding arbitrary 26 key/value pairs used by the scripted process. 27 """ 28 self.target = None 29 self.args = None 30 if isinstance(target, lldb.SBTarget) and target.IsValid(): 31 self.target = target 32 if isinstance(args, lldb.SBStructuredData) and args.IsValid(): 33 self.args = args 34 35 @abstractmethod 36 def get_memory_region_containing_address(addr): 37 """ Get the memory region for the scripted process, containing a 38 specific address. 39 40 Args: 41 addr (int): Address to look for in the scripted process memory 42 regions. 43 44 Returns: 45 lldb.SBMemoryRegionInfo: The memory region containing the address. 46 None if out of bounds. 47 """ 48 pass 49 50 @abstractmethod 51 def get_thread_with_id(tid): 52 """ Get the scripted process thread with a specific ID. 53 54 Args: 55 tid (int): Thread ID to look for in the scripted process. 56 57 Returns: 58 Dict: The thread represented as a dictionary, withr the 59 tid thread ID. None if tid doesn't match any of the scripted 60 process threads. 61 """ 62 pass 63 64 @abstractmethod 65 def get_registers_for_thread(tid): 66 """ Get the register context dictionary for a certain thread of 67 the scripted process. 68 69 Args: 70 tid (int): Thread ID for the thread's register context. 71 72 Returns: 73 Dict: The register context represented as a dictionary, for the 74 tid thread. None if tid doesn't match any of the scripted 75 process threads. 76 """ 77 pass 78 79 @abstractmethod 80 def read_memory_at_address(addr, size): 81 """ Get a memory buffer from the scripted process at a certain address, 82 of a certain size. 83 84 Args: 85 addr (int): Address from which we should start reading. 86 size (int): Size of the memory to read. 87 88 Returns: 89 lldb.SBData: An `lldb.SBData` buffer with the target byte size and 90 byte order storing the memory read. 91 """ 92 pass 93 94 @abstractmethod 95 def get_loaded_images(self): 96 """ Get the list of loaded images for the scripted process. 97 98 ``` 99 class ScriptedProcessImage: 100 def __init__(name, file_spec, uuid, load_address): 101 self.name = name 102 self.file_spec = file_spec 103 self.uuid = uuid 104 self.load_address = load_address 105 ``` 106 107 Returns: 108 List[ScriptedProcessImage]: A list of `ScriptedProcessImage` 109 containing for each entry, the name of the library, a UUID, 110 an `lldb.SBFileSpec` and a load address. 111 None if the list is empty. 112 """ 113 pass 114 115 def get_process_id(self): 116 """ Get the scripted process identifier. 117 118 Returns: 119 int: The scripted process identifier. 120 """ 121 return 0 122 123 124 def launch(self): 125 """ Simulate the scripted process launch. 126 127 Returns: 128 lldb.SBError: An `lldb.SBError` with error code 0. 129 """ 130 return lldb.SBError() 131 132 def resume(self): 133 """ Simulate the scripted process resume. 134 135 Returns: 136 lldb.SBError: An `lldb.SBError` with error code 0. 137 """ 138 return lldb.SBError() 139 140 @abstractmethod 141 def should_stop(self): 142 """ Check if the scripted process plugin should produce the stop event. 143 144 Returns: 145 bool: True if scripted process should broadcast a stop event. 146 False otherwise. 147 """ 148 pass 149 150 def stop(self): 151 """ Trigger the scripted process stop. 152 153 Returns: 154 lldb.SBError: An `lldb.SBError` with error code 0. 155 """ 156 return lldb.SBError() 157 158 @abstractmethod 159 def is_alive(self): 160 """ Check if the scripted process is alive. 161 162 Returns: 163 bool: True if scripted process is alive. False otherwise. 164 """ 165 pass 166 167 @abstractmethod 168 def get_scripted_thread_plugin(self): 169 """ Get scripted thread plugin name. 170 171 Returns: 172 str: Name of the scripted thread plugin. 173 """ 174 return None 175 176@six.add_metaclass(ABCMeta) 177class ScriptedThread: 178 179 """ 180 The base class for a scripted thread. 181 182 Most of the base class methods are `@abstractmethod` that need to be 183 overwritten by the inheriting class. 184 185 DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE. 186 THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. 187 """ 188 189 @abstractmethod 190 def __init__(self, target): 191 """ Construct a scripted thread. 192 193 Args: 194 target (lldb.SBTarget): The target launching the scripted process. 195 args (lldb.SBStructuredData): A Dictionary holding arbitrary 196 key/value pairs used by the scripted process. 197 """ 198 self.target = None 199 self.args = None 200 if isinstance(target, lldb.SBTarget) and target.IsValid(): 201 self.target = target 202 203 self.id = None 204 self.name = None 205 self.queue = None 206 self.state = None 207 self.stop_reason = None 208 self.register_info = None 209 self.register_ctx = [] 210 self.frames = [] 211 212 @abstractmethod 213 def get_thread_id(self): 214 """ Get the scripted thread identifier. 215 216 Returns: 217 int: The identifier of the scripted thread. 218 """ 219 pass 220 221 @abstractmethod 222 def get_name(self): 223 """ Get the scripted thread name. 224 225 Returns: 226 str: The name of the scripted thread. 227 """ 228 pass 229 230 def get_state(self): 231 """ Get the scripted thread state type. 232 233 eStateStopped, ///< Process or thread is stopped and can be examined. 234 eStateRunning, ///< Process or thread is running and can't be examined. 235 eStateStepping, ///< Process or thread is in the process of stepping and can 236 /// not be examined. 237 238 Returns: 239 int: The state type of the scripted thread. 240 Returns lldb.eStateStopped by default. 241 """ 242 return lldb.eStateStopped 243 244 def get_queue(self): 245 """ Get the scripted thread associated queue name. 246 This method is optional. 247 248 Returns: 249 str: The queue name associated with the scripted thread. 250 """ 251 pass 252 253 @abstractmethod 254 def get_stop_reason(self): 255 """ Get the dictionary describing the stop reason type with some data. 256 This method is optional. 257 258 Returns: 259 Dict: The dictionary holding the stop reason type and the possibly 260 the stop reason data. 261 """ 262 pass 263 264 def get_stackframes(self): 265 """ Get the list of stack frames for the scripted thread. 266 267 ``` 268 class ScriptedStackFrame: 269 def __init__(idx, cfa, pc, symbol_ctx): 270 self.idx = idx 271 self.cfa = cfa 272 self.pc = pc 273 self.symbol_ctx = symbol_ctx 274 ``` 275 276 Returns: 277 List[ScriptedFrame]: A list of `ScriptedStackFrame` 278 containing for each entry, the frame index, the canonical 279 frame address, the program counter value for that frame 280 and a symbol context. 281 None if the list is empty. 282 """ 283 return 0 284 285 def get_register_info(self): 286 if self.register_info is None: 287 self.register_info = dict() 288 triple = self.target.triple 289 if triple: 290 arch = triple.split('-')[0] 291 if arch == 'x86_64': 292 self.register_info['sets'] = ['GPR', 'FPU', 'EXC'] 293 self.register_info['registers'] = [ 294 {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, 295 {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, 296 {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', }, 297 {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', }, 298 {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', }, 299 {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', }, 300 {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', }, 301 {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', }, 302 {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', }, 303 {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', }, 304 {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, 305 {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, 306 {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, 307 {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, 308 {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, 309 {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, 310 {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, 311 {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, 312 {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 313 {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 314 {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 315 ] 316 return self.register_info 317 318 @abstractmethod 319 def get_register_context(self): 320 """ Get the scripted thread register context 321 322 Returns: 323 str: A byte representing all register's value. 324 """ 325 pass 326