1import sys, subprocess, os, re, time, getopt, shlex 2import lldb 3from functools import wraps 4from ctypes import c_ulonglong as uint64_t 5from ctypes import c_void_p as voidptr_t 6import code 7import core 8from core import caching 9from core.standard import * 10from core.configuration import * 11from core.kernelcore import * 12from utils import * 13from core.lazytarget import * 14 15MODULE_NAME=__name__ 16 17""" Kernel Debugging macros for lldb. 18 Please make sure you read the README COMPLETELY BEFORE reading anything below. 19 It is very critical that you read coding guidelines in Section E in README file. 20""" 21 22# End Utility functions 23# Debugging specific utility functions 24 25#decorators. Not to be called directly. 26 27def static_var(var_name, initial_value): 28 def _set_var(obj): 29 setattr(obj, var_name, initial_value) 30 return obj 31 return _set_var 32 33def header(initial_value): 34 def _set_header(obj): 35 setattr(obj, 'header', initial_value) 36 return obj 37 return _set_header 38 39# holds type declarations done by xnu. 40#DONOTTOUCHME: Exclusive use of lldb_type_summary only. 41lldb_summary_definitions = {} 42def lldb_type_summary(types_list): 43 """ A function decorator to register a summary for a type in lldb. 44 params: types_list - [] an array of types that you wish to register a summary callback function. (ex. ['task *', 'task_t']) 45 returns: Nothing. This is a decorator. 46 """ 47 def _get_summary(obj): 48 def _internal_summary_function(lldbval, internal_dict): 49 out_string= "" 50 if internal_dict != None and len(obj.header) > 0 : 51 out_string += "\n" + obj.header +"\n" 52 out_string += obj( core.value(lldbval) ) 53 return out_string 54 55 myglobals = globals() 56 summary_function_name = "LLDBSummary" + obj.__name__ 57 myglobals[summary_function_name] = _internal_summary_function 58 summary_function = myglobals[summary_function_name] 59 summary_function.__doc__ = obj.__doc__ 60 61 global lldb_summary_definitions 62 for single_type in types_list: 63 if config['showTypeSummary']: 64 if single_type in lldb_summary_definitions.keys(): 65 lldb.debugger.HandleCommand("type summary delete --category kernel \""+ single_type + "\"") 66 lldb.debugger.HandleCommand("type summary add \""+ single_type +"\" --category kernel --python-function " + MODULE_NAME + "." + summary_function_name) 67 lldb_summary_definitions[single_type] = obj 68 69 return obj 70 return _get_summary 71 72#global cache of documentation for lldb commands exported by this module 73#DONOTTOUCHME: Exclusive use of lldb_command only. 74lldb_command_documentation = {} 75 76def lldb_command(cmd_name, option_string = ''): 77 """ A function decorator to define a command with namd 'cmd_name' in the lldb scope to call python function. 78 params: cmd_name - str : name of command to be set in lldb prompt. 79 option_string - str: getopt like option string. Only CAPITAL LETTER options allowed. 80 see README on Customizing command options. 81 """ 82 if option_string != option_string.upper(): 83 raise RuntimeError("Cannot setup command with lowercase option args. %s" % option_string) 84 85 def _cmd(obj): 86 def _internal_command_function(debugger, command, result, internal_dict): 87 global config, lldb_run_command_state 88 stream = CommandOutput(result) 89 # need to avoid printing on stdout if called from lldb_run_command. 90 if 'active' in lldb_run_command_state and lldb_run_command_state['active']: 91 debuglog('Running %s from lldb_run_command' % command) 92 else: 93 result.SetImmediateOutputFile(sys.__stdout__) 94 95 command_args = shlex.split(command) 96 lldb.debugger.HandleCommand('type category disable kernel' ) 97 def_verbose_level = config['verbosity'] 98 99 try: 100 stream.setOptions(command_args, option_string) 101 if stream.verbose_level != 0: 102 config['verbosity'] += stream.verbose_level 103 with RedirectStdStreams(stdout=stream) : 104 if option_string: 105 obj(cmd_args=stream.target_cmd_args, cmd_options=stream.target_cmd_options) 106 else: 107 obj(cmd_args=stream.target_cmd_args) 108 except KeyboardInterrupt: 109 print "Execution interrupted by user" 110 except ArgumentError as arg_error: 111 if str(arg_error) != "HELP": 112 print "Argument Error: " + str(arg_error) 113 print "{0:s}:\n {1:s}".format(cmd_name, obj.__doc__.strip()) 114 return False 115 except Exception as exc: 116 if not config['debug']: 117 print """ 118************ LLDB found an exception ************ 119There has been an uncaught exception. A possible cause could be that remote connection has been disconnected. 120However, it is recommended that you report the exception to lldb/kernel debugging team about it. 121************ Please run 'xnudebug debug enable' to start collecting logs. ************ 122 """ 123 raise 124 125 if config['showTypeSummary']: 126 lldb.debugger.HandleCommand('type category enable kernel' ) 127 128 if stream.pluginRequired : 129 plugin = LoadXNUPlugin(stream.pluginName) 130 if plugin == None : 131 print "Could not load plugins."+stream.pluginName 132 return 133 plugin.plugin_init(kern, config, lldb, kern.IsDebuggerConnected()) 134 return_data = plugin.plugin_execute(cmd_name, result.GetOutput()) 135 ProcessXNUPluginResult(return_data) 136 plugin.plugin_cleanup() 137 138 #restore the verbose level after command is complete 139 config['verbosity'] = def_verbose_level 140 141 return 142 143 myglobals = globals() 144 command_function_name = obj.__name__+"Command" 145 myglobals[command_function_name] = _internal_command_function 146 command_function = myglobals[command_function_name] 147 if not obj.__doc__ : 148 print "ERROR: Cannot register command({:s}) without documentation".format(cmd_name) 149 return obj 150 command_function.__doc__ = obj.__doc__ 151 global lldb_command_documentation 152 if cmd_name in lldb_command_documentation: 153 lldb.debugger.HandleCommand("command script delete "+cmd_name) 154 lldb_command_documentation[cmd_name] = (obj.__name__, obj.__doc__.lstrip(), option_string) 155 lldb.debugger.HandleCommand("command script add -f " + MODULE_NAME + "." + command_function_name + " " + cmd_name) 156 return obj 157 return _cmd 158 159def lldb_alias(alias_name, cmd_line): 160 """ define an alias in the lldb command line. 161 A programatic way of registering an alias. This basically does 162 (lldb)command alias alias_name "cmd_line" 163 ex. 164 lldb_alias('readphys16', 'readphys 16') 165 """ 166 alias_name = alias_name.strip() 167 cmd_line = cmd_line.strip() 168 lldb.debugger.HandleCommand("command alias " + alias_name + " "+ cmd_line) 169 170def SetupLLDBTypeSummaries(reset=False): 171 global lldb_summary_definitions, MODULE_NAME 172 if reset == True: 173 lldb.debugger.HandleCommand("type category delete kernel ") 174 for single_type in lldb_summary_definitions.keys(): 175 summary_function = lldb_summary_definitions[single_type] 176 lldb_cmd = "type summary add \""+ single_type +"\" --category kernel --python-function " + MODULE_NAME + ".LLDBSummary" + summary_function.__name__ 177 debuglog(lldb_cmd) 178 lldb.debugger.HandleCommand(lldb_cmd) 179 if config['showTypeSummary']: 180 lldb.debugger.HandleCommand("type category enable kernel") 181 else: 182 lldb.debugger.HandleCommand("type category disable kernel") 183 184 return 185 186def LoadXNUPlugin(name): 187 """ Try to load a plugin from the plugins directory. 188 """ 189 retval = None 190 name=name.strip() 191 try: 192 module_obj = __import__('plugins.'+name, globals(), locals(), [], -1) 193 module_obj = module_obj.__dict__[name] 194 defs = dir(module_obj) 195 if 'plugin_init' in defs and 'plugin_execute' in defs and 'plugin_cleanup' in defs: 196 retval = module_obj 197 else: 198 print "Plugin is not correctly implemented. Please read documentation on implementing plugins" 199 except: 200 print "plugin not found :"+name 201 202 return retval 203 204def ProcessXNUPluginResult(result_data): 205 """ Look at the returned data from plugin and see if anymore actions are required or not 206 params: result_data - list of format (status, out_string, more_commands) 207 """ 208 ret_status = result_data[0] 209 ret_string = result_data[1] 210 ret_commands = result_data[2] 211 212 if ret_status == False: 213 print "Plugin failed: " + ret_string 214 return 215 print ret_string 216 if len(ret_commands) >= 0: 217 for cmd in ret_commands: 218 print "Running command on behalf of plugin:" + cmd 219 lldb.debugger.HandleCommand(cmd) 220 return 221 222# holds tests registered with xnu. 223#DONOTTOUCHME: Exclusive use of xnudebug_test only 224lldb_command_tests = {} 225def xnudebug_test(test_name): 226 """ A function decoratore to register a test with the framework. Each test is supposed to be of format 227 def Test<name>(kernel_target, config, lldb_obj, isConnected ) 228 229 NOTE: The testname should start with "Test" else exception will be raised. 230 """ 231 def _test(obj): 232 global lldb_command_tests 233 if obj.__name__.find("Test") != 0 : 234 print "Test name ", obj.__name__ , " should start with Test" 235 raise ValueError 236 lldb_command_tests[test_name] = (test_name, obj.__name__, obj, obj.__doc__) 237 return obj 238 return _test 239 240 241# End Debugging specific utility functions 242# Kernel Debugging specific classes and accessor methods 243 244# global access object for target kernel 245 246def GetObjectAtIndexFromArray(array_base, index): 247 """ Subscript indexing for arrays that are represented in C as pointers. 248 for ex. int *arr = malloc(20*sizeof(int)); 249 now to get 3rd int from 'arr' you'd do 250 arr[2] in C 251 GetObjectAtIndexFromArray(arr_val,2) 252 params: 253 array_base : core.value - representing a pointer type (ex. base of type 'ipc_entry *') 254 index : int - 0 based index into the array 255 returns: 256 core.value : core.value of the same type as array_base_val but pointing to index'th element 257 """ 258 array_base_val = array_base.GetSBValue() 259 base_address = array_base_val.GetValueAsUnsigned() 260 size = array_base_val.GetType().GetPointeeType().GetByteSize() 261 obj_address = base_address + (index * size) 262 obj = kern.GetValueFromAddress(obj_address, array_base_val.GetType().GetName()) 263 return Cast(obj, array_base_val.GetType()) 264 265 266kern = None 267 268def GetLLDBThreadForKernelThread(thread_obj): 269 """ Get a reference to lldb.SBThread representation for kernel thread. 270 params: 271 thread_obj : core.cvalue - thread object of type thread_t 272 returns 273 lldb.SBThread - lldb thread object for getting backtrace/registers etc. 274 """ 275 tid = unsigned(thread_obj.thread_id) 276 lldb_process = LazyTarget.GetProcess() 277 sbthread = lldb_process.GetThreadByID(tid) 278 if not sbthread.IsValid(): 279 # in case lldb doesnt know about this thread, create one 280 if hasattr(lldb_process, "CreateOSPluginThread"): 281 debuglog("creating os plugin thread on the fly for {0:d} 0x{1:x}".format(tid, thread_obj)) 282 lldb_process.CreateOSPluginThread(tid, unsigned(thread_obj)) 283 else: 284 raise RuntimeError("LLDB process does not support CreateOSPluginThread.") 285 sbthread = lldb_process.GetThreadByID(tid) 286 287 if not sbthread.IsValid(): 288 raise RuntimeError("Unable to find lldb thread for tid={0:d} thread = {1:#018x} (#16049947: have you put 'settings set target.load-script-from-symbol-file true' in your .lldbinit?)".format(tid, thread_obj)) 289 290 return sbthread 291 292def GetThreadBackTrace(thread_obj, verbosity = vHUMAN, prefix = ""): 293 """ Get a string to display back trace for a thread. 294 params: 295 thread_obj - core.cvalue : a thread object of type thread_t. 296 verbosity - int : either of vHUMAN, vSCRIPT or vDETAIL to describe the verbosity of output 297 prefix - str : a string prefix added before the line for each frame. 298 isContinuation - bool : is thread a continuation? 299 returns: 300 str - a multi line string showing each frame in backtrace. 301 """ 302 is_continuation = not bool(unsigned(thread_obj.kernel_stack)) 303 thread_val = GetLLDBThreadForKernelThread(thread_obj) 304 out_string = "" 305 kernel_stack = unsigned(thread_obj.kernel_stack) 306 reserved_stack = unsigned(thread_obj.reserved_stack) 307 if not is_continuation: 308 if kernel_stack and reserved_stack: 309 out_string += prefix + "reserved_stack = {:#018x}\n".format(reserved_stack) 310 out_string += prefix + "kernel_stack = {:#018x}\n".format(kernel_stack) 311 else: 312 out_string += prefix + "continuation =" 313 iteration = 0 314 last_frame_p = 0 315 for frame in thread_val.frames: 316 addr = frame.GetPCAddress() 317 load_addr = addr.GetLoadAddress(LazyTarget.GetTarget()) 318 function = frame.GetFunction() 319 frame_p = frame.GetFP() 320 mod_name = frame.GetModule().GetFileSpec().GetFilename() 321 322 if iteration == 0 and not is_continuation: 323 out_string += prefix +"stacktop = {:#018x}\n".format(frame_p) 324 325 if not function: 326 # No debug info for 'function'. 327 out_string += prefix 328 if not is_continuation: 329 out_string += "{fp:#018x} ".format(fp = frame_p) 330 331 symbol = frame.GetSymbol() 332 if not symbol: 333 symbol_name = "None" 334 symbol_offset = load_addr 335 kmod_val = kern.globals.kmod 336 for kval in IterateLinkedList(kmod_val, 'next'): 337 if load_addr >= unsigned(kval.address) and \ 338 load_addr <= (unsigned(kval.address) + unsigned(kval.size)): 339 symbol_name = kval.name 340 symbol_offset = load_addr - unsigned(kval.address) 341 break 342 out_string += "{:#018x} {:s} + {:#x} \n".format(load_addr, symbol_name, symbol_offset) 343 else: 344 file_addr = addr.GetFileAddress() 345 start_addr = symbol.GetStartAddress().GetFileAddress() 346 symbol_name = symbol.GetName() 347 symbol_offset = file_addr - start_addr 348 out_string += "{addr:#018x} {mod}`{symbol} + {offset:#x} \n".format(addr=load_addr, 349 mod=mod_name, symbol=symbol_name, offset=symbol_offset) 350 else: 351 # Debug info is available for 'function'. 352 func_name = frame.GetFunctionName() 353 file_name = frame.GetLineEntry().GetFileSpec().GetFilename() 354 line_num = frame.GetLineEntry().GetLine() 355 func_name = '%s [inlined]' % func_name if frame.IsInlined() else func_name 356 if is_continuation and frame.IsInlined(): 357 debuglog("Skipping frame for thread {:#018x} since its inlined".format(thread_obj)) 358 continue 359 out_string += prefix 360 if not is_continuation: 361 out_string += "{fp:#018x} ".format(fp=frame_p) 362 out_string += "{addr:#018x} {func}{args} \n".format(addr=load_addr, 363 func=func_name, 364 file=file_name, line=line_num, 365 args="(" + (str(frame.arguments).replace("\n", ", ") if len(frame.arguments) > 0 else "void") + ")") 366 iteration += 1 367 if frame_p: 368 last_frame_p = frame_p 369 370 if not is_continuation and last_frame_p: 371 out_string += prefix + "stackbottom = {:#018x}".format(last_frame_p) 372 out_string = out_string.replace("variable not available","") 373 return out_string 374 375def GetSourceInformationForAddress(addr): 376 """ convert and address to function +offset information. 377 params: addr - int address in the binary to be symbolicated 378 returns: string of format "0xaddress: function + offset" 379 """ 380 symbols = kern.SymbolicateFromAddress(addr) 381 format_string = "{0:#018x} <{1:s} + {2:#0x}>" 382 offset = 0 383 function_name = "" 384 if len(symbols) > 0: 385 s = symbols[0] 386 function_name = str(s.name) 387 offset = addr - s.GetStartAddress().GetLoadAddress(LazyTarget.GetTarget()) 388 if function_name == "": 389 function_name = "???" 390 return format_string.format(addr, function_name, offset) 391 392def GetFrameLocalVariable(variable_name, frame_no=0): 393 """ Find a local variable by name 394 params: 395 variable_name: str - name of variable to search for 396 returns: 397 core.value - if the variable is found. 398 None - if not found or not Valid 399 """ 400 retval = None 401 sbval = None 402 lldb_SBThread = LazyTarget.GetProcess().GetSelectedThread() 403 frame = lldb_SBThread.GetSelectedFrame() 404 if frame_no : 405 frame = lldb_SBThread.GetFrameAtIndex(frame_no) 406 if frame : 407 sbval = frame.FindVariable(variable_name) 408 if sbval and sbval.IsValid(): 409 retval = core.cvalue.value(sbval) 410 return retval 411 412# Begin Macros for kernel debugging 413 414@lldb_command('kgmhelp') 415def KernelDebugCommandsHelp(cmd_args=None): 416 """ Show a list of registered commands for kenel debugging. 417 """ 418 global lldb_command_documentation 419 print "List of commands provided by " + MODULE_NAME + " for kernel debugging." 420 cmds = lldb_command_documentation.keys() 421 cmds.sort() 422 for cmd in cmds: 423 if type(lldb_command_documentation[cmd][-1]) == type(""): 424 print " {0: <20s} - {1}".format(cmd , lldb_command_documentation[cmd][1].split("\n")[0].strip()) 425 else: 426 print " {0: <20s} - {1}".format(cmd , "No help string found.") 427 print """ 428 Each of the functions listed here accept the following common options. 429 -h Show the help string for the command. 430 -o <path/to/filename> The output of this command execution will be saved to file. Parser information or errors will 431 not be sent to file though. eg /tmp/output.txt 432 -s <filter_string> The "filter_string" param is parsed to python regex expression and each line of output 433 will be printed/saved only if it matches the expression. 434 -v [-v...] Each additional -v will increase the verbosity of the command. 435 -p <plugin_name> Send the output of the command to plugin. Please see README for usage of plugins. 436 437 Additionally, each command implementation may have more options. "(lldb) help <command> " will show these options. 438 """ 439 return None 440 441 442@lldb_command('showraw') 443def ShowRawCommand(cmd_args=None): 444 """ A command to disable the kernel summaries and show data as seen by the system. 445 This is useful when trying to read every field of a struct as compared to brief summary 446 """ 447 command = " ".join(cmd_args) 448 lldb.debugger.HandleCommand('type category disable kernel' ) 449 lldb.debugger.HandleCommand( command ) 450 lldb.debugger.HandleCommand('type category enable kernel' ) 451 452 453@lldb_command('xnudebug') 454def XnuDebugCommand(cmd_args=None): 455 """ command interface for operating on the xnu macros. Allowed commands are as follows 456 reload: 457 Reload a submodule from the xnu/tools/lldb directory. Do not include the ".py" suffix in modulename. 458 usage: xnudebug reload <modulename> (eg. memory, process, stats etc) 459 test: 460 Start running registered test with <name> from various modules. 461 usage: xnudebug test <name> (eg. test_memstats) 462 testall: 463 Go through all registered tests and run them 464 debug: 465 Toggle state of debug configuration flag. 466 """ 467 global config 468 command_args = cmd_args 469 if len(command_args) == 0: 470 raise ArgumentError("No command specified.") 471 supported_subcommands = ['debug', 'reload', 'test', 'testall'] 472 subcommand = GetLongestMatchOption(command_args[0], supported_subcommands, True) 473 474 if len(subcommand) == 0: 475 raise ArgumentError("Subcommand (%s) is not a valid command. " % str(command_args[0])) 476 477 subcommand = subcommand[0].lower() 478 if subcommand == 'debug': 479 if command_args[-1].lower().find('dis') >=0 and config['debug']: 480 config['debug'] = False 481 print "Disabled debug logging." 482 elif command_args[-1].lower().find('dis') < 0 and not config['debug']: 483 config['debug'] = True 484 EnableLLDBAPILogging() # provided by utils.py 485 print "Enabled debug logging. \nPlease run 'xnudebug debug disable' to disable it again. " 486 487 if subcommand == 'reload': 488 module_name = command_args[-1] 489 if module_name in sys.modules: 490 reload(sys.modules[module_name]) 491 print module_name + " is reloaded from " + sys.modules[module_name].__file__ 492 else: 493 print "Unable to locate module named ", module_name 494 if subcommand == 'testall': 495 for test_name in lldb_command_tests.keys(): 496 print "[BEGIN]", test_name 497 res = lldb_command_tests[test_name][2](kern, config, lldb, True) 498 if res: 499 print "[PASSED] {:s}".format(test_name) 500 else: 501 print "[FAILED] {:s}".format(test_name) 502 if subcommand == 'test': 503 test_name = command_args[-1] 504 if test_name in lldb_command_tests: 505 test = lldb_command_tests[test_name] 506 print "Running test {:s}".format(test[0]) 507 if test[2](kern, config, lldb, True) : 508 print "[PASSED] {:s}".format(test[0]) 509 else: 510 print "[FAILED] {:s}".format(test[0]) 511 return "" 512 else: 513 print "No such test registered with name: {:s}".format(test_name) 514 print "XNUDEBUG Available tests are:" 515 for i in lldb_command_tests.keys(): 516 print i 517 return None 518 519 return False 520 521@lldb_command('showversion') 522def ShowVersion(cmd_args=None): 523 """ Read the kernel version string from a fixed address in low 524 memory. Useful if you don't know which kernel is on the other end, 525 and need to find the appropriate symbols. Beware that if you've 526 loaded a symbol file, but aren't connected to a remote target, 527 the version string from the symbol file will be displayed instead. 528 This macro expects to be connected to the remote kernel to function 529 correctly. 530 531 """ 532 print kern.version 533 534 535@lldb_command('paniclog') 536def ShowPanicLog(cmd_args=None): 537 """ Display the paniclog information 538 usage: (lldb) paniclog 539 options: 540 -v : increase verbosity 541 """ 542 panic_buf = kern.globals.debug_buf_addr 543 panic_buf_start = unsigned(panic_buf) 544 panic_buf_end = unsigned(kern.globals.debug_buf_ptr) 545 num_bytes = panic_buf_end - panic_buf_start 546 if num_bytes == 0 : 547 return 548 warn_str = "" 549 if num_bytes > 4096 and config['verbosity'] == vHUMAN: 550 num_bytes = 4096 551 warn_str = "LLDBMacro Warning: The paniclog is too large. Trimming to 4096 bytes." 552 warn_str += " If you wish to see entire log please use '-v' argument." 553 out_str = "" 554 for i in range(num_bytes): 555 p_char = str(panic_buf[i]) 556 out_str += p_char 557 if p_char == '\n': 558 print out_str 559 out_str = "" 560 if warn_str: 561 print warn_str 562 return 563 564@lldb_command('showbootargs') 565def ShowBootArgs(cmd_args=None): 566 """ Display boot arguments passed to the target kernel 567 """ 568 bootargs = Cast(kern.GetGlobalVariable('PE_state').bootArgs, 'boot_args *') 569 bootargs_cmd = bootargs.CommandLine 570 print str(bootargs_cmd) 571 572@static_var("last_process_uniq_id", 1) 573def GetDebuggerStopIDValue(): 574 """ Create a unique session identifier. 575 returns: 576 int - a unique number identified by processid and stopid. 577 """ 578 stop_id = 0 579 process_obj = LazyTarget.GetProcess() 580 if hasattr(process_obj, "GetStopID"): 581 stop_id = process_obj.GetStopID() 582 proc_uniq_id = 0 583 if hasattr(process_obj, 'GetUniqueID'): 584 proc_uniq_id = process_obj.GetUniqueID() 585 #FIXME <rdar://problem/13034329> forces us to do this twice 586 proc_uniq_id = process_obj.GetUniqueID() 587 else: 588 GetDebuggerStopIDValue.last_process_uniq_id +=1 589 proc_uniq_id = GetDebuggerStopIDValue.last_process_uniq_id + 1 590 591 stop_id_str = "{:d}:{:d}".format(proc_uniq_id, stop_id) 592 return hash(stop_id_str) 593 594# The initialization code to add your commands 595_xnu_framework_init = False 596def __lldb_init_module(debugger, internal_dict): 597 global kern, lldb_command_documentation, config, _xnu_framework_init 598 if _xnu_framework_init: 599 return 600 _xnu_framework_init = True 601 caching._GetDebuggerSessionID = GetDebuggerStopIDValue 602 debugger.HandleCommand('type summary add --regex --summary-string "${var%s}" -C yes -p -v "char \[[0-9]*\]"') 603 debugger.HandleCommand('type format add --format hex -C yes uintptr_t') 604 kern = KernelTarget(debugger) 605 print "xnu debug macros loaded successfully. Run showlldbtypesummaries to enable type summaries." 606 607__lldb_init_module(lldb.debugger, None) 608 609@lldb_command("showlldbtypesummaries") 610def ShowLLDBTypeSummaries(cmd_args=[]): 611 """ Enable/Disable kernel type summaries. Default is disabled. 612 Usage: showlldbtypesummaries [enable|disable] 613 default is enable 614 """ 615 global config 616 action = "enable" 617 trailer_msg = '' 618 if len(cmd_args) > 0 and cmd_args[0].lower().find('disable') >=0: 619 action = "disable" 620 config['showTypeSummary'] = False 621 trailer_msg = "Please run 'showlldbtypesummaries enable' to enable the summary feature." 622 else: 623 config['showTypeSummary'] = True 624 SetupLLDBTypeSummaries(True) 625 trailer_msg = "Please run 'showlldbtypesummaries disable' to disable the summary feature." 626 lldb_run_command("type category "+ action +" kernel") 627 print "Successfully "+action+"d the kernel type summaries. %s" % trailer_msg 628 629@lldb_command('walkqueue_head', 'S') 630def WalkQueueHead(cmd_args=[], cmd_options={}): 631 """ walk a queue_head_t and list all members in it. Note this is for queue_head_t. refer to osfmk/kern/queue.h 632 Option: -S - suppress summary output. 633 Usage: (lldb) walkqueue_head <queue_entry *> <struct type> <fieldname> 634 ex: (lldb) walkqueue_head 0x7fffff80 "thread *" "task_threads" 635 636 """ 637 global lldb_summary_definitions 638 if not cmd_args: 639 raise ArgumentError("invalid arguments") 640 if len(cmd_args) != 3: 641 raise ArgumentError("insufficient arguments") 642 queue_head = kern.GetValueFromAddress(cmd_args[0], 'struct queue_entry *') 643 el_type = cmd_args[1] 644 field_name = cmd_args[2] 645 showsummary = False 646 if el_type in lldb_summary_definitions: 647 showsummary = True 648 if '-S' in cmd_options: 649 showsummary = False 650 651 for i in IterateQueue(queue_head, el_type, field_name): 652 if showsummary: 653 print lldb_summary_definitions[el_type](i) 654 else: 655 print "{0: <#020x}".format(i) 656 657 658 659@lldb_command('walklist_entry', 'S') 660def WalkList(cmd_args=[], cmd_options={}): 661 """ iterate over a list as defined with LIST_ENTRY in bsd/sys/queue.h 662 params: 663 object addr - value : address of object 664 element_type - str : Type of the next element 665 field_name - str : Name of the field in next element's structure 666 667 Option: -S - suppress summary output. 668 Usage: (lldb) walklist_entry <obj with list_entry *> <struct type> <fieldname> 669 ex: (lldb) walklist_entry 0x7fffff80 "struct proc *" "p_sibling" 670 671 """ 672 global lldb_summary_definitions 673 if not cmd_args: 674 raise ArgumentError("invalid arguments") 675 if len(cmd_args) != 3: 676 raise ArgumentError("insufficient arguments") 677 el_type = cmd_args[1] 678 queue_head = kern.GetValueFromAddress(cmd_args[0], el_type) 679 field_name = cmd_args[2] 680 681 showsummary = False 682 if el_type in lldb_summary_definitions: 683 showsummary = True 684 if '-S' in cmd_options: 685 showsummary = False 686 elt = queue_head 687 while unsigned(elt) != 0: 688 i = elt 689 elt = elt.__getattr__(field_name).le_next 690 if showsummary: 691 print lldb_summary_definitions[el_type](i) 692 else: 693 print "{0: <#020x}".format(i) 694 695 696 697from memory import * 698from process import * 699from ipc import * 700from pmap import * 701from ioreg import * 702from mbufs import * 703from net import * 704from kdp import * 705from userspace import * 706from pci import * 707from misc import * 708from apic import * 709from scheduler import * 710from atm import * 711from structanalyze import * 712from ipcimportancedetail import * 713from bank import * 714 715