]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/misc.py
xnu-4570.61.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / misc.py
CommitLineData
39236c6e
A
1"""
2Miscellaneous (Intel) platform-specific commands.
3"""
4
5from xnu import *
6import xnudefines
7
5ba3f43e
A
8from scheduler import *
9
39236c6e
A
10@lldb_command('showmcastate')
11def showMCAstate(cmd_args=None):
12 """
13 Print machine-check register state after MC exception.
14 """
15 if kern.arch != 'x86_64':
16 print "Not available for current architecture."
17 return
18
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)
28 cpu = 0
29 while kern.globals.cpu_data_ptr[cpu]:
30 cd = kern.globals.cpu_data_ptr[cpu]
31 mc = cd.cpu_mca_state
32 if mc:
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',
37 'mca_mci_ctl',
38 'mca_mci_status',
39 'mca_mci_addr',
40 'mca_mci_misc')
41 for i in range(int(kern.globals.mca_error_bank_count)):
42 bank = mc.mca_error_bank[i]
43 print val.format(i,
44 bank.mca_mci_ctl,
45 bank.mca_mci_status.u64,
46 bank.mca_mci_addr,
47 bank.mca_mci_misc)
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))
51 cpu = cpu + 1
52
53def dumpTimerList(anchor):
54 """
55 Utility function to dump the timer entries in list (anchor).
56 """
57 entry = Cast(anchor.head, 'queue_t')
58 if entry == addressof(anchor):
59 print '(empty)'
60 return
61
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 *')
5ba3f43e
A
67 recent_timestamp = GetRecentTimestamp()
68 if (recent_timestamp < call_entry.deadline):
39236c6e 69 delta_sign = ' '
5ba3f43e 70 timer_fire = call_entry.deadline - recent_timestamp
39236c6e
A
71 else:
72 delta_sign = '-'
5ba3f43e
A
73 timer_fire = recent_timestamp - call_entry.deadline
74
75 func_name = kern.Symbolicate(call_entry.func)
76
77 tval = ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d} ({:#018x})({:#018x},{:#018x}) ({:s})'
39236c6e
A
78 print tval.format(entry,
79 call_entry.deadline,
80 timer_call.soft_deadline,
81 delta_sign,
82 timer_fire/1000000000,
83 timer_fire%1000000000,
84 call_entry.func,
85 call_entry.param0,
5ba3f43e
A
86 call_entry.param1,
87 func_name)
39236c6e
A
88 entry = entry.next
89
5ba3f43e
A
90def GetCpuDataForCpuID(cpu_id):
91 """
92 Find struct cpu_data for a CPU
93 ARM is complicated
94 """
95 if kern.arch == 'x86_64':
96 cpu_data = kern.globals.cpu_data_ptr[cpu_id]
97 return cpu_data
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*')
104
39236c6e
A
105@lldb_command('longtermtimers')
106def longtermTimers(cmd_args=None):
107 """
108 Print details of long-term timers and stats.
109 """
39236c6e
A
110
111 lt = kern.globals.timer_longterm
112 ltt = lt.threshold
113 EndofAllTime = -1
114 if ltt.interval == EndofAllTime:
115 print "Longterm timers disabled"
116 return
117
118 if lt.escalates > 0:
119 ratio = lt.enqueues / lt.escalates
120 else:
121 ratio = lt.enqueues
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'
133 else:
134 print ' threshold.preempted : {:d}' .format(ltt.preempted)
135 if ltt.deadline == EndofAllTime:
136 print ' threshold.deadline : None'
137 else:
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)
147
148
149@lldb_command('processortimers')
150def processorTimers(cmd_args=None):
151 """
152 Print details of processor timers, noting anything suspicious
153 Also include long-term timer details
154 """
155 hdr = '{:<32s}{:<18s} {:<18s} {:<18s}'
156 print hdr.format('Processor','Last dispatch','Next deadline','difference')
157 p = kern.globals.processor_list
158 while p:
159 cpu = p.cpu_id
5ba3f43e
A
160 cpu_data = GetCpuDataForCpuID(cpu)
161 rt_timer = cpu_data.rtclock_timer
39236c6e
A
162 diff = p.last_dispatch - rt_timer.deadline
163 tmr = 'Processor {:d}: {:#018x} {:#018x} {:#018x} {:#018x} {:s}'
164 print tmr.format(cpu,
165 p,
166 p.last_dispatch,
167 rt_timer.deadline,
168 diff,
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)
5ba3f43e 172 dumpTimerList(rt_timer.queue)
39236c6e
A
173 p = p.processor_list
174 longtermTimers()
175
176
177@lldb_command('showtimerwakeupstats')
178def showTimerWakeupStats(cmd_args=None):
179 """
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.
183 """
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(
188 proc.p_pid,
189 proc.p_comm,
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'):
5ba3f43e
A
200## if thread.thread_interrupt_wakeups == 0:
201## continue
39236c6e
A
202 print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format(
203 thread.thread_id,
204 thread.thread_tag,
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,
209 0,0,0,0,
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)
218
219def DoReadMsr64(msr_address, lcpu):
220 """ Read a 64-bit MSR from the specified CPU
221 Params:
222 msr_address: int - MSR index to read from
223 lcpu: int - CPU identifier
224 Returns:
225 64-bit value read from the MSR
226 """
227 result = 0xbad10ad
228
229 if "kdp" != GetConnectionProtocol():
230 print "Target is not connected over kdp. Cannot read MSR."
231 return result
232
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"
238 return result
239
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"
243 return result
244
245 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_readmsr64_req_t *')
246 header_value = GetKDPPacketHeaderInt(
247 request=GetEnumValue('kdp_req_t::KDP_READMSR64'),
248 length=kdp_pkt_size)
249
250 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
251 print "DoReadMsr64() failed to write header_value"
252 return result
253 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
254 print "DoReadMsr64() failed to write msr_address"
255 return result
256 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
257 print "DoReadMsr64() failed to write lcpu"
258 return result
259 if not WriteInt32ToMemoryAddress(1, input_address):
260 print "DoReadMsr64() failed to write to input_address"
261 return result
262
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 *'))
267 else:
268 print "DoReadMsr64() result_pkt.error != 0"
269 return result
270
271def DoWriteMsr64(msr_address, lcpu, data):
272 """ Write a 64-bit MSR
273 Params:
274 msr_address: int - MSR index to write to
275 lcpu: int - CPU identifier
276 data: int - value to write
277 Returns:
278 True upon success, False if error
279 """
280 if "kdp" != GetConnectionProtocol():
281 print "Target is not connected over kdp. Cannot write MSR."
282 return False
283
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"
289 return False
290
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"
294 return False
295
296 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_writemsr64_req_t *')
297 header_value = GetKDPPacketHeaderInt(
298 request=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'),
299 length=kdp_pkt_size)
300
301 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
302 print "DoWriteMsr64() failed to write header_value"
303 return False
304 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
305 print "DoWriteMsr64() failed to write msr_address"
306 return False
307 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
308 print "DoWriteMsr64() failed to write lcpu"
309 return False
310 if not WriteInt64ToMemoryAddress(data, int(addressof(kgm_pkt.data))):
311 print "DoWriteMsr64() failed to write data"
312 return False
313 if not WriteInt32ToMemoryAddress(1, input_address):
314 print "DoWriteMsr64() failed to write to input_address"
315 return False
316
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"
321 return False
322
323 return True
324
325@lldb_command('readmsr64')
326def ReadMsr64(cmd_args=None):
327 """ Read the specified MSR. The CPU can be optionally specified
328 Syntax: readmsr64 <msr> [lcpu]
329 """
330 if cmd_args == None or len(cmd_args) < 1:
331 print ReadMsr64.__doc__
332 return
333
334 msr_address = ArgumentStringToInt(cmd_args[0])
335 if len(cmd_args) > 1:
336 lcpu = ArgumentStringToInt(cmd_args[1])
337 else:
338 lcpu = int(xnudefines.lcpu_self)
339
340 msr_value = DoReadMsr64(msr_address, lcpu)
341 print "MSR[{:x}]: {:#016x}".format(msr_address, msr_value)
342
343@lldb_command('writemsr64')
344def WriteMsr64(cmd_args=None):
345 """ Write the specified MSR. The CPU can be optionally specified
346 Syntax: writemsr64 <msr> <value> [lcpu]
347 """
348 if cmd_args == None or len(cmd_args) < 2:
349 print WriteMsr64.__doc__
350 return
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])
355 else:
356 lcpu = xnudefines.lcpu_self
357
358 if not DoWriteMsr64(msr_address, lcpu, write_val):
359 print "writemsr64 FAILED"
360
3e170ce0
A
361def GetEVFlags(debug_arg):
362 """ Return the EV Flags for the given kernel debug arg value
363 params:
364 debug_arg - value from arg member of kernel debug buffer entry
365 returns:
366 str - string representing the EV Flag for given input arg value
367 """
368 out_str = ""
369 if debug_arg & 1:
370 out_str += "EV_RE "
371 if debug_arg & 2:
372 out_str += "EV_WR "
373 if debug_arg & 4:
374 out_str += "EV_EX "
375 if debug_arg & 8:
376 out_str += "EV_RM "
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:
390 out_str += "EV_OOB "
391 if debug_arg & 0x08000:
392 out_str += "EV_FIN "
393 if debug_arg & 0x10000:
394 out_str += "EV_RESET "
395 if debug_arg & 0x20000:
396 out_str += "EV_TIMEOUT "
397
398 return out_str
399
400def GetKernelDebugBufferEntry(kdbg_entry):
401 """ Extract the information from given kernel debug buffer entry and return the summary
402 params:
403 kdebug_entry - kd_buf - address of kernel debug buffer entry
404 returns:
405 str - formatted output information of kd_buf entry
406 """
407 out_str = ""
408 code_info_str = ""
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
415
5ba3f43e 416 if kern.arch == 'x86_64' or kern.arch.startswith('arm64'):
3e170ce0
A
417 kdebug_cpu = kdebug_entry.cpuid
418 ts_hi = (kdebug_entry.timestamp >> 32) & 0xFFFFFFFF
419 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
420 else:
421 kdebug_cpu = (kdebug_entry.timestamp >> 56)
422 ts_hi = (kdebug_entry.timestamp >> 32) & 0x00FFFFFF
423 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
424
425 kdebug_class = (debugid >> 24) & 0x000FF
426 kdebug_subclass = (debugid >> 16) & 0x000FF
427 kdebug_code = (debugid >> 2) & 0x03FFF
428 kdebug_qual = (debugid) & 0x00003
429
430 if kdebug_qual == 0:
431 kdebug_qual = '-'
432 elif kdebug_qual == 1:
433 kdebug_qual = 'S'
434 elif kdebug_qual == 2:
435 kdebug_qual = 'E'
436 elif kdebug_qual == 3:
437 kdebug_qual = '?'
438
439 # preamble and qual
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)
442
443 # class
444 kdbg_class = ""
445 if kdebug_class == 1:
446 kdbg_class = "MACH"
447 elif kdebug_class == 2:
448 kdbg_class = "NET "
449 elif kdebug_class == 3:
450 kdbg_class = "FS "
451 elif kdebug_class == 4:
452 kdbg_class = "BSD "
453 elif kdebug_class == 5:
454 kdbg_class = "IOK "
455 elif kdebug_class == 6:
456 kdbg_class = "DRVR"
457 elif kdebug_class == 7:
458 kdbg_class = "TRAC"
459 elif kdebug_class == 8:
460 kdbg_class = "DLIL"
461 elif kdebug_class == 9:
462 kdbg_class = "WQ "
463 elif kdebug_class == 10:
464 kdbg_class = "CS "
465 elif kdebug_class == 11:
466 kdbg_class = "CG "
467 elif kdebug_class == 20:
468 kdbg_class = "MISC"
469 elif kdebug_class == 30:
470 kdbg_class = "SEC "
471 elif kdebug_class == 31:
472 kdbg_class = "DYLD"
473 elif kdebug_class == 32:
474 kdbg_class = "QT "
475 elif kdebug_class == 33:
476 kdbg_class = "APPS"
477 elif kdebug_class == 34:
478 kdbg_class = "LAUN"
479 elif kdebug_class == 36:
480 kdbg_class = "PPT "
481 elif kdebug_class == 37:
482 kdbg_class = "PERF"
483 elif kdebug_class == 38:
484 kdbg_class = "IMP "
485 elif kdebug_class == 39:
486 kdbg_class = "PCTL"
487 elif kdebug_class == 40:
488 kdbg_class = "BANK"
489 elif kdebug_class == 41:
490 kdbg_class = "XPC "
491 elif kdebug_class == 42:
492 kdbg_class = "ATM "
493 elif kdebug_class == 128:
494 kdbg_class = "ANS "
495 elif kdebug_class == 129:
496 kdbg_class = "SIO "
497 elif kdebug_class == 130:
498 kdbg_class = "SEP "
499 elif kdebug_class == 131:
500 kdbg_class = "ISP "
501 elif kdebug_class == 132:
502 kdbg_class = "OSCA"
503 elif kdebug_class == 133:
504 kdbg_class = "EGFX"
505 elif kdebug_class == 255:
506 kdbg_class = "MIG "
507 else:
508 out_str += "{:^#10x} ".format(kdebug_class)
509
510 if kdbg_class:
511 out_str += "{:^10s} ".format(kdbg_class)
512
513 # subclass and code
514 out_str += " {:>#5x} {:>8d} ".format(kdebug_subclass, kdebug_code)
515
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 "
521 if kdebug_arg1 == 1:
522 code_info_str += "before sleep"
523 elif kdebug_arg1 == 2:
524 code_info_str += "after sleep"
525 else:
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)
540 if kdebug_arg2 == 0:
541 code_info_str += "remove first "
542 else:
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 "
547 if kdebug_arg1 == 0:
548 code_info_str += "result=NULL "
549 else:
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)
569 if kdebug_arg2 & 1:
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)
594 else:
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)
599
600 # finish up
601 out_str += "{:<25s}\n".format(code_info_str)
602 return out_str
603
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'))
607def ShowKernelDebugBufferCPU(cmd_args=None):
608 """ Prints the last N entries in the kernel debug buffer for specified cpu
609 Syntax: showkerneldebugbuffercpu <cpu_num> <count>
610 """
611 if cmd_args == None or len(cmd_args) < 2:
612 raise ArgumentError("Invalid arguments passed.")
613
614 out_str = ""
615 kdbg_str = ""
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"
622 if entry_count == 0:
623 out_str += "<count> is 0, dumping 50 entries\n"
624 entry_count = 50
625
626 if cpu_number >= kern.globals.kd_ctrl_page.kdebug_cpus:
627 kdbg_str += "cpu number too big\n"
628 else:
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
643 else:
644 kdbg_str += "Trace buffer not enabled for CPU {:d}\n".format(cpu_number)
645
646 if kdbg_str:
647 out_str += kdbg_str
648 print out_str
649
650@lldb_command('showkerneldebugbuffer')
651def ShowKernelDebugBuffer(cmd_args=None):
652 """ Prints the last N entries in the kernel debug buffer per cpu
653 Syntax: showkerneldebugbuffer <count>
654 """
655 if cmd_args == None or len(cmd_args) < 1:
656 raise ArgumentError("Invalid arguments passed.")
657
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])
661 if entrycount == 0:
662 print "<count> is 0, dumping 50 entries per cpu\n"
663 entrycount = 50
664 cpu_num = 0
665 while cpu_num < kern.globals.kd_ctrl_page.kdebug_cpus:
666 ShowKernelDebugBufferCPU([str(cpu_num), str(entrycount)])
667 cpu_num += 1
668 else:
669 print "Trace buffer not enabled\n"
5ba3f43e
A
670
671@lldb_command('dumprawtracefile','U:')
672def DumpRawTraceFile(cmd_args=[], cmd_options={}):
673 """
674 support for ktrace(1)
675
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.
678
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.
683
684 cf. kdbg_read()\bsd/kern/kdebug.c
685 """
686
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"
690 return
691
692 if ((kern.arch == "x86_64") or (kern.arch == "arm64")) :
693 lp64 = True
694 elif kern.arch == "arm" :
695 lp64 = False
696 else :
697 print "unknown kern.arch {:s}\n".format(kern.arch)
698 return
699
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.
706 htab = {}
707
708 if lp64 :
709 KDBG_TIMESTAMP_MASK = 0xffffffffffffffff
710 else :
711 KDBG_TIMESTAMP_MASK = 0x00ffffffffffffff
712 KDBG_CPU_SHIFT = 56
713
714 barrier_min = 0
715 barrier_max = 0
716 out_of_events = False
717 lostevents = 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
722
723 opt_verbose = config['verbosity']
724 opt_progress = (opt_verbose > vHUMAN) and (opt_verbose < vDETAIL)
725 progress_count = 0
726 progress_stride = 32
727
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")
732
733 uptime = long(-1)
734 if "-U" in cmd_options:
735 uptime = long(cmd_options["-U"])
736 if opt_verbose > vHUMAN :
737 print "uptime : {:d}".format(uptime)
738
739 nkdbufs = kern.globals.nkdbufs
740
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
744
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)
747
748 if nkdbufs == 0 :
749 print "0 nkdbufs, nothing extracted"
750 return
751
752 if htab[kd_ctrl_page].enabled != 0 :
753 barrier_max = uptime & KDBG_TIMESTAMP_MASK
754
755 f = htab[kd_ctrl_page].kdebug_flags
756 wrapped = f & xnudefines.KDBG_WRAPPED
757 if wrapped != 0 :
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
761
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]
766
767 kdsp = htab[kdbp].kd_list_head.raw
768 if kdsp == xnudefines.KDS_PTR_NULL :
769 continue
770
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
777
778
779 # generate trace file header; threadmap is stubbed/TBD
780 version_no = xnudefines.RAW_VERSION1
781 thread_count = 0
782 TOD_secs = uptime
783 TOD_usecs = 0
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))
788
789 count = nkdbufs
790 while count != 0 :
791 tempbuf = ""
792 tempbuf_number = 0
793 tempbuf_count = min(count, xnudefines.KDCOPYBUF_COUNT)
794
795 # while space
796 while tempbuf_count != 0 :
797
798 if opt_progress == True :
799 progress_count += 1
800 if (progress_count % progress_stride) == 0 :
801 sys.stderr.write('.')
802 sys.stderr.flush()
803
804 earliest_time = 0xffffffffffffffff
805 min_kdbp = None
806 min_cpu = 0
807
808 # Check all CPUs
809 for cpu in range(htab[kd_ctrl_page].kdebug_cpus) :
810
811 kdbp = unsigned(addressof(kern.globals.kdbip[cpu]))
812 if not kdbp in htab :
813 htab[kdbp] = kern.globals.kdbip[cpu]
814
815 # Skip CPUs without data.
816 kdsp = htab[kdbp].kd_list_head
817 if kdsp.raw == xnudefines.KDS_PTR_NULL :
818 continue
819
820 kdsp_shadow = kdsp
821
822 # Get from cpu data to buffer header to buffer
823 ix = kdsp.buffer_index
824 off = kdsp.offset
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]
828
829 kdsp_actual_shadow = kdsp_actual
830
831 # Skip buffer if there are no events left.
832 rcursor = htab[kdsp_actual].kds_readlast
833 if rcursor == htab[kdsp_actual].kds_bufindx :
834 continue
835
836 t = htab[kdsp_actual].kds_records[rcursor].timestamp & KDBG_TIMESTAMP_MASK
837
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
843 rcursor = r + 1
844
845 if rcursor >= xnudefines.EVENTS_PER_STORAGE_UNIT :
846
847 kdsp = htab[kdbp].kd_list_head
848 if kdsp.raw == xnudefines.KDS_PTR_NULL :
849 goto_next_cpu = True
850 break
851
852 kdsp_shadow = kdsp;
853
854 ix = kdsp.buffer_index
855 off = kdsp.offset
856 kdsp_actual = unsigned(addressof(kern.globals.kd_bufs[ix].kdsb_addr[off]))
857
858 kdsp_actual_shadow = kdsp_actual;
859 rcursor = htab[kdsp_actual].kds_readlast;
860
861 t = htab[kdsp_actual].kds_records[rcursor].timestamp & KDBG_TIMESTAMP_MASK
862
863 if goto_next_cpu == True :
864 continue
865
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
869 # buffers.
870 out_of_events = True
871 break
872
873 if t < (htab[kdsp_actual].kds_timestamp & KDBG_TIMESTAMP_MASK) :
874 # indicates we've not yet completed filling
875 # in this event...
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
879 # call to kdbg_read
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)
883 out_of_events = True
884 break
885
886 if t < earliest_time :
887 earliest_time = t
888 min_kdbp = kdbp
889 min_cpu = cpu
890
891
892 if (min_kdbp is None) or (out_of_events == True) :
893 # all buffers ran empty
894 out_of_events = True
895 break
896
897 kdsp = htab[min_kdbp].kd_list_head
898
899 ix = kdsp.buffer_index
900 off = kdsp.offset
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]
904
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]
909
910 # Concatenate event into buffer
911 # XXX condition here is on __LP64__
912 if 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)
915 else :
916 tempbuf += struct.pack('QIIIIII',
917 e.timestamp, e.arg1, e.arg2, e.arg3, e.arg4, e.arg5, e.debugid)
918
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
923
924 e.timestamp = htab[min_kdbp].kd_prev_timebase & KDBG_TIMESTAMP_MASK
925 e.timestamp |= (min_cpu << KDBG_CPU_SHIFT)
926 else :
927 htab[min_kdbp].kd_prev_timebase = earliest_time
928
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)
932
933 events_count_found += 1
934
935 # nextevent:
936 tempbuf_count -= 1
937 tempbuf_number += 1
938
939 if opt_progress == True :
940 sys.stderr.write('\n')
941 sys.stderr.flush()
942
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)
945
946 # write trace events to output file
947 if tempbuf_number != 0 :
948 count -= tempbuf_number
949 wfd.write(buffer(tempbuf))
950
951 if out_of_events == True :
952 # all trace buffers are empty
953 if opt_verbose > vHUMAN :
954 print "out of events"
955 break
956
957 wfd.close()
958
959 return
960
961
962def PrintIteratedElem(i, elem, elem_type, do_summary, summary, regex):
963 try:
964 if do_summary and summary:
965 s = summary(elem)
966 if regex:
967 if regex.match(s):
968 print "[{:d}] {:s}".format(i, s)
969 else:
970 print "[{:d}] {:s}".format(i, s)
971 else:
972 if regex:
973 if regex.match(str(elem)):
974 print "[{:4d}] ({:s}){:#x}".format(i, elem_type, unsigned(elem))
975 else:
976 print "[{:4d}] ({:s}){:#x}".format(i, elem_type, unsigned(elem))
977 except:
978 print "Exception while looking at elem {:#x}".format(unsigned(elem))
979 return
980
981@lldb_command('q_iterate', "LQSG:")
982def 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
985 usage:
986 iterate [options] {queue_head_ptr} {element_type} {field_name}
987 option:
988 -L iterate over a linkage chain (method 1) [default]
989 -Q iterate over a queue (method 2)
990
991 -S auto-summarize known types
992 -G regex to filter the output
993 e.g.
994 iterate_linkage `&coalitions_q` 'coalition *' coalitions
995 """
996 if not cmd_args:
997 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
998
999 qhead = kern.GetValueFromAddress(cmd_args[0], 'struct queue_entry *')
1000 if not qhead:
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}")
1006
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
1015
1016 do_summary = False
1017 if "-S" in cmd_options:
1018 do_summary = True
1019 regex = None
1020 if "-G" in cmd_options:
1021 regex = re.compile(".*{:s}.*".format(cmd_options["-G"]))
1022 print "Looking for: {:s}".format(regex.pattern)
1023
1024 global lldb_summary_definitions
1025 summary = None
1026 if elem_type in lldb_summary_definitions:
1027 summary = lldb_summary_definitions[elem_type]
1028 if do_summary:
1029 print summary.header
1030
1031 try:
1032 i = 0
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)
1036 i = i + 1
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)
1040 i = i + 1
1041 except:
1042 print "Exception while looking at queue_head: {:#x}".format(unsigned(qhead))