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
))