2 Miscellaneous (Intel) platform-specific commands.
8 from scheduler
import *
10 @lldb_command('showmcastate')
11 def showMCAstate(cmd_args
=None):
13 Print machine-check register state after MC exception.
15 if kern
.arch
!= 'x86_64':
16 print "Not available for current architecture."
19 present
= ["not present", "present"]
20 print 'MCA {:s}, control MSR {:s}, threshold status {:s}'.format(
21 present
[int(kern
.globals.mca_MCA_present
)],
22 present
[int(kern
.globals.mca_control_MSR_present
)],
23 present
[int(kern
.globals.mca_threshold_status_present
)])
24 print '{:d} error banks, family code {:#0x}, machine-check dump state: {:d}'.format(
25 kern
.globals.mca_error_bank_count
,
26 kern
.globals.mca_dump_state
,
27 kern
.globals.mca_family
)
29 while kern
.globals.cpu_data_ptr
[cpu
]:
30 cd
= kern
.globals.cpu_data_ptr
[cpu
]
33 print 'CPU {:d}: mca_mcg_ctl: {:#018x} mca_mcg_status {:#018x}'.format(cpu
, mc
.mca_mcg_ctl
, mc
.mca_mcg_status
.u64
)
34 hdr
= '{:<4s} {:<18s} {:<18s} {:<18s} {:<18s}'
35 val
= '{:>3d}: {:#018x} {:#018x} {:#018x} {:#018x}'
36 print hdr
.format('bank',
41 for i
in range(int(kern
.globals.mca_error_bank_count
)):
42 bank
= mc
.mca_error_bank
[i
]
45 bank
.mca_mci_status
.u64
,
48 print 'register state:'
49 reg
= cd
.cpu_desc_index
.cdi_ktss
.ist1
- sizeof('x86_saved_state_t')
50 print lldb_run_command('p/x *(x86_saved_state_t *) ' + hex(reg
))
53 def dumpTimerList(anchor
):
55 Utility function to dump the timer entries in list (anchor).
57 entry
= Cast(anchor
.head
, 'queue_t')
58 if entry
== addressof(anchor
):
62 thdr
= ' {:<22s}{:<17s}{:<16s} {:<14s} {:<18s}'
63 print thdr
.format('entry:','deadline','soft_deadline','to go','(*func)(param0,param1')
64 while entry
!= addressof(anchor
):
65 timer_call
= Cast(entry
, 'timer_call_t')
66 call_entry
= Cast(entry
, 'struct call_entry *')
67 recent_timestamp
= GetRecentTimestamp()
68 if (recent_timestamp
< call_entry
.deadline
):
70 timer_fire
= call_entry
.deadline
- recent_timestamp
73 timer_fire
= recent_timestamp
- call_entry
.deadline
75 func_name
= kern
.Symbolicate(call_entry
.func
)
77 tval
= ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d} ({:#018x})({:#018x},{:#018x}) ({:s})'
78 print tval
.format(entry
,
80 timer_call
.soft_deadline
,
82 timer_fire
/1000000000,
83 timer_fire
%1000000000,
90 def GetCpuDataForCpuID(cpu_id
):
92 Find struct cpu_data for a CPU
95 if kern
.arch
== 'x86_64':
96 cpu_data
= kern
.globals.cpu_data_ptr
[cpu_id
]
98 elif kern
.arch
in ['arm', 'arm64'] :
99 data_entries_addr
= kern
.GetLoadAddressForSymbol('CpuDataEntries')
100 data_entries
= kern
.GetValueFromAddress(data_entries_addr
, 'cpu_data_entry_t *')
101 data_entry
= data_entries
[cpu_id
];
102 cpu_data_addr
= data_entry
.cpu_data_vaddr
103 return Cast(cpu_data_addr
, 'cpu_data_t*')
105 @lldb_command('longtermtimers')
106 def longtermTimers(cmd_args
=None):
108 Print details of long-term timers and stats.
111 lt
= kern
.globals.timer_longterm
114 if ltt
.interval
== EndofAllTime
:
115 print "Longterm timers disabled"
119 ratio
= lt
.enqueues
/ lt
.escalates
122 print 'Longterm timer object: {:#018x}'.format(addressof(lt
))
123 print ' queue count : {:d}' .format(lt
.queue
.count
)
124 print ' number of enqueues : {:d}' .format(lt
.enqueues
)
125 print ' number of dequeues : {:d}' .format(lt
.dequeues
)
126 print ' number of escalates : {:d}' .format(lt
.escalates
)
127 print ' enqueues/escalates : {:d}' .format(ratio
)
128 print ' threshold.interval : {:d}' .format(ltt
.interval
)
129 print ' threshold.margin : {:d}' .format(ltt
.margin
)
130 print ' scan_time : {:d}' .format(lt
.scan_time
)
131 if ltt
.preempted
== EndofAllTime
:
132 print ' threshold.preempted : None'
134 print ' threshold.preempted : {:d}' .format(ltt
.preempted
)
135 if ltt
.deadline
== EndofAllTime
:
136 print ' threshold.deadline : None'
138 print ' threshold.deadline : {:d}' .format(ltt
.deadline
)
139 print ' threshold.call : {:#018x}'.format(ltt
.call
)
140 print ' actual deadline set : {:d}' .format(ltt
.deadline_set
)
141 print ' threshold.scans : {:d}' .format(ltt
.scans
)
142 print ' threshold.preempts : {:d}' .format(ltt
.preempts
)
143 print ' threshold.latency : {:d}' .format(ltt
.latency
)
144 print ' - min : {:d}' .format(ltt
.latency_min
)
145 print ' - max : {:d}' .format(ltt
.latency_max
)
146 dumpTimerList(lt
.queue
)
149 @lldb_command('processortimers')
150 def processorTimers(cmd_args
=None):
152 Print details of processor timers, noting anything suspicious
153 Also include long-term timer details
155 hdr
= '{:<32s}{:<18s} {:<18s} {:<18s}'
156 print hdr
.format('Processor','Last dispatch','Next deadline','difference')
157 p
= kern
.globals.processor_list
160 cpu_data
= GetCpuDataForCpuID(cpu
)
161 rt_timer
= cpu_data
.rtclock_timer
162 diff
= p
.last_dispatch
- rt_timer
.deadline
163 tmr
= 'Processor {:d}: {:#018x} {:#018x} {:#018x} {:#018x} {:s}'
164 print tmr
.format(cpu
,
169 ['probably BAD', '(ok)'][int(diff
< 0)])
170 if kern
.arch
== 'x86_64':
171 print 'Next deadline set at: {:#018x}. Timer call list:'.format(rt_timer
.when_set
)
172 dumpTimerList(rt_timer
.queue
)
177 @lldb_command('showtimerwakeupstats')
178 def showTimerWakeupStats(cmd_args
=None):
180 Displays interrupt and platform idle wakeup frequencies
181 associated with each thread, timer time-to-deadline frequencies, and
182 CPU time with user/system break down where applicable, with thread tags.
184 for task
in kern
.tasks
:
185 proc
= Cast(task
.bsd_info
, 'proc_t')
186 print dereference(task
)
187 print '{:d}({:s}), terminated thread timer wakeups: {:d} {:d} 2ms: {:d} 5ms: {:d} UT: {:d} ST: {:d}'.format(
190 # Commented-out references below to be addressed by rdar://13009660.
191 0, #task.task_interrupt_wakeups,
192 0, #task.task_platform_idle_wakeups,
193 task
.task_timer_wakeups_bin_1
,
194 task
.task_timer_wakeups_bin_2
,
195 task
.total_user_time
,
196 task
.total_system_time
)
197 tot_wakes
= 0 #task.task_interrupt_wakeups
198 tot_platform_wakes
= 0 #task.task_platform_idle_wakeups
199 for thread
in IterateQueue(task
.threads
, 'thread_t', 'task_threads'):
200 ## if thread.thread_interrupt_wakeups == 0:
202 print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format(
205 0, #thread.thread_interrupt_wakeups,
206 0, #thread.thread_platform_idle_wakeups,
207 0, #thread.thread_callout_interrupt_wakeups,
208 0, #thread.thread_callout_platform_idle_wakeups,
210 thread
.thread_timer_wakeups_bin_1
,
211 thread
.thread_timer_wakeups_bin_2
,
212 thread
.user_timer
.all_bits
,
213 thread
.system_timer
.all_bits
)
214 tot_wakes
+= 0 #thread.thread_interrupt_wakeups
215 tot_platform_wakes
+= 0 #thread.thread_platform_idle_wakeups
216 print 'Task total wakeups: {:d} {:d}'.format(
217 tot_wakes
, tot_platform_wakes
)
219 def DoReadMsr64(msr_address
, lcpu
):
220 """ Read a 64-bit MSR from the specified CPU
222 msr_address: int - MSR index to read from
223 lcpu: int - CPU identifier
225 64-bit value read from the MSR
229 if "kdp" != GetConnectionProtocol():
230 print "Target is not connected over kdp. Cannot read MSR."
233 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
234 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
235 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
236 if not WriteInt32ToMemoryAddress(0, input_address
):
237 print "DoReadMsr64() failed to write 0 to input_address"
240 kdp_pkt_size
= GetType('kdp_readmsr64_req_t').GetByteSize()
241 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
242 print "DoReadMsr64() failed to write kdp_pkt_size"
245 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_readmsr64_req_t *')
246 header_value
= GetKDPPacketHeaderInt(
247 request
=GetEnumValue('kdp_req_t::KDP_READMSR64'),
250 if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))):
251 print "DoReadMsr64() failed to write header_value"
253 if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))):
254 print "DoReadMsr64() failed to write msr_address"
256 if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))):
257 print "DoReadMsr64() failed to write lcpu"
259 if not WriteInt32ToMemoryAddress(1, input_address
):
260 print "DoReadMsr64() failed to write to input_address"
263 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
),
264 'kdp_readmsr64_reply_t *')
265 if (result_pkt
.error
== 0):
266 result
= dereference(Cast(addressof(result_pkt
.data
), 'uint64_t *'))
268 print "DoReadMsr64() result_pkt.error != 0"
271 def DoWriteMsr64(msr_address
, lcpu
, data
):
272 """ Write a 64-bit MSR
274 msr_address: int - MSR index to write to
275 lcpu: int - CPU identifier
276 data: int - value to write
278 True upon success, False if error
280 if "kdp" != GetConnectionProtocol():
281 print "Target is not connected over kdp. Cannot write MSR."
284 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
285 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
286 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
287 if not WriteInt32ToMemoryAddress(0, input_address
):
288 print "DoWriteMsr64() failed to write 0 to input_address"
291 kdp_pkt_size
= GetType('kdp_writemsr64_req_t').GetByteSize()
292 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
293 print "DoWriteMsr64() failed to kdp_pkt_size"
296 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_writemsr64_req_t *')
297 header_value
= GetKDPPacketHeaderInt(
298 request
=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'),
301 if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))):
302 print "DoWriteMsr64() failed to write header_value"
304 if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))):
305 print "DoWriteMsr64() failed to write msr_address"
307 if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))):
308 print "DoWriteMsr64() failed to write lcpu"
310 if not WriteInt64ToMemoryAddress(data
, int(addressof(kgm_pkt
.data
))):
311 print "DoWriteMsr64() failed to write data"
313 if not WriteInt32ToMemoryAddress(1, input_address
):
314 print "DoWriteMsr64() failed to write to input_address"
317 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
),
318 'kdp_writemsr64_reply_t *')
319 if not result_pkt
.error
== 0:
320 print "DoWriteMsr64() error received in reply packet"
325 @lldb_command('readmsr64')
326 def ReadMsr64(cmd_args
=None):
327 """ Read the specified MSR. The CPU can be optionally specified
328 Syntax: readmsr64 <msr> [lcpu]
330 if cmd_args
== None or len(cmd_args
) < 1:
331 print ReadMsr64
.__doc__
334 msr_address
= ArgumentStringToInt(cmd_args
[0])
335 if len(cmd_args
) > 1:
336 lcpu
= ArgumentStringToInt(cmd_args
[1])
338 lcpu
= int(xnudefines
.lcpu_self
)
340 msr_value
= DoReadMsr64(msr_address
, lcpu
)
341 print "MSR[{:x}]: {:#016x}".format(msr_address
, msr_value
)
343 @lldb_command('writemsr64')
344 def WriteMsr64(cmd_args
=None):
345 """ Write the specified MSR. The CPU can be optionally specified
346 Syntax: writemsr64 <msr> <value> [lcpu]
348 if cmd_args
== None or len(cmd_args
) < 2:
349 print WriteMsr64
.__doc__
351 msr_address
= ArgumentStringToInt(cmd_args
[0])
352 write_val
= ArgumentStringToInt(cmd_args
[1])
353 if len(cmd_args
) > 2:
354 lcpu
= ArgumentStringToInt(cmd_args
[2])
356 lcpu
= xnudefines
.lcpu_self
358 if not DoWriteMsr64(msr_address
, lcpu
, write_val
):
359 print "writemsr64 FAILED"
361 def GetEVFlags(debug_arg
):
362 """ Return the EV Flags for the given kernel debug arg value
364 debug_arg - value from arg member of kernel debug buffer entry
366 str - string representing the EV Flag for given input arg value
377 if debug_arg
& 0x00100:
378 out_str
+= "EV_RBYTES "
379 if debug_arg
& 0x00200:
380 out_str
+= "EV_WBYTES "
381 if debug_arg
& 0x00400:
382 out_str
+= "EV_RCLOSED "
383 if debug_arg
& 0x00800:
384 out_str
+= "EV_RCONN "
385 if debug_arg
& 0x01000:
386 out_str
+= "EV_WCLOSED "
387 if debug_arg
& 0x02000:
388 out_str
+= "EV_WCONN "
389 if debug_arg
& 0x04000:
391 if debug_arg
& 0x08000:
393 if debug_arg
& 0x10000:
394 out_str
+= "EV_RESET "
395 if debug_arg
& 0x20000:
396 out_str
+= "EV_TIMEOUT "
400 def GetKernelDebugBufferEntry(kdbg_entry
):
401 """ Extract the information from given kernel debug buffer entry and return the summary
403 kdebug_entry - kd_buf - address of kernel debug buffer entry
405 str - formatted output information of kd_buf entry
409 kdebug_entry
= kern
.GetValueFromAddress(kdbg_entry
, 'kd_buf *')
410 debugid
= kdebug_entry
.debugid
411 kdebug_arg1
= kdebug_entry
.arg1
412 kdebug_arg2
= kdebug_entry
.arg2
413 kdebug_arg3
= kdebug_entry
.arg3
414 kdebug_arg4
= kdebug_entry
.arg4
416 if kern
.arch
== 'x86_64' or kern
.arch
.startswith('arm64'):
417 kdebug_cpu
= kdebug_entry
.cpuid
418 ts_hi
= (kdebug_entry
.timestamp
>> 32) & 0xFFFFFFFF
419 ts_lo
= kdebug_entry
.timestamp
& 0xFFFFFFFF
421 kdebug_cpu
= (kdebug_entry
.timestamp
>> 56)
422 ts_hi
= (kdebug_entry
.timestamp
>> 32) & 0x00FFFFFF
423 ts_lo
= kdebug_entry
.timestamp
& 0xFFFFFFFF
425 kdebug_class
= (debugid
>> 24) & 0x000FF
426 kdebug_subclass
= (debugid
>> 16) & 0x000FF
427 kdebug_code
= (debugid
>> 2) & 0x03FFF
428 kdebug_qual
= (debugid
) & 0x00003
432 elif kdebug_qual
== 1:
434 elif kdebug_qual
== 2:
436 elif kdebug_qual
== 3:
440 out_str
+= "{:<#20x} {:>6d} {:>#12x} ".format(kdebug_entry
, kdebug_cpu
, kdebug_entry
.arg5
)
441 out_str
+= " {:#010x}{:08x} {:>6s} ".format(ts_hi
, ts_lo
, kdebug_qual
)
445 if kdebug_class
== 1:
447 elif kdebug_class
== 2:
449 elif kdebug_class
== 3:
451 elif kdebug_class
== 4:
453 elif kdebug_class
== 5:
455 elif kdebug_class
== 6:
457 elif kdebug_class
== 7:
459 elif kdebug_class
== 8:
461 elif kdebug_class
== 9:
463 elif kdebug_class
== 10:
465 elif kdebug_class
== 11:
467 elif kdebug_class
== 20:
469 elif kdebug_class
== 30:
471 elif kdebug_class
== 31:
473 elif kdebug_class
== 32:
475 elif kdebug_class
== 33:
477 elif kdebug_class
== 34:
479 elif kdebug_class
== 36:
481 elif kdebug_class
== 37:
483 elif kdebug_class
== 38:
485 elif kdebug_class
== 39:
487 elif kdebug_class
== 40:
489 elif kdebug_class
== 41:
491 elif kdebug_class
== 42:
493 elif kdebug_class
== 128:
495 elif kdebug_class
== 129:
497 elif kdebug_class
== 130:
499 elif kdebug_class
== 131:
501 elif kdebug_class
== 132:
503 elif kdebug_class
== 133:
505 elif kdebug_class
== 255:
508 out_str
+= "{:^#10x} ".format(kdebug_class
)
511 out_str
+= "{:^10s} ".format(kdbg_class
)
514 out_str
+= " {:>#5x} {:>8d} ".format(kdebug_subclass
, kdebug_code
)
516 # space for debugid-specific processing
517 # EVPROC from bsd/kern/sys_generic.c
518 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
519 if debugid
== 0x14100048:
520 code_info_str
+= "waitevent "
522 code_info_str
+= "before sleep"
523 elif kdebug_arg1
== 2:
524 code_info_str
+= "after sleep"
526 code_info_str
+= "????????????"
527 code_info_str
+= " chan={:#08x} ".format(kdebug_arg2
)
528 elif debugid
== 0x14100049:
529 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_START)
530 code_info_str
+= "waitevent "
531 elif debugid
== 0x1410004a:
532 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_END)
533 code_info_str
+= "waitevent error={:d} ".format(kdebug_arg1
)
534 code_info_str
+= "eqp={:#08x} ".format(kdebug_arg4
)
535 code_info_str
+= GetEVFlags(kdebug_arg3
)
536 code_info_str
+= "er_handle={:d} ".format(kdebug_arg2
)
537 elif debugid
== 0x14100059:
538 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_START)
539 code_info_str
+= "evprocdeque proc={:#08x} ".format(kdebug_arg1
)
541 code_info_str
+= "remove first "
543 code_info_str
+= "remove {:#08x} ".format(kdebug_arg2
)
544 elif debugid
== 0x1410005a:
545 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_END)
546 code_info_str
+= "evprocdeque "
548 code_info_str
+= "result=NULL "
550 code_info_str
+= "result={:#08x} ".format(kdebug_arg1
)
551 elif debugid
== 0x14100041:
552 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_START)
553 code_info_str
+= "postevent "
554 code_info_str
+= GetEVFlags(kdebug_arg1
)
555 elif debugid
== 0x14100040:
556 # MISCDBG_CODE(DBG_EVENT,DBG_POST)
557 code_info_str
+= "postevent "
558 code_info_str
+= "evq={:#08x} ".format(kdebug_arg1
)
559 code_info_str
+= "er_eventbits="
560 code_info_str
+= GetEVFlags(kdebug_arg2
)
561 code_info_str
+="mask="
562 code_info_str
+= GetEVFlags(kdebug_arg3
)
563 elif debugid
== 0x14100042:
564 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_END)
565 code_info_str
+= "postevent "
566 elif debugid
== 0x14100055:
567 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_START)
568 code_info_str
+= "evprocenque eqp={:#08x} ".format(kdebug_arg1
)
570 code_info_str
+= "EV_QUEUED "
571 code_info_str
+= GetEVFlags(kdebug_arg3
)
572 elif debugid
== 0x14100050:
573 # MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
574 code_info_str
+= "evprocenque before wakeup eqp={:#08x} ".format(kdebug_arg4
)
575 elif debugid
== 0x14100056:
576 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_END)
577 code_info_str
+= "evprocenque "
578 elif debugid
== 0x1410004d:
579 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_START)
580 code_info_str
+= "modwatch "
581 elif debugid
== 0x1410004c:
582 # MISCDBG_CODE(DBG_EVENT,DBG_MOD)
583 code_info_str
+= "modwatch er_handle={:d} ".format(kdebug_arg1
)
584 code_info_str
+= GetEVFlags(kdebug_arg2
)
585 code_info_str
+= "evq={:#08x} ", kdebug_arg3
586 elif debugid
== 0x1410004e:
587 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_END)
588 code_info_str
+= "modwatch er_handle={:d} ".format(kdebug_arg1
)
589 code_info_str
+= "ee_eventmask="
590 code_info_str
+= GetEVFlags(kdebug_arg2
)
591 code_info_str
+= "sp={:#08x} ".format(kdebug_arg3
)
592 code_info_str
+= "flag="
593 code_info_str
+= GetEVFlags(kdebug_arg4
)
595 code_info_str
+= "arg1={:#010x} ".format(kdebug_arg1
)
596 code_info_str
+= "arg2={:#010x} ".format(kdebug_arg2
)
597 code_info_str
+= "arg3={:#010x} ".format(kdebug_arg3
)
598 code_info_str
+= "arg4={:#010x} ".format(kdebug_arg4
)
601 out_str
+= "{:<25s}\n".format(code_info_str
)
604 @lldb_command('showkerneldebugbuffercpu')
605 @header("{0: ^20s} {1: >6s} {2: >12s} {3: ^20s} {4: >6s} {5: ^10s} {6: >5s} {7: >8s} {8: ^25s}".
606 format('kd_buf', 'CPU', 'Thread', 'Timestamp', 'S/E', 'Class', 'Sub', 'Code', 'Code Specific Info'))
607 def ShowKernelDebugBufferCPU(cmd_args
=None):
608 """ Prints the last N entries in the kernel debug buffer for specified cpu
609 Syntax: showkerneldebugbuffercpu <cpu_num> <count>
611 if cmd_args
== None or len(cmd_args
) < 2:
612 raise ArgumentError("Invalid arguments passed.")
616 cpu_number
= ArgumentStringToInt(cmd_args
[0])
617 entry_count
= ArgumentStringToInt(cmd_args
[1])
618 debugentriesfound
= 0
619 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
620 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& 0x80000000):
621 out_str
+= ShowKernelDebugBufferCPU
.header
+ "\n"
623 out_str
+= "<count> is 0, dumping 50 entries\n"
626 if cpu_number
>= kern
.globals.kd_ctrl_page
.kdebug_cpus
:
627 kdbg_str
+= "cpu number too big\n"
629 kdbp
= addressof(kern
.globals.kdbip
[cpu_number
])
630 kdsp
= kdbp
.kd_list_head
631 while ((kdsp
.raw
!= 0 and kdsp
.raw
!= 0x00000000ffffffff) and (entry_count
> 0)):
632 kd_buffer
= kern
.globals.kd_bufs
[kdsp
.buffer_index
]
633 kdsp_actual
= addressof(kd_buffer
.kdsb_addr
[kdsp
.offset
])
634 if kdsp_actual
.kds_readlast
!= kdsp_actual
.kds_bufindx
:
635 kds_buf
= kdsp_actual
.kds_records
[kdsp_actual
.kds_bufindx
]
636 kds_bufptr
= addressof(kds_buf
)
637 while (entry_count
> 0) and \
638 (unsigned(kds_bufptr
) > unsigned(addressof(kdsp_actual
.kds_records
[kdsp_actual
.kds_readlast
]))):
639 kds_bufptr
= kds_bufptr
- sizeof(kds_buf
)
640 entry_count
= entry_count
- 1
641 kdbg_str
+= GetKernelDebugBufferEntry(kds_bufptr
)
642 kdsp
= kdsp_actual
.kds_next
644 kdbg_str
+= "Trace buffer not enabled for CPU {:d}\n".format(cpu_number
)
650 @lldb_command('showkerneldebugbuffer')
651 def ShowKernelDebugBuffer(cmd_args
=None):
652 """ Prints the last N entries in the kernel debug buffer per cpu
653 Syntax: showkerneldebugbuffer <count>
655 if cmd_args
== None or len(cmd_args
) < 1:
656 raise ArgumentError("Invalid arguments passed.")
658 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
659 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& 0x80000000):
660 entrycount
= ArgumentStringToInt(cmd_args
[0])
662 print "<count> is 0, dumping 50 entries per cpu\n"
665 while cpu_num
< kern
.globals.kd_ctrl_page
.kdebug_cpus
:
666 ShowKernelDebugBufferCPU([str(cpu_num
), str(entrycount
)])
669 print "Trace buffer not enabled\n"
671 @lldb_command('dumprawtracefile','U:')
672 def DumpRawTraceFile(cmd_args
=[], cmd_options
={}):
674 support for ktrace(1)
676 NB: trace is not wordsize flexible, so use ktrace(1) compiled for the compatible model,
677 e.g. if you dump from __LP64__ system, you will need to run ktrace(1) compiled __LP64__ to process the raw data file.
679 read the kernel's debug trace buffer, and dump to a "raw" ktrace(1) file
680 Usage: dumprawtracefile <output_filename>
681 -U <uptime> : specify system uptime in nsec, obtained e.g. from paniclog
682 Be patient, it is teh slow.
684 cf. kdbg_read()\bsd/kern/kdebug.c
687 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
688 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& xnudefines
.KDBG_BFINIT
) == 0 :
689 print "Trace buffer not enabled\n"
692 if ((kern
.arch
== "x86_64") or (kern
.arch
== "arm64")) :
694 elif kern
.arch
== "arm" :
697 print "unknown kern.arch {:s}\n".format(kern
.arch
)
700 # Various kern.globals are hashed by address, to
701 # a) avoid redundant kdp fetch from, and
702 # b) avoid all stores to
703 # the target system kernel structures.
704 # Stores to hashed structures remain strictly local to the lldb host,
705 # they are never written back to the target.
709 KDBG_TIMESTAMP_MASK
= 0xffffffffffffffff
711 KDBG_TIMESTAMP_MASK
= 0x00ffffffffffffff
716 out_of_events
= False
718 lostevent_timestamp
= 0
719 lostevent_debugid
= (((xnudefines
.DBG_TRACE
& 0xff) << 24) |
((xnudefines
.DBG_TRACE_INFO
& 0xff) << 16) |
((2 & 0x3fff) << 2)) # 0x01020008
720 events_count_lost
= 0
721 events_count_found
= 0
723 opt_verbose
= config
['verbosity']
724 opt_progress
= (opt_verbose
> vHUMAN
) and (opt_verbose
< vDETAIL
)
728 output_filename
= str(cmd_args
[0])
729 if opt_verbose
> vHUMAN
:
730 print "output file : {:s}".format(output_filename
)
731 wfd
= open(output_filename
, "wb")
734 if "-U" in cmd_options
:
735 uptime
= long(cmd_options
["-U"])
736 if opt_verbose
> vHUMAN
:
737 print "uptime : {:d}".format(uptime
)
739 nkdbufs
= kern
.globals.nkdbufs
741 kd_ctrl_page
= kern
.globals.kd_ctrl_page
742 if not kd_ctrl_page
in htab
:
743 htab
[kd_ctrl_page
] = kern
.globals.kd_ctrl_page
745 if opt_verbose
> vHUMAN
:
746 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
)
749 print "0 nkdbufs, nothing extracted"
752 if htab
[kd_ctrl_page
].enabled
!= 0 :
753 barrier_max
= uptime
& KDBG_TIMESTAMP_MASK
755 f
= htab
[kd_ctrl_page
].kdebug_flags
756 wrapped
= f
& xnudefines
.KDBG_WRAPPED
758 barrier_min
= htab
[kd_ctrl_page
].oldest_time
759 htab
[kd_ctrl_page
].kdebug_flags
= htab
[kd_ctrl_page
].kdebug_flags
& ~xnudefines
.KDBG_WRAPPED
760 htab
[kd_ctrl_page
].oldest_time
= 0
762 for cpu
in range(htab
[kd_ctrl_page
].kdebug_cpus
) :
763 kdbp
= unsigned(addressof(kern
.globals.kdbip
[cpu
]))
764 if not kdbp
in htab
:
765 htab
[kdbp
] = kern
.globals.kdbip
[cpu
]
767 kdsp
= htab
[kdbp
].kd_list_head
.raw
768 if kdsp
== xnudefines
.KDS_PTR_NULL
:
771 ix
= htab
[kdbp
].kd_list_head
.buffer_index
772 off
= htab
[kdbp
].kd_list_head
.offset
773 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
774 if not kdsp_actual
in htab
:
775 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
776 htab
[kdsp_actual
].kds_lostevents
= False
779 # generate trace file header; threadmap is stubbed/TBD
780 version_no
= xnudefines
.RAW_VERSION1
784 header
= struct
.pack('IIqI', version_no
, thread_count
, TOD_secs
, TOD_usecs
)
785 pad_bytes
= 4096 - (len(header
) & 4095)
786 header
+= "\x00" * pad_bytes
787 wfd
.write(buffer(header
))
793 tempbuf_count
= min(count
, xnudefines
.KDCOPYBUF_COUNT
)
796 while tempbuf_count
!= 0 :
798 if opt_progress
== True :
800 if (progress_count
% progress_stride
) == 0 :
801 sys
.stderr
.write('.')
804 earliest_time
= 0xffffffffffffffff
809 for cpu
in range(htab
[kd_ctrl_page
].kdebug_cpus
) :
811 kdbp
= unsigned(addressof(kern
.globals.kdbip
[cpu
]))
812 if not kdbp
in htab
:
813 htab
[kdbp
] = kern
.globals.kdbip
[cpu
]
815 # Skip CPUs without data.
816 kdsp
= htab
[kdbp
].kd_list_head
817 if kdsp
.raw
== xnudefines
.KDS_PTR_NULL
:
822 # Get from cpu data to buffer header to buffer
823 ix
= kdsp
.buffer_index
825 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
826 if not kdsp_actual
in htab
:
827 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
829 kdsp_actual_shadow
= kdsp_actual
831 # Skip buffer if there are no events left.
832 rcursor
= htab
[kdsp_actual
].kds_readlast
833 if rcursor
== htab
[kdsp_actual
].kds_bufindx
:
836 t
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp
& KDBG_TIMESTAMP_MASK
838 # Ignore events that have aged out due to wrapping.
839 goto_next_cpu
= False;
840 while (t
< unsigned(barrier_min
)) :
841 r
= htab
[kdsp_actual
].kds_readlast
842 htab
[kdsp_actual
].kds_readlast
= r
+ 1
845 if rcursor
>= xnudefines
.EVENTS_PER_STORAGE_UNIT
:
847 kdsp
= htab
[kdbp
].kd_list_head
848 if kdsp
.raw
== xnudefines
.KDS_PTR_NULL
:
854 ix
= kdsp
.buffer_index
856 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
858 kdsp_actual_shadow
= kdsp_actual
;
859 rcursor
= htab
[kdsp_actual
].kds_readlast
;
861 t
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp
& KDBG_TIMESTAMP_MASK
863 if goto_next_cpu
== True :
866 if (t
> barrier_max
) and (barrier_max
> 0) :
867 # Need to flush IOPs again before we
868 # can sort any more data from the
873 if t
< (htab
[kdsp_actual
].kds_timestamp
& KDBG_TIMESTAMP_MASK
) :
874 # indicates we've not yet completed filling
876 # this should only occur when we're looking
877 # at the buf that the record head is utilizing
878 # we'll pick these events up on the next
880 # we bail at this point so that we don't
881 # get an out-of-order timestream by continuing
882 # to read events from the other CPUs' timestream(s)
886 if t
< earliest_time
:
892 if (min_kdbp
is None) or (out_of_events
== True) :
893 # all buffers ran empty
897 kdsp
= htab
[min_kdbp
].kd_list_head
899 ix
= kdsp
.buffer_index
901 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
902 if not kdsp_actual
in htab
:
903 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
905 # Copy earliest event into merged events scratch buffer.
906 r
= htab
[kdsp_actual
].kds_readlast
907 htab
[kdsp_actual
].kds_readlast
= r
+ 1
908 e
= htab
[kdsp_actual
].kds_records
[r
]
910 # Concatenate event into buffer
911 # XXX condition here is on __LP64__
913 tempbuf
+= struct
.pack('QQQQQQIIQ',
914 e
.timestamp
, e
.arg1
, e
.arg2
, e
.arg3
, e
.arg4
, e
.arg5
, e
.debugid
, e
.cpuid
, e
.unused
)
916 tempbuf
+= struct
.pack('QIIIIII',
917 e
.timestamp
, e
.arg1
, e
.arg2
, e
.arg3
, e
.arg4
, e
.arg5
, e
.debugid
)
919 # Watch for out of order timestamps
920 if earliest_time
< (htab
[min_kdbp
].kd_prev_timebase
& KDBG_TIMESTAMP_MASK
) :
921 ## if so, use the previous timestamp + 1 cycle
922 htab
[min_kdbp
].kd_prev_timebase
+= 1
924 e
.timestamp
= htab
[min_kdbp
].kd_prev_timebase
& KDBG_TIMESTAMP_MASK
925 e
.timestamp |
= (min_cpu
<< KDBG_CPU_SHIFT
)
927 htab
[min_kdbp
].kd_prev_timebase
= earliest_time
929 if opt_verbose
>= vDETAIL
:
930 print "{0:#018x} {1:#018x} {2:#018x} {3:#018x} {4:#018x} {5:#018x} {6:#010x} {7:#010x} {8:#018x}".format(
931 e
.timestamp
, e
.arg1
, e
.arg2
, e
.arg3
, e
.arg4
, e
.arg5
, e
.debugid
, e
.cpuid
, e
.unused
)
933 events_count_found
+= 1
939 if opt_progress
== True :
940 sys
.stderr
.write('\n')
943 if opt_verbose
> vHUMAN
:
944 print "events_count_lost {0:#x}, events_count_found {1:#x}, progress_count {2:#x}".format(events_count_lost
, events_count_found
, progress_count
)
946 # write trace events to output file
947 if tempbuf_number
!= 0 :
948 count
-= tempbuf_number
949 wfd
.write(buffer(tempbuf
))
951 if out_of_events
== True :
952 # all trace buffers are empty
953 if opt_verbose
> vHUMAN
:
954 print "out of events"
962 def PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
):
964 if do_summary
and summary
:
968 print "[{:d}] {:s}".format(i
, s
)
970 print "[{:d}] {:s}".format(i
, s
)
973 if regex
.match(str(elem
)):
974 print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
))
976 print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
))
978 print "Exception while looking at elem {:#x}".format(unsigned(elem
))
981 @lldb_command('q_iterate', "LQSG:")
982 def QIterate(cmd_args
=None, cmd_options
={}):
983 """ Iterate over a LinkageChain or Queue (osfmk/kern/queue.h method 1 or 2 respectively)
984 This is equivalent to the qe_foreach_element() macro
986 iterate [options] {queue_head_ptr} {element_type} {field_name}
988 -L iterate over a linkage chain (method 1) [default]
989 -Q iterate over a queue (method 2)
991 -S auto-summarize known types
992 -G regex to filter the output
994 iterate_linkage `&coalitions_q` 'coalition *' coalitions
997 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
999 qhead
= kern
.GetValueFromAddress(cmd_args
[0], 'struct queue_entry *')
1001 raise ArgumentError("Unknown queue_head pointer: %r" % cmd_args
)
1002 elem_type
= cmd_args
[1]
1003 field_name
= cmd_args
[2]
1004 if not elem_type
or not field_name
:
1005 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
1007 do_queue_iterate
= False
1008 do_linkage_iterate
= True
1009 if "-Q" in cmd_options
:
1010 do_queue_iterate
= True
1011 do_linkage_iterate
= False
1012 if "-L" in cmd_options
:
1013 do_queue_iterate
= False
1014 do_linkage_iterate
= True
1017 if "-S" in cmd_options
:
1020 if "-G" in cmd_options
:
1021 regex
= re
.compile(".*{:s}.*".format(cmd_options
["-G"]))
1022 print "Looking for: {:s}".format(regex
.pattern
)
1024 global lldb_summary_definitions
1026 if elem_type
in lldb_summary_definitions
:
1027 summary
= lldb_summary_definitions
[elem_type
]
1029 print summary
.header
1033 if do_linkage_iterate
:
1034 for elem
in IterateLinkageChain(qhead
, elem_type
, field_name
):
1035 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
)
1037 elif do_queue_iterate
:
1038 for elem
in IterateQueue(qhead
, elem_type
, field_name
):
1039 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
)
1042 print "Exception while looking at queue_head: {:#x}".format(unsigned(qhead
))