]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/misc.py
a9b7bafda28d5afef037d6018ffd6e55b4fab096
[apple/xnu.git] / tools / lldbmacros / misc.py
1 """
2 Miscellaneous (Intel) platform-specific commands.
3 """
4
5 from xnu import *
6 import xnudefines
7
8 @lldb_command('showmcastate')
9 def showMCAstate(cmd_args=None):
10 """
11 Print machine-check register state after MC exception.
12 """
13 if kern.arch != 'x86_64':
14 print "Not available for current architecture."
15 return
16
17 present = ["not present", "present"]
18 print 'MCA {:s}, control MSR {:s}, threshold status {:s}'.format(
19 present[int(kern.globals.mca_MCA_present)],
20 present[int(kern.globals.mca_control_MSR_present)],
21 present[int(kern.globals.mca_threshold_status_present)])
22 print '{:d} error banks, family code {:#0x}, machine-check dump state: {:d}'.format(
23 kern.globals.mca_error_bank_count,
24 kern.globals.mca_dump_state,
25 kern.globals.mca_family)
26 cpu = 0
27 while kern.globals.cpu_data_ptr[cpu]:
28 cd = kern.globals.cpu_data_ptr[cpu]
29 mc = cd.cpu_mca_state
30 if mc:
31 print 'CPU {:d}: mca_mcg_ctl: {:#018x} mca_mcg_status {:#018x}'.format(cpu, mc.mca_mcg_ctl, mc.mca_mcg_status.u64)
32 hdr = '{:<4s} {:<18s} {:<18s} {:<18s} {:<18s}'
33 val = '{:>3d}: {:#018x} {:#018x} {:#018x} {:#018x}'
34 print hdr.format('bank',
35 'mca_mci_ctl',
36 'mca_mci_status',
37 'mca_mci_addr',
38 'mca_mci_misc')
39 for i in range(int(kern.globals.mca_error_bank_count)):
40 bank = mc.mca_error_bank[i]
41 print val.format(i,
42 bank.mca_mci_ctl,
43 bank.mca_mci_status.u64,
44 bank.mca_mci_addr,
45 bank.mca_mci_misc)
46 print 'register state:'
47 reg = cd.cpu_desc_index.cdi_ktss.ist1 - sizeof('x86_saved_state_t')
48 print lldb_run_command('p/x *(x86_saved_state_t *) ' + hex(reg))
49 cpu = cpu + 1
50
51 def dumpTimerList(anchor):
52 """
53 Utility function to dump the timer entries in list (anchor).
54 """
55 entry = Cast(anchor.head, 'queue_t')
56 if entry == addressof(anchor):
57 print '(empty)'
58 return
59
60 thdr = ' {:<22s}{:<17s}{:<16s} {:<14s} {:<18s}'
61 print thdr.format('entry:','deadline','soft_deadline','to go','(*func)(param0,param1')
62 while entry != addressof(anchor):
63 timer_call = Cast(entry, 'timer_call_t')
64 call_entry = Cast(entry, 'struct call_entry *')
65 debugger_entry = kern.globals.debugger_entry_time
66 if (debugger_entry < call_entry.deadline):
67 delta_sign = ' '
68 timer_fire = call_entry.deadline - debugger_entry
69 else:
70 delta_sign = '-'
71 timer_fire = debugger_entry - call_entry.deadline
72 tval = ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d} ({:#018x})({:#018x},{:#018x})'
73 print tval.format(entry,
74 call_entry.deadline,
75 timer_call.soft_deadline,
76 delta_sign,
77 timer_fire/1000000000,
78 timer_fire%1000000000,
79 call_entry.func,
80 call_entry.param0,
81 call_entry.param1)
82 entry = entry.next
83
84 @lldb_command('longtermtimers')
85 def longtermTimers(cmd_args=None):
86 """
87 Print details of long-term timers and stats.
88 """
89 if kern.arch != 'x86_64':
90 print "Not available for current architecture."
91 return
92
93 lt = kern.globals.timer_longterm
94 ltt = lt.threshold
95 EndofAllTime = -1
96 if ltt.interval == EndofAllTime:
97 print "Longterm timers disabled"
98 return
99
100 if lt.escalates > 0:
101 ratio = lt.enqueues / lt.escalates
102 else:
103 ratio = lt.enqueues
104 print 'Longterm timer object: {:#018x}'.format(addressof(lt))
105 print ' queue count : {:d}' .format(lt.queue.count)
106 print ' number of enqueues : {:d}' .format(lt.enqueues)
107 print ' number of dequeues : {:d}' .format(lt.dequeues)
108 print ' number of escalates : {:d}' .format(lt.escalates)
109 print ' enqueues/escalates : {:d}' .format(ratio)
110 print ' threshold.interval : {:d}' .format(ltt.interval)
111 print ' threshold.margin : {:d}' .format(ltt.margin)
112 print ' scan_time : {:d}' .format(lt.scan_time)
113 if ltt.preempted == EndofAllTime:
114 print ' threshold.preempted : None'
115 else:
116 print ' threshold.preempted : {:d}' .format(ltt.preempted)
117 if ltt.deadline == EndofAllTime:
118 print ' threshold.deadline : None'
119 else:
120 print ' threshold.deadline : {:d}' .format(ltt.deadline)
121 print ' threshold.call : {:#018x}'.format(ltt.call)
122 print ' actual deadline set : {:d}' .format(ltt.deadline_set)
123 print ' threshold.scans : {:d}' .format(ltt.scans)
124 print ' threshold.preempts : {:d}' .format(ltt.preempts)
125 print ' threshold.latency : {:d}' .format(ltt.latency)
126 print ' - min : {:d}' .format(ltt.latency_min)
127 print ' - max : {:d}' .format(ltt.latency_max)
128 dumpTimerList(lt.queue)
129
130
131 @lldb_command('processortimers')
132 def processorTimers(cmd_args=None):
133 """
134 Print details of processor timers, noting anything suspicious
135 Also include long-term timer details
136 """
137 hdr = '{:<32s}{:<18s} {:<18s} {:<18s}'
138 print hdr.format('Processor','Last dispatch','Next deadline','difference')
139 p = kern.globals.processor_list
140 while p:
141 cpu = p.cpu_id
142 rt_timer = kern.globals.cpu_data_ptr[cpu].rtclock_timer
143 diff = p.last_dispatch - rt_timer.deadline
144 tmr = 'Processor {:d}: {:#018x} {:#018x} {:#018x} {:#018x} {:s}'
145 print tmr.format(cpu,
146 p,
147 p.last_dispatch,
148 rt_timer.deadline,
149 diff,
150 ['probably BAD', '(ok)'][int(diff < 0)])
151 if kern.arch == 'x86_64':
152 print 'Next deadline set at: {:#018x}. Timer call list:'.format(rt_timer.when_set)
153 dumpTimerList(rt_timer.queue)
154 p = p.processor_list
155 longtermTimers()
156
157
158 @lldb_command('showtimerwakeupstats')
159 def showTimerWakeupStats(cmd_args=None):
160 """
161 Displays interrupt and platform idle wakeup frequencies
162 associated with each thread, timer time-to-deadline frequencies, and
163 CPU time with user/system break down where applicable, with thread tags.
164 """
165 for task in kern.tasks:
166 proc = Cast(task.bsd_info, 'proc_t')
167 print dereference(task)
168 print '{:d}({:s}), terminated thread timer wakeups: {:d} {:d} 2ms: {:d} 5ms: {:d} UT: {:d} ST: {:d}'.format(
169 proc.p_pid,
170 proc.p_comm,
171 # Commented-out references below to be addressed by rdar://13009660.
172 0, #task.task_interrupt_wakeups,
173 0, #task.task_platform_idle_wakeups,
174 task.task_timer_wakeups_bin_1,
175 task.task_timer_wakeups_bin_2,
176 task.total_user_time,
177 task.total_system_time)
178 tot_wakes = 0 #task.task_interrupt_wakeups
179 tot_platform_wakes = 0 #task.task_platform_idle_wakeups
180 for thread in IterateQueue(task.threads, 'thread_t', 'task_threads'):
181 # if thread.thread_interrupt_wakeups == 0:
182 # continue
183 print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format(
184 thread.thread_id,
185 thread.thread_tag,
186 0, #thread.thread_interrupt_wakeups,
187 0, #thread.thread_platform_idle_wakeups,
188 0, #thread.thread_callout_interrupt_wakeups,
189 0, #thread.thread_callout_platform_idle_wakeups,
190 0,0,0,0,
191 thread.thread_timer_wakeups_bin_1,
192 thread.thread_timer_wakeups_bin_2,
193 thread.user_timer.all_bits,
194 thread.system_timer.all_bits)
195 tot_wakes += 0 #thread.thread_interrupt_wakeups
196 tot_platform_wakes += 0 #thread.thread_platform_idle_wakeups
197 print 'Task total wakeups: {:d} {:d}'.format(
198 tot_wakes, tot_platform_wakes)
199
200 def DoReadMsr64(msr_address, lcpu):
201 """ Read a 64-bit MSR from the specified CPU
202 Params:
203 msr_address: int - MSR index to read from
204 lcpu: int - CPU identifier
205 Returns:
206 64-bit value read from the MSR
207 """
208 result = 0xbad10ad
209
210 if "kdp" != GetConnectionProtocol():
211 print "Target is not connected over kdp. Cannot read MSR."
212 return result
213
214 input_address = unsigned(addressof(kern.globals.manual_pkt.input))
215 len_address = unsigned(addressof(kern.globals.manual_pkt.len))
216 data_address = unsigned(addressof(kern.globals.manual_pkt.data))
217 if not WriteInt32ToMemoryAddress(0, input_address):
218 print "DoReadMsr64() failed to write 0 to input_address"
219 return result
220
221 kdp_pkt_size = GetType('kdp_readmsr64_req_t').GetByteSize()
222 if not WriteInt32ToMemoryAddress(kdp_pkt_size, len_address):
223 print "DoReadMsr64() failed to write kdp_pkt_size"
224 return result
225
226 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_readmsr64_req_t *')
227 header_value = GetKDPPacketHeaderInt(
228 request=GetEnumValue('kdp_req_t::KDP_READMSR64'),
229 length=kdp_pkt_size)
230
231 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
232 print "DoReadMsr64() failed to write header_value"
233 return result
234 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
235 print "DoReadMsr64() failed to write msr_address"
236 return result
237 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
238 print "DoReadMsr64() failed to write lcpu"
239 return result
240 if not WriteInt32ToMemoryAddress(1, input_address):
241 print "DoReadMsr64() failed to write to input_address"
242 return result
243
244 result_pkt = Cast(addressof(kern.globals.manual_pkt.data),
245 'kdp_readmsr64_reply_t *')
246 if (result_pkt.error == 0):
247 result = dereference(Cast(addressof(result_pkt.data), 'uint64_t *'))
248 else:
249 print "DoReadMsr64() result_pkt.error != 0"
250 return result
251
252 def DoWriteMsr64(msr_address, lcpu, data):
253 """ Write a 64-bit MSR
254 Params:
255 msr_address: int - MSR index to write to
256 lcpu: int - CPU identifier
257 data: int - value to write
258 Returns:
259 True upon success, False if error
260 """
261 if "kdp" != GetConnectionProtocol():
262 print "Target is not connected over kdp. Cannot write MSR."
263 return False
264
265 input_address = unsigned(addressof(kern.globals.manual_pkt.input))
266 len_address = unsigned(addressof(kern.globals.manual_pkt.len))
267 data_address = unsigned(addressof(kern.globals.manual_pkt.data))
268 if not WriteInt32ToMemoryAddress(0, input_address):
269 print "DoWriteMsr64() failed to write 0 to input_address"
270 return False
271
272 kdp_pkt_size = GetType('kdp_writemsr64_req_t').GetByteSize()
273 if not WriteInt32ToMemoryAddress(kdp_pkt_size, len_address):
274 print "DoWriteMsr64() failed to kdp_pkt_size"
275 return False
276
277 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_writemsr64_req_t *')
278 header_value = GetKDPPacketHeaderInt(
279 request=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'),
280 length=kdp_pkt_size)
281
282 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
283 print "DoWriteMsr64() failed to write header_value"
284 return False
285 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
286 print "DoWriteMsr64() failed to write msr_address"
287 return False
288 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
289 print "DoWriteMsr64() failed to write lcpu"
290 return False
291 if not WriteInt64ToMemoryAddress(data, int(addressof(kgm_pkt.data))):
292 print "DoWriteMsr64() failed to write data"
293 return False
294 if not WriteInt32ToMemoryAddress(1, input_address):
295 print "DoWriteMsr64() failed to write to input_address"
296 return False
297
298 result_pkt = Cast(addressof(kern.globals.manual_pkt.data),
299 'kdp_writemsr64_reply_t *')
300 if not result_pkt.error == 0:
301 print "DoWriteMsr64() error received in reply packet"
302 return False
303
304 return True
305
306 @lldb_command('readmsr64')
307 def ReadMsr64(cmd_args=None):
308 """ Read the specified MSR. The CPU can be optionally specified
309 Syntax: readmsr64 <msr> [lcpu]
310 """
311 if cmd_args == None or len(cmd_args) < 1:
312 print ReadMsr64.__doc__
313 return
314
315 msr_address = ArgumentStringToInt(cmd_args[0])
316 if len(cmd_args) > 1:
317 lcpu = ArgumentStringToInt(cmd_args[1])
318 else:
319 lcpu = int(xnudefines.lcpu_self)
320
321 msr_value = DoReadMsr64(msr_address, lcpu)
322 print "MSR[{:x}]: {:#016x}".format(msr_address, msr_value)
323
324 @lldb_command('writemsr64')
325 def WriteMsr64(cmd_args=None):
326 """ Write the specified MSR. The CPU can be optionally specified
327 Syntax: writemsr64 <msr> <value> [lcpu]
328 """
329 if cmd_args == None or len(cmd_args) < 2:
330 print WriteMsr64.__doc__
331 return
332 msr_address = ArgumentStringToInt(cmd_args[0])
333 write_val = ArgumentStringToInt(cmd_args[1])
334 if len(cmd_args) > 2:
335 lcpu = ArgumentStringToInt(cmd_args[2])
336 else:
337 lcpu = xnudefines.lcpu_self
338
339 if not DoWriteMsr64(msr_address, lcpu, write_val):
340 print "writemsr64 FAILED"
341
342 def GetEVFlags(debug_arg):
343 """ Return the EV Flags for the given kernel debug arg value
344 params:
345 debug_arg - value from arg member of kernel debug buffer entry
346 returns:
347 str - string representing the EV Flag for given input arg value
348 """
349 out_str = ""
350 if debug_arg & 1:
351 out_str += "EV_RE "
352 if debug_arg & 2:
353 out_str += "EV_WR "
354 if debug_arg & 4:
355 out_str += "EV_EX "
356 if debug_arg & 8:
357 out_str += "EV_RM "
358 if debug_arg & 0x00100:
359 out_str += "EV_RBYTES "
360 if debug_arg & 0x00200:
361 out_str += "EV_WBYTES "
362 if debug_arg & 0x00400:
363 out_str += "EV_RCLOSED "
364 if debug_arg & 0x00800:
365 out_str += "EV_RCONN "
366 if debug_arg & 0x01000:
367 out_str += "EV_WCLOSED "
368 if debug_arg & 0x02000:
369 out_str += "EV_WCONN "
370 if debug_arg & 0x04000:
371 out_str += "EV_OOB "
372 if debug_arg & 0x08000:
373 out_str += "EV_FIN "
374 if debug_arg & 0x10000:
375 out_str += "EV_RESET "
376 if debug_arg & 0x20000:
377 out_str += "EV_TIMEOUT "
378
379 return out_str
380
381 def GetKernelDebugBufferEntry(kdbg_entry):
382 """ Extract the information from given kernel debug buffer entry and return the summary
383 params:
384 kdebug_entry - kd_buf - address of kernel debug buffer entry
385 returns:
386 str - formatted output information of kd_buf entry
387 """
388 out_str = ""
389 code_info_str = ""
390 kdebug_entry = kern.GetValueFromAddress(kdbg_entry, 'kd_buf *')
391 debugid = kdebug_entry.debugid
392 kdebug_arg1 = kdebug_entry.arg1
393 kdebug_arg2 = kdebug_entry.arg2
394 kdebug_arg3 = kdebug_entry.arg3
395 kdebug_arg4 = kdebug_entry.arg4
396
397 if kern.arch in ('x86_64', 'arm64'):
398 kdebug_cpu = kdebug_entry.cpuid
399 ts_hi = (kdebug_entry.timestamp >> 32) & 0xFFFFFFFF
400 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
401 else:
402 kdebug_cpu = (kdebug_entry.timestamp >> 56)
403 ts_hi = (kdebug_entry.timestamp >> 32) & 0x00FFFFFF
404 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
405
406 kdebug_class = (debugid >> 24) & 0x000FF
407 kdebug_subclass = (debugid >> 16) & 0x000FF
408 kdebug_code = (debugid >> 2) & 0x03FFF
409 kdebug_qual = (debugid) & 0x00003
410
411 if kdebug_qual == 0:
412 kdebug_qual = '-'
413 elif kdebug_qual == 1:
414 kdebug_qual = 'S'
415 elif kdebug_qual == 2:
416 kdebug_qual = 'E'
417 elif kdebug_qual == 3:
418 kdebug_qual = '?'
419
420 # preamble and qual
421 out_str += "{:<#20x} {:>6d} {:>#12x} ".format(kdebug_entry, kdebug_cpu, kdebug_entry.arg5)
422 out_str += " {:#010x}{:08x} {:>6s} ".format(ts_hi, ts_lo, kdebug_qual)
423
424 # class
425 kdbg_class = ""
426 if kdebug_class == 1:
427 kdbg_class = "MACH"
428 elif kdebug_class == 2:
429 kdbg_class = "NET "
430 elif kdebug_class == 3:
431 kdbg_class = "FS "
432 elif kdebug_class == 4:
433 kdbg_class = "BSD "
434 elif kdebug_class == 5:
435 kdbg_class = "IOK "
436 elif kdebug_class == 6:
437 kdbg_class = "DRVR"
438 elif kdebug_class == 7:
439 kdbg_class = "TRAC"
440 elif kdebug_class == 8:
441 kdbg_class = "DLIL"
442 elif kdebug_class == 9:
443 kdbg_class = "WQ "
444 elif kdebug_class == 10:
445 kdbg_class = "CS "
446 elif kdebug_class == 11:
447 kdbg_class = "CG "
448 elif kdebug_class == 20:
449 kdbg_class = "MISC"
450 elif kdebug_class == 30:
451 kdbg_class = "SEC "
452 elif kdebug_class == 31:
453 kdbg_class = "DYLD"
454 elif kdebug_class == 32:
455 kdbg_class = "QT "
456 elif kdebug_class == 33:
457 kdbg_class = "APPS"
458 elif kdebug_class == 34:
459 kdbg_class = "LAUN"
460 elif kdebug_class == 36:
461 kdbg_class = "PPT "
462 elif kdebug_class == 37:
463 kdbg_class = "PERF"
464 elif kdebug_class == 38:
465 kdbg_class = "IMP "
466 elif kdebug_class == 39:
467 kdbg_class = "PCTL"
468 elif kdebug_class == 40:
469 kdbg_class = "BANK"
470 elif kdebug_class == 41:
471 kdbg_class = "XPC "
472 elif kdebug_class == 42:
473 kdbg_class = "ATM "
474 elif kdebug_class == 128:
475 kdbg_class = "ANS "
476 elif kdebug_class == 129:
477 kdbg_class = "SIO "
478 elif kdebug_class == 130:
479 kdbg_class = "SEP "
480 elif kdebug_class == 131:
481 kdbg_class = "ISP "
482 elif kdebug_class == 132:
483 kdbg_class = "OSCA"
484 elif kdebug_class == 133:
485 kdbg_class = "EGFX"
486 elif kdebug_class == 255:
487 kdbg_class = "MIG "
488 else:
489 out_str += "{:^#10x} ".format(kdebug_class)
490
491 if kdbg_class:
492 out_str += "{:^10s} ".format(kdbg_class)
493
494 # subclass and code
495 out_str += " {:>#5x} {:>8d} ".format(kdebug_subclass, kdebug_code)
496
497 # space for debugid-specific processing
498 # EVPROC from bsd/kern/sys_generic.c
499 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
500 if debugid == 0x14100048:
501 code_info_str += "waitevent "
502 if kdebug_arg1 == 1:
503 code_info_str += "before sleep"
504 elif kdebug_arg1 == 2:
505 code_info_str += "after sleep"
506 else:
507 code_info_str += "????????????"
508 code_info_str += " chan={:#08x} ".format(kdebug_arg2)
509 elif debugid == 0x14100049:
510 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_START)
511 code_info_str += "waitevent "
512 elif debugid == 0x1410004a:
513 # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_END)
514 code_info_str += "waitevent error={:d} ".format(kdebug_arg1)
515 code_info_str += "eqp={:#08x} ".format(kdebug_arg4)
516 code_info_str += GetEVFlags(kdebug_arg3)
517 code_info_str += "er_handle={:d} ".format(kdebug_arg2)
518 elif debugid == 0x14100059:
519 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_START)
520 code_info_str += "evprocdeque proc={:#08x} ".format(kdebug_arg1)
521 if kdebug_arg2 == 0:
522 code_info_str += "remove first "
523 else:
524 code_info_str += "remove {:#08x} ".format(kdebug_arg2)
525 elif debugid == 0x1410005a:
526 # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_END)
527 code_info_str += "evprocdeque "
528 if kdebug_arg1 == 0:
529 code_info_str += "result=NULL "
530 else:
531 code_info_str += "result={:#08x} ".format(kdebug_arg1)
532 elif debugid == 0x14100041:
533 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_START)
534 code_info_str += "postevent "
535 code_info_str += GetEVFlags(kdebug_arg1)
536 elif debugid == 0x14100040:
537 # MISCDBG_CODE(DBG_EVENT,DBG_POST)
538 code_info_str += "postevent "
539 code_info_str += "evq={:#08x} ".format(kdebug_arg1)
540 code_info_str += "er_eventbits="
541 code_info_str += GetEVFlags(kdebug_arg2)
542 code_info_str +="mask="
543 code_info_str += GetEVFlags(kdebug_arg3)
544 elif debugid == 0x14100042:
545 # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_END)
546 code_info_str += "postevent "
547 elif debugid == 0x14100055:
548 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_START)
549 code_info_str += "evprocenque eqp={:#08x} ".format(kdebug_arg1)
550 if kdebug_arg2 & 1:
551 code_info_str += "EV_QUEUED "
552 code_info_str += GetEVFlags(kdebug_arg3)
553 elif debugid == 0x14100050:
554 # MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
555 code_info_str += "evprocenque before wakeup eqp={:#08x} ".format(kdebug_arg4)
556 elif debugid == 0x14100056:
557 # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_END)
558 code_info_str += "evprocenque "
559 elif debugid == 0x1410004d:
560 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_START)
561 code_info_str += "modwatch "
562 elif debugid == 0x1410004c:
563 # MISCDBG_CODE(DBG_EVENT,DBG_MOD)
564 code_info_str += "modwatch er_handle={:d} ".format(kdebug_arg1)
565 code_info_str += GetEVFlags(kdebug_arg2)
566 code_info_str += "evq={:#08x} ", kdebug_arg3
567 elif debugid == 0x1410004e:
568 # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_END)
569 code_info_str += "modwatch er_handle={:d} ".format(kdebug_arg1)
570 code_info_str += "ee_eventmask="
571 code_info_str += GetEVFlags(kdebug_arg2)
572 code_info_str += "sp={:#08x} ".format(kdebug_arg3)
573 code_info_str += "flag="
574 code_info_str += GetEVFlags(kdebug_arg4)
575 else:
576 code_info_str += "arg1={:#010x} ".format(kdebug_arg1)
577 code_info_str += "arg2={:#010x} ".format(kdebug_arg2)
578 code_info_str += "arg3={:#010x} ".format(kdebug_arg3)
579 code_info_str += "arg4={:#010x} ".format(kdebug_arg4)
580
581 # finish up
582 out_str += "{:<25s}\n".format(code_info_str)
583 return out_str
584
585 @lldb_command('showkerneldebugbuffercpu')
586 @header("{0: ^20s} {1: >6s} {2: >12s} {3: ^20s} {4: >6s} {5: ^10s} {6: >5s} {7: >8s} {8: ^25s}".
587 format('kd_buf', 'CPU', 'Thread', 'Timestamp', 'S/E', 'Class', 'Sub', 'Code', 'Code Specific Info'))
588 def ShowKernelDebugBufferCPU(cmd_args=None):
589 """ Prints the last N entries in the kernel debug buffer for specified cpu
590 Syntax: showkerneldebugbuffercpu <cpu_num> <count>
591 """
592 if cmd_args == None or len(cmd_args) < 2:
593 raise ArgumentError("Invalid arguments passed.")
594
595 out_str = ""
596 kdbg_str = ""
597 cpu_number = ArgumentStringToInt(cmd_args[0])
598 entry_count = ArgumentStringToInt(cmd_args[1])
599 debugentriesfound = 0
600 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
601 if (kern.globals.kd_ctrl_page.kdebug_flags & 0x80000000):
602 out_str += ShowKernelDebugBufferCPU.header + "\n"
603 if entry_count == 0:
604 out_str += "<count> is 0, dumping 50 entries\n"
605 entry_count = 50
606
607 if cpu_number >= kern.globals.kd_ctrl_page.kdebug_cpus:
608 kdbg_str += "cpu number too big\n"
609 else:
610 kdbp = addressof(kern.globals.kdbip[cpu_number])
611 kdsp = kdbp.kd_list_head
612 while ((kdsp.raw != 0 and kdsp.raw != 0x00000000ffffffff) and (entry_count > 0)):
613 kd_buffer = kern.globals.kd_bufs[kdsp.buffer_index]
614 kdsp_actual = addressof(kd_buffer.kdsb_addr[kdsp.offset])
615 if kdsp_actual.kds_readlast != kdsp_actual.kds_bufindx:
616 kds_buf = kdsp_actual.kds_records[kdsp_actual.kds_bufindx]
617 kds_bufptr = addressof(kds_buf)
618 while (entry_count > 0) and \
619 (unsigned(kds_bufptr) > unsigned(addressof(kdsp_actual.kds_records[kdsp_actual.kds_readlast]))):
620 kds_bufptr = kds_bufptr - sizeof(kds_buf)
621 entry_count = entry_count - 1
622 kdbg_str += GetKernelDebugBufferEntry(kds_bufptr)
623 kdsp = kdsp_actual.kds_next
624 else:
625 kdbg_str += "Trace buffer not enabled for CPU {:d}\n".format(cpu_number)
626
627 if kdbg_str:
628 out_str += kdbg_str
629 print out_str
630
631 @lldb_command('showkerneldebugbuffer')
632 def ShowKernelDebugBuffer(cmd_args=None):
633 """ Prints the last N entries in the kernel debug buffer per cpu
634 Syntax: showkerneldebugbuffer <count>
635 """
636 if cmd_args == None or len(cmd_args) < 1:
637 raise ArgumentError("Invalid arguments passed.")
638
639 # Check if KDBG_BFINIT (0x80000000) is set in kdebug_flags
640 if (kern.globals.kd_ctrl_page.kdebug_flags & 0x80000000):
641 entrycount = ArgumentStringToInt(cmd_args[0])
642 if entrycount == 0:
643 print "<count> is 0, dumping 50 entries per cpu\n"
644 entrycount = 50
645 cpu_num = 0
646 while cpu_num < kern.globals.kd_ctrl_page.kdebug_cpus:
647 ShowKernelDebugBufferCPU([str(cpu_num), str(entrycount)])
648 cpu_num += 1
649 else:
650 print "Trace buffer not enabled\n"