447 lines · python
1#!/usr/bin/env python2 3import lldb4import struct5 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 the14 first time."""15 self.process = None16 self.registers = None17 self.threads = None18 if isinstance(process, lldb.SBProcess) and process.IsValid():19 self.process = process20 self.threads = None # Will be an dictionary containing info for each thread21 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 the25 # correct thing to use for this plug-in.26 return self.process.target27 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_info39 return None40 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 thread44 # 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 breakpoint51 # 'none' thread is just stopped because the process is stopped52 # 'trace' the thread just single stepped53 # 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 contiguous57 # in memory. Don't specify this if your register layout in memory doesn't match the layout58 # described by the dictionary returned from a call to the59 # 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 "register_data_addr": 0x100000000,82 },83 ]84 return self.threads85 86 def get_register_info(self):87 if self.registers is None:88 self.registers = dict()89 triple = self.process.target.triple90 if triple:91 arch = triple.split("-")[0]92 if arch == "x86_64":93 self.registers["sets"] = ["GPR", "FPU", "EXC"]94 self.registers["registers"] = [95 {96 "name": "rax",97 "bitsize": 64,98 "offset": 0,99 "encoding": "uint",100 "format": "hex",101 "set": 0,102 "gcc": 0,103 "dwarf": 0,104 },105 {106 "name": "rbx",107 "bitsize": 64,108 "offset": 8,109 "encoding": "uint",110 "format": "hex",111 "set": 0,112 "gcc": 3,113 "dwarf": 3,114 },115 {116 "name": "rcx",117 "bitsize": 64,118 "offset": 16,119 "encoding": "uint",120 "format": "hex",121 "set": 0,122 "gcc": 2,123 "dwarf": 2,124 "generic": "arg4",125 "alt-name": "arg4",126 },127 {128 "name": "rdx",129 "bitsize": 64,130 "offset": 24,131 "encoding": "uint",132 "format": "hex",133 "set": 0,134 "gcc": 1,135 "dwarf": 1,136 "generic": "arg3",137 "alt-name": "arg3",138 },139 {140 "name": "rdi",141 "bitsize": 64,142 "offset": 32,143 "encoding": "uint",144 "format": "hex",145 "set": 0,146 "gcc": 5,147 "dwarf": 5,148 "generic": "arg1",149 "alt-name": "arg1",150 },151 {152 "name": "rsi",153 "bitsize": 64,154 "offset": 40,155 "encoding": "uint",156 "format": "hex",157 "set": 0,158 "gcc": 4,159 "dwarf": 4,160 "generic": "arg2",161 "alt-name": "arg2",162 },163 {164 "name": "rbp",165 "bitsize": 64,166 "offset": 48,167 "encoding": "uint",168 "format": "hex",169 "set": 0,170 "gcc": 6,171 "dwarf": 6,172 "generic": "fp",173 "alt-name": "fp",174 },175 {176 "name": "rsp",177 "bitsize": 64,178 "offset": 56,179 "encoding": "uint",180 "format": "hex",181 "set": 0,182 "gcc": 7,183 "dwarf": 7,184 "generic": "sp",185 "alt-name": "sp",186 },187 {188 "name": "r8",189 "bitsize": 64,190 "offset": 64,191 "encoding": "uint",192 "format": "hex",193 "set": 0,194 "gcc": 8,195 "dwarf": 8,196 "generic": "arg5",197 "alt-name": "arg5",198 },199 {200 "name": "r9",201 "bitsize": 64,202 "offset": 72,203 "encoding": "uint",204 "format": "hex",205 "set": 0,206 "gcc": 9,207 "dwarf": 9,208 "generic": "arg6",209 "alt-name": "arg6",210 },211 {212 "name": "r10",213 "bitsize": 64,214 "offset": 80,215 "encoding": "uint",216 "format": "hex",217 "set": 0,218 "gcc": 10,219 "dwarf": 10,220 },221 {222 "name": "r11",223 "bitsize": 64,224 "offset": 88,225 "encoding": "uint",226 "format": "hex",227 "set": 0,228 "gcc": 11,229 "dwarf": 11,230 },231 {232 "name": "r12",233 "bitsize": 64,234 "offset": 96,235 "encoding": "uint",236 "format": "hex",237 "set": 0,238 "gcc": 12,239 "dwarf": 12,240 },241 {242 "name": "r13",243 "bitsize": 64,244 "offset": 104,245 "encoding": "uint",246 "format": "hex",247 "set": 0,248 "gcc": 13,249 "dwarf": 13,250 },251 {252 "name": "r14",253 "bitsize": 64,254 "offset": 112,255 "encoding": "uint",256 "format": "hex",257 "set": 0,258 "gcc": 14,259 "dwarf": 14,260 },261 {262 "name": "r15",263 "bitsize": 64,264 "offset": 120,265 "encoding": "uint",266 "format": "hex",267 "set": 0,268 "gcc": 15,269 "dwarf": 15,270 },271 {272 "name": "rip",273 "bitsize": 64,274 "offset": 128,275 "encoding": "uint",276 "format": "hex",277 "set": 0,278 "gcc": 16,279 "dwarf": 16,280 "generic": "pc",281 "alt-name": "pc",282 },283 {284 "name": "rflags",285 "bitsize": 64,286 "offset": 136,287 "encoding": "uint",288 "format": "hex",289 "set": 0,290 "generic": "flags",291 "alt-name": "flags",292 },293 {294 "name": "cs",295 "bitsize": 64,296 "offset": 144,297 "encoding": "uint",298 "format": "hex",299 "set": 0,300 },301 {302 "name": "fs",303 "bitsize": 64,304 "offset": 152,305 "encoding": "uint",306 "format": "hex",307 "set": 0,308 },309 {310 "name": "gs",311 "bitsize": 64,312 "offset": 160,313 "encoding": "uint",314 "format": "hex",315 "set": 0,316 },317 ]318 return self.registers319 320 def get_register_data(self, tid):321 if tid == 0x111111111:322 return struct.pack(323 "21Q",324 1,325 2,326 3,327 4,328 5,329 6,330 7,331 8,332 9,333 10,334 11,335 12,336 13,337 14,338 15,339 16,340 17,341 18,342 19,343 20,344 21,345 )346 elif tid == 0x222222222:347 return struct.pack(348 "21Q",349 11,350 12,351 13,352 14,353 15,354 16,355 17,356 18,357 19,358 110,359 111,360 112,361 113,362 114,363 115,364 116,365 117,366 118,367 119,368 120,369 121,370 )371 elif tid == 0x333333333:372 return struct.pack(373 "21Q",374 21,375 22,376 23,377 24,378 25,379 26,380 27,381 28,382 29,383 210,384 211,385 212,386 213,387 214,388 215,389 216,390 217,391 218,392 219,393 220,394 221,395 )396 elif tid == 0x444444444:397 return struct.pack(398 "21Q",399 31,400 32,401 33,402 34,403 35,404 36,405 37,406 38,407 39,408 310,409 311,410 312,411 313,412 314,413 315,414 316,415 317,416 318,417 319,418 320,419 321,420 )421 else:422 return struct.pack(423 "21Q",424 41,425 42,426 43,427 44,428 45,429 46,430 47,431 48,432 49,433 410,434 411,435 412,436 413,437 414,438 415,439 416,440 417,441 418,442 419,443 420,444 421,445 )446 return None447