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