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