1#!/usr/bin/env python 2 3import lldb 4import struct 5 6 7class OperatingSystemPlugIn(object): 8 """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" 9 10 def __init__(self, process): 11 '''Initialization needs a valid.SBProcess object. 12 13 This plug-in will get created after a live process is valid and has stopped for the 14 first time.''' 15 self.process = None 16 self.registers = None 17 self.threads = None 18 if isinstance(process, lldb.SBProcess) and process.IsValid(): 19 self.process = process 20 self.threads = None # Will be an dictionary containing info for each thread 21 22 def get_target(self): 23 # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target" 24 # tracks the current target in the LLDB command interpreter which isn't the 25 # correct thing to use for this plug-in. 26 return self.process.target 27 28 def create_thread(self, tid, context): 29 if tid == 0x444444444: 30 thread_info = { 31 'tid': tid, 32 'name': 'four', 33 'queue': 'queue4', 34 'state': 'stopped', 35 'stop_reason': 'none'} 36 self.threads.append(thread_info) 37 return thread_info 38 return None 39 40 def get_thread_info(self): 41 if not self.threads: 42 # The sample dictionary below shows the values that can be returned for a thread 43 # tid => thread ID (mandatory) 44 # name => thread name (optional key/value pair) 45 # queue => thread dispatch queue name (optional key/value pair) 46 # state => thred state (mandatory, set to 'stopped' for now) 47 # stop_reason => thread stop reason. (mandatory, usually set to 'none') 48 # Possible values include: 49 # 'breakpoint' if the thread is stopped at a breakpoint 50 # 'none' thread is just stopped because the process is stopped 51 # 'trace' the thread just single stepped 52 # The usual value for this while threads are in memory is 'none' 53 # register_data_addr => the address of the register data in memory (optional key/value pair) 54 # Specifying this key/value pair for a thread will avoid a call to get_register_data() 55 # and can be used when your registers are in a thread context structure that is contiguous 56 # in memory. Don't specify this if your register layout in memory doesn't match the layout 57 # described by the dictionary returned from a call to the 58 # get_register_info() method. 59 self.threads = [{'tid': 0x111111111, 60 'name': 'one', 61 'queue': 'queue1', 62 'state': 'stopped', 63 'stop_reason': 'breakpoint'}, 64 {'tid': 0x222222222, 65 'name': 'two', 66 'queue': 'queue2', 67 'state': 'stopped', 68 'stop_reason': 'none'}, 69 {'tid': 0x333333333, 70 'name': 'three', 71 'queue': 'queue3', 72 'state': 'stopped', 73 'stop_reason': 'trace', 74 'register_data_addr': 0x100000000}] 75 return self.threads 76 77 def get_register_info(self): 78 if self.registers is None: 79 self.registers = dict() 80 triple = self.process.target.triple 81 if triple: 82 arch = triple.split('-')[0] 83 if arch == 'x86_64': 84 self.registers['sets'] = ['GPR', 'FPU', 'EXC'] 85 self.registers['registers'] = [ 86 {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, 87 {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, 88 {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', }, 89 {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', }, 90 {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', }, 91 {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', }, 92 {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', }, 93 {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', }, 94 {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', }, 95 {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', }, 96 {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, 97 {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, 98 {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, 99 {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, 100 {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, 101 {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, 102 {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, 103 {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, 104 {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 105 {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 106 {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}, 107 ] 108 return self.registers 109 110 def get_register_data(self, tid): 111 if tid == 0x111111111: 112 return struct.pack( 113 '21Q', 114 1, 115 2, 116 3, 117 4, 118 5, 119 6, 120 7, 121 8, 122 9, 123 10, 124 11, 125 12, 126 13, 127 14, 128 15, 129 16, 130 17, 131 18, 132 19, 133 20, 134 21) 135 elif tid == 0x222222222: 136 return struct.pack( 137 '21Q', 138 11, 139 12, 140 13, 141 14, 142 15, 143 16, 144 17, 145 18, 146 19, 147 110, 148 111, 149 112, 150 113, 151 114, 152 115, 153 116, 154 117, 155 118, 156 119, 157 120, 158 121) 159 elif tid == 0x333333333: 160 return struct.pack( 161 '21Q', 162 21, 163 22, 164 23, 165 24, 166 25, 167 26, 168 27, 169 28, 170 29, 171 210, 172 211, 173 212, 174 213, 175 214, 176 215, 177 216, 178 217, 179 218, 180 219, 181 220, 182 221) 183 elif tid == 0x444444444: 184 return struct.pack( 185 '21Q', 186 31, 187 32, 188 33, 189 34, 190 35, 191 36, 192 37, 193 38, 194 39, 195 310, 196 311, 197 312, 198 313, 199 314, 200 315, 201 316, 202 317, 203 318, 204 319, 205 320, 206 321) 207 else: 208 return struct.pack( 209 '21Q', 210 41, 211 42, 212 43, 213 44, 214 45, 215 46, 216 47, 217 48, 218 49, 219 410, 220 411, 221 412, 222 413, 223 414, 224 415, 225 416, 226 417, 227 418, 228 419, 229 420, 230 421) 231 return None 232