]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/misc.py
xnu-6153.11.26.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
0a7de745
A
10@lldb_command('showlogstream')
11def showLogStream(cmd_args=None):
12 """
13 Dump the state of the kernel log stream
14 """
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)
18 count = 0
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)
25 count = count + 1
26 print "found {} entries".format(count)
27
28 count = 0
29 for entry in IterateSTAILQ_HEAD(kern.globals.oslog_stream_free_head, "buf_entries"):
30 count = count + 1
31 print "free list: {} entries".format(count)
32
33 count = 0
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)
39 count = count + 1
40
39236c6e
A
41@lldb_command('showmcastate')
42def showMCAstate(cmd_args=None):
43 """
44 Print machine-check register state after MC exception.
45 """
46 if kern.arch != 'x86_64':
47 print "Not available for current architecture."
48 return
49
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)
59 cpu = 0
60 while kern.globals.cpu_data_ptr[cpu]:
61 cd = kern.globals.cpu_data_ptr[cpu]
62 mc = cd.cpu_mca_state
63 if mc:
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',
68 'mca_mci_ctl',
69 'mca_mci_status',
70 'mca_mci_addr',
71 'mca_mci_misc')
72 for i in range(int(kern.globals.mca_error_bank_count)):
73 bank = mc.mca_error_bank[i]
74 print val.format(i,
75 bank.mca_mci_ctl,
76 bank.mca_mci_status.u64,
77 bank.mca_mci_addr,
78 bank.mca_mci_misc)
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))
82 cpu = cpu + 1
83
84def dumpTimerList(anchor):
85 """
86 Utility function to dump the timer entries in list (anchor).
87 """
88 entry = Cast(anchor.head, 'queue_t')
89 if entry == addressof(anchor):
90 print '(empty)'
91 return
92
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 *')
5ba3f43e
A
98 recent_timestamp = GetRecentTimestamp()
99 if (recent_timestamp < call_entry.deadline):
39236c6e 100 delta_sign = ' '
5ba3f43e 101 timer_fire = call_entry.deadline - recent_timestamp
39236c6e
A
102 else:
103 delta_sign = '-'
5ba3f43e
A
104 timer_fire = recent_timestamp - call_entry.deadline
105
106 func_name = kern.Symbolicate(call_entry.func)
107
108 tval = ' {:#018x}: {:16d} {:16d} {:s}{:3d}.{:09d} ({:#018x})({:#018x},{:#018x}) ({:s})'
39236c6e
A
109 print tval.format(entry,
110 call_entry.deadline,
111 timer_call.soft_deadline,
112 delta_sign,
113 timer_fire/1000000000,
114 timer_fire%1000000000,
115 call_entry.func,
116 call_entry.param0,
5ba3f43e
A
117 call_entry.param1,
118 func_name)
39236c6e
A
119 entry = entry.next
120
5ba3f43e
A
121def GetCpuDataForCpuID(cpu_id):
122 """
123 Find struct cpu_data for a CPU
124 ARM is complicated
125 """
126 if kern.arch == 'x86_64':
127 cpu_data = kern.globals.cpu_data_ptr[cpu_id]
128 return cpu_data
d9a64523 129 elif kern.arch.startswith('arm'):
5ba3f43e
A
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*')
135
39236c6e
A
136@lldb_command('longtermtimers')
137def longtermTimers(cmd_args=None):
138 """
139 Print details of long-term timers and stats.
140 """
39236c6e
A
141
142 lt = kern.globals.timer_longterm
143 ltt = lt.threshold
144 EndofAllTime = -1
145 if ltt.interval == EndofAllTime:
146 print "Longterm timers disabled"
147 return
148
149 if lt.escalates > 0:
150 ratio = lt.enqueues / lt.escalates
151 else:
152 ratio = lt.enqueues
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'
164 else:
165 print ' threshold.preempted : {:d}' .format(ltt.preempted)
166 if ltt.deadline == EndofAllTime:
167 print ' threshold.deadline : None'
168 else:
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)
178
179
180@lldb_command('processortimers')
181def processorTimers(cmd_args=None):
182 """
183 Print details of processor timers, noting anything suspicious
184 Also include long-term timer details
185 """
186 hdr = '{:<32s}{:<18s} {:<18s} {:<18s}'
187 print hdr.format('Processor','Last dispatch','Next deadline','difference')
188 p = kern.globals.processor_list
189 while p:
190 cpu = p.cpu_id
5ba3f43e
A
191 cpu_data = GetCpuDataForCpuID(cpu)
192 rt_timer = cpu_data.rtclock_timer
39236c6e
A
193 diff = p.last_dispatch - rt_timer.deadline
194 tmr = 'Processor {:d}: {:#018x} {:#018x} {:#018x} {:#018x} {:s}'
195 print tmr.format(cpu,
196 p,
197 p.last_dispatch,
198 rt_timer.deadline,
199 diff,
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)
5ba3f43e 203 dumpTimerList(rt_timer.queue)
39236c6e
A
204 p = p.processor_list
205 longtermTimers()
206
207
208@lldb_command('showtimerwakeupstats')
209def showTimerWakeupStats(cmd_args=None):
210 """
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.
214 """
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(
219 proc.p_pid,
220 proc.p_comm,
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'):
5ba3f43e
A
231## if thread.thread_interrupt_wakeups == 0:
232## continue
39236c6e
A
233 print '\tThread ID 0x{:x}, Tag 0x{:x}, timer wakeups: {:d} {:d} {:d} {:d} <2ms: {:d}, <5ms: {:d} UT: {:d} ST: {:d}'.format(
234 thread.thread_id,
235 thread.thread_tag,
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,
240 0,0,0,0,
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)
249
250def DoReadMsr64(msr_address, lcpu):
251 """ Read a 64-bit MSR from the specified CPU
252 Params:
253 msr_address: int - MSR index to read from
254 lcpu: int - CPU identifier
255 Returns:
256 64-bit value read from the MSR
257 """
258 result = 0xbad10ad
259
260 if "kdp" != GetConnectionProtocol():
261 print "Target is not connected over kdp. Cannot read MSR."
262 return result
263
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"
269 return result
270
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"
274 return result
275
276 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_readmsr64_req_t *')
277 header_value = GetKDPPacketHeaderInt(
278 request=GetEnumValue('kdp_req_t::KDP_READMSR64'),
279 length=kdp_pkt_size)
280
281 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
282 print "DoReadMsr64() failed to write header_value"
283 return result
284 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
285 print "DoReadMsr64() failed to write msr_address"
286 return result
287 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
288 print "DoReadMsr64() failed to write lcpu"
289 return result
290 if not WriteInt32ToMemoryAddress(1, input_address):
291 print "DoReadMsr64() failed to write to input_address"
292 return result
293
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 *'))
298 else:
299 print "DoReadMsr64() result_pkt.error != 0"
300 return result
301
302def DoWriteMsr64(msr_address, lcpu, data):
303 """ Write a 64-bit MSR
304 Params:
305 msr_address: int - MSR index to write to
306 lcpu: int - CPU identifier
307 data: int - value to write
308 Returns:
309 True upon success, False if error
310 """
311 if "kdp" != GetConnectionProtocol():
312 print "Target is not connected over kdp. Cannot write MSR."
313 return False
314
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"
320 return False
321
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"
325 return False
326
327 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_writemsr64_req_t *')
328 header_value = GetKDPPacketHeaderInt(
329 request=GetEnumValue('kdp_req_t::KDP_WRITEMSR64'),
330 length=kdp_pkt_size)
331
332 if not WriteInt64ToMemoryAddress(header_value, int(addressof(kgm_pkt.hdr))):
333 print "DoWriteMsr64() failed to write header_value"
334 return False
335 if not WriteInt32ToMemoryAddress(msr_address, int(addressof(kgm_pkt.address))):
336 print "DoWriteMsr64() failed to write msr_address"
337 return False
338 if not WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))):
339 print "DoWriteMsr64() failed to write lcpu"
340 return False
341 if not WriteInt64ToMemoryAddress(data, int(addressof(kgm_pkt.data))):
342 print "DoWriteMsr64() failed to write data"
343 return False
344 if not WriteInt32ToMemoryAddress(1, input_address):
345 print "DoWriteMsr64() failed to write to input_address"
346 return False
347
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"
352 return False
353
354 return True
355
356@lldb_command('readmsr64')
357def ReadMsr64(cmd_args=None):
358 """ Read the specified MSR. The CPU can be optionally specified
359 Syntax: readmsr64 <msr> [lcpu]
360 """
361 if cmd_args == None or len(cmd_args) < 1:
362 print ReadMsr64.__doc__
363 return
364
365 msr_address = ArgumentStringToInt(cmd_args[0])
366 if len(cmd_args) > 1:
367 lcpu = ArgumentStringToInt(cmd_args[1])
368 else:
369 lcpu = int(xnudefines.lcpu_self)
370
371 msr_value = DoReadMsr64(msr_address, lcpu)
372 print "MSR[{:x}]: {:#016x}".format(msr_address, msr_value)
373
374@lldb_command('writemsr64')
375def WriteMsr64(cmd_args=None):
376 """ Write the specified MSR. The CPU can be optionally specified
377 Syntax: writemsr64 <msr> <value> [lcpu]
378 """
379 if cmd_args == None or len(cmd_args) < 2:
380 print WriteMsr64.__doc__
381 return
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])
386 else:
387 lcpu = xnudefines.lcpu_self
388
389 if not DoWriteMsr64(msr_address, lcpu, write_val):
390 print "writemsr64 FAILED"
391
3e170ce0
A
392def GetEVFlags(debug_arg):
393 """ Return the EV Flags for the given kernel debug arg value
394 params:
395 debug_arg - value from arg member of kernel debug buffer entry
396 returns:
397 str - string representing the EV Flag for given input arg value
398 """
399 out_str = ""
400 if debug_arg & 1:
401 out_str += "EV_RE "
402 if debug_arg & 2:
403 out_str += "EV_WR "
404 if debug_arg & 4:
405 out_str += "EV_EX "
406 if debug_arg & 8:
407 out_str += "EV_RM "
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:
421 out_str += "EV_OOB "
422 if debug_arg & 0x08000:
423 out_str += "EV_FIN "
424 if debug_arg & 0x10000:
425 out_str += "EV_RESET "
426 if debug_arg & 0x20000:
427 out_str += "EV_TIMEOUT "
428
429 return out_str
430
431def GetKernelDebugBufferEntry(kdbg_entry):
432 """ Extract the information from given kernel debug buffer entry and return the summary
433 params:
434 kdebug_entry - kd_buf - address of kernel debug buffer entry
435 returns:
436 str - formatted output information of kd_buf entry
437 """
438 out_str = ""
439 code_info_str = ""
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
446
5ba3f43e 447 if kern.arch == 'x86_64' or kern.arch.startswith('arm64'):
3e170ce0
A
448 kdebug_cpu = kdebug_entry.cpuid
449 ts_hi = (kdebug_entry.timestamp >> 32) & 0xFFFFFFFF
450 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
451 else:
452 kdebug_cpu = (kdebug_entry.timestamp >> 56)
453 ts_hi = (kdebug_entry.timestamp >> 32) & 0x00FFFFFF
454 ts_lo = kdebug_entry.timestamp & 0xFFFFFFFF
455
456 kdebug_class = (debugid >> 24) & 0x000FF
457 kdebug_subclass = (debugid >> 16) & 0x000FF
458 kdebug_code = (debugid >> 2) & 0x03FFF
459 kdebug_qual = (debugid) & 0x00003
460
461 if kdebug_qual == 0:
462 kdebug_qual = '-'
463 elif kdebug_qual == 1:
464 kdebug_qual = 'S'
465 elif kdebug_qual == 2:
466 kdebug_qual = 'E'
467 elif kdebug_qual == 3:
468 kdebug_qual = '?'
469
470 # preamble and qual
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)
473
474 # class
475 kdbg_class = ""
476 if kdebug_class == 1:
477 kdbg_class = "MACH"
478 elif kdebug_class == 2:
479 kdbg_class = "NET "
480 elif kdebug_class == 3:
481 kdbg_class = "FS "
482 elif kdebug_class == 4:
483 kdbg_class = "BSD "
484 elif kdebug_class == 5:
485 kdbg_class = "IOK "
486 elif kdebug_class == 6:
487 kdbg_class = "DRVR"
488 elif kdebug_class == 7:
489 kdbg_class = "TRAC"
490 elif kdebug_class == 8:
491 kdbg_class = "DLIL"
492 elif kdebug_class == 9:
493 kdbg_class = "WQ "
494 elif kdebug_class == 10:
495 kdbg_class = "CS "
496 elif kdebug_class == 11:
497 kdbg_class = "CG "
498 elif kdebug_class == 20:
499 kdbg_class = "MISC"
500 elif kdebug_class == 30:
501 kdbg_class = "SEC "
502 elif kdebug_class == 31:
503 kdbg_class = "DYLD"
504 elif kdebug_class == 32:
505 kdbg_class = "QT "
506 elif kdebug_class == 33:
507 kdbg_class = "APPS"
508 elif kdebug_class == 34:
509 kdbg_class = "LAUN"
510 elif kdebug_class == 36:
511 kdbg_class = "PPT "
512 elif kdebug_class == 37:
513 kdbg_class = "PERF"
514 elif kdebug_class == 38:
515 kdbg_class = "IMP "
516 elif kdebug_class == 39:
517 kdbg_class = "PCTL"
518 elif kdebug_class == 40:
519 kdbg_class = "BANK"
520 elif kdebug_class == 41:
521 kdbg_class = "XPC "
522 elif kdebug_class == 42:
523 kdbg_class = "ATM "
524 elif kdebug_class == 128:
525 kdbg_class = "ANS "
526 elif kdebug_class == 129:
527 kdbg_class = "SIO "
528 elif kdebug_class == 130:
529 kdbg_class = "SEP "
530 elif kdebug_class == 131:
531 kdbg_class = "ISP "
532 elif kdebug_class == 132:
533 kdbg_class = "OSCA"
534 elif kdebug_class == 133:
535 kdbg_class = "EGFX"
536 elif kdebug_class == 255:
537 kdbg_class = "MIG "
538 else:
539 out_str += "{:^#10x} ".format(kdebug_class)
540
541 if kdbg_class:
542 out_str += "{:^10s} ".format(kdbg_class)
543
544 # subclass and code
545 out_str += " {:>#5x} {:>8d} ".format(kdebug_subclass, kdebug_code)
546
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 "
552 if kdebug_arg1 == 1:
553 code_info_str += "before sleep"
554 elif kdebug_arg1 == 2:
555 code_info_str += "after sleep"
556 else:
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)
571 if kdebug_arg2 == 0:
572 code_info_str += "remove first "
573 else:
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 "
578 if kdebug_arg1 == 0:
579 code_info_str += "result=NULL "
580 else:
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)
600 if kdebug_arg2 & 1:
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)
625 else:
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)
630
631 # finish up
632 out_str += "{:<25s}\n".format(code_info_str)
633 return out_str
634
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'))
638def ShowKernelDebugBufferCPU(cmd_args=None):
639 """ Prints the last N entries in the kernel debug buffer for specified cpu
640 Syntax: showkerneldebugbuffercpu <cpu_num> <count>
641 """
642 if cmd_args == None or len(cmd_args) < 2:
643 raise ArgumentError("Invalid arguments passed.")
644
645 out_str = ""
646 kdbg_str = ""
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"
653 if entry_count == 0:
654 out_str += "<count> is 0, dumping 50 entries\n"
655 entry_count = 50
656
657 if cpu_number >= kern.globals.kd_ctrl_page.kdebug_cpus:
658 kdbg_str += "cpu number too big\n"
659 else:
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
674 else:
675 kdbg_str += "Trace buffer not enabled for CPU {:d}\n".format(cpu_number)
676
677 if kdbg_str:
678 out_str += kdbg_str
679 print out_str
680
681@lldb_command('showkerneldebugbuffer')
682def ShowKernelDebugBuffer(cmd_args=None):
683 """ Prints the last N entries in the kernel debug buffer per cpu
684 Syntax: showkerneldebugbuffer <count>
685 """
686 if cmd_args == None or len(cmd_args) < 1:
687 raise ArgumentError("Invalid arguments passed.")
688
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])
692 if entrycount == 0:
693 print "<count> is 0, dumping 50 entries per cpu\n"
694 entrycount = 50
695 cpu_num = 0
696 while cpu_num < kern.globals.kd_ctrl_page.kdebug_cpus:
697 ShowKernelDebugBufferCPU([str(cpu_num), str(entrycount)])
698 cpu_num += 1
699 else:
700 print "Trace buffer not enabled\n"
5ba3f43e
A
701
702@lldb_command('dumprawtracefile','U:')
703def DumpRawTraceFile(cmd_args=[], cmd_options={}):
704 """
705 support for ktrace(1)
706
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.
709
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.
714
715 cf. kdbg_read()\bsd/kern/kdebug.c
716 """
717
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"
721 return
722
d9a64523 723 if ((kern.arch == "x86_64") or kern.arch.startswith("arm64")) :
5ba3f43e
A
724 lp64 = True
725 elif kern.arch == "arm" :
726 lp64 = False
727 else :
728 print "unknown kern.arch {:s}\n".format(kern.arch)
729 return
730
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.
737 htab = {}
738
739 if lp64 :
740 KDBG_TIMESTAMP_MASK = 0xffffffffffffffff
741 else :
742 KDBG_TIMESTAMP_MASK = 0x00ffffffffffffff
743 KDBG_CPU_SHIFT = 56
744
745 barrier_min = 0
746 barrier_max = 0
747 out_of_events = False
748 lostevents = False
749 lostevent_timestamp = 0
750 lostevent_debugid = (((xnudefines.DBG_TRACE & 0xff) << 24) | ((xnudefines.DBG_TRACE_INFO & 0xff) << 16) | ((2 & 0x3fff) << 2)) # 0x01020008
751 events_count_lost = 0
752 events_count_found = 0
753
754 opt_verbose = config['verbosity']
755 opt_progress = (opt_verbose > vHUMAN) and (opt_verbose < vDETAIL)
756 progress_count = 0
757 progress_stride = 32
758
759 output_filename = str(cmd_args[0])
760 if opt_verbose > vHUMAN :
761 print "output file : {:s}".format(output_filename)
762 wfd = open(output_filename, "wb")
763
764 uptime = long(-1)
765 if "-U" in cmd_options:
766 uptime = long(cmd_options["-U"])
767 if opt_verbose > vHUMAN :
768 print "uptime : {:d}".format(uptime)
769
770 nkdbufs = kern.globals.nkdbufs
771
772 kd_ctrl_page = kern.globals.kd_ctrl_page
773 if not kd_ctrl_page in htab :
774 htab[kd_ctrl_page] = kern.globals.kd_ctrl_page
775
776 if opt_verbose > vHUMAN :
777 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)
778
779 if nkdbufs == 0 :
780 print "0 nkdbufs, nothing extracted"
781 return
782
783 if htab[kd_ctrl_page].enabled != 0 :
784 barrier_max = uptime & KDBG_TIMESTAMP_MASK
785
786 f = htab[kd_ctrl_page].kdebug_flags
787 wrapped = f & xnudefines.KDBG_WRAPPED
788 if wrapped != 0 :
789 barrier_min = htab[kd_ctrl_page].oldest_time
790 htab[kd_ctrl_page].kdebug_flags = htab[kd_ctrl_page].kdebug_flags & ~xnudefines.KDBG_WRAPPED
791 htab[kd_ctrl_page].oldest_time = 0
792
793 for cpu in range(htab[kd_ctrl_page].kdebug_cpus) :
794 kdbp = unsigned(addressof(kern.globals.kdbip[cpu]))
795 if not kdbp in htab :
796 htab[kdbp] = kern.globals.kdbip[cpu]
797
798 kdsp = htab[kdbp].kd_list_head.raw
799 if kdsp == xnudefines.KDS_PTR_NULL :
800 continue
801
802 ix = htab[kdbp].kd_list_head.buffer_index
803 off = htab[kdbp].kd_list_head.offset
804 kdsp_actual = unsigned(addressof(kern.globals.kd_bufs[ix].kdsb_addr[off]))
805 if not kdsp_actual in htab :
806 htab[kdsp_actual] = kern.globals.kd_bufs[ix].kdsb_addr[off]
807 htab[kdsp_actual].kds_lostevents = False
808
809
810 # generate trace file header; threadmap is stubbed/TBD
811 version_no = xnudefines.RAW_VERSION1
812 thread_count = 0
813 TOD_secs = uptime
814 TOD_usecs = 0
815 header = struct.pack('IIqI', version_no, thread_count, TOD_secs, TOD_usecs)
816 pad_bytes = 4096 - (len(header) & 4095)
817 header += "\x00" * pad_bytes
818 wfd.write(buffer(header))
819
820 count = nkdbufs
821 while count != 0 :
822 tempbuf = ""
823 tempbuf_number = 0
824 tempbuf_count = min(count, xnudefines.KDCOPYBUF_COUNT)
825
826 # while space
827 while tempbuf_count != 0 :
828
829 if opt_progress == True :
830 progress_count += 1
831 if (progress_count % progress_stride) == 0 :
832 sys.stderr.write('.')
833 sys.stderr.flush()
834
835 earliest_time = 0xffffffffffffffff
836 min_kdbp = None
837 min_cpu = 0
838
839 # Check all CPUs
840 for cpu in range(htab[kd_ctrl_page].kdebug_cpus) :
841
842 kdbp = unsigned(addressof(kern.globals.kdbip[cpu]))
843 if not kdbp in htab :
844 htab[kdbp] = kern.globals.kdbip[cpu]
845
846 # Skip CPUs without data.
847 kdsp = htab[kdbp].kd_list_head
848 if kdsp.raw == xnudefines.KDS_PTR_NULL :
849 continue
850
851 kdsp_shadow = kdsp
852
853 # Get from cpu data to buffer header to buffer
854 ix = kdsp.buffer_index
855 off = kdsp.offset
856 kdsp_actual = unsigned(addressof(kern.globals.kd_bufs[ix].kdsb_addr[off]))
857 if not kdsp_actual in htab :
858 htab[kdsp_actual] = kern.globals.kd_bufs[ix].kdsb_addr[off]
859
860 kdsp_actual_shadow = kdsp_actual
861
862 # Skip buffer if there are no events left.
863 rcursor = htab[kdsp_actual].kds_readlast
864 if rcursor == htab[kdsp_actual].kds_bufindx :
865 continue
866
867 t = htab[kdsp_actual].kds_records[rcursor].timestamp & KDBG_TIMESTAMP_MASK
868
869 # Ignore events that have aged out due to wrapping.
870 goto_next_cpu = False;
871 while (t < unsigned(barrier_min)) :
872 r = htab[kdsp_actual].kds_readlast
873 htab[kdsp_actual].kds_readlast = r + 1
874 rcursor = r + 1
875
876 if rcursor >= xnudefines.EVENTS_PER_STORAGE_UNIT :
877
878 kdsp = htab[kdbp].kd_list_head
879 if kdsp.raw == xnudefines.KDS_PTR_NULL :
880 goto_next_cpu = True
881 break
882
883 kdsp_shadow = kdsp;
884
885 ix = kdsp.buffer_index
886 off = kdsp.offset
887 kdsp_actual = unsigned(addressof(kern.globals.kd_bufs[ix].kdsb_addr[off]))
888
889 kdsp_actual_shadow = kdsp_actual;
890 rcursor = htab[kdsp_actual].kds_readlast;
891
892 t = htab[kdsp_actual].kds_records[rcursor].timestamp & KDBG_TIMESTAMP_MASK
893
894 if goto_next_cpu == True :
895 continue
896
897 if (t > barrier_max) and (barrier_max > 0) :
898 # Need to flush IOPs again before we
899 # can sort any more data from the
900 # buffers.
901 out_of_events = True
902 break
903
904 if t < (htab[kdsp_actual].kds_timestamp & KDBG_TIMESTAMP_MASK) :
905 # indicates we've not yet completed filling
906 # in this event...
907 # this should only occur when we're looking
908 # at the buf that the record head is utilizing
909 # we'll pick these events up on the next
910 # call to kdbg_read
911 # we bail at this point so that we don't
912 # get an out-of-order timestream by continuing
913 # to read events from the other CPUs' timestream(s)
914 out_of_events = True
915 break
916
917 if t < earliest_time :
918 earliest_time = t
919 min_kdbp = kdbp
920 min_cpu = cpu
921
922
923 if (min_kdbp is None) or (out_of_events == True) :
924 # all buffers ran empty
925 out_of_events = True
926 break
927
928 kdsp = htab[min_kdbp].kd_list_head
929
930 ix = kdsp.buffer_index
931 off = kdsp.offset
932 kdsp_actual = unsigned(addressof(kern.globals.kd_bufs[ix].kdsb_addr[off]))
933 if not kdsp_actual in htab :
934 htab[kdsp_actual] = kern.globals.kd_bufs[ix].kdsb_addr[off]
935
936 # Copy earliest event into merged events scratch buffer.
937 r = htab[kdsp_actual].kds_readlast
938 htab[kdsp_actual].kds_readlast = r + 1
939 e = htab[kdsp_actual].kds_records[r]
940
941 # Concatenate event into buffer
942 # XXX condition here is on __LP64__
943 if lp64 :
944 tempbuf += struct.pack('QQQQQQIIQ',
cb323159
A
945 unsigned(e.timestamp),
946 unsigned(e.arg1),
947 unsigned(e.arg2),
948 unsigned(e.arg3),
949 unsigned(e.arg4),
950 unsigned(e.arg5),
951 unsigned(e.debugid),
952 unsigned(e.cpuid),
953 unsigned(e.unused))
5ba3f43e 954 else :
cb323159
A
955 tempbuf += struct.pack('QIIIIII',
956 unsigned(e.timestamp),
957 unsigned(e.arg1),
958 unsigned(e.arg2),
959 unsigned(e.arg3),
960 unsigned(e.arg4),
961 unsigned(e.arg5),
962 unsigned(e.debugid))
5ba3f43e
A
963
964 # Watch for out of order timestamps
965 if earliest_time < (htab[min_kdbp].kd_prev_timebase & KDBG_TIMESTAMP_MASK) :
966 ## if so, use the previous timestamp + 1 cycle
967 htab[min_kdbp].kd_prev_timebase += 1
968
969 e.timestamp = htab[min_kdbp].kd_prev_timebase & KDBG_TIMESTAMP_MASK
970 e.timestamp |= (min_cpu << KDBG_CPU_SHIFT)
971 else :
972 htab[min_kdbp].kd_prev_timebase = earliest_time
973
974 if opt_verbose >= vDETAIL :
975 print "{0:#018x} {1:#018x} {2:#018x} {3:#018x} {4:#018x} {5:#018x} {6:#010x} {7:#010x} {8:#018x}".format(
976 e.timestamp, e.arg1, e.arg2, e.arg3, e.arg4, e.arg5, e.debugid, e.cpuid, e.unused)
977
978 events_count_found += 1
979
980 # nextevent:
981 tempbuf_count -= 1
982 tempbuf_number += 1
983
984 if opt_progress == True :
985 sys.stderr.write('\n')
986 sys.stderr.flush()
987
988 if opt_verbose > vHUMAN :
989 print "events_count_lost {0:#x}, events_count_found {1:#x}, progress_count {2:#x}".format(events_count_lost, events_count_found, progress_count)
990
991 # write trace events to output file
992 if tempbuf_number != 0 :
993 count -= tempbuf_number
994 wfd.write(buffer(tempbuf))
995
996 if out_of_events == True :
997 # all trace buffers are empty
998 if opt_verbose > vHUMAN :
999 print "out of events"
1000 break
1001
1002 wfd.close()
1003
1004 return
1005
1006
1007def PrintIteratedElem(i, elem, elem_type, do_summary, summary, regex):
1008 try:
1009 if do_summary and summary:
1010 s = summary(elem)
1011 if regex:
1012 if regex.match(s):
1013 print "[{:d}] {:s}".format(i, s)
1014 else:
1015 print "[{:d}] {:s}".format(i, s)
1016 else:
1017 if regex:
1018 if regex.match(str(elem)):
1019 print "[{:4d}] ({:s}){:#x}".format(i, elem_type, unsigned(elem))
1020 else:
1021 print "[{:4d}] ({:s}){:#x}".format(i, elem_type, unsigned(elem))
1022 except:
1023 print "Exception while looking at elem {:#x}".format(unsigned(elem))
1024 return
1025
1026@lldb_command('q_iterate', "LQSG:")
1027def QIterate(cmd_args=None, cmd_options={}):
1028 """ Iterate over a LinkageChain or Queue (osfmk/kern/queue.h method 1 or 2 respectively)
1029 This is equivalent to the qe_foreach_element() macro
1030 usage:
1031 iterate [options] {queue_head_ptr} {element_type} {field_name}
1032 option:
1033 -L iterate over a linkage chain (method 1) [default]
1034 -Q iterate over a queue (method 2)
1035
1036 -S auto-summarize known types
1037 -G regex to filter the output
1038 e.g.
1039 iterate_linkage `&coalitions_q` 'coalition *' coalitions
1040 """
1041 if not cmd_args:
1042 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
1043
1044 qhead = kern.GetValueFromAddress(cmd_args[0], 'struct queue_entry *')
1045 if not qhead:
1046 raise ArgumentError("Unknown queue_head pointer: %r" % cmd_args)
1047 elem_type = cmd_args[1]
1048 field_name = cmd_args[2]
1049 if not elem_type or not field_name:
1050 raise ArgumentError("usage: iterate_linkage {queue_head_ptr} {element_type} {field_name}")
1051
1052 do_queue_iterate = False
1053 do_linkage_iterate = True
1054 if "-Q" in cmd_options:
1055 do_queue_iterate = True
1056 do_linkage_iterate = False
1057 if "-L" in cmd_options:
1058 do_queue_iterate = False
1059 do_linkage_iterate = True
1060
1061 do_summary = False
1062 if "-S" in cmd_options:
1063 do_summary = True
1064 regex = None
1065 if "-G" in cmd_options:
1066 regex = re.compile(".*{:s}.*".format(cmd_options["-G"]))
1067 print "Looking for: {:s}".format(regex.pattern)
1068
1069 global lldb_summary_definitions
1070 summary = None
1071 if elem_type in lldb_summary_definitions:
1072 summary = lldb_summary_definitions[elem_type]
1073 if do_summary:
1074 print summary.header
1075
1076 try:
1077 i = 0
1078 if do_linkage_iterate:
1079 for elem in IterateLinkageChain(qhead, elem_type, field_name):
1080 PrintIteratedElem(i, elem, elem_type, do_summary, summary, regex)
1081 i = i + 1
1082 elif do_queue_iterate:
1083 for elem in IterateQueue(qhead, elem_type, field_name):
1084 PrintIteratedElem(i, elem, elem_type, do_summary, summary, regex)
1085 i = i + 1
1086 except:
1087 print "Exception while looking at queue_head: {:#x}".format(unsigned(qhead))