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(anchor
):
86 Utility function to dump the timer entries in list (anchor).
88 entry
= Cast(anchor
.head
, 'queue_t')
89 if entry
== addressof(anchor
):
93 thdr
= ' {:<22s}{:<17s}{:<16s} {:<14s} {:<18s}'
94 print thdr
.format('entry:','deadline','soft_deadline','to go','(*func)(param0,param1')
95 while entry
!= addressof(anchor
):
96 timer_call
= Cast(entry
, 'timer_call_t')
97 call_entry
= Cast(entry
, 'struct call_entry *')
98 recent_timestamp
= GetRecentTimestamp()
99 if (recent_timestamp
< call_entry
.deadline
):
101 timer_fire
= call_entry
.deadline
- recent_timestamp
104 timer_fire
= recent_timestamp
- call_entry
.deadline
106 func_name
= kern
.Symbolicate(call_entry
.func
)
108 tval
= ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d} ({:#018x})({:#018x},{:#018x}) ({:s})'
109 print tval
.format(entry
,
111 timer_call
.soft_deadline
,
113 timer_fire
/1000000000,
114 timer_fire
%1000000000,
121 def GetCpuDataForCpuID(cpu_id
):
123 Find struct cpu_data for a CPU
126 if kern
.arch
== 'x86_64':
127 cpu_data
= kern
.globals.cpu_data_ptr
[cpu_id
]
129 elif kern
.arch
.startswith('arm'):
130 data_entries_addr
= kern
.GetLoadAddressForSymbol('CpuDataEntries')
131 data_entries
= kern
.GetValueFromAddress(data_entries_addr
, 'cpu_data_entry_t *')
132 data_entry
= data_entries
[cpu_id
];
133 cpu_data_addr
= data_entry
.cpu_data_vaddr
134 return Cast(cpu_data_addr
, 'cpu_data_t*')
136 @lldb_command('longtermtimers')
137 def longtermTimers(cmd_args
=None):
139 Print details of long-term timers and stats.
142 lt
= kern
.globals.timer_longterm
145 if ltt
.interval
== EndofAllTime
:
146 print "Longterm timers disabled"
150 ratio
= lt
.enqueues
/ lt
.escalates
153 print 'Longterm timer object: {:#018x}'.format(addressof(lt
))
154 print ' queue count : {:d}' .format(lt
.queue
.count
)
155 print ' number of enqueues : {:d}' .format(lt
.enqueues
)
156 print ' number of dequeues : {:d}' .format(lt
.dequeues
)
157 print ' number of escalates : {:d}' .format(lt
.escalates
)
158 print ' enqueues/escalates : {:d}' .format(ratio
)
159 print ' threshold.interval : {:d}' .format(ltt
.interval
)
160 print ' threshold.margin : {:d}' .format(ltt
.margin
)
161 print ' scan_time : {:d}' .format(lt
.scan_time
)
162 if ltt
.preempted
== EndofAllTime
:
163 print ' threshold.preempted : None'
165 print ' threshold.preempted : {:d}' .format(ltt
.preempted
)
166 if ltt
.deadline
== EndofAllTime
:
167 print ' threshold.deadline : None'
169 print ' threshold.deadline : {:d}' .format(ltt
.deadline
)
170 print ' threshold.call : {:#018x}'.format(ltt
.call
)
171 print ' actual deadline set : {:d}' .format(ltt
.deadline_set
)
172 print ' threshold.scans : {:d}' .format(ltt
.scans
)
173 print ' threshold.preempts : {:d}' .format(ltt
.preempts
)
174 print ' threshold.latency : {:d}' .format(ltt
.latency
)
175 print ' - min : {:d}' .format(ltt
.latency_min
)
176 print ' - max : {:d}' .format(ltt
.latency_max
)
177 dumpTimerList(lt
.queue
)
180 @lldb_command('processortimers')
181 def processorTimers(cmd_args
=None):
183 Print details of processor timers, noting anything suspicious
184 Also include long-term timer details
186 hdr
= '{:<32s}{:<18s} {:<18s} {:<18s}'
187 print hdr
.format('Processor','Last dispatch','Next deadline','difference')
188 p
= kern
.globals.processor_list
191 cpu_data
= GetCpuDataForCpuID(cpu
)
192 rt_timer
= cpu_data
.rtclock_timer
193 diff
= p
.last_dispatch
- rt_timer
.deadline
194 tmr
= 'Processor {:d}: {:#018x} {:#018x} {:#018x} {:#018x} {:s}'
195 print tmr
.format(cpu
,
200 ['probably BAD', '(ok)'][int(diff
< 0)])
201 if kern
.arch
== 'x86_64':
202 print 'Next deadline set at: {:#018x}. Timer call list:'.format(rt_timer
.when_set
)
203 dumpTimerList(rt_timer
.queue
)
208 @lldb_command('showtimerwakeupstats')
209 def showTimerWakeupStats(cmd_args
=None):
211 Displays interrupt and platform idle wakeup frequencies
212 associated with each thread, timer time-to-deadline frequencies, and
213 CPU time with user/system break down where applicable, with thread tags.
215 for task
in kern
.tasks
:
216 proc
= Cast(task
.bsd_info
, 'proc_t')
217 print dereference(task
)
218 print '{:d}({:s}), terminated thread timer wakeups: {:d} {:d} 2ms: {:d} 5ms: {:d} UT: {:d} ST: {:d}'.format(
221 # Commented-out references below to be addressed by rdar://13009660.
222 0, #task.task_interrupt_wakeups,
223 0, #task.task_platform_idle_wakeups,
224 task
.task_timer_wakeups_bin_1
,
225 task
.task_timer_wakeups_bin_2
,
226 task
.total_user_time
,
227 task
.total_system_time
)
228 tot_wakes
= 0 #task.task_interrupt_wakeups
229 tot_platform_wakes
= 0 #task.task_platform_idle_wakeups
230 for thread
in IterateQueue(task
.threads
, 'thread_t', 'task_threads'):
231 ## if thread.thread_interrupt_wakeups == 0:
233 print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format(
236 0, #thread.thread_interrupt_wakeups,
237 0, #thread.thread_platform_idle_wakeups,
238 0, #thread.thread_callout_interrupt_wakeups,
239 0, #thread.thread_callout_platform_idle_wakeups,
241 thread
.thread_timer_wakeups_bin_1
,
242 thread
.thread_timer_wakeups_bin_2
,
243 thread
.user_timer
.all_bits
,
244 thread
.system_timer
.all_bits
)
245 tot_wakes
+= 0 #thread.thread_interrupt_wakeups
246 tot_platform_wakes
+= 0 #thread.thread_platform_idle_wakeups
247 print 'Task total wakeups: {:d} {:d}'.format(
248 tot_wakes
, tot_platform_wakes
)
250 def DoReadMsr64(msr_address
, lcpu
):
251 """ Read a 64-bit MSR from the specified CPU
253 msr_address: int - MSR index to read from
254 lcpu: int - CPU identifier
256 64-bit value read from the MSR
260 if "kdp" != GetConnectionProtocol():
261 print "Target is not connected over kdp. Cannot read MSR."
264 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
265 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
266 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
267 if not WriteInt32ToMemoryAddress(0, input_address
):
268 print "DoReadMsr64() failed to write 0 to input_address"
271 kdp_pkt_size
= GetType('kdp_readmsr64_req_t').GetByteSize()
272 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
273 print "DoReadMsr64() failed to write kdp_pkt_size"
276 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_readmsr64_req_t *')
277 header_value
= GetKDPPacketHeaderInt(
278 request
=GetEnumValue('kdp_req_t::KDP_READMSR64'),
281 if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))):
282 print "DoReadMsr64() failed to write header_value"
284 if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))):
285 print "DoReadMsr64() failed to write msr_address"
287 if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))):
288 print "DoReadMsr64() failed to write lcpu"
290 if not WriteInt32ToMemoryAddress(1, input_address
):
291 print "DoReadMsr64() failed to write to input_address"
294 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
),
295 'kdp_readmsr64_reply_t *')
296 if (result_pkt
.error
== 0):
297 result
= dereference(Cast(addressof(result_pkt
.data
), 'uint64_t *'))
299 print "DoReadMsr64() result_pkt.error != 0"
302 def DoWriteMsr64(msr_address
, lcpu
, data
):
303 """ Write a 64-bit MSR
305 msr_address: int - MSR index to write to
306 lcpu: int - CPU identifier
307 data: int - value to write
309 True upon success, False if error
311 if "kdp" != GetConnectionProtocol():
312 print "Target is not connected over kdp. Cannot write MSR."
315 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
316 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
317 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
318 if not WriteInt32ToMemoryAddress(0, input_address
):
319 print "DoWriteMsr64() failed to write 0 to input_address"
322 kdp_pkt_size
= GetType('kdp_writemsr64_req_t').GetByteSize()
323 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
324 print "DoWriteMsr64() failed to kdp_pkt_size"
327 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_writemsr64_req_t *')
328 header_value
= GetKDPPacketHeaderInt(
329 request
=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'),
332 if not WriteInt64ToMemoryAddress(header_value
, int(addressof(kgm_pkt
.hdr
))):
333 print "DoWriteMsr64() failed to write header_value"
335 if not WriteInt32ToMemoryAddress(msr_address
, int(addressof(kgm_pkt
.address
))):
336 print "DoWriteMsr64() failed to write msr_address"
338 if not WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))):
339 print "DoWriteMsr64() failed to write lcpu"
341 if not WriteInt64ToMemoryAddress(data
, int(addressof(kgm_pkt
.data
))):
342 print "DoWriteMsr64() failed to write data"
344 if not WriteInt32ToMemoryAddress(1, input_address
):
345 print "DoWriteMsr64() failed to write to input_address"
348 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
),
349 'kdp_writemsr64_reply_t *')
350 if not result_pkt
.error
== 0:
351 print "DoWriteMsr64() error received in reply packet"
356 @lldb_command('readmsr64')
357 def ReadMsr64(cmd_args
=None):
358 """ Read the specified MSR. The CPU can be optionally specified
359 Syntax: readmsr64 <msr> [lcpu]
361 if cmd_args
== None or len(cmd_args
) < 1:
362 print ReadMsr64
.__doc__
365 msr_address
= ArgumentStringToInt(cmd_args
[0])
366 if len(cmd_args
) > 1:
367 lcpu
= ArgumentStringToInt(cmd_args
[1])
369 lcpu
= int(xnudefines
.lcpu_self
)
371 msr_value
= DoReadMsr64(msr_address
, lcpu
)
372 print "MSR[{:x}]: {:#016x}".format(msr_address
, msr_value
)
374 @lldb_command('writemsr64')
375 def WriteMsr64(cmd_args
=None):
376 """ Write the specified MSR. The CPU can be optionally specified
377 Syntax: writemsr64 <msr> <value> [lcpu]
379 if cmd_args
== None or len(cmd_args
) < 2:
380 print WriteMsr64
.__doc__
382 msr_address
= ArgumentStringToInt(cmd_args
[0])
383 write_val
= ArgumentStringToInt(cmd_args
[1])
384 if len(cmd_args
) > 2:
385 lcpu
= ArgumentStringToInt(cmd_args
[2])
387 lcpu
= xnudefines
.lcpu_self
389 if not DoWriteMsr64(msr_address
, lcpu
, write_val
):
390 print "writemsr64 FAILED"
392 def GetEVFlags(debug_arg
):
393 """ Return the EV Flags for the given kernel debug arg value
395 debug_arg - value from arg member of kernel debug buffer entry
397 str - string representing the EV Flag for given input arg value
408 if debug_arg
& 0x00100:
409 out_str
+= "EV_RBYTES "
410 if debug_arg
& 0x00200:
411 out_str
+= "EV_WBYTES "
412 if debug_arg
& 0x00400:
413 out_str
+= "EV_RCLOSED "
414 if debug_arg
& 0x00800:
415 out_str
+= "EV_RCONN "
416 if debug_arg
& 0x01000:
417 out_str
+= "EV_WCLOSED "
418 if debug_arg
& 0x02000:
419 out_str
+= "EV_WCONN "
420 if debug_arg
& 0x04000:
422 if debug_arg
& 0x08000:
424 if debug_arg
& 0x10000:
425 out_str
+= "EV_RESET "
426 if debug_arg
& 0x20000:
427 out_str
+= "EV_TIMEOUT "
431 def GetKernelDebugBufferEntry(kdbg_entry
):
432 """ Extract the information from given kernel debug buffer entry and return the summary
434 kdebug_entry - kd_buf - address of kernel debug buffer entry
436 str - formatted output information of kd_buf entry
440 kdebug_entry
= kern
.GetValueFromAddress(kdbg_entry
, 'kd_buf *')
441 debugid
= kdebug_entry
.debugid
442 kdebug_arg1
= kdebug_entry
.arg1
443 kdebug_arg2
= kdebug_entry
.arg2
444 kdebug_arg3
= kdebug_entry
.arg3
445 kdebug_arg4
= kdebug_entry
.arg4
447 if kern
.arch
== 'x86_64' or kern
.arch
.startswith('arm64'):
448 kdebug_cpu
= kdebug_entry
.cpuid
449 ts_hi
= (kdebug_entry
.timestamp
>> 32) & 0xFFFFFFFF
450 ts_lo
= kdebug_entry
.timestamp
& 0xFFFFFFFF
452 kdebug_cpu
= (kdebug_entry
.timestamp
>> 56)
453 ts_hi
= (kdebug_entry
.timestamp
>> 32) & 0x00FFFFFF
454 ts_lo
= kdebug_entry
.timestamp
& 0xFFFFFFFF
456 kdebug_class
= (debugid
>> 24) & 0x000FF
457 kdebug_subclass
= (debugid
>> 16) & 0x000FF
458 kdebug_code
= (debugid
>> 2) & 0x03FFF
459 kdebug_qual
= (debugid
) & 0x00003
463 elif kdebug_qual
== 1:
465 elif kdebug_qual
== 2:
467 elif kdebug_qual
== 3:
471 out_str
+= "{:<#20x} {:>6d} {:>#12x} ".format(kdebug_entry
, kdebug_cpu
, kdebug_entry
.arg5
)
472 out_str
+= " {:#010x}{:08x} {:>6s} ".format(ts_hi
, ts_lo
, kdebug_qual
)
476 if kdebug_class
== 1:
478 elif kdebug_class
== 2:
480 elif kdebug_class
== 3:
482 elif kdebug_class
== 4:
484 elif kdebug_class
== 5:
486 elif kdebug_class
== 6:
488 elif kdebug_class
== 7:
490 elif kdebug_class
== 8:
492 elif kdebug_class
== 9:
494 elif kdebug_class
== 10:
496 elif kdebug_class
== 11:
498 elif kdebug_class
== 20:
500 elif kdebug_class
== 30:
502 elif kdebug_class
== 31:
504 elif kdebug_class
== 32:
506 elif kdebug_class
== 33:
508 elif kdebug_class
== 34:
510 elif kdebug_class
== 36:
512 elif kdebug_class
== 37:
514 elif kdebug_class
== 38:
516 elif kdebug_class
== 39:
518 elif kdebug_class
== 40:
520 elif kdebug_class
== 41:
522 elif kdebug_class
== 42:
524 elif kdebug_class
== 128:
526 elif kdebug_class
== 129:
528 elif kdebug_class
== 130:
530 elif kdebug_class
== 131:
532 elif kdebug_class
== 132:
534 elif kdebug_class
== 133:
536 elif kdebug_class
== 255:
539 out_str
+= "{:^#10x} ".format(kdebug_class
)
542 out_str
+= "{:^10s} ".format(kdbg_class
)
545 out_str
+= " {:>#5x} {:>8d} ".format(kdebug_subclass
, kdebug_code
)
547 # space for debugid-specific processing
548 # EVPROC from bsd/kern/sys_generic.c
549 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
550 if debugid
== 0x14100048:
551 code_info_str
+= "waitevent "
553 code_info_str
+= "before sleep"
554 elif kdebug_arg1
== 2:
555 code_info_str
+= "after sleep"
557 code_info_str
+= "????????????"
558 code_info_str
+= " chan={:#08x} ".format(kdebug_arg2
)
559 elif debugid
== 0x14100049:
560 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_START)
561 code_info_str
+= "waitevent "
562 elif debugid
== 0x1410004a:
563 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_END)
564 code_info_str
+= "waitevent error={:d} ".format(kdebug_arg1
)
565 code_info_str
+= "eqp={:#08x} ".format(kdebug_arg4
)
566 code_info_str
+= GetEVFlags(kdebug_arg3
)
567 code_info_str
+= "er_handle={:d} ".format(kdebug_arg2
)
568 elif debugid
== 0x14100059:
569 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_START)
570 code_info_str
+= "evprocdeque proc={:#08x} ".format(kdebug_arg1
)
572 code_info_str
+= "remove first "
574 code_info_str
+= "remove {:#08x} ".format(kdebug_arg2
)
575 elif debugid
== 0x1410005a:
576 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_END)
577 code_info_str
+= "evprocdeque "
579 code_info_str
+= "result=NULL "
581 code_info_str
+= "result={:#08x} ".format(kdebug_arg1
)
582 elif debugid
== 0x14100041:
583 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_START)
584 code_info_str
+= "postevent "
585 code_info_str
+= GetEVFlags(kdebug_arg1
)
586 elif debugid
== 0x14100040:
587 # MISCDBG_CODE(DBG_EVENT,DBG_POST)
588 code_info_str
+= "postevent "
589 code_info_str
+= "evq={:#08x} ".format(kdebug_arg1
)
590 code_info_str
+= "er_eventbits="
591 code_info_str
+= GetEVFlags(kdebug_arg2
)
592 code_info_str
+="mask="
593 code_info_str
+= GetEVFlags(kdebug_arg3
)
594 elif debugid
== 0x14100042:
595 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_END)
596 code_info_str
+= "postevent "
597 elif debugid
== 0x14100055:
598 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_START)
599 code_info_str
+= "evprocenque eqp={:#08x} ".format(kdebug_arg1
)
601 code_info_str
+= "EV_QUEUED "
602 code_info_str
+= GetEVFlags(kdebug_arg3
)
603 elif debugid
== 0x14100050:
604 # MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
605 code_info_str
+= "evprocenque before wakeup eqp={:#08x} ".format(kdebug_arg4
)
606 elif debugid
== 0x14100056:
607 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_END)
608 code_info_str
+= "evprocenque "
609 elif debugid
== 0x1410004d:
610 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_START)
611 code_info_str
+= "modwatch "
612 elif debugid
== 0x1410004c:
613 # MISCDBG_CODE(DBG_EVENT,DBG_MOD)
614 code_info_str
+= "modwatch er_handle={:d} ".format(kdebug_arg1
)
615 code_info_str
+= GetEVFlags(kdebug_arg2
)
616 code_info_str
+= "evq={:#08x} ", kdebug_arg3
617 elif debugid
== 0x1410004e:
618 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_END)
619 code_info_str
+= "modwatch er_handle={:d} ".format(kdebug_arg1
)
620 code_info_str
+= "ee_eventmask="
621 code_info_str
+= GetEVFlags(kdebug_arg2
)
622 code_info_str
+= "sp={:#08x} ".format(kdebug_arg3
)
623 code_info_str
+= "flag="
624 code_info_str
+= GetEVFlags(kdebug_arg4
)
626 code_info_str
+= "arg1={:#010x} ".format(kdebug_arg1
)
627 code_info_str
+= "arg2={:#010x} ".format(kdebug_arg2
)
628 code_info_str
+= "arg3={:#010x} ".format(kdebug_arg3
)
629 code_info_str
+= "arg4={:#010x} ".format(kdebug_arg4
)
632 out_str
+= "{:<25s}\n".format(code_info_str
)
635 @lldb_command('showkerneldebugbuffercpu')
636 @header("{0: ^20s} {1: >6s} {2: >12s} {3: ^20s} {4: >6s} {5: ^10s} {6: >5s} {7: >8s} {8: ^25s}".
637 format('kd_buf', 'CPU', 'Thread', 'Timestamp', 'S/E', 'Class', 'Sub', 'Code', 'Code Specific Info'))
638 def ShowKernelDebugBufferCPU(cmd_args
=None):
639 """ Prints the last N entries in the kernel debug buffer for specified cpu
640 Syntax: showkerneldebugbuffercpu <cpu_num> <count>
642 if cmd_args
== None or len(cmd_args
) < 2:
643 raise ArgumentError("Invalid arguments passed.")
647 cpu_number
= ArgumentStringToInt(cmd_args
[0])
648 entry_count
= ArgumentStringToInt(cmd_args
[1])
649 debugentriesfound
= 0
650 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
651 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& 0x80000000):
652 out_str
+= ShowKernelDebugBufferCPU
.header
+ "\n"
654 out_str
+= "<count> is 0, dumping 50 entries\n"
657 if cpu_number
>= kern
.globals.kd_ctrl_page
.kdebug_cpus
:
658 kdbg_str
+= "cpu number too big\n"
660 kdbp
= addressof(kern
.globals.kdbip
[cpu_number
])
661 kdsp
= kdbp
.kd_list_head
662 while ((kdsp
.raw
!= 0 and kdsp
.raw
!= 0x00000000ffffffff) and (entry_count
> 0)):
663 kd_buffer
= kern
.globals.kd_bufs
[kdsp
.buffer_index
]
664 kdsp_actual
= addressof(kd_buffer
.kdsb_addr
[kdsp
.offset
])
665 if kdsp_actual
.kds_readlast
!= kdsp_actual
.kds_bufindx
:
666 kds_buf
= kdsp_actual
.kds_records
[kdsp_actual
.kds_bufindx
]
667 kds_bufptr
= addressof(kds_buf
)
668 while (entry_count
> 0) and \
669 (unsigned(kds_bufptr
) > unsigned(addressof(kdsp_actual
.kds_records
[kdsp_actual
.kds_readlast
]))):
670 kds_bufptr
= kds_bufptr
- sizeof(kds_buf
)
671 entry_count
= entry_count
- 1
672 kdbg_str
+= GetKernelDebugBufferEntry(kds_bufptr
)
673 kdsp
= kdsp_actual
.kds_next
675 kdbg_str
+= "Trace buffer not enabled for CPU {:d}\n".format(cpu_number
)
681 @lldb_command('showkerneldebugbuffer')
682 def ShowKernelDebugBuffer(cmd_args
=None):
683 """ Prints the last N entries in the kernel debug buffer per cpu
684 Syntax: showkerneldebugbuffer <count>
686 if cmd_args
== None or len(cmd_args
) < 1:
687 raise ArgumentError("Invalid arguments passed.")
689 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
690 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& 0x80000000):
691 entrycount
= ArgumentStringToInt(cmd_args
[0])
693 print "<count> is 0, dumping 50 entries per cpu\n"
696 while cpu_num
< kern
.globals.kd_ctrl_page
.kdebug_cpus
:
697 ShowKernelDebugBufferCPU([str(cpu_num
), str(entrycount
)])
700 print "Trace buffer not enabled\n"
702 @lldb_command('dumprawtracefile','U:')
703 def DumpRawTraceFile(cmd_args
=[], cmd_options
={}):
705 support for ktrace(1)
707 NB: trace is not wordsize flexible, so use ktrace(1) compiled for the compatible model,
708 e.g. if you dump from __LP64__ system, you will need to run ktrace(1) compiled __LP64__ to process the raw data file.
710 read the kernel's debug trace buffer, and dump to a "raw" ktrace(1) file
711 Usage: dumprawtracefile <output_filename>
712 -U <uptime> : specify system uptime in nsec, obtained e.g. from paniclog
713 Be patient, it is teh slow.
715 cf. kdbg_read()\bsd/kern/kdebug.c
718 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
719 if (kern
.globals.kd_ctrl_page
.kdebug_flags
& xnudefines
.KDBG_BFINIT
) == 0 :
720 print "Trace buffer not enabled\n"
723 if ((kern
.arch
== "x86_64") or kern
.arch
.startswith("arm64")) :
725 elif kern
.arch
== "arm" :
728 print "unknown kern.arch {:s}\n".format(kern
.arch
)
731 # Various kern.globals are hashed by address, to
732 # a) avoid redundant kdp fetch from, and
733 # b) avoid all stores to
734 # the target system kernel structures.
735 # Stores to hashed structures remain strictly local to the lldb host,
736 # they are never written back to the target.
740 KDBG_TIMESTAMP_MASK
= 0xffffffffffffffff
743 KDBG_TIMESTAMP_MASK
= 0x00ffffffffffffff
748 out_of_events
= False
750 lostevent_timestamp
= 0
751 lostevent_debugid
= (((xnudefines
.DBG_TRACE
& 0xff) << 24) |
((xnudefines
.DBG_TRACE_INFO
& 0xff) << 16) |
((2 & 0x3fff) << 2)) # 0x01020008
752 events_count_lost
= 0
753 events_count_found
= 0
755 opt_verbose
= config
['verbosity']
756 opt_progress
= (opt_verbose
> vHUMAN
) and (opt_verbose
< vDETAIL
)
760 output_filename
= str(cmd_args
[0])
761 if opt_verbose
> vHUMAN
:
762 print "output file : {:s}".format(output_filename
)
763 wfd
= open(output_filename
, "wb")
766 if "-U" in cmd_options
:
767 uptime
= long(cmd_options
["-U"])
768 if opt_verbose
> vHUMAN
:
769 print "uptime : {:d}".format(uptime
)
771 nkdbufs
= kern
.globals.nkdbufs
773 kd_ctrl_page
= kern
.globals.kd_ctrl_page
774 if not kd_ctrl_page
in htab
:
775 htab
[kd_ctrl_page
] = kern
.globals.kd_ctrl_page
777 if opt_verbose
> vHUMAN
:
778 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
)
781 print "0 nkdbufs, nothing extracted"
784 if htab
[kd_ctrl_page
].enabled
!= 0 :
785 barrier_max
= uptime
& KDBG_TIMESTAMP_MASK
787 f
= htab
[kd_ctrl_page
].kdebug_flags
788 wrapped
= f
& xnudefines
.KDBG_WRAPPED
790 barrier_min
= htab
[kd_ctrl_page
].oldest_time
791 htab
[kd_ctrl_page
].kdebug_flags
= htab
[kd_ctrl_page
].kdebug_flags
& ~xnudefines
.KDBG_WRAPPED
792 htab
[kd_ctrl_page
].oldest_time
= 0
794 for cpu
in range(htab
[kd_ctrl_page
].kdebug_cpus
) :
795 kdbp
= unsigned(addressof(kern
.globals.kdbip
[cpu
]))
796 if not kdbp
in htab
:
797 htab
[kdbp
] = kern
.globals.kdbip
[cpu
]
799 kdsp
= htab
[kdbp
].kd_list_head
.raw
800 if kdsp
== xnudefines
.KDS_PTR_NULL
:
803 ix
= htab
[kdbp
].kd_list_head
.buffer_index
804 off
= htab
[kdbp
].kd_list_head
.offset
805 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
806 if not kdsp_actual
in htab
:
807 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
808 htab
[kdsp_actual
].kds_lostevents
= False
811 # generate trace file header; threadmap is stubbed/TBD
812 version_no
= xnudefines
.RAW_VERSION1
816 header
= struct
.pack('IIqI', version_no
, thread_count
, TOD_secs
, TOD_usecs
)
817 pad_bytes
= 4096 - (len(header
) & 4095)
818 header
+= "\x00" * pad_bytes
819 wfd
.write(buffer(header
))
825 tempbuf_count
= min(count
, xnudefines
.KDCOPYBUF_COUNT
)
828 while tempbuf_count
!= 0 :
830 if opt_progress
== True :
832 if (progress_count
% progress_stride
) == 0 :
833 sys
.stderr
.write('.')
836 earliest_time
= 0xffffffffffffffff
841 for cpu
in range(htab
[kd_ctrl_page
].kdebug_cpus
) :
843 kdbp
= unsigned(addressof(kern
.globals.kdbip
[cpu
]))
844 if not kdbp
in htab
:
845 htab
[kdbp
] = kern
.globals.kdbip
[cpu
]
847 # Skip CPUs without data.
848 kdsp
= htab
[kdbp
].kd_list_head
849 if kdsp
.raw
== xnudefines
.KDS_PTR_NULL
:
854 # Get from cpu data to buffer header to buffer
855 ix
= kdsp
.buffer_index
857 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
858 if not kdsp_actual
in htab
:
859 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
861 kdsp_actual_shadow
= kdsp_actual
863 # Skip buffer if there are no events left.
864 rcursor
= htab
[kdsp_actual
].kds_readlast
865 if rcursor
== htab
[kdsp_actual
].kds_bufindx
:
868 t
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp
& KDBG_TIMESTAMP_MASK
870 # Ignore events that have aged out due to wrapping.
871 goto_next_cpu
= False;
872 while (t
< unsigned(barrier_min
)) :
873 r
= htab
[kdsp_actual
].kds_readlast
874 htab
[kdsp_actual
].kds_readlast
= r
+ 1
877 if rcursor
>= xnudefines
.EVENTS_PER_STORAGE_UNIT
:
879 kdsp
= htab
[kdbp
].kd_list_head
880 if kdsp
.raw
== xnudefines
.KDS_PTR_NULL
:
886 ix
= kdsp
.buffer_index
888 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
890 kdsp_actual_shadow
= kdsp_actual
;
891 rcursor
= htab
[kdsp_actual
].kds_readlast
;
893 t
= htab
[kdsp_actual
].kds_records
[rcursor
].timestamp
& KDBG_TIMESTAMP_MASK
895 if goto_next_cpu
== True :
898 if (t
> barrier_max
) and (barrier_max
> 0) :
899 # Need to flush IOPs again before we
900 # can sort any more data from the
905 if t
< (htab
[kdsp_actual
].kds_timestamp
& KDBG_TIMESTAMP_MASK
) :
906 # indicates we've not yet completed filling
908 # this should only occur when we're looking
909 # at the buf that the record head is utilizing
910 # we'll pick these events up on the next
912 # we bail at this point so that we don't
913 # get an out-of-order timestream by continuing
914 # to read events from the other CPUs' timestream(s)
918 if t
< earliest_time
:
924 if (min_kdbp
is None) or (out_of_events
== True) :
925 # all buffers ran empty
929 kdsp
= htab
[min_kdbp
].kd_list_head
931 ix
= kdsp
.buffer_index
933 kdsp_actual
= unsigned(addressof(kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]))
934 if not kdsp_actual
in htab
:
935 htab
[kdsp_actual
] = kern
.globals.kd_bufs
[ix
].kdsb_addr
[off
]
937 # Copy earliest event into merged events scratch buffer.
938 r
= htab
[kdsp_actual
].kds_readlast
939 htab
[kdsp_actual
].kds_readlast
= r
+ 1
940 e
= htab
[kdsp_actual
].kds_records
[r
]
942 # Concatenate event into buffer
943 # XXX condition here is on __LP64__
945 tempbuf
+= struct
.pack('QQQQQQIIQ',
946 unsigned(e
.timestamp
),
956 tempbuf
+= struct
.pack('QIIIIII',
957 unsigned(e
.timestamp
),
965 # Watch for out of order timestamps
966 if earliest_time
< (htab
[min_kdbp
].kd_prev_timebase
& KDBG_TIMESTAMP_MASK
) :
967 ## if so, use the previous timestamp + 1 cycle
968 htab
[min_kdbp
].kd_prev_timebase
+= 1
970 e
.timestamp
= htab
[min_kdbp
].kd_prev_timebase
& KDBG_TIMESTAMP_MASK
972 e
.timestamp |
= (min_cpu
<< KDBG_CPU_SHIFT
)
974 htab
[min_kdbp
].kd_prev_timebase
= earliest_time
976 if opt_verbose
>= vDETAIL
:
977 print "{0:#018x} {1:#018x} {2:#018x} {3:#018x} {4:#018x} {5:#018x} {6:#010x} {7:#010x} {8:#018x}".format(
978 e
.timestamp
, e
.arg1
, e
.arg2
, e
.arg3
, e
.arg4
, e
.arg5
, e
.debugid
, e
.cpuid
, e
.unused
)
980 events_count_found
+= 1
986 if opt_progress
== True :
987 sys
.stderr
.write('\n')
990 if opt_verbose
> vHUMAN
:
991 print "events_count_lost {0:#x}, events_count_found {1:#x}, progress_count {2:#x}".format(events_count_lost
, events_count_found
, progress_count
)
993 # write trace events to output file
994 if tempbuf_number
!= 0 :
995 count
-= tempbuf_number
996 wfd
.write(buffer(tempbuf
))
998 if out_of_events
== True :
999 # all trace buffers are empty
1000 if opt_verbose
> vHUMAN
:
1001 print "out of events"
1009 def PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
):
1011 if do_summary
and summary
:
1015 print "[{:d}] {:s}".format(i
, s
)
1017 print "[{:d}] {:s}".format(i
, s
)
1020 if regex
.match(str(elem
)):
1021 print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
))
1023 print "[{:4d}] ({:s}){:#x}".format(i
, elem_type
, unsigned(elem
))
1025 print "Exception while looking at elem {:#x}".format(unsigned(elem
))
1028 @lldb_command('q_iterate', "LQSG:")
1029 def QIterate(cmd_args
=None, cmd_options
={}):
1030 """ Iterate over a LinkageChain or Queue (osfmk/kern/queue.h method 1 or 2 respectively)
1031 This is equivalent to the qe_foreach_element() macro
1033 iterate [options] {queue_head_ptr} {element_type} {field_name}
1035 -L iterate over a linkage chain (method 1) [default]
1036 -Q iterate over a queue (method 2)
1038 -S auto-summarize known types
1039 -G regex to filter the output
1041 iterate_linkage `&coalitions_q` 'coalition *' coalitions
1044 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
1046 qhead
= kern
.GetValueFromAddress(cmd_args
[0], 'struct queue_entry *')
1048 raise ArgumentError("Unknown queue_head pointer: %r" % cmd_args
)
1049 elem_type
= cmd_args
[1]
1050 field_name
= cmd_args
[2]
1051 if not elem_type
or not field_name
:
1052 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
1054 do_queue_iterate
= False
1055 do_linkage_iterate
= True
1056 if "-Q" in cmd_options
:
1057 do_queue_iterate
= True
1058 do_linkage_iterate
= False
1059 if "-L" in cmd_options
:
1060 do_queue_iterate
= False
1061 do_linkage_iterate
= True
1064 if "-S" in cmd_options
:
1067 if "-G" in cmd_options
:
1068 regex
= re
.compile(".*{:s}.*".format(cmd_options
["-G"]))
1069 print "Looking for: {:s}".format(regex
.pattern
)
1071 global lldb_summary_definitions
1073 if elem_type
in lldb_summary_definitions
:
1074 summary
= lldb_summary_definitions
[elem_type
]
1076 print summary
.header
1080 if do_linkage_iterate
:
1081 for elem
in IterateLinkageChain(qhead
, elem_type
, field_name
):
1082 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
)
1084 elif do_queue_iterate
:
1085 for elem
in IterateQueue(qhead
, elem_type
, field_name
):
1086 PrintIteratedElem(i
, elem
, elem_type
, do_summary
, summary
, regex
)
1089 print "Exception while looking at queue_head: {:#x}".format(unsigned(qhead
))