1 import sys
, subprocess
, os
, re
, time
, getopt
, shlex
 
   3 from functools 
import wraps
 
   4 from ctypes 
import c_ulonglong 
as uint64_t
 
   5 from ctypes 
import c_void_p 
as voidptr_t
 
   8 from core 
import caching
 
   9 from core
.standard 
import * 
  10 from core
.configuration 
import * 
  11 from core
.kernelcore 
import * 
  13 from core
.lazytarget 
import * 
  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.  
  22 # End Utility functions 
  23 # Debugging specific utility functions  
  25 #decorators. Not to be called directly. 
  27 def static_var(var_name
, initial_value
): 
  29         setattr(obj
, var_name
, initial_value
) 
  33 def header(initial_value
): 
  35         setattr(obj
, 'header', initial_value
) 
  39 # holds type declarations done by xnu.  
  40 #DONOTTOUCHME: Exclusive use of lldb_type_summary only. 
  41 lldb_summary_definitions 
= {}  
  42 def 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. 
  47     def _get_summary(obj
): 
  48         def _internal_summary_function(lldbval
, internal_dict
): 
  50             if internal_dict 
!= None and len(obj
.header
) > 0 : 
  51                 out_string 
+= "\n" + obj
.header 
+"\n" 
  52             out_string 
+= obj( core
.value(lldbval
) ) 
  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
__ 
  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
 
  72 #global cache of documentation for lldb commands exported by this module  
  73 #DONOTTOUCHME: Exclusive use of lldb_command only. 
  74 lldb_command_documentation 
= {} 
  76 def 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. 
  82     if option_string 
!= option_string
.upper(): 
  83         raise RuntimeError("Cannot setup command with lowercase option args. %s" % option_string
) 
  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
) 
  93                 result
.SetImmediateOutputFile(sys
.__stdout
__) 
  95             command_args 
= shlex
.split(command
) 
  96             lldb
.debugger
.HandleCommand('type category disable kernel' ) 
  97             def_verbose_level 
= config
['verbosity'] 
 100                 stream
.setOptions(command_args
, option_string
) 
 101                 if stream
.verbose_level 
!= 0: 
 102                     config
['verbosity'] = stream
.verbose_level 
 
 103                 with RedirectStdStreams(stdout
=stream
) : 
 105                         obj(cmd_args
=stream
.target_cmd_args
, cmd_options
=stream
.target_cmd_options
) 
 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()) 
 115             except Exception as exc
: 
 116                 if not config
['debug']: 
 118 ************ LLDB found an exception ************ 
 119 There has been an uncaught exception. A possible cause could be that remote connection has been disconnected. 
 120 However, 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. ************ 
 125             if config
['showTypeSummary']: 
 126                 lldb
.debugger
.HandleCommand('type category enable kernel' ) 
 128             if stream
.pluginRequired 
: 
 129                 plugin 
= LoadXNUPlugin(stream
.pluginName
) 
 131                     print "Could not load plugins."+stream
.pluginName
 
 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() 
 138             #restore the verbose level after command is complete 
 139             config
['verbosity'] = def_verbose_level
 
 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
] 
 148             print "ERROR: Cannot register command({:s}) without documentation".format(cmd_name
) 
 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
) 
 159 def 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" 
 164         lldb_alias('readphys16', 'readphys 16') 
 166     alias_name 
= alias_name
.strip() 
 167     cmd_line 
= cmd_line
.strip() 
 168     lldb
.debugger
.HandleCommand("command alias " + alias_name 
+ " "+ cmd_line
) 
 170 def SetupLLDBTypeSummaries(reset
=False): 
 171     global lldb_summary_definitions
, MODULE_NAME
 
 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
__ 
 178         lldb
.debugger
.HandleCommand(lldb_cmd
) 
 179     if config
['showTypeSummary']: 
 180             lldb
.debugger
.HandleCommand("type category enable  kernel") 
 182             lldb
.debugger
.HandleCommand("type category disable kernel") 
 186 def LoadXNUPlugin(name
): 
 187     """ Try to load a plugin from the plugins directory.  
 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
: 
 198             print "Plugin is not correctly implemented. Please read documentation on implementing plugins" 
 200         print "plugin not found :"+name
 
 204 def 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) 
 208     ret_status 
= result_data
[0] 
 209     ret_string 
= result_data
[1] 
 210     ret_commands 
= result_data
[2] 
 212     if ret_status 
== False: 
 213         print "Plugin failed: " + 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
) 
 222 # holds tests registered with xnu. 
 223 #DONOTTOUCHME: Exclusive use of xnudebug_test only 
 224 lldb_command_tests 
= {} 
 225 def 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 ) 
 229         NOTE: The testname should start with "Test" else exception will be raised. 
 232         global lldb_command_tests
 
 233         if obj
.__name
__.find("Test") != 0 : 
 234             print "Test name ", obj
.__name
__ , " should start with Test"  
 236         lldb_command_tests
[test_name
] = (test_name
, obj
.__name
__, obj
, obj
.__doc
__) 
 241 # End Debugging specific utility functions 
 242 # Kernel Debugging specific classes and accessor methods  
 244 # global access object for target kernel 
 246 def 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  
 251         GetObjectAtIndexFromArray(arr_val,2) 
 253             array_base : core.value - representing a pointer type (ex. base of type 'ipc_entry *') 
 254             index : int - 0 based index into the array 
 256             core.value : core.value of the same type as array_base_val but pointing to index'th element 
 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()) 
 268 def GetLLDBThreadForKernelThread(thread_obj
): 
 269     """ Get a reference to lldb.SBThread representation for kernel thread. 
 271             thread_obj : core.cvalue - thread object of type thread_t  
 273             lldb.SBThread - lldb thread object for getting backtrace/registers etc. 
 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
)) 
 284             raise RuntimeError("LLDB process does not support CreateOSPluginThread.") 
 285         sbthread 
= lldb_process
.GetThreadByID(tid
) 
 287     if not sbthread
.IsValid(): 
 288         raise RuntimeError("Unable to find lldb thread for tid={0:d} thread = {1:#018x}".format(tid
, thread_obj
)) 
 292 def GetThreadBackTrace(thread_obj
, verbosity 
= vHUMAN
, prefix 
= ""): 
 293     """ Get a string to display back trace for a thread. 
 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? 
 300             str - a multi line string showing each frame in backtrace. 
 302     is_continuation 
= not bool(unsigned(thread_obj
.kernel_stack
)) 
 303     thread_val 
= GetLLDBThreadForKernelThread(thread_obj
) 
 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
) 
 312         out_string 
+= prefix 
+ "continuation =" 
 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() 
 322         if iteration 
== 0 and not is_continuation
: 
 323             out_string 
+= prefix 
+"stacktop = {:#018x}\n".format(frame_p
) 
 326             # No debug info for 'function'. 
 327             symbol 
= frame
.GetSymbol() 
 328             file_addr 
= addr
.GetFileAddress() 
 329             start_addr 
= symbol
.GetStartAddress().GetFileAddress() 
 330             symbol_name 
= symbol
.GetName() 
 331             symbol_offset 
= file_addr 
- start_addr
 
 333             if not is_continuation
: 
 334                 out_string 
+= "{fp:#018x} ".format(fp 
= frame_p
)  
 335             out_string 
+= "{addr:#018x} {mod}`{symbol} + {offset} \n".format(addr
=load_addr
, mod
=mod_name
, symbol
=symbol_name
, offset
=symbol_offset
) 
 337             # Debug info is available for 'function'. 
 338             func_name 
= frame
.GetFunctionName() 
 339             file_name 
= frame
.GetLineEntry().GetFileSpec().GetFilename() 
 340             line_num 
= frame
.GetLineEntry().GetLine() 
 341             func_name 
= '%s [inlined]' % func_name 
if frame
.IsInlined() else func_name
 
 342             if is_continuation 
and frame
.IsInlined(): 
 343                 debuglog("Skipping frame for thread {:#018x} since its inlined".format(thread_obj
)) 
 346             if not is_continuation
: 
 347                 out_string 
+= "{fp:#018x} ".format(fp
=frame_p
) 
 348             out_string 
+= "{addr:#018x} {func}{args} \n".format(addr
=load_addr
, 
 350                                     file=file_name
, line
=line_num
, 
 351                                     args
="(" + (str(frame
.arguments
).replace("\n", ", ") if len(frame
.arguments
) > 0 else "void") + ")") 
 354             last_frame_p 
= frame_p
 
 356     if not is_continuation 
and last_frame_p
: 
 357         out_string 
+= prefix 
+ "stackbottom = {:#018x}".format(last_frame_p
) 
 358     out_string 
= out_string
.replace("variable not available","") 
 361 def GetSourceInformationForAddress(addr
): 
 362     """ convert and address to function +offset information.  
 363         params: addr - int address in the binary to be symbolicated 
 364         returns: string of format "0xaddress: function + offset"  
 366     symbols 
= kern
.SymbolicateFromAddress(addr
) 
 367     format_string 
= "{0:#018x} <{1:s} + {2:#0x}>" 
 372         function_name 
= str(s
.name
) 
 373         offset 
= addr 
- s
.GetStartAddress().GetLoadAddress(LazyTarget
.GetTarget()) 
 374     if function_name 
== "": 
 375         function_name 
= "???" 
 376     return format_string
.format(addr
, function_name
, offset
) 
 378 def GetFrameLocalVariable(variable_name
, frame_no
=0): 
 379     """ Find a local variable by name 
 381           variable_name: str - name of variable to search for 
 383           core.value - if the variable is found. 
 384           None   - if not found or not Valid 
 388     lldb_SBThread 
= LazyTarget
.GetProcess().GetSelectedThread() 
 389     frame 
= lldb_SBThread
.GetSelectedFrame() 
 391       frame 
= lldb_SBThread
.GetFrameAtIndex(frame_no
) 
 393       sbval 
= frame
.FindVariable(variable_name
) 
 394     if sbval 
and sbval
.IsValid(): 
 395       retval 
= core
.cvalue
.value(sbval
) 
 398 # Begin Macros for kernel debugging 
 400 @lldb_command('kgmhelp') 
 401 def KernelDebugCommandsHelp(cmd_args
=None): 
 402     """ Show a list of registered commands for kenel debugging. 
 404     global lldb_command_documentation
 
 405     print "List of commands provided by " + MODULE_NAME 
+ " for kernel debugging." 
 406     cmds 
= lldb_command_documentation
.keys() 
 409         if type(lldb_command_documentation
[cmd
][-1]) == type(""): 
 410             print " {0: <20s} - {1}".format(cmd 
, lldb_command_documentation
[cmd
][1].split("\n")[0].strip()) 
 412             print " {0: <20s} - {1}".format(cmd 
, "No help string found.") 
 414     Each of the functions listed here accept the following common options.  
 415         -h  Show the help string for the command. 
 416         -o <path/to/filename>   The output of this command execution will be saved to file. Parser information or errors will  
 417                                 not be sent to file though. eg /tmp/output.txt 
 418         -s <filter_string>      The "filter_string" param is parsed to python regex expression and each line of output  
 419                                 will be printed/saved only if it matches the expression.  
 420         -v [-v...]  Each additional -v will increase the verbosity of the command. 
 421         -p <plugin_name>        Send the output of the command to plugin. Please see README for usage of plugins. 
 423     Additionally, each command implementation may have more options. "(lldb) help <command> " will show these options. 
 428 @lldb_command('showraw')     
 429 def ShowRawCommand(cmd_args
=None): 
 430     """ A command to disable the kernel summaries and show data as seen by the system.  
 431         This is useful when trying to read every field of a struct as compared to brief summary 
 433     command 
= " ".join(cmd_args
) 
 434     lldb
.debugger
.HandleCommand('type category disable kernel' ) 
 435     lldb
.debugger
.HandleCommand( command 
) 
 436     lldb
.debugger
.HandleCommand('type category enable kernel' ) 
 439 @lldb_command('xnudebug') 
 440 def XnuDebugCommand(cmd_args
=None): 
 441     """  command interface for operating on the xnu macros. Allowed commands are as follows 
 443             Reload a submodule from the xnu/tools/lldb directory. Do not include the ".py" suffix in modulename. 
 444             usage: xnudebug reload <modulename> (eg. memory, process, stats etc) 
 446             Start running registered test with <name> from various modules. 
 447             usage: xnudebug test <name> (eg. test_memstats) 
 449             Go through all registered tests and run them 
 451             Toggle state of debug configuration flag. 
 454     command_args 
= cmd_args
 
 455     if len(command_args
) == 0: 
 456         raise ArgumentError("No command specified.") 
 457     supported_subcommands 
= ['debug', 'reload', 'test', 'testall'] 
 458     subcommand 
= GetLongestMatchOption(command_args
[0], supported_subcommands
, True) 
 460     if len(subcommand
) == 0: 
 461         raise ArgumentError("Subcommand (%s) is not a valid command. " % str(command_args
[0])) 
 463     subcommand 
= subcommand
[0].lower() 
 464     if subcommand 
== 'debug': 
 465         if command_args
[-1].lower().find('dis') >=0 and config
['debug']: 
 466             config
['debug'] = False 
 467             print "Disabled debug logging." 
 468         elif command_args
[-1].lower().find('dis') < 0 and not config
['debug']: 
 469             config
['debug'] = True 
 470             EnableLLDBAPILogging()  # provided by utils.py 
 471             print "Enabled debug logging. \nPlease run 'xnudebug debug disable' to disable it again. " 
 473     if subcommand 
== 'reload': 
 474         module_name 
= command_args
[-1] 
 475         if module_name 
in sys
.modules
: 
 476             reload(sys
.modules
[module_name
]) 
 477             print module_name 
+ " is reloaded from " + sys
.modules
[module_name
].__file
__ 
 479             print "Unable to locate module named ", module_name
 
 480     if subcommand 
== 'testall': 
 481         for test_name 
in lldb_command_tests
.keys(): 
 482             print "[BEGIN]", test_name
 
 483             res 
= lldb_command_tests
[test_name
][2](kern
, config
, lldb
, True) 
 485                 print "[PASSED] {:s}".format(test_name
) 
 487                 print "[FAILED] {:s}".format(test_name
) 
 488     if subcommand 
== 'test': 
 489         test_name 
= command_args
[-1] 
 490         if test_name 
in lldb_command_tests
: 
 491             test 
= lldb_command_tests
[test_name
] 
 492             print "Running test {:s}".format(test
[0]) 
 493             if test
[2](kern
, config
, lldb
, True) :  
 494                 print "[PASSED] {:s}".format(test
[0]) 
 496                 print "[FAILED] {:s}".format(test
[0]) 
 499             print "No such test registered with name: {:s}".format(test_name
) 
 500             print "XNUDEBUG Available tests are:" 
 501             for i 
in lldb_command_tests
.keys(): 
 507 @lldb_command('showversion') 
 508 def ShowVersion(cmd_args
=None): 
 509     """ Read the kernel version string from a fixed address in low 
 510         memory. Useful if you don't know which kernel is on the other end, 
 511         and need to find the appropriate symbols. Beware that if you've 
 512         loaded a symbol file, but aren't connected to a remote target, 
 513         the version string from the symbol file will be displayed instead. 
 514         This macro expects to be connected to the remote kernel to function 
 521 @lldb_command('paniclog') 
 522 def ShowPanicLog(cmd_args
=None): 
 523     """ Display the paniclog information 
 525     panic_buf 
= kern
.globals.debug_buf
 
 526     panic_buf_start 
= addressof(panic_buf
) 
 527     panic_buf_end 
= unsigned(kern
.globals.debug_buf_ptr
) 
 528     num_bytes 
= panic_buf_end 
- panic_buf_start
 
 531     panic_data 
= panic_buf
.GetSBValue().GetData() 
 534     for i 
in range(0, num_bytes
): 
 535         c 
= panic_data
.GetUnsignedInt8(err
, i
) 
 549 @lldb_command('showbootargs') 
 550 def ShowBootArgs(cmd_args
=None): 
 551     """ Display boot arguments passed to the target kernel 
 553     bootargs 
= Cast(kern
.GetGlobalVariable('PE_state').bootArgs
, 'boot_args *') 
 554     bootargs_cmd 
= bootargs
.CommandLine
 
 555     print str(bootargs_cmd
) 
 557 @static_var("last_process_uniq_id", 1) 
 558 def GetDebuggerStopIDValue(): 
 559     """ Create a unique session identifier.  
 561             int - a unique number identified by processid and stopid. 
 564     process_obj 
= LazyTarget
.GetProcess() 
 565     if hasattr(process_obj
, "GetStopID"): 
 566         stop_id 
= process_obj
.GetStopID() 
 568     if hasattr(process_obj
, 'GetUniqueID'): 
 569         proc_uniq_id 
= process_obj
.GetUniqueID() 
 570         #FIXME <rdar://problem/13034329> forces us to do this twice 
 571         proc_uniq_id 
= process_obj
.GetUniqueID() 
 573         GetDebuggerStopIDValue
.last_process_uniq_id 
+=1 
 574         proc_uniq_id 
= GetDebuggerStopIDValue
.last_process_uniq_id 
+ 1 
 576     stop_id_str 
= "{:d}:{:d}".format(proc_uniq_id
, stop_id
)         
 577     return hash(stop_id_str
) 
 579 # The initialization code to add your commands 
 580 _xnu_framework_init 
= False 
 581 def __lldb_init_module(debugger
, internal_dict
): 
 582     global kern
, lldb_command_documentation
, config
, _xnu_framework_init
 
 583     if _xnu_framework_init
: 
 585     _xnu_framework_init 
= True 
 586     caching
._GetDebuggerSessionID 
= GetDebuggerStopIDValue
 
 587     debugger
.HandleCommand('type summary add --regex --summary-string "${var%s}" -C yes -p -v "char \[[0-9]*\]"') 
 588     debugger
.HandleCommand('type format add --format hex -C yes uintptr_t') 
 589     kern 
= KernelTarget(debugger
) 
 590     print "xnu debug macros loaded successfully. Run showlldbtypesummaries to enable type summaries." 
 592 __lldb_init_module(lldb
.debugger
, None) 
 594 @lldb_command("showlldbtypesummaries") 
 595 def ShowLLDBTypeSummaries(cmd_args
=[]): 
 596     """ Enable/Disable kernel type summaries. Default is disabled. 
 597         Usage: showlldbtypesummaries [enable|disable] 
 603     if len(cmd_args
) > 0 and cmd_args
[0].lower().find('disable') >=0: 
 605         config
['showTypeSummary'] = False 
 606         trailer_msg 
= "Please run 'showlldbtypesummaries enable' to enable the summary feature." 
 608         config
['showTypeSummary'] = True 
 609         SetupLLDBTypeSummaries(True) 
 610         trailer_msg 
= "Please run 'showlldbtypesummaries disable' to disable the summary feature." 
 611     lldb_run_command("type category "+ action 
+" kernel") 
 612     print "Successfully "+action
+"d the kernel type summaries. %s" % trailer_msg
 
 615 from process 
import * 
 622 from userspace 
import * 
 626 from scheduler 
import *