1from xnu import * 2 3@lldb_command('showmicrostackshot', 'O:', fancy=True) 4def show_microstackshot(cmd_args=None, cmd_options={}, O=None): 5 """ 6 Show information about the microstackshot subsystem. 7 8 Usage: (lldb) showmicrostackshot [-O <offset>] 9 """ 10 11 metadata = kern.GetGlobalVariable('telemetry_metadata') 12 print('metadata:') 13 print('{:>12s}: {}'.format('generation', metadata.tm_generation)) 14 print('{:>12s}: {}'.format('samples', metadata.tm_samples_recorded)) 15 print('{:>12s}: {}'.format('skips', metadata.tm_samples_skipped)) 16 print('{:>12s}: {}'.format('source', metadata.tm_source)) 17 print('{:>12s}: {}'.format('period', metadata.tm_period)) 18 19 kern_ring = kern.GetGlobalVariable("_telemetry_kernel_ring") 20 print() 21 print('kernel ringbuffer:') 22 print('{:>12s}: {}'.format('capacity', kern_ring.mr_capacity)) 23 print('{:>12s}: {}'.format('head', kern_ring.mr_head_tail.mrht_head)) 24 print('{:>12s}: {}'.format('tail', kern_ring.mr_head_tail.mrht_tail)) 25 print('{:>12s}: {}'.format('available', (kern_ring.mr_head_tail.mrht_tail - kern_ring.mr_head_tail.mrht_head) % kern_ring.mr_capacity)) 26 27 if kern_ring.mr_head_tail.mrht_tail & 0x3 != 0: 28 print('tail is not aligned') 29 return 30 31 print() 32 print('kernel samples:') 33 base_kern_text = kern.GetGlobalVariable('vm_kernel_stext') 34 35 next_record = unsigned(cmd_options.get('-O') or kern_ring.mr_head_tail.mrht_tail) 36 print(next_record) 37 while (kern_ring.mr_head_tail.mrht_head - next_record) > 0: 38 next_record_ptr = kern_ring.mr_buffer + (next_record % kern_ring.mr_capacity) 39 next_sample = kern.GetValueFromAddress(next_record_ptr, 'struct _telemetry_kernel_sample *') 40 if next_sample.tks_magic != xnudefines.TKS_MAGIC: 41 print('magic value for sample at position {} is {}, not {}'.format( 42 next_record % kern_ring.mr_capacity, next_sample.tks_magic, 43 xnudefines.TKS_MAGIC)) 44 break 45 print('{}.{:09d}: @{} thread 0x{:x} on CPU {}:'.format(next_sample.tks_time_secs, 46 next_sample.tks_time_usecs * 1000, next_record, next_sample.tks_thread_id, 47 next_sample.tks_cpu)) 48 call_stack_size = unsigned(next_sample.tks_call_stack_size) 49 next_record += sizeof('struct _telemetry_kernel_sample') + call_stack_size 50 call_stack = Cast(addressof(next_sample[1]), 'uint32_t *') 51 for i in range(call_stack_size // 4): 52 if call_stack[i] == 0: 53 continue 54 addr = base_kern_text + call_stack[i] 55 syms = kern.SymbolicateFromAddress(addr) 56 name = syms[0].GetName() if syms else '... try showkmodaddr ...' 57 print('\t0x{:16x} ({})'.format(addr, name)) 58 59 print('end at {}'.format(next_record)) 60