2 Miscellaneous (Intel) platform-specific commands. 
   8 from scheduler 
import * 
  10 @lldb_command('showlogstream') 
  11 def showLogStream(cmd_args
=None): 
  13     Dump the state of the kernel log stream 
  15     mbp 
= kern
.globals.oslog_streambufp
 
  16     print "streaming buffer space avail: {0:>#x} of {1:>#x} bytes\n".format(kern
.globals.oslog_stream_buf_bytesavail
, kern
.globals.oslog_stream_buf_size
) 
  17     print " read head: offset {0:>#x}\nwrite head: offset {1:>#x}\n".format(mbp
.msg_bufr
, mbp
.msg_bufx
) 
  19     print "  id  timestamp   offset size off+size type metadata" 
  20     for entry 
in IterateSTAILQ_HEAD(kern
.globals.oslog_stream_buf_head
, "buf_entries"): 
  21         next_start 
= entry
.offset 
+ entry
.size
 
  22         if (next_start 
> 0x1000): 
  23             next_start 
= next_start 
- 0x1000 
  24         print "{0:>4d}: {1:<d}  {2:>5x} {3:>4d} {4:>5x} {5:<d}    {6:<d}".format(count
, entry
.timestamp
, entry
.offset
, entry
.size
, next_start
, entry
.type, entry
.metadata
) 
  26     print "found {} entries".format(count
) 
  29     for entry 
in IterateSTAILQ_HEAD(kern
.globals.oslog_stream_free_head
, "buf_entries"): 
  31     print "free list: {} entries".format(count
) 
  34     for outer 
in IterateSTAILQ_HEAD(kern
.globals.oslog_stream_buf_head
, "buf_entries"): 
  35         for inner 
in IterateSTAILQ_HEAD(kern
.globals.oslog_stream_buf_head
, "buf_entries"): 
  36             if ((outer
.offset 
> inner
.offset
) and 
  37                 (outer
.offset 
< inner
.offset 
+ inner
.size
)): 
  38                 print "error: overlapping entries: {:>3x} <--> {:>3x}".format(outer
.offset
, inner
.offset
) 
  41 @lldb_command('showmcastate') 
  42 def showMCAstate(cmd_args
=None): 
  44     Print machine-check register state after MC exception. 
  46     if kern
.arch 
!= 'x86_64': 
  47         print "Not available for current architecture." 
  50     present 
= ["not present", "present"] 
  51     print 'MCA {:s}, control MSR {:s}, threshold status {:s}'.format( 
  52     present
[int(kern
.globals.mca_MCA_present
)], 
  53     present
[int(kern
.globals.mca_control_MSR_present
)], 
  54     present
[int(kern
.globals.mca_threshold_status_present
)]) 
  55     print '{:d} error banks, family code {:#0x}, machine-check dump state: {:d}'.format( 
  56         kern
.globals.mca_error_bank_count
, 
  57         kern
.globals.mca_dump_state
, 
  58         kern
.globals.mca_family
) 
  60     while kern
.globals.cpu_data_ptr
[cpu
]: 
  61         cd 
= kern
.globals.cpu_data_ptr
[cpu
] 
  64             print 'CPU {:d}: mca_mcg_ctl: {:#018x} mca_mcg_status {:#018x}'.format(cpu
, mc
.mca_mcg_ctl
, mc
.mca_mcg_status
.u64
) 
  65             hdr 
= '{:<4s} {:<18s} {:<18s} {:<18s} {:<18s}' 
  66             val 
= '{:>3d}: {:#018x} {:#018x} {:#018x} {:#018x}' 
  67             print hdr
.format('bank', 
  72             for i 
in range(int(kern
.globals.mca_error_bank_count
)): 
  73                 bank 
= mc
.mca_error_bank
[i
] 
  76                     bank
.mca_mci_status
.u64
, 
  79         print 'register state:' 
  80         reg 
= cd
.cpu_desc_index
.cdi_ktss
.ist1 
- sizeof('x86_saved_state_t') 
  81         print lldb_run_command('p/x *(x86_saved_state_t *) ' + hex(reg
)) 
  84 def dumpTimerList(mpqueue
): 
  86     Utility function to dump the timer entries in list (anchor). 
  87     anchor is a struct mpqueue_head. 
  90     if mpqueue
.count 
== 0: 
  94     thdr 
= ' {:<24s}{:<17s}{:<16s} {:<14s} {:<18s} count: {:d} ' 
  95     tval 
= ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d}  ({:#018x})({:#018x}, {:#018x}) ({:s}) {:s}' 
  97     print thdr
.format('Entry', 'Deadline', 'soft_deadline', 'Secs To Go', '(*func)(param0, param1)', mpqueue
.count
) 
  99     for timer_call 
in ParanoidIterateLinkageChain(mpqueue
.head
, 'struct timer_call *', 'tc_qlink'): 
 100         recent_timestamp 
= GetRecentTimestamp() 
 101         if (recent_timestamp 
< timer_call
.tc_pqlink
.deadline
): 
 103             timer_fire 
= timer_call
.tc_pqlink
.deadline 
- recent_timestamp
 
 106             timer_fire 
= recent_timestamp 
- timer_call
.tc_pqlink
.deadline
 
 108         func_name 
= kern
.Symbolicate(timer_call
.tc_func
) 
 112         strip_func 
= kern
.StripKernelPAC(unsigned(timer_call
.tc_func
)) 
 114         func_syms 
= kern
.SymbolicateFromAddress(strip_func
) 
 115         # returns an array of SBSymbol 
 117         if func_syms 
and func_syms
[0] : 
 118             func_sym 
= func_syms
[0] 
 119             func_name 
= func_sym
.GetName() 
 122                 if "thread_call_delayed_timer" in func_name 
: 
 123                     group 
= Cast(timer_call
.tc_param0
, 'struct thread_call_group *') 
 124                     flavor 
= Cast(timer_call
.tc_param1
, 'thread_call_flavor_t') 
 126                     # There's got to be a better way to stringify the enum 
 127                     flavorname 
= str(flavor
).partition(" = ")[2] 
 129                     extra_string 
+= "{:s} {:s}".format(group
.tcg_name
, flavorname
) 
 131                 if "thread_timer_expire" in func_name 
: 
 132                     thread 
= Cast(timer_call
.tc_param0
, 'thread_t') 
 134                     tid 
= thread
.thread_id
 
 135                     name 
= GetThreadName(thread
) 
 136                     pid 
= GetProcPIDForTask(thread
.task
) 
 137                     procname 
= GetProcNameForTask(thread
.task
) 
 139                     extra_string 
+= "thread: 0x{:x} {:s} task:{:s}[{:d}]".format( 
 140                             tid
, name
, procname
, pid
) 
 142                 print "exception generating extra_string for call: {:#018x}".format(timer_call
) 
 143                 if dumpTimerList
.enable_debug 
: 
 146         tval 
= ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d}  ({:#018x})({:#018x},{:#018x}) ({:s}) {:s}' 
 147         print tval
.format(timer_call
, 
 148             timer_call
.tc_pqlink
.deadline
, 
 149             timer_call
.tc_soft_deadline
, 
 151             timer_fire
/1000000000, 
 152             timer_fire
%1000000000, 
 154             timer_call
.tc_param0
, 
 155             timer_call
.tc_param1
, 
 156             func_name
, extra_string
) 
 158 dumpTimerList
.enable_debug 
= False 
 160 def GetCpuDataForCpuID(cpu_id
): 
 162     Find struct cpu_data for a CPU 
 165     if kern
.arch 
== 'x86_64': 
 166         cpu_data 
= kern
.globals.cpu_data_ptr
[cpu_id
] 
 168     elif kern
.arch
.startswith('arm'): 
 169         data_entries_addr 
= kern
.GetLoadAddressForSymbol('CpuDataEntries') 
 170         data_entries 
= kern
.GetValueFromAddress(data_entries_addr
, 'cpu_data_entry_t *') 
 171         data_entry 
= data_entries
[cpu_id
]; 
 172         cpu_data_addr 
= data_entry
.cpu_data_vaddr
 
 173         return Cast(cpu_data_addr
, 'cpu_data_t*') 
 175 @lldb_command('longtermtimers') 
 176 def longtermTimers(cmd_args
=None): 
 178     Print details of long-term timers and stats. 
 181     lt 
= kern
.globals.timer_longterm
 
 183     EndofAllTime 
= long(-1) 
 184     if long(ltt
.interval
) == EndofAllTime
: 
 185         print "Longterm timers disabled" 
 189         ratio 
= lt
.enqueues 
/ lt
.escalates
 
 192     print     'Longterm timer object: {:#018x}'.format(addressof(lt
)) 
 193     print     ' queue count         : {:d}'    .format(lt
.queue
.count
) 
 194     print     ' number of enqueues  : {:d}'    .format(lt
.enqueues
) 
 195     print     ' number of dequeues  : {:d}'    .format(lt
.dequeues
) 
 196     print     ' number of escalates : {:d}'    .format(lt
.escalates
) 
 197     print     ' enqueues/escalates  : {:d}'    .format(ratio
) 
 198     print     ' threshold.interval  : {:d}'    .format(ltt
.interval
) 
 199     print     ' threshold.margin    : {:d}'    .format(ltt
.margin
) 
 200     print     ' scan_time           : {:#018x} ({:d})'.format(lt
.scan_time
, lt
.scan_time
) 
 201     if long(ltt
.preempted
) == EndofAllTime
: 
 202         print ' threshold.preempted : None' 
 204         print ' threshold.preempted : {:#018x} ({:d})'.format(ltt
.preempted
, ltt
.preempted
) 
 205     if long(ltt
.deadline
) == EndofAllTime
: 
 206         print ' threshold.deadline  : None' 
 208         print ' threshold.deadline  : {:#018x} ({:d})'.format(ltt
.deadline
, ltt
.deadline
) 
 209         print ' threshold.call      : {:#018x}'.format(ltt
.call
) 
 210         print ' actual deadline set : {:#018x} ({:d})'.format(ltt
.deadline_set
, ltt
.deadline_set
) 
 211     print     ' threshold.scans     : {:d}'    .format(ltt
.scans
) 
 212     print     ' threshold.preempts  : {:d}'    .format(ltt
.preempts
) 
 213     print     ' threshold.latency   : {:d}'    .format(ltt
.latency
) 
 214     print     '               - min : {:d}'    .format(ltt
.latency_min
) 
 215     print     '               - max : {:d}'    .format(ltt
.latency_max
) 
 216     dumpTimerList(lt
.queue
) 
 219 @lldb_command('processortimers') 
 220 def processorTimers(cmd_args
=None): 
 222     Print details of processor timers, noting anything suspicious 
 223     Also include long-term timer details 
 225     hdr 
= '{:15s}{:<18s} {:<18s} {:<18s} {:<18s}' 
 226     print hdr
.format('Processor #', 'Processor pointer', 'Last dispatch', 'Next deadline', 'Difference') 
 228     p 
= kern
.globals.processor_list
 
 229     EndOfAllTime 
= long(-1) 
 232         cpu_data 
= GetCpuDataForCpuID(cpu
) 
 233         rt_timer 
= cpu_data
.rtclock_timer
 
 234         diff 
= long(rt_timer
.deadline
) - long(p
.last_dispatch
) 
 235         valid_deadline 
= long(rt_timer
.deadline
) != EndOfAllTime
 
 236         tmr 
= 'Processor {:<3d}: {:#018x} {:#018x} {:18s} {:18s} {:s}' 
 237         print tmr
.format(cpu
, 
 240             "{:#018x}".format(rt_timer
.deadline
) if valid_deadline 
else "None", 
 241             "{:#018x}".format(diff
) if valid_deadline 
else "N/A", 
 242             ['(PAST DEADLINE)', '(ok)'][int(diff 
> 0)] if valid_deadline 
else "") 
 244             if kern
.arch 
== 'x86_64': 
 245                 print 'Next deadline set at: {:#018x}. Timer call list:'.format(rt_timer
.when_set
) 
 246             dumpTimerList(rt_timer
.queue
) 
 253 @lldb_command('showtimerwakeupstats') 
 254 def showTimerWakeupStats(cmd_args
=None): 
 256     Displays interrupt and platform idle wakeup frequencies 
 257     associated with each thread, timer time-to-deadline frequencies, and 
 258     CPU time with user/system break down where applicable, with thread tags. 
 260     for task 
in kern
.tasks
: 
 261         proc 
= Cast(task
.bsd_info
, 'proc_t') 
 262         print dereference(task
) 
 263         print '{:d}({:s}), terminated thread timer wakeups: {:d} {:d} 2ms: {:d} 5ms: {:d} UT: {:d} ST: {:d}'.format( 
 266 # Commented-out references below to be addressed by rdar://13009660. 
 267             0, #task.task_interrupt_wakeups, 
 268             0, #task.task_platform_idle_wakeups, 
 269             task
.task_timer_wakeups_bin_1
, 
 270             task
.task_timer_wakeups_bin_2
, 
 271             task
.total_user_time
, 
 272             task
.total_system_time
) 
 273         tot_wakes 
= 0 #task.task_interrupt_wakeups 
 274         tot_platform_wakes 
= 0 #task.task_platform_idle_wakeups 
 275         for thread 
in IterateQueue(task
.threads
, 'thread_t', 'task_threads'): 
 276 ##        if thread.thread_interrupt_wakeups == 0: 
 278             print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format( 
 281                 0, #thread.thread_interrupt_wakeups, 
 282                 0, #thread.thread_platform_idle_wakeups, 
 283                 0, #thread.thread_callout_interrupt_wakeups, 
 284                 0, #thread.thread_callout_platform_idle_wakeups, 
 286                 thread
.thread_timer_wakeups_bin_1
, 
 287                 thread
.thread_timer_wakeups_bin_2
, 
 288                 thread
.user_timer
.all_bits
, 
 289                 thread
.system_timer
.all_bits
) 
 290             tot_wakes 
+= 0 #thread.thread_interrupt_wakeups 
 291             tot_platform_wakes 
+= 0 #thread.thread_platform_idle_wakeups 
 292         print 'Task total wakeups: {:d} {:d}'.format( 
 293             tot_wakes
, tot_platform_wakes
) 
 295 @lldb_command('showrunningtimers') 
 296 def ShowRunningTimers(cmd_args
=None): 
 298     Print the state of all running timers. 
 300     Usage: showrunningtimers 
 302     pset 
= addressof(kern
.globals.pset0
) 
 303     processor_array 
= kern
.globals.processor_array
 
 306     while processor_array
[i
] != 0: 
 307         processor 
= processor_array
[i
] 
 308         print('{}: {}'.format( 
 309                 i
, 'on' if processor
.running_timers_active 
else 'off')) 
 310         print('\tquantum: {}'.format( 
 311                 unsigned(processor
.running_timers
[0].tc_pqlink
.deadline
))) 
 312         print('\tkperf: {}'.format( 
 313                 unsigned(processor
.running_timers
[1].tc_pqlink
.deadline
))) 
 316 def DoReadMsr64(msr_address
, lcpu
): 
 317     """ Read a 64-bit MSR from the specified CPU 
 319             msr_address: int - MSR index to read from 
 320             lcpu: int - CPU identifier 
 322             64-bit value read from the MSR 
 326     if "kdp" != GetConnectionProtocol(): 
 327         print "Target is not connected over kdp. Cannot read MSR." 
 330     input_address 
= unsigned(addressof(kern
.globals.manual_pkt
.input)) 
 331     len_address 
= unsigned(addressof(kern
.globals.manual_pkt
.len)) 
 332     data_address 
= unsigned(addressof(kern
.globals.manual_pkt
.data
)) 
 333     if not WriteInt32ToMemoryAddress(0, input_address
): 
 334         print "DoReadMsr64() failed to write 0 to input_address" 
 337     kdp_pkt_size 
= GetType('kdp_readmsr64_req_t').GetByteSize() 
 338     if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
): 
 339         print "DoReadMsr64() failed to write kdp_pkt_size" 
 342     kgm_pkt 
= kern
.GetValueFromAddress(data_address
, 'kdp_readmsr64_req_t *') 
 343     header_value 
= GetKDPPacketHeaderInt( 
 344         request
=GetEnumValue('kdp_req_t::KDP_READMSR64'), 
 347     if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))): 
 348         print "DoReadMsr64() failed to write header_value" 
 350     if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))): 
 351         print "DoReadMsr64() failed to write msr_address" 
 353     if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))): 
 354         print "DoReadMsr64() failed to write lcpu" 
 356     if not WriteInt32ToMemoryAddress(1, input_address
): 
 357         print "DoReadMsr64() failed to write to input_address" 
 360     result_pkt 
= Cast(addressof(kern
.globals.manual_pkt
.data
), 
 361         'kdp_readmsr64_reply_t *') 
 362     if (result_pkt
.error 
== 0): 
 363         result 
= dereference(Cast(addressof(result_pkt
.data
), 'uint64_t *')) 
 365         print "DoReadMsr64() result_pkt.error != 0" 
 368 def DoWriteMsr64(msr_address
, lcpu
, data
): 
 369     """ Write a 64-bit MSR 
 371             msr_address: int - MSR index to write to 
 372             lcpu: int - CPU identifier 
 373             data: int - value to write 
 375             True upon success, False if error 
 377     if "kdp" != GetConnectionProtocol(): 
 378         print "Target is not connected over kdp. Cannot write MSR." 
 381     input_address 
= unsigned(addressof(kern
.globals.manual_pkt
.input)) 
 382     len_address 
= unsigned(addressof(kern
.globals.manual_pkt
.len)) 
 383     data_address 
= unsigned(addressof(kern
.globals.manual_pkt
.data
)) 
 384     if not WriteInt32ToMemoryAddress(0, input_address
): 
 385         print "DoWriteMsr64() failed to write 0 to input_address" 
 388     kdp_pkt_size 
= GetType('kdp_writemsr64_req_t').GetByteSize() 
 389     if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
): 
 390         print "DoWriteMsr64() failed to kdp_pkt_size" 
 393     kgm_pkt 
= kern
.GetValueFromAddress(data_address
, 'kdp_writemsr64_req_t *') 
 394     header_value 
= GetKDPPacketHeaderInt( 
 395         request
=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'), 
 398     if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))): 
 399         print "DoWriteMsr64() failed to write header_value" 
 401     if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))): 
 402         print "DoWriteMsr64() failed to write msr_address" 
 404     if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))): 
 405         print "DoWriteMsr64() failed to write lcpu" 
 407     if not WriteInt64ToMemoryAddress(data
, int(addressof(kgm_pkt
.data
))): 
 408         print "DoWriteMsr64() failed to write data" 
 410     if not WriteInt32ToMemoryAddress(1, input_address
): 
 411         print "DoWriteMsr64() failed to write to input_address" 
 414     result_pkt 
= Cast(addressof(kern
.globals.manual_pkt
.data
), 
 415         'kdp_writemsr64_reply_t *') 
 416     if not result_pkt
.error 
== 0: 
 417         print "DoWriteMsr64() error received in reply packet" 
 422 @lldb_command('readmsr64') 
 423 def ReadMsr64(cmd_args
=None): 
 424     """ Read the specified MSR. The CPU can be optionally specified 
 425         Syntax: readmsr64 <msr> [lcpu] 
 427     if cmd_args 
== None or len(cmd_args
) < 1: 
 428         print ReadMsr64
.__doc__
 
 431     msr_address 
= ArgumentStringToInt(cmd_args
[0]) 
 432     if len(cmd_args
) > 1: 
 433         lcpu 
= ArgumentStringToInt(cmd_args
[1]) 
 435         lcpu 
= int(xnudefines
.lcpu_self
) 
 437     msr_value 
= DoReadMsr64(msr_address
, lcpu
) 
 438     print "MSR[{:x}]: {:#016x}".format(msr_address
, msr_value
) 
 440 @lldb_command('writemsr64') 
 441 def WriteMsr64(cmd_args
=None): 
 442     """ Write the specified MSR. The CPU can be optionally specified 
 443         Syntax: writemsr64 <msr> <value> [lcpu] 
 445     if cmd_args 
== None or len(cmd_args
) < 2: 
 446         print WriteMsr64
.__doc__
 
 448     msr_address 
= ArgumentStringToInt(cmd_args
[0]) 
 449     write_val 
= ArgumentStringToInt(cmd_args
[1]) 
 450     if len(cmd_args
) > 2: 
 451         lcpu 
= ArgumentStringToInt(cmd_args
[2]) 
 453         lcpu 
= xnudefines
.lcpu_self
 
 455     if not DoWriteMsr64(msr_address
, lcpu
, write_val
): 
 456         print "writemsr64 FAILED" 
 458 def GetKernelDebugBufferEntry(kdbg_entry
): 
 459     """ Extract the information from given kernel debug buffer entry and return the summary 
 461             kdebug_entry - kd_buf - address of kernel debug buffer entry 
 463             str - formatted output information of kd_buf entry 
 467     kdebug_entry 
= kern
.GetValueFromAddress(kdbg_entry
, 'kd_buf *') 
 468     debugid     
= kdebug_entry
.debugid
 
 469     kdebug_arg1 
= kdebug_entry
.arg1
 
 470     kdebug_arg2 
= kdebug_entry
.arg2
 
 471     kdebug_arg3 
= kdebug_entry
.arg3
 
 472     kdebug_arg4 
= kdebug_entry
.arg4
 
 474     if kern
.arch 
== 'x86_64' or kern
.arch
.startswith('arm64'): 
 475         kdebug_cpu   
= kdebug_entry
.cpuid
 
 476         ts_hi        
= (kdebug_entry
.timestamp 
>> 32) & 0xFFFFFFFF 
 477         ts_lo        
= kdebug_entry
.timestamp 
& 0xFFFFFFFF 
 479         kdebug_cpu   
= (kdebug_entry
.timestamp 
>> 56) 
 480         ts_hi        
= (kdebug_entry
.timestamp 
>> 32) & 0x00FFFFFF 
 481         ts_lo        
= kdebug_entry
.timestamp 
& 0xFFFFFFFF 
 483     kdebug_class    
= (debugid 
>> 24) & 0x000FF 
 484     kdebug_subclass 
= (debugid 
>> 16) & 0x000FF 
 485     kdebug_code     
= (debugid 
>>  2) & 0x03FFF 
 486     kdebug_qual     
= (debugid
) & 0x00003 
 490     elif kdebug_qual 
== 1: 
 492     elif kdebug_qual 
== 2: 
 494     elif kdebug_qual 
== 3: 
 498     out_str 
+= "{:<#20x} {:>6d} {:>#12x} ".format(kdebug_entry
, kdebug_cpu
, kdebug_entry
.arg5
) 
 499     out_str 
+= " {:#010x}{:08x} {:>6s} ".format(ts_hi
, ts_lo
, kdebug_qual
) 
 503     if kdebug_class 
== 1: 
 505     elif kdebug_class 
== 2: 
 507     elif kdebug_class 
== 3: 
 509     elif kdebug_class 
== 4: 
 511     elif kdebug_class 
== 5: 
 513     elif kdebug_class 
== 6: 
 515     elif kdebug_class 
== 7: 
 517     elif kdebug_class 
== 8: 
 519     elif kdebug_class 
== 9: 
 521     elif kdebug_class 
== 10: 
 523     elif kdebug_class 
== 11: 
 525     elif kdebug_class 
== 20: 
 527     elif kdebug_class 
== 30: 
 529     elif kdebug_class 
== 31: 
 531     elif kdebug_class 
== 32: 
 533     elif kdebug_class 
== 33: 
 535     elif kdebug_class 
== 34: 
 537     elif kdebug_class 
== 36: 
 539     elif kdebug_class 
== 37: 
 541     elif kdebug_class 
== 38: 
 543     elif kdebug_class 
== 39: 
 545     elif kdebug_class 
== 40: 
 547     elif kdebug_class 
== 41: 
 549     elif kdebug_class 
== 42: 
 551     elif kdebug_class 
== 128: 
 553     elif kdebug_class 
== 129: 
 555     elif kdebug_class 
== 130: 
 557     elif kdebug_class 
== 131: 
 559     elif kdebug_class 
== 132: 
 561     elif kdebug_class 
== 133: 
 563     elif kdebug_class 
== 255: 
 566         out_str 
+= "{:^#10x} ".format(kdebug_class
) 
 569         out_str 
+= "{:^10s} ".format(kdbg_class
) 
 572     out_str 
+= " {:>#5x} {:>8d}   ".format(kdebug_subclass
, kdebug_code
) 
 574     # space for debugid-specific processing 
 575     code_info_str 
+= "arg1={:#010x} ".format(kdebug_arg1
) 
 576     code_info_str 
+= "arg2={:#010x} ".format(kdebug_arg2
) 
 577     code_info_str 
+= "arg3={:#010x} ".format(kdebug_arg3
) 
 578     code_info_str 
+= "arg4={:#010x} ".format(kdebug_arg4
) 
 581     out_str 
+= "{:<25s}\n".format(code_info_str
) 
 584 @lldb_command('showkerneldebugbuffercpu') 
 585 @header("{0: ^20s} {1: >6s} {2: >12s} {3: ^20s} {4: >6s} {5: ^10s} {6: >5s} {7: >8s} {8: ^25s}". 
 586     format('kd_buf', 'CPU', 'Thread', 'Timestamp', 'S/E', 'Class', 'Sub', 'Code', 'Code Specific Info')) 
 587 def ShowKernelDebugBufferCPU(cmd_args
=None): 
 588     """ Prints the last N entries in the kernel debug buffer for specified cpu 
 589         Syntax: showkerneldebugbuffercpu <cpu_num> <count> 
 591     if cmd_args 
== None or len(cmd_args
) < 2: 
 592         raise ArgumentError("Invalid arguments passed.") 
 596     cpu_number 
= ArgumentStringToInt(cmd_args
[0]) 
 597     entry_count 
= ArgumentStringToInt(cmd_args
[1]) 
 598     debugentriesfound 
= 0 
 599     #  Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags 
 600     if (kern
.globals.kd_ctrl_page
.kdebug_flags 
& 0x80000000):    
 601         out_str 
+= ShowKernelDebugBufferCPU
.header 
+ "\n" 
 603             out_str 
+= "<count> is 0, dumping 50 entries\n" 
 606         if cpu_number 
>= kern
.globals.kd_ctrl_page
.kdebug_cpus
: 
 607             kdbg_str 
+= "cpu number too big\n" 
 609             kdbp 
= addressof(kern
.globals.kdbip
[cpu_number
]) 
 610             kdsp 
= kdbp
.kd_list_head
 
 611             while ((kdsp
.raw 
!= 0 and kdsp
.raw 
!= 0x00000000ffffffff) and (entry_count 
> 0)): 
 612                 kd_buffer 
= kern
.globals.kd_bufs
[kdsp
.buffer_index
] 
 613                 kdsp_actual 
= addressof(kd_buffer
.kdsb_addr
[kdsp
.offset
]) 
 614                 if kdsp_actual
.kds_readlast 
!= kdsp_actual
.kds_bufindx
: 
 615                     kds_buf 
= kdsp_actual
.kds_records
[kdsp_actual
.kds_bufindx
] 
 616                     kds_bufptr 
= addressof(kds_buf
) 
 617                     while (entry_count 
> 0) and \
 
 618                         (unsigned(kds_bufptr
) > unsigned(addressof(kdsp_actual
.kds_records
[kdsp_actual
.kds_readlast
]))): 
 619                         kds_bufptr 
= kds_bufptr 
- sizeof(kds_buf
) 
 620                         entry_count 
= entry_count 
- 1 
 621                         kdbg_str 
+= GetKernelDebugBufferEntry(kds_bufptr
) 
 622                 kdsp 
= kdsp_actual
.kds_next
 
 624         kdbg_str 
+= "Trace buffer not enabled for CPU {:d}\n".format(cpu_number
) 
 630 @lldb_command('showkerneldebugbuffer') 
 631 def ShowKernelDebugBuffer(cmd_args
=None): 
 632     """ Prints the last N entries in the kernel debug buffer per cpu 
 633         Syntax: showkerneldebugbuffer <count> 
 635     if cmd_args 
== None or len(cmd_args
) < 1: 
 636         raise ArgumentError("Invalid arguments passed.") 
 638     #  Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags 
 639     if (kern
.globals.kd_ctrl_page
.kdebug_flags 
& 0x80000000): 
 640         entrycount 
= ArgumentStringToInt(cmd_args
[0]) 
 642             print "<count> is 0, dumping 50 entries per cpu\n" 
 645         while cpu_num 
< kern
.globals.kd_ctrl_page
.kdebug_cpus
: 
 646             ShowKernelDebugBufferCPU([str(cpu_num
), str(entrycount
)]) 
 649         print "Trace buffer not enabled\n" 
 651 @lldb_command('dumprawtracefile','U:') 
 652 def DumpRawTraceFile(cmd_args
=[], cmd_options
={}): 
 654         support for ktrace(1) 
 656         NB: trace is not wordsize flexible, so use ktrace(1) compiled for the compatible model, 
 657         e.g. if you dump from __LP64__ system, you will need to run ktrace(1) compiled __LP64__ to process the raw data file. 
 659         read the kernel's debug trace buffer, and dump to a "raw" ktrace(1) file 
 660         Usage: dumprawtracefile <output_filename> 
 661             -U <uptime> : specify system uptime in nsec, obtained e.g. from paniclog 
 662         Be patient, it is teh slow. 
 664         cf. kdbg_read()\bsd/kern/kdebug.c 
 667     #  Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags  
 668     if (kern
.globals.kd_ctrl_page
.kdebug_flags 
& xnudefines
.KDBG_BFINIT
) == 0 : 
 669         print "Trace buffer not enabled\n" 
 672     if ((kern
.arch 
== "x86_64") or kern
.arch
.startswith("arm64")) : 
 674     elif kern
.arch 
== "arm" : 
 677         print "unknown kern.arch {:s}\n".format(kern
.arch
) 
 680     # Various kern.globals are hashed by address, to 
 681     #  a) avoid redundant kdp fetch from, and 
 682     #  b) avoid all stores to 
 683     # the target system kernel structures. 
 684     # Stores to hashed structures remain strictly local to the lldb host, 
 685     # they are never written back to the target. 
 689         KDBG_TIMESTAMP_MASK 
= 0xffffffffffffffff 
 692         KDBG_TIMESTAMP_MASK 
= 0x00ffffffffffffff 
 697     out_of_events       
= False 
 699     lostevent_timestamp 
= 0 
 700     lostevent_debugid   
= (((xnudefines
.DBG_TRACE 
& 0xff) << 24) | 
((xnudefines
.DBG_TRACE_INFO 
& 0xff) << 16) | 
((2 & 0x3fff)  << 2)) # 0x01020008 
 701     events_count_lost   
= 0 
 702     events_count_found  
= 0 
 704     opt_verbose 
= config
['verbosity'] 
 705     opt_progress 
= (opt_verbose 
> vHUMAN
) and (opt_verbose 
< vDETAIL
) 
 709     output_filename 
= str(cmd_args
[0]) 
 710     if opt_verbose 
> vHUMAN 
: 
 711         print "output file : {:s}".format(output_filename
) 
 712     wfd 
= open(output_filename
, "wb") 
 715     if "-U" in cmd_options
: 
 716         uptime 
= long(cmd_options
["-U"]) 
 717     if opt_verbose 
> vHUMAN 
: 
 718         print "uptime : {:d}".format(uptime
) 
 720     nkdbufs 
= kern
.globals.nkdbufs
 
 722     kd_ctrl_page 
= kern
.globals.kd_ctrl_page
 
 723     if not kd_ctrl_page 
in htab 
: 
 724         htab
[kd_ctrl_page
] = kern
.globals.kd_ctrl_page
 
 726     if opt_verbose 
> vHUMAN 
: 
 727         print "nkdbufs {0:#x}, enabled {1:#x}, flags {2:#x}, cpus {3:#x}".format(nkdbufs
, htab
[kd_ctrl_page
].enabled
, htab
[kd_ctrl_page
].kdebug_flags
, htab
[kd_ctrl_page
].kdebug_cpus
) 
 730         print "0 nkdbufs, nothing extracted" 
 733     if htab
[kd_ctrl_page
].enabled 
!= 0 : 
 734         barrier_max 
= uptime 
& KDBG_TIMESTAMP_MASK
 
 736         f 
= htab
[kd_ctrl_page
].kdebug_flags
 
 737         wrapped 
= f 
& xnudefines
.KDBG_WRAPPED
 
 739         barrier_min 
= htab
[kd_ctrl_page
].oldest_time
 
 740         htab
[kd_ctrl_page
].kdebug_flags 
= htab
[kd_ctrl_page
].kdebug_flags 
& ~xnudefines
.KDBG_WRAPPED
 
 741         htab
[kd_ctrl_page
].oldest_time 
= 0 
 743         for cpu 
in range(htab
[kd_ctrl_page
].kdebug_cpus
) : 
 744             kdbp 
= unsigned(addressof(kern
.globals.kdbip
[cpu
])) 
 745             if not kdbp 
in htab 
: 
 746                 htab
[kdbp
] = kern
.globals.kdbip
[cpu
] 
 748             kdsp 
= htab
[kdbp
].kd_list_head
.raw
 
 749             if kdsp 
== xnudefines
.KDS_PTR_NULL 
: 
 752             ix 
= htab
[kdbp
].kd_list_head
.buffer_index
 
 753             off 
= htab
[kdbp
].kd_list_head
.offset
 
 754             kdsp_actual 
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
])) 
 755             if not kdsp_actual 
in htab 
: 
 756                 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
] 
 757             htab
[kdsp_actual
].kds_lostevents 
= False 
 760     # generate trace file header; threadmap is stubbed/TBD 
 761     version_no 
= xnudefines
.RAW_VERSION1
 
 765     header 
= struct
.pack('IIqI', version_no
, thread_count
, TOD_secs
, TOD_usecs
) 
 766     pad_bytes 
= 4096 - (len(header
) & 4095) 
 767     header 
+= "\x00" * pad_bytes
 
 768     wfd
.write(buffer(header
)) 
 774         tempbuf_count 
= min(count
, xnudefines
.KDCOPYBUF_COUNT
) 
 777         while tempbuf_count 
!= 0 : 
 779             if opt_progress 
== True : 
 781                 if (progress_count 
% progress_stride
) == 0 : 
 782                     sys
.stderr
.write('.') 
 785             earliest_time 
= 0xffffffffffffffff 
 790             for cpu 
in range(htab
[kd_ctrl_page
].kdebug_cpus
) : 
 792                 kdbp 
= unsigned(addressof(kern
.globals.kdbip
[cpu
])) 
 793                 if not kdbp 
in htab 
: 
 794                     htab
[kdbp
] = kern
.globals.kdbip
[cpu
] 
 796                 # Skip CPUs without data. 
 797                 kdsp 
= htab
[kdbp
].kd_list_head
 
 798                 if kdsp
.raw 
== xnudefines
.KDS_PTR_NULL 
: 
 803                 # Get from cpu data to buffer header to buffer 
 804                 ix 
= kdsp
.buffer_index
 
 806                 kdsp_actual 
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
])) 
 807                 if not kdsp_actual 
in htab 
: 
 808                     htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
] 
 810                 kdsp_actual_shadow 
= kdsp_actual
 
 812                 # Skip buffer if there are no events left. 
 813                 rcursor 
= htab
[kdsp_actual
].kds_readlast
 
 814                 if rcursor 
== htab
[kdsp_actual
].kds_bufindx 
: 
 817                 t 
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp 
& KDBG_TIMESTAMP_MASK
 
 819                 # Ignore events that have aged out due to wrapping. 
 820                 goto_next_cpu 
= False; 
 821                 while (t 
< unsigned(barrier_min
)) : 
 822                     r 
= htab
[kdsp_actual
].kds_readlast
 
 823                     htab
[kdsp_actual
].kds_readlast 
= r 
+ 1 
 826                     if rcursor 
>= xnudefines
.EVENTS_PER_STORAGE_UNIT 
: 
 828                         kdsp 
= htab
[kdbp
].kd_list_head
 
 829                         if kdsp
.raw 
== xnudefines
.KDS_PTR_NULL 
: 
 835                         ix  
= kdsp
.buffer_index
 
 837                         kdsp_actual 
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
])) 
 839                         kdsp_actual_shadow 
= kdsp_actual
; 
 840                         rcursor 
= htab
[kdsp_actual
].kds_readlast
; 
 842                     t 
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp 
& KDBG_TIMESTAMP_MASK
 
 844                 if goto_next_cpu 
== True : 
 847                 if (t 
> barrier_max
) and (barrier_max 
> 0) : 
 848                     # Need to flush IOPs again before we 
 849                     # can sort any more data from the 
 854                 if t 
< (htab
[kdsp_actual
].kds_timestamp 
& KDBG_TIMESTAMP_MASK
) : 
 855                     # indicates we've not yet completed filling 
 857                     # this should only occur when we're looking 
 858                     # at the buf that the record head is utilizing 
 859                     # we'll pick these events up on the next 
 861                     # we bail at this point so that we don't 
 862                     # get an out-of-order timestream by continuing 
 863                     # to read events from the other CPUs' timestream(s) 
 867                 if t 
< earliest_time 
: 
 873             if (min_kdbp 
is None) or (out_of_events 
== True) : 
 874                 # all buffers ran empty 
 878             kdsp 
= htab
[min_kdbp
].kd_list_head
 
 880             ix 
= kdsp
.buffer_index
 
 882             kdsp_actual 
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
])) 
 883             if not kdsp_actual 
in htab 
: 
 884                 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
] 
 886             # Copy earliest event into merged events scratch buffer. 
 887             r 
= htab
[kdsp_actual
].kds_readlast
 
 888             htab
[kdsp_actual
].kds_readlast 
= r 
+ 1 
 889             e 
= htab
[kdsp_actual
].kds_records
[r
] 
 891             # Concatenate event into buffer 
 892             # XXX condition here is on __LP64__ 
 894                 tempbuf 
+= struct
.pack('QQQQQQIIQ',  
 895                         unsigned(e
.timestamp
), 
 905                 tempbuf 
+= struct
.pack('QIIIIII', 
 906                         unsigned(e
.timestamp
), 
 914             # Watch for out of order timestamps 
 915             if earliest_time 
< (htab
[min_kdbp
].kd_prev_timebase 
& KDBG_TIMESTAMP_MASK
) : 
 916                 ## if so, use the previous timestamp + 1 cycle 
 917                 htab
[min_kdbp
].kd_prev_timebase 
+= 1 
 919                 e
.timestamp 
= htab
[min_kdbp
].kd_prev_timebase 
& KDBG_TIMESTAMP_MASK
 
 921                     e
.timestamp |
= (min_cpu 
<< KDBG_CPU_SHIFT
) 
 923                 htab
[min_kdbp
].kd_prev_timebase 
= earliest_time
 
 925             if opt_verbose 
>= vDETAIL 
: 
 926                 print "{0:#018x} {1:#018x} {2:#018x} {3:#018x} {4:#018x} {5:#018x} {6:#010x} {7:#010x} {8:#018x}".format( 
 927                     e
.timestamp
, e
.arg1
, e
.arg2
, e
.arg3
, e
.arg4
, e
.arg5
, e
.debugid
, e
.cpuid
, e
.unused
) 
 929             events_count_found 
+= 1 
 935         if opt_progress 
== True : 
 936             sys
.stderr
.write('\n') 
 939         if opt_verbose 
> vHUMAN 
: 
 940             print "events_count_lost {0:#x}, events_count_found {1:#x}, progress_count {2:#x}".format(events_count_lost
, events_count_found
, progress_count
) 
 942         # write trace events to output file 
 943         if tempbuf_number 
!= 0 : 
 944             count 
-= tempbuf_number
 
 945             wfd
.write(buffer(tempbuf
)) 
 947         if out_of_events 
== True : 
 948             # all trace buffers are empty 
 949             if opt_verbose 
> vHUMAN 
: 
 950                 print "out of events" 
 958 def GetTimebaseInfo(): 
 960         tb 
= kern
.GetValueFromAddress( 
 961                 'RTClockData', '_rtclock_data_').rtc_timebase_const
 
 965         # Intel -- use the 1-1 timebase. 
 971 def PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
): 
 973         if do_summary 
and summary
: 
 977                     print "[{:d}] {:s}".format(i
, s
) 
 979                 print "[{:d}] {:s}".format(i
, s
) 
 982                 if regex
.match(str(elem
)): 
 983                     print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
)) 
 985                 print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
)) 
 987         print "Exception while looking at elem {:#x}".format(unsigned(elem
)) 
 990 @lldb_command('q_iterate', "LQSG:") 
 991 def QIterate(cmd_args
=None, cmd_options
={}): 
 992     """ Iterate over a LinkageChain or Queue (osfmk/kern/queue.h method 1 or 2 respectively) 
 993         This is equivalent to the qe_foreach_element() macro 
 995             iterate [options] {queue_head_ptr} {element_type} {field_name} 
 997             -L    iterate over a linkage chain (method 1) [default] 
 998             -Q    iterate over a queue         (method 2) 
1000             -S    auto-summarize known types 
1001             -G    regex to filter the output 
1003             iterate_linkage `&coalitions_q` 'coalition *' coalitions 
1006         raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}") 
1008     qhead 
= kern
.GetValueFromAddress(cmd_args
[0], 'struct queue_entry *') 
1010         raise ArgumentError("Unknown queue_head pointer: %r" % cmd_args
) 
1011     elem_type 
= cmd_args
[1] 
1012     field_name 
= cmd_args
[2] 
1013     if not elem_type 
or not field_name
: 
1014         raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}") 
1016     do_queue_iterate 
= False 
1017     do_linkage_iterate 
= True 
1018     if "-Q" in cmd_options
: 
1019         do_queue_iterate 
= True 
1020         do_linkage_iterate 
= False 
1021     if "-L" in cmd_options
: 
1022         do_queue_iterate 
= False 
1023         do_linkage_iterate 
= True 
1026     if "-S" in cmd_options
: 
1029     if "-G" in cmd_options
: 
1030         regex 
= re
.compile(".*{:s}.*".format(cmd_options
["-G"])) 
1031         print "Looking for: {:s}".format(regex
.pattern
) 
1033     global lldb_summary_definitions
 
1035     if elem_type 
in lldb_summary_definitions
: 
1036         summary 
= lldb_summary_definitions
[elem_type
] 
1038             print summary
.header
 
1042         if do_linkage_iterate
: 
1043             for elem 
in IterateLinkageChain(qhead
, elem_type
, field_name
): 
1044                 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
) 
1046         elif do_queue_iterate
: 
1047             for elem 
in IterateQueue(qhead
, elem_type
, field_name
): 
1048                 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
) 
1051         print "Exception while looking at queue_head: {:#x}".format(unsigned(qhead
))