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 } 37 self.threads.append(thread_info) 38 return thread_info 39 return None 40 41 def get_thread_info(self): 42 if not self.threads: 43 # The sample dictionary below shows the values that can be returned for a thread 44 # tid => thread ID (mandatory) 45 # name => thread name (optional key/value pair) 46 # queue => thread dispatch queue name (optional key/value pair) 47 # state => thred state (mandatory, set to 'stopped' for now) 48 # stop_reason => thread stop reason. (mandatory, usually set to 'none') 49 # Possible values include: 50 # 'breakpoint' if the thread is stopped at a breakpoint 51 # 'none' thread is just stopped because the process is stopped 52 # 'trace' the thread just single stepped 53 # The usual value for this while threads are in memory is 'none' 54 # register_data_addr => the address of the register data in memory (optional key/value pair) 55 # Specifying this key/value pair for a thread will avoid a call to get_register_data() 56 # and can be used when your registers are in a thread context structure that is contiguous 57 # in memory. Don't specify this if your register layout in memory doesn't match the layout 58 # described by the dictionary returned from a call to the 59 # get_register_info() method. 60 self.threads = [ 61 { 62 "tid": 0x111111111, 63 "name": "one", 64 "queue": "queue1", 65 "state": "stopped", 66 "stop_reason": "breakpoint", 67 }, 68 { 69 "tid": 0x222222222, 70 "name": "two", 71 "queue": "queue2", 72 "state": "stopped", 73 "stop_reason": "none", 74 }, 75 { 76 "tid": 0x333333333, 77 "name": "three", 78 "queue": "queue3", 79 "state": "stopped", 80 "stop_reason": "trace", 81 }, 82 ] 83 return self.threads 84 85 def get_register_info(self): 86 if self.registers is None: 87 self.registers = dict() 88 self.registers["sets"] = ["GPR"] 89 self.registers["registers"] = [ 90 { 91 "name": "rax", 92 "bitsize": 64, 93 "offset": 0, 94 "encoding": "uint", 95 "format": "hex", 96 "set": 0, 97 "gcc": 0, 98 "dwarf": 0, 99 }, 100 { 101 "name": "rbx", 102 "bitsize": 64, 103 "offset": 8, 104 "encoding": "uint", 105 "format": "hex", 106 "set": 0, 107 "gcc": 3, 108 "dwarf": 3, 109 }, 110 { 111 "name": "rcx", 112 "bitsize": 64, 113 "offset": 16, 114 "encoding": "uint", 115 "format": "hex", 116 "set": 0, 117 "gcc": 2, 118 "dwarf": 2, 119 "generic": "arg4", 120 "alt-name": "arg4", 121 }, 122 { 123 "name": "rdx", 124 "bitsize": 64, 125 "offset": 24, 126 "encoding": "uint", 127 "format": "hex", 128 "set": 0, 129 "gcc": 1, 130 "dwarf": 1, 131 "generic": "arg3", 132 "alt-name": "arg3", 133 }, 134 { 135 "name": "rdi", 136 "bitsize": 64, 137 "offset": 32, 138 "encoding": "uint", 139 "format": "hex", 140 "set": 0, 141 "gcc": 5, 142 "dwarf": 5, 143 "generic": "arg1", 144 "alt-name": "arg1", 145 }, 146 { 147 "name": "rsi", 148 "bitsize": 64, 149 "offset": 40, 150 "encoding": "uint", 151 "format": "hex", 152 "set": 0, 153 "gcc": 4, 154 "dwarf": 4, 155 "generic": "arg2", 156 "alt-name": "arg2", 157 }, 158 { 159 "name": "rbp", 160 "bitsize": 64, 161 "offset": 48, 162 "encoding": "uint", 163 "format": "hex", 164 "set": 0, 165 "gcc": 6, 166 "dwarf": 6, 167 "generic": "fp", 168 "alt-name": "fp", 169 }, 170 { 171 "name": "rsp", 172 "bitsize": 64, 173 "offset": 56, 174 "encoding": "uint", 175 "format": "hex", 176 "set": 0, 177 "gcc": 7, 178 "dwarf": 7, 179 "generic": "sp", 180 "alt-name": "sp", 181 }, 182 { 183 "name": "r8", 184 "bitsize": 64, 185 "offset": 64, 186 "encoding": "uint", 187 "format": "hex", 188 "set": 0, 189 "gcc": 8, 190 "dwarf": 8, 191 "generic": "arg5", 192 "alt-name": "arg5", 193 }, 194 { 195 "name": "r9", 196 "bitsize": 64, 197 "offset": 72, 198 "encoding": "uint", 199 "format": "hex", 200 "set": 0, 201 "gcc": 9, 202 "dwarf": 9, 203 "generic": "arg6", 204 "alt-name": "arg6", 205 }, 206 { 207 "name": "r10", 208 "bitsize": 64, 209 "offset": 80, 210 "encoding": "uint", 211 "format": "hex", 212 "set": 0, 213 "gcc": 10, 214 "dwarf": 10, 215 }, 216 { 217 "name": "r11", 218 "bitsize": 64, 219 "offset": 88, 220 "encoding": "uint", 221 "format": "hex", 222 "set": 0, 223 "gcc": 11, 224 "dwarf": 11, 225 }, 226 { 227 "name": "r12", 228 "bitsize": 64, 229 "offset": 96, 230 "encoding": "uint", 231 "format": "hex", 232 "set": 0, 233 "gcc": 12, 234 "dwarf": 12, 235 }, 236 { 237 "name": "r13", 238 "bitsize": 64, 239 "offset": 104, 240 "encoding": "uint", 241 "format": "hex", 242 "set": 0, 243 "gcc": 13, 244 "dwarf": 13, 245 }, 246 { 247 "name": "r14", 248 "bitsize": 64, 249 "offset": 112, 250 "encoding": "uint", 251 "format": "hex", 252 "set": 0, 253 "gcc": 14, 254 "dwarf": 14, 255 }, 256 { 257 "name": "r15", 258 "bitsize": 64, 259 "offset": 120, 260 "encoding": "uint", 261 "format": "hex", 262 "set": 0, 263 "gcc": 15, 264 "dwarf": 15, 265 }, 266 { 267 "name": "rip", 268 "bitsize": 64, 269 "offset": 128, 270 "encoding": "uint", 271 "format": "hex", 272 "set": 0, 273 "gcc": 16, 274 "dwarf": 16, 275 "generic": "pc", 276 "alt-name": "pc", 277 }, 278 { 279 "name": "rflags", 280 "bitsize": 64, 281 "offset": 136, 282 "encoding": "uint", 283 "format": "hex", 284 "set": 0, 285 "generic": "flags", 286 "alt-name": "flags", 287 }, 288 { 289 "name": "cs", 290 "bitsize": 64, 291 "offset": 144, 292 "encoding": "uint", 293 "format": "hex", 294 "set": 0, 295 }, 296 { 297 "name": "fs", 298 "bitsize": 64, 299 "offset": 152, 300 "encoding": "uint", 301 "format": "hex", 302 "set": 0, 303 }, 304 { 305 "name": "gs", 306 "bitsize": 64, 307 "offset": 160, 308 "encoding": "uint", 309 "format": "hex", 310 "set": 0, 311 }, 312 ] 313 return self.registers 314 315 def get_register_data(self, tid): 316 return struct.pack( 317 "21Q", 318 tid + 1, 319 tid + 2, 320 tid + 3, 321 tid + 4, 322 tid + 5, 323 tid + 6, 324 tid + 7, 325 tid + 8, 326 tid + 9, 327 tid + 10, 328 tid + 11, 329 tid + 12, 330 tid + 13, 331 tid + 14, 332 tid + 15, 333 tid + 16, 334 tid + 17, 335 tid + 18, 336 tid + 19, 337 tid + 20, 338 tid + 21, 339 ) 340