1*5c2921b0SApple OSS Distributionsfrom __future__ import absolute_import, division, print_function 2*5c2921b0SApple OSS Distributions 3*5c2921b0SApple OSS Distributionsfrom builtins import map 4*5c2921b0SApple OSS Distributionsfrom builtins import range 5*5c2921b0SApple OSS Distributionsfrom builtins import object 6*5c2921b0SApple OSS Distributions 7*5c2921b0SApple OSS Distributionsfrom xnu import * 8*5c2921b0SApple OSS Distributionsfrom utils import * 9*5c2921b0SApple OSS Distributionsfrom core.lazytarget import * 10*5c2921b0SApple OSS Distributionsfrom misc import * 11*5c2921b0SApple OSS Distributionsfrom scheduler import * 12*5c2921b0SApple OSS Distributionsfrom kcdata import kcdata_item_iterator, KCObject, GetTypeForName, KCCompressedBufferObject 13*5c2921b0SApple OSS Distributionsfrom collections import namedtuple 14*5c2921b0SApple OSS Distributionsfrom future.utils import PY2 15*5c2921b0SApple OSS Distributionsimport heapq 16*5c2921b0SApple OSS Distributionsimport os 17*5c2921b0SApple OSS Distributionsimport plistlib 18*5c2921b0SApple OSS Distributionsimport struct 19*5c2921b0SApple OSS Distributionsimport subprocess 20*5c2921b0SApple OSS Distributionsimport sys 21*5c2921b0SApple OSS Distributionsimport tempfile 22*5c2921b0SApple OSS Distributionsimport time 23*5c2921b0SApple OSS Distributions 24*5c2921b0SApple OSS Distributions# From the defines in bsd/sys/kdebug.h: 25*5c2921b0SApple OSS Distributions 26*5c2921b0SApple OSS DistributionsKdebugClassNames = { 27*5c2921b0SApple OSS Distributions 1: "MACH", 28*5c2921b0SApple OSS Distributions 2: "NETWORK", 29*5c2921b0SApple OSS Distributions 3: "FSYSTEM", 30*5c2921b0SApple OSS Distributions 4: "BSD", 31*5c2921b0SApple OSS Distributions 5: "IOKIT", 32*5c2921b0SApple OSS Distributions 6: "DRIVERS", 33*5c2921b0SApple OSS Distributions 7: "TRACE", 34*5c2921b0SApple OSS Distributions 8: "DLIL", 35*5c2921b0SApple OSS Distributions 9: "WORKQUEUE", 36*5c2921b0SApple OSS Distributions 10: "CORESTORAGE", 37*5c2921b0SApple OSS Distributions 11: "CG", 38*5c2921b0SApple OSS Distributions 20: "MISC", 39*5c2921b0SApple OSS Distributions 30: "SECURITY", 40*5c2921b0SApple OSS Distributions 31: "DYLD", 41*5c2921b0SApple OSS Distributions 32: "QT", 42*5c2921b0SApple OSS Distributions 33: "APPS", 43*5c2921b0SApple OSS Distributions 34: "LAUNCHD", 44*5c2921b0SApple OSS Distributions 36: "PPT", 45*5c2921b0SApple OSS Distributions 37: "PERF", 46*5c2921b0SApple OSS Distributions 38: "IMPORTANCE", 47*5c2921b0SApple OSS Distributions 39: "PERFCTRL", 48*5c2921b0SApple OSS Distributions 40: "BANK", 49*5c2921b0SApple OSS Distributions 41: "XPC", 50*5c2921b0SApple OSS Distributions 42: "ATM", 51*5c2921b0SApple OSS Distributions 43: "ARIADNE", 52*5c2921b0SApple OSS Distributions 44: "DAEMON", 53*5c2921b0SApple OSS Distributions 45: "ENERGYTRACE", 54*5c2921b0SApple OSS Distributions 49: "IMG", 55*5c2921b0SApple OSS Distributions 50: "CLPC", 56*5c2921b0SApple OSS Distributions 128: "ANS", 57*5c2921b0SApple OSS Distributions 129: "SIO", 58*5c2921b0SApple OSS Distributions 130: "SEP", 59*5c2921b0SApple OSS Distributions 131: "ISP", 60*5c2921b0SApple OSS Distributions 132: "OSCAR", 61*5c2921b0SApple OSS Distributions 133: "EMBEDDEDGFX" 62*5c2921b0SApple OSS Distributions} 63*5c2921b0SApple OSS Distributions 64*5c2921b0SApple OSS Distributionsdef GetKdebugClassName(class_num): 65*5c2921b0SApple OSS Distributions return (KdebugClassNames[class_num] + ' ({})'.format(class_num) if class_num in KdebugClassNames else 'unknown ({})'.format(class_num)) 66*5c2921b0SApple OSS Distributions 67*5c2921b0SApple OSS Distributions@lldb_type_summary(['typefilter_t']) 68*5c2921b0SApple OSS Distributions@header('{0: <20s}'.format("class") + ' '.join(map('{:02x}'.format, list(range(0, 255, 8))))) 69*5c2921b0SApple OSS Distributionsdef GetKdebugTypefilter(typefilter): 70*5c2921b0SApple OSS Distributions """ Summarizes the provided typefilter. 71*5c2921b0SApple OSS Distributions """ 72*5c2921b0SApple OSS Distributions classes = 256 73*5c2921b0SApple OSS Distributions subclasses_per_class = 256 74*5c2921b0SApple OSS Distributions 75*5c2921b0SApple OSS Distributions # 8 bits at a time 76*5c2921b0SApple OSS Distributions subclasses_per_element = 64 77*5c2921b0SApple OSS Distributions cur_typefilter = cast(typefilter, 'uint64_t *') 78*5c2921b0SApple OSS Distributions subclasses_fmts = ' '.join(['{:02x}'] * 8) 79*5c2921b0SApple OSS Distributions 80*5c2921b0SApple OSS Distributions elements_per_class = subclasses_per_class // subclasses_per_element 81*5c2921b0SApple OSS Distributions 82*5c2921b0SApple OSS Distributions out_str = '' 83*5c2921b0SApple OSS Distributions for i in range(0, classes): 84*5c2921b0SApple OSS Distributions print_class = False 85*5c2921b0SApple OSS Distributions subclasses = [0] * elements_per_class 86*5c2921b0SApple OSS Distributions 87*5c2921b0SApple OSS Distributions # check subclass ranges for set bits, remember those subclasses 88*5c2921b0SApple OSS Distributions for j in range(0, elements_per_class): 89*5c2921b0SApple OSS Distributions element = unsigned(cur_typefilter[i * elements_per_class + j]) 90*5c2921b0SApple OSS Distributions if element != 0: 91*5c2921b0SApple OSS Distributions print_class = True 92*5c2921b0SApple OSS Distributions if print_class: 93*5c2921b0SApple OSS Distributions subclasses[j] = element 94*5c2921b0SApple OSS Distributions 95*5c2921b0SApple OSS Distributions ## if any of the bits were set in a class, print the entire class 96*5c2921b0SApple OSS Distributions if print_class: 97*5c2921b0SApple OSS Distributions out_str += '{:<20s}'.format(GetKdebugClassName(i)) 98*5c2921b0SApple OSS Distributions for element in subclasses: 99*5c2921b0SApple OSS Distributions # split up the 64-bit values into byte-sized pieces 100*5c2921b0SApple OSS Distributions bytes = [unsigned((element >> i) & 0xff) for i in (0, 8, 16, 24, 32, 40, 48, 56)] 101*5c2921b0SApple OSS Distributions out_str += subclasses_fmts.format(*bytes) 102*5c2921b0SApple OSS Distributions out_str += ' ' 103*5c2921b0SApple OSS Distributions 104*5c2921b0SApple OSS Distributions out_str += '\n' 105*5c2921b0SApple OSS Distributions 106*5c2921b0SApple OSS Distributions return out_str 107*5c2921b0SApple OSS Distributions 108*5c2921b0SApple OSS Distributions@lldb_command('showkdebugtypefilter') 109*5c2921b0SApple OSS Distributionsdef ShowKdebugTypefilter(cmd_args=None): 110*5c2921b0SApple OSS Distributions """ Show the current kdebug typefilter (or the typefilter at an address) 111*5c2921b0SApple OSS Distributions 112*5c2921b0SApple OSS Distributions usage: showkdebugtypefilter [<address>] 113*5c2921b0SApple OSS Distributions """ 114*5c2921b0SApple OSS Distributions 115*5c2921b0SApple OSS Distributions if cmd_args: 116*5c2921b0SApple OSS Distributions typefilter = kern.GetValueFromAddress(cmd_args[0], 'typefilter_t') 117*5c2921b0SApple OSS Distributions if unsigned(typefilter) == 0: 118*5c2921b0SApple OSS Distributions raise ArgumentError('argument provided is NULL') 119*5c2921b0SApple OSS Distributions 120*5c2921b0SApple OSS Distributions print(GetKdebugTypefilter.header) 121*5c2921b0SApple OSS Distributions print('-' * len(GetKdebugTypefilter.header)) 122*5c2921b0SApple OSS Distributions 123*5c2921b0SApple OSS Distributions print(GetKdebugTypefilter(typefilter)) 124*5c2921b0SApple OSS Distributions return 125*5c2921b0SApple OSS Distributions 126*5c2921b0SApple OSS Distributions typefilter = kern.globals.kdbg_typefilter 127*5c2921b0SApple OSS Distributions if unsigned(typefilter) == 0: 128*5c2921b0SApple OSS Distributions raise ArgumentError('no argument provided and active typefilter is not set') 129*5c2921b0SApple OSS Distributions 130*5c2921b0SApple OSS Distributions print(GetKdebugTypefilter.header) 131*5c2921b0SApple OSS Distributions print('-' * len(GetKdebugTypefilter.header)) 132*5c2921b0SApple OSS Distributions print(GetKdebugTypefilter(typefilter)) 133*5c2921b0SApple OSS Distributions 134*5c2921b0SApple OSS Distributionsdef GetKdebugStatus(): 135*5c2921b0SApple OSS Distributions """ Get a string summary of the kdebug subsystem. 136*5c2921b0SApple OSS Distributions """ 137*5c2921b0SApple OSS Distributions out = '' 138*5c2921b0SApple OSS Distributions 139*5c2921b0SApple OSS Distributions kdc_flags = kern.globals.kd_control_trace.kdc_flags 140*5c2921b0SApple OSS Distributions out += 'kdebug flags: {}\n'.format(xnudefines.GetStateString(xnudefines.kdebug_flags_strings, kdc_flags)) 141*5c2921b0SApple OSS Distributions events = kern.globals.kd_buffer_trace.kdb_event_count 142*5c2921b0SApple OSS Distributions buf_mb = events * (64 if kern.arch == 'x86_64' or kern.arch.startswith('arm64') else 32) // 1000000 143*5c2921b0SApple OSS Distributions out += 'events allocated: {:<d} ({:<d} MB)\n'.format(events, buf_mb) 144*5c2921b0SApple OSS Distributions out += 'enabled: {}\n'.format('yes' if kern.globals.kdebug_enable != 0 else 'no') 145*5c2921b0SApple OSS Distributions if kdc_flags & xnudefines.KDBG_TYPEFILTER_CHECK: 146*5c2921b0SApple OSS Distributions out += 'typefilter:\n' 147*5c2921b0SApple OSS Distributions out += GetKdebugTypefilter.header + '\n' 148*5c2921b0SApple OSS Distributions out += '-' * len(GetKdebugTypefilter.header) + '\n' 149*5c2921b0SApple OSS Distributions typefilter = kern.globals.kdbg_typefilter 150*5c2921b0SApple OSS Distributions if unsigned(typefilter) != 0: 151*5c2921b0SApple OSS Distributions out += GetKdebugTypefilter(typefilter) 152*5c2921b0SApple OSS Distributions 153*5c2921b0SApple OSS Distributions return out 154*5c2921b0SApple OSS Distributions 155*5c2921b0SApple OSS Distributions@lldb_command('showkdebug') 156*5c2921b0SApple OSS Distributionsdef ShowKdebug(cmd_args=None): 157*5c2921b0SApple OSS Distributions """ Show the current kdebug state. 158*5c2921b0SApple OSS Distributions 159*5c2921b0SApple OSS Distributions usage: showkdebug 160*5c2921b0SApple OSS Distributions """ 161*5c2921b0SApple OSS Distributions 162*5c2921b0SApple OSS Distributions print(GetKdebugStatus()) 163*5c2921b0SApple OSS Distributions 164*5c2921b0SApple OSS Distributions@lldb_type_summary(['kperf_timer']) 165*5c2921b0SApple OSS Distributions@header('{:<10s} {:<7s} {:<20s} {:<20s}'.format('period-ns', 'action', 'deadline', 'fire-time')) 166*5c2921b0SApple OSS Distributionsdef GetKperfTimerSummary(timer): 167*5c2921b0SApple OSS Distributions """ Get a string summary of a kperf timer. 168*5c2921b0SApple OSS Distributions 169*5c2921b0SApple OSS Distributions params: 170*5c2921b0SApple OSS Distributions timer: the kptimer object to get a summary of 171*5c2921b0SApple OSS Distributions """ 172*5c2921b0SApple OSS Distributions try: 173*5c2921b0SApple OSS Distributions fire_time = timer.kt_fire_time 174*5c2921b0SApple OSS Distributions except: 175*5c2921b0SApple OSS Distributions fire_time = 0 176*5c2921b0SApple OSS Distributions return '{:<10d} {:<7d} {:<20d} {:<20d}\n'.format( 177*5c2921b0SApple OSS Distributions kern.GetNanotimeFromAbstime(timer.kt_period_abs), timer.kt_actionid, 178*5c2921b0SApple OSS Distributions timer.kt_cur_deadline, fire_time) 179*5c2921b0SApple OSS Distributions 180*5c2921b0SApple OSS Distributions@lldb_type_summary(['action']) 181*5c2921b0SApple OSS Distributions@header('{:<10s} {:<20s} {:<20s}'.format('pid-filter', 'user-data', 'samplers')) 182*5c2921b0SApple OSS Distributionsdef GetKperfActionSummary(action): 183*5c2921b0SApple OSS Distributions """ Get a string summary of a kperf action. 184*5c2921b0SApple OSS Distributions 185*5c2921b0SApple OSS Distributions params: 186*5c2921b0SApple OSS Distributions action: the action object to get a summary of 187*5c2921b0SApple OSS Distributions """ 188*5c2921b0SApple OSS Distributions samplers = xnudefines.GetStateString(xnudefines.kperf_samplers_strings, action.sample) 189*5c2921b0SApple OSS Distributions return '{:<10s} {:<20x} {:<20s}\n'.format( 190*5c2921b0SApple OSS Distributions '-' if action.pid_filter < 0 else str(action.pid_filter), action.userdata, samplers) 191*5c2921b0SApple OSS Distributions 192*5c2921b0SApple OSS Distributionsdef GetKperfKdebugFilterDescription(): 193*5c2921b0SApple OSS Distributions kdebug_filter = kern.globals.kperf_kdebug_filter 194*5c2921b0SApple OSS Distributions desc = '' 195*5c2921b0SApple OSS Distributions for i in range(kdebug_filter.n_debugids): 196*5c2921b0SApple OSS Distributions filt_index = 1 if i >= 16 else 0 197*5c2921b0SApple OSS Distributions filt_type = (kdebug_filter.types[filt_index] >> ((i % 16) * 4)) & 0xf 198*5c2921b0SApple OSS Distributions debugid = kdebug_filter.debugids[i] 199*5c2921b0SApple OSS Distributions if filt_type < 2: 200*5c2921b0SApple OSS Distributions prefix = 'C' 201*5c2921b0SApple OSS Distributions width = 2 202*5c2921b0SApple OSS Distributions id = debugid >> 24 203*5c2921b0SApple OSS Distributions elif filt_type < 4: 204*5c2921b0SApple OSS Distributions prefix = 'S' 205*5c2921b0SApple OSS Distributions width = 4 206*5c2921b0SApple OSS Distributions id = debugid >> 16 207*5c2921b0SApple OSS Distributions else: 208*5c2921b0SApple OSS Distributions prefix = 'D' 209*5c2921b0SApple OSS Distributions width = 8 210*5c2921b0SApple OSS Distributions id = debugid 211*5c2921b0SApple OSS Distributions 212*5c2921b0SApple OSS Distributions suffix = '' 213*5c2921b0SApple OSS Distributions if (filt_type % 2) == 1: 214*5c2921b0SApple OSS Distributions if debugid & xnudefines.DBG_FUNC_START: 215*5c2921b0SApple OSS Distributions suffix = 's' 216*5c2921b0SApple OSS Distributions elif debugid & xnudefines.DBG_FUNC_END: 217*5c2921b0SApple OSS Distributions suffix = 'r' 218*5c2921b0SApple OSS Distributions else: 219*5c2921b0SApple OSS Distributions suffix = 'n' 220*5c2921b0SApple OSS Distributions 221*5c2921b0SApple OSS Distributions if i > 0: 222*5c2921b0SApple OSS Distributions desc += ',' 223*5c2921b0SApple OSS Distributions desc += '{prefix}{id:0{width}x}{suffix}'.format( 224*5c2921b0SApple OSS Distributions prefix=prefix, id=id, width=width, suffix=suffix) 225*5c2921b0SApple OSS Distributions 226*5c2921b0SApple OSS Distributions return desc 227*5c2921b0SApple OSS Distributions 228*5c2921b0SApple OSS Distributionsdef GetKperfStatus(): 229*5c2921b0SApple OSS Distributions """ Get a string summary of the kperf subsystem. 230*5c2921b0SApple OSS Distributions """ 231*5c2921b0SApple OSS Distributions out = '' 232*5c2921b0SApple OSS Distributions 233*5c2921b0SApple OSS Distributions kperf_status = int(kern.globals.kperf_status) 234*5c2921b0SApple OSS Distributions out += 'sampling: ' 235*5c2921b0SApple OSS Distributions if kperf_status == GetEnumValue('kperf_sampling::KPERF_SAMPLING_OFF'): 236*5c2921b0SApple OSS Distributions out += 'off\n' 237*5c2921b0SApple OSS Distributions elif kperf_status == GetEnumValue('kperf_sampling::KPERF_SAMPLING_SHUTDOWN'): 238*5c2921b0SApple OSS Distributions out += 'shutting down\n' 239*5c2921b0SApple OSS Distributions elif kperf_status == GetEnumValue('kperf_sampling::KPERF_SAMPLING_ON'): 240*5c2921b0SApple OSS Distributions out += 'on\n' 241*5c2921b0SApple OSS Distributions else: 242*5c2921b0SApple OSS Distributions out += 'unknown\n' 243*5c2921b0SApple OSS Distributions 244*5c2921b0SApple OSS Distributions pet = kern.globals.kptimer.g_pet_active 245*5c2921b0SApple OSS Distributions pet_timer_id = kern.globals.kptimer.g_pet_active 246*5c2921b0SApple OSS Distributions if pet != 0: 247*5c2921b0SApple OSS Distributions pet_idle_rate = kern.globals.pet_idle_rate 248*5c2921b0SApple OSS Distributions out += 'legacy PET is active (timer = {:<d}, idle rate = {:<d})\n'.format(pet_timer_id, pet_idle_rate) 249*5c2921b0SApple OSS Distributions else: 250*5c2921b0SApple OSS Distributions out += 'legacy PET is off\n' 251*5c2921b0SApple OSS Distributions 252*5c2921b0SApple OSS Distributions lw_pet = kern.globals.kppet.g_lightweight 253*5c2921b0SApple OSS Distributions if lw_pet != 0: 254*5c2921b0SApple OSS Distributions lw_pet_gen = kern.globals.kppet_gencount 255*5c2921b0SApple OSS Distributions out += 'lightweight PET is active (timer = {:<d}, generation count = {:<d})\n'.format(pet_timer_id, lw_pet_gen) 256*5c2921b0SApple OSS Distributions else: 257*5c2921b0SApple OSS Distributions out += 'lightweight PET is off\n' 258*5c2921b0SApple OSS Distributions 259*5c2921b0SApple OSS Distributions actions = kern.globals.actionc 260*5c2921b0SApple OSS Distributions actions_arr = kern.globals.actionv 261*5c2921b0SApple OSS Distributions 262*5c2921b0SApple OSS Distributions out += 'actions:\n' 263*5c2921b0SApple OSS Distributions out += '{:<5s} '.format('id') + GetKperfActionSummary.header + '\n' 264*5c2921b0SApple OSS Distributions for i in range(0, actions): 265*5c2921b0SApple OSS Distributions out += '{:<5d} '.format(i) + GetKperfActionSummary(actions_arr[i]) 266*5c2921b0SApple OSS Distributions 267*5c2921b0SApple OSS Distributions timers = kern.globals.kptimer.g_ntimers 268*5c2921b0SApple OSS Distributions timers_arr = kern.globals.kptimer.g_timers 269*5c2921b0SApple OSS Distributions 270*5c2921b0SApple OSS Distributions out += 'timers:\n' 271*5c2921b0SApple OSS Distributions out += '{:<5s} '.format('id') + GetKperfTimerSummary.header + '\n' 272*5c2921b0SApple OSS Distributions for i in range(0, timers): 273*5c2921b0SApple OSS Distributions out += '{:<5d} '.format(i) + GetKperfTimerSummary(timers_arr[i]) 274*5c2921b0SApple OSS Distributions 275*5c2921b0SApple OSS Distributions return out 276*5c2921b0SApple OSS Distributions 277*5c2921b0SApple OSS Distributions 278*5c2921b0SApple OSS Distributionsdef GetKtraceStatus(): 279*5c2921b0SApple OSS Distributions """ Get a string summary of the ktrace subsystem. 280*5c2921b0SApple OSS Distributions """ 281*5c2921b0SApple OSS Distributions out = '' 282*5c2921b0SApple OSS Distributions 283*5c2921b0SApple OSS Distributions state = kern.globals.ktrace_state 284*5c2921b0SApple OSS Distributions if state == GetEnumValue('ktrace_state_t::KTRACE_STATE_OFF'): 285*5c2921b0SApple OSS Distributions out += 'ktrace is off\n' 286*5c2921b0SApple OSS Distributions else: 287*5c2921b0SApple OSS Distributions out += 'ktrace is active (' 288*5c2921b0SApple OSS Distributions if state == GetEnumValue('ktrace_state_t::KTRACE_STATE_FG'): 289*5c2921b0SApple OSS Distributions out += 'foreground)' 290*5c2921b0SApple OSS Distributions else: 291*5c2921b0SApple OSS Distributions out += 'background)' 292*5c2921b0SApple OSS Distributions out += '\n' 293*5c2921b0SApple OSS Distributions owner = kern.globals.ktrace_last_owner_execname 294*5c2921b0SApple OSS Distributions owner_pid = kern.globals.ktrace_owning_pid 295*5c2921b0SApple OSS Distributions out += 'owned by: {:<s} [{}]\n'.format(owner, unsigned(owner_pid)) 296*5c2921b0SApple OSS Distributions active_mask = kern.globals.ktrace_active_mask 297*5c2921b0SApple OSS Distributions out += 'active systems: {:<#x}\n'.format(active_mask) 298*5c2921b0SApple OSS Distributions 299*5c2921b0SApple OSS Distributions return out 300*5c2921b0SApple OSS Distributions 301*5c2921b0SApple OSS Distributions 302*5c2921b0SApple OSS Distributionsdef GetKtraceConfig(): 303*5c2921b0SApple OSS Distributions kdebug_state = 0 304*5c2921b0SApple OSS Distributions if (kern.globals.kd_control_trace.kdc_flags & xnudefines.KDBG_BUFINIT) != 0: 305*5c2921b0SApple OSS Distributions kdebug_state = 1 306*5c2921b0SApple OSS Distributions if kern.globals.kdebug_enable: 307*5c2921b0SApple OSS Distributions kdebug_state = 3 308*5c2921b0SApple OSS Distributions kdebug_wrapping = True 309*5c2921b0SApple OSS Distributions if (kern.globals.kd_control_trace.kdc_live_flags & xnudefines.KDBG_NOWRAP): 310*5c2921b0SApple OSS Distributions kdebug_wrapping = False 311*5c2921b0SApple OSS Distributions 312*5c2921b0SApple OSS Distributions kperf_state = 3 if ( 313*5c2921b0SApple OSS Distributions unsigned(kern.globals.kperf_status) == 314*5c2921b0SApple OSS Distributions GetEnumValue('kperf_sampling::KPERF_SAMPLING_ON')) else 0 315*5c2921b0SApple OSS Distributions 316*5c2921b0SApple OSS Distributions action_count = kern.globals.actionc 317*5c2921b0SApple OSS Distributions actions = kern.globals.actionv 318*5c2921b0SApple OSS Distributions action_samplers = [] 319*5c2921b0SApple OSS Distributions action_user_datas = [] 320*5c2921b0SApple OSS Distributions action_pid_filters = [] 321*5c2921b0SApple OSS Distributions for i in range(action_count): 322*5c2921b0SApple OSS Distributions action = actions[i] 323*5c2921b0SApple OSS Distributions action_samplers.append(unsigned(action.sample)) 324*5c2921b0SApple OSS Distributions action_user_datas.append(unsigned(action.userdata)) 325*5c2921b0SApple OSS Distributions action_pid_filters.append(unsigned(action.pid_filter)) 326*5c2921b0SApple OSS Distributions 327*5c2921b0SApple OSS Distributions timer_count = kern.globals.kptimer.g_ntimers 328*5c2921b0SApple OSS Distributions timers = kern.globals.kptimer.g_timers 329*5c2921b0SApple OSS Distributions timer_actions = [] 330*5c2921b0SApple OSS Distributions timer_periods_ns = [] 331*5c2921b0SApple OSS Distributions 332*5c2921b0SApple OSS Distributions for i in range(timer_count): 333*5c2921b0SApple OSS Distributions timer = timers[i] 334*5c2921b0SApple OSS Distributions timer_actions.append(unsigned(timer.kt_actionid)) 335*5c2921b0SApple OSS Distributions timer_periods_ns.append( 336*5c2921b0SApple OSS Distributions kern.GetNanotimeFromAbstime(unsigned(timer.kt_period_abs))) 337*5c2921b0SApple OSS Distributions 338*5c2921b0SApple OSS Distributions pet_mode = 0 339*5c2921b0SApple OSS Distributions if kern.globals.kppet.g_lightweight: 340*5c2921b0SApple OSS Distributions pet_mode = 2 341*5c2921b0SApple OSS Distributions elif kern.globals.kptimer.g_pet_active: 342*5c2921b0SApple OSS Distributions pet_mode = 1 343*5c2921b0SApple OSS Distributions 344*5c2921b0SApple OSS Distributions return { 345*5c2921b0SApple OSS Distributions 'owner_name': str(kern.globals.ktrace_last_owner_execname), 346*5c2921b0SApple OSS Distributions 'owner_kind': unsigned(kern.globals.ktrace_state), 347*5c2921b0SApple OSS Distributions 'owner_pid': int(kern.globals.ktrace_owning_pid), 348*5c2921b0SApple OSS Distributions 349*5c2921b0SApple OSS Distributions 'kdebug_state': kdebug_state, 350*5c2921b0SApple OSS Distributions 'kdebug_buffer_size': unsigned(kern.globals.kd_buffer_trace.kdb_event_count), 351*5c2921b0SApple OSS Distributions 'kdebug_typefilter': plist_data(struct.pack('B', 0xff) * 4096 * 2), # XXX 352*5c2921b0SApple OSS Distributions 'kdebug_procfilt_mode': 0, # XXX 353*5c2921b0SApple OSS Distributions 'kdebug_procfilt': [], # XXX 354*5c2921b0SApple OSS Distributions 'kdebug_wrapping': kdebug_wrapping, 355*5c2921b0SApple OSS Distributions 356*5c2921b0SApple OSS Distributions 'kperf_state': kperf_state, 357*5c2921b0SApple OSS Distributions 'kperf_actions_sampler': action_samplers, 358*5c2921b0SApple OSS Distributions 'kperf_actions_user_data': action_user_datas, 359*5c2921b0SApple OSS Distributions 'kperf_actions_pid_filter': action_pid_filters, 360*5c2921b0SApple OSS Distributions 'kperf_timers_action_id': timer_actions, 361*5c2921b0SApple OSS Distributions 'kperf_timers_period_ns': timer_periods_ns, 362*5c2921b0SApple OSS Distributions 'kperf_pet_mode': pet_mode, 363*5c2921b0SApple OSS Distributions 'kperf_pet_timer_id': unsigned(kern.globals.kptimer.g_pet_timerid), 364*5c2921b0SApple OSS Distributions 'kperf_pet_idle_rate': unsigned(kern.globals.kppet.g_idle_rate), 365*5c2921b0SApple OSS Distributions 366*5c2921b0SApple OSS Distributions 'kperf_kdebug_action_id': unsigned(kern.globals.kperf_kdebug_action), 367*5c2921b0SApple OSS Distributions 'kperf_kdebug_filter': GetKperfKdebugFilterDescription(), 368*5c2921b0SApple OSS Distributions 369*5c2921b0SApple OSS Distributions # XXX 370*5c2921b0SApple OSS Distributions 'kpc_state': 0, 371*5c2921b0SApple OSS Distributions 'kpc_classes': 0, 372*5c2921b0SApple OSS Distributions 'kpc_thread_classes': 0, 373*5c2921b0SApple OSS Distributions 'kpc_periods': [], 374*5c2921b0SApple OSS Distributions 'kpc_action_ids': [], 375*5c2921b0SApple OSS Distributions 'kpc_config': [], 376*5c2921b0SApple OSS Distributions 377*5c2921b0SApple OSS Distributions 'context_kind': 2, # backwards-facing 378*5c2921b0SApple OSS Distributions 'reason': 'core file debugging', 379*5c2921b0SApple OSS Distributions 'command': '(lldb) savekdebugtrace', 380*5c2921b0SApple OSS Distributions 'trigger_kind': 2, # diagnostics trigger 381*5c2921b0SApple OSS Distributions } 382*5c2921b0SApple OSS Distributions 383*5c2921b0SApple OSS Distributions 384*5c2921b0SApple OSS Distributions@lldb_command('showktrace') 385*5c2921b0SApple OSS Distributionsdef ShowKtrace(cmd_args=None): 386*5c2921b0SApple OSS Distributions """ Show the current ktrace state, including subsystems. 387*5c2921b0SApple OSS Distributions 388*5c2921b0SApple OSS Distributions usage: showktrace 389*5c2921b0SApple OSS Distributions """ 390*5c2921b0SApple OSS Distributions 391*5c2921b0SApple OSS Distributions print(GetKtraceStatus()) 392*5c2921b0SApple OSS Distributions print(' ') 393*5c2921b0SApple OSS Distributions print('kdebug:') 394*5c2921b0SApple OSS Distributions print(GetKdebugStatus()) 395*5c2921b0SApple OSS Distributions print(' ') 396*5c2921b0SApple OSS Distributions print('kperf:') 397*5c2921b0SApple OSS Distributions print(GetKperfStatus()) 398*5c2921b0SApple OSS Distributions 399*5c2921b0SApple OSS Distributions 400*5c2921b0SApple OSS Distributionsclass KDEvent(object): 401*5c2921b0SApple OSS Distributions """ 402*5c2921b0SApple OSS Distributions Wrapper around kevent pointer that handles sorting logic. 403*5c2921b0SApple OSS Distributions """ 404*5c2921b0SApple OSS Distributions def __init__(self, timestamp, kevent, k64): 405*5c2921b0SApple OSS Distributions self.kevent = kevent 406*5c2921b0SApple OSS Distributions self.timestamp = timestamp 407*5c2921b0SApple OSS Distributions self.k64 = k64 408*5c2921b0SApple OSS Distributions 409*5c2921b0SApple OSS Distributions def get_kevent(self): 410*5c2921b0SApple OSS Distributions return self.kevent 411*5c2921b0SApple OSS Distributions 412*5c2921b0SApple OSS Distributions def __eq__(self, other): 413*5c2921b0SApple OSS Distributions return self.timestamp == other.timestamp 414*5c2921b0SApple OSS Distributions 415*5c2921b0SApple OSS Distributions def __lt__(self, other): 416*5c2921b0SApple OSS Distributions return self.timestamp < other.timestamp 417*5c2921b0SApple OSS Distributions 418*5c2921b0SApple OSS Distributions def __gt__(self, other): 419*5c2921b0SApple OSS Distributions return self.timestamp > other.timestamp 420*5c2921b0SApple OSS Distributions 421*5c2921b0SApple OSS Distributions def __hash__(self): 422*5c2921b0SApple OSS Distributions return hash(self.timestamp) 423*5c2921b0SApple OSS Distributions 424*5c2921b0SApple OSS Distributions 425*5c2921b0SApple OSS Distributionsclass KDCPU(object): 426*5c2921b0SApple OSS Distributions """ 427*5c2921b0SApple OSS Distributions Represents all events from a single CPU. 428*5c2921b0SApple OSS Distributions """ 429*5c2921b0SApple OSS Distributions def __init__(self, cpuid, k64, verbose, starting_timestamp=None): 430*5c2921b0SApple OSS Distributions self.cpuid = cpuid 431*5c2921b0SApple OSS Distributions self.iter_store = None 432*5c2921b0SApple OSS Distributions self.k64 = k64 433*5c2921b0SApple OSS Distributions self.verbose = verbose 434*5c2921b0SApple OSS Distributions self.timestamp_mask = ((1 << 48) - 1) if not self.k64 else ~0 435*5c2921b0SApple OSS Distributions self.last_timestamp = 0 436*5c2921b0SApple OSS Distributions 437*5c2921b0SApple OSS Distributions kdstoreinfo = kern.globals.kd_buffer_trace.kdb_info[cpuid] 438*5c2921b0SApple OSS Distributions self.kdstorep = kdstoreinfo.kd_list_head 439*5c2921b0SApple OSS Distributions 440*5c2921b0SApple OSS Distributions if self.kdstorep.raw == xnudefines.KDS_PTR_NULL: 441*5c2921b0SApple OSS Distributions # Return no events and stop at first call to __next__. 442*5c2921b0SApple OSS Distributions return 443*5c2921b0SApple OSS Distributions 444*5c2921b0SApple OSS Distributions self.iter_store = self.get_kdstore(self.kdstorep) 445*5c2921b0SApple OSS Distributions skipped_storage_count = 0 446*5c2921b0SApple OSS Distributions if starting_timestamp: 447*5c2921b0SApple OSS Distributions while True: 448*5c2921b0SApple OSS Distributions newest_event = addressof(self.iter_store.kds_records[xnudefines.EVENTS_PER_STORAGE_UNIT - 1]) 449*5c2921b0SApple OSS Distributions timestamp = unsigned(newest_event.timestamp) & self.timestamp_mask 450*5c2921b0SApple OSS Distributions if timestamp >= starting_timestamp: 451*5c2921b0SApple OSS Distributions if verbose: 452*5c2921b0SApple OSS Distributions print('done skipping events at time {}'.format(timestamp)) 453*5c2921b0SApple OSS Distributions break 454*5c2921b0SApple OSS Distributions next_store = self.iter_store.kds_next 455*5c2921b0SApple OSS Distributions if next_store.raw == xnudefines.KDS_PTR_NULL: 456*5c2921b0SApple OSS Distributions if verbose: 457*5c2921b0SApple OSS Distributions print('found no valid events from CPU {}'.format(cpuid)) 458*5c2921b0SApple OSS Distributions self.iter_store = None 459*5c2921b0SApple OSS Distributions return 460*5c2921b0SApple OSS Distributions self.iter_store = self.get_kdstore(next_store) 461*5c2921b0SApple OSS Distributions skipped_storage_count += 1 462*5c2921b0SApple OSS Distributions if verbose and skipped_storage_count > 0: 463*5c2921b0SApple OSS Distributions print('CPU {} skipped {} storage units'.format( 464*5c2921b0SApple OSS Distributions cpuid, skipped_storage_count)) 465*5c2921b0SApple OSS Distributions 466*5c2921b0SApple OSS Distributions # XXX Doesn't have the same logic to avoid un-mergeable events 467*5c2921b0SApple OSS Distributions # (respecting barrier_min and bufindx) as the C code. 468*5c2921b0SApple OSS Distributions 469*5c2921b0SApple OSS Distributions self.iter_idx = self.iter_store.kds_readlast 470*5c2921b0SApple OSS Distributions 471*5c2921b0SApple OSS Distributions def get_kdstore(self, kdstorep): 472*5c2921b0SApple OSS Distributions """ 473*5c2921b0SApple OSS Distributions See POINTER_FROM_KDSPTR. 474*5c2921b0SApple OSS Distributions """ 475*5c2921b0SApple OSS Distributions buf = kern.globals.kd_buffer_trace.kd_bufs[kdstorep.buffer_index] 476*5c2921b0SApple OSS Distributions return addressof(buf.kdr_addr[kdstorep.offset]) 477*5c2921b0SApple OSS Distributions 478*5c2921b0SApple OSS Distributions # Event iterator implementation returns KDEvent instance 479*5c2921b0SApple OSS Distributions 480*5c2921b0SApple OSS Distributions def __iter__(self): 481*5c2921b0SApple OSS Distributions return self 482*5c2921b0SApple OSS Distributions 483*5c2921b0SApple OSS Distributions def __next__(self): 484*5c2921b0SApple OSS Distributions # This CPU is out of events. 485*5c2921b0SApple OSS Distributions if self.iter_store is None: 486*5c2921b0SApple OSS Distributions raise StopIteration 487*5c2921b0SApple OSS Distributions 488*5c2921b0SApple OSS Distributions if self.iter_idx == self.iter_store.kds_bufindx: 489*5c2921b0SApple OSS Distributions self.iter_store = None 490*5c2921b0SApple OSS Distributions raise StopIteration 491*5c2921b0SApple OSS Distributions 492*5c2921b0SApple OSS Distributions keventp = addressof(self.iter_store.kds_records[self.iter_idx]) 493*5c2921b0SApple OSS Distributions timestamp = unsigned(keventp.timestamp) & self.timestamp_mask 494*5c2921b0SApple OSS Distributions if self.last_timestamp == 0 and self.verbose: 495*5c2921b0SApple OSS Distributions print('first event from CPU {} is at time {}'.format( 496*5c2921b0SApple OSS Distributions self.cpuid, timestamp)) 497*5c2921b0SApple OSS Distributions self.last_timestamp = timestamp 498*5c2921b0SApple OSS Distributions 499*5c2921b0SApple OSS Distributions # Check for writer overrun. 500*5c2921b0SApple OSS Distributions if timestamp < self.iter_store.kds_timestamp: 501*5c2921b0SApple OSS Distributions raise StopIteration 502*5c2921b0SApple OSS Distributions 503*5c2921b0SApple OSS Distributions self.iter_idx += 1 504*5c2921b0SApple OSS Distributions 505*5c2921b0SApple OSS Distributions if self.iter_idx == xnudefines.EVENTS_PER_STORAGE_UNIT: 506*5c2921b0SApple OSS Distributions snext = self.iter_store.kds_next 507*5c2921b0SApple OSS Distributions if snext.raw == xnudefines.KDS_PTR_NULL: 508*5c2921b0SApple OSS Distributions # Terminate iteration in next loop. Current element is the 509*5c2921b0SApple OSS Distributions # last one in this CPU buffer. 510*5c2921b0SApple OSS Distributions self.iter_store = None 511*5c2921b0SApple OSS Distributions else: 512*5c2921b0SApple OSS Distributions self.iter_store = self.get_kdstore(snext) 513*5c2921b0SApple OSS Distributions self.iter_idx = self.iter_store.kds_readlast 514*5c2921b0SApple OSS Distributions 515*5c2921b0SApple OSS Distributions return KDEvent(timestamp, keventp, self.k64) 516*5c2921b0SApple OSS Distributions 517*5c2921b0SApple OSS Distributions # Python 2 compatibility 518*5c2921b0SApple OSS Distributions # pragma pylint: disable=next-method-defined 519*5c2921b0SApple OSS Distributions def next(self): 520*5c2921b0SApple OSS Distributions return self.__next__() 521*5c2921b0SApple OSS Distributions 522*5c2921b0SApple OSS Distributions 523*5c2921b0SApple OSS Distributionsdef IterateKdebugEvents(verbose=False, humanize=False, last=None, 524*5c2921b0SApple OSS Distributions include_coprocessors=True): 525*5c2921b0SApple OSS Distributions """ 526*5c2921b0SApple OSS Distributions Yield events from the in-memory kdebug trace buffers. 527*5c2921b0SApple OSS Distributions """ 528*5c2921b0SApple OSS Distributions ctrl = kern.globals.kd_control_trace 529*5c2921b0SApple OSS Distributions 530*5c2921b0SApple OSS Distributions if (ctrl.kdc_flags & xnudefines.KDBG_BUFINIT) == 0: 531*5c2921b0SApple OSS Distributions return 532*5c2921b0SApple OSS Distributions 533*5c2921b0SApple OSS Distributions barrier_min = ctrl.kdc_oldest_time 534*5c2921b0SApple OSS Distributions 535*5c2921b0SApple OSS Distributions if (ctrl.kdc_live_flags & xnudefines.KDBG_WRAPPED) != 0: 536*5c2921b0SApple OSS Distributions # TODO Yield a wrap event with the barrier_min timestamp. 537*5c2921b0SApple OSS Distributions pass 538*5c2921b0SApple OSS Distributions 539*5c2921b0SApple OSS Distributions k64 = kern.ptrsize == 8 540*5c2921b0SApple OSS Distributions 541*5c2921b0SApple OSS Distributions cpu_count = kern.globals.machine_info.logical_cpu_max 542*5c2921b0SApple OSS Distributions if include_coprocessors: 543*5c2921b0SApple OSS Distributions cpu_count = ctrl.kdebug_cpus 544*5c2921b0SApple OSS Distributions 545*5c2921b0SApple OSS Distributions start_timestamp = None 546*5c2921b0SApple OSS Distributions if last is not None: 547*5c2921b0SApple OSS Distributions (numer, denom) = GetTimebaseInfo() 548*5c2921b0SApple OSS Distributions duration = (last * 1e9) * denom / numer 549*5c2921b0SApple OSS Distributions now = GetRecentTimestamp() 550*5c2921b0SApple OSS Distributions start_timestamp = unsigned(now - duration) 551*5c2921b0SApple OSS Distributions if verbose: 552*5c2921b0SApple OSS Distributions print('starting at time {} ({} - {})'.format( 553*5c2921b0SApple OSS Distributions start_timestamp, now, duration)) 554*5c2921b0SApple OSS Distributions 555*5c2921b0SApple OSS Distributions # Merge sort all events from all CPUs. 556*5c2921b0SApple OSS Distributions cpus = [KDCPU(cpuid, k64, verbose, starting_timestamp=start_timestamp) 557*5c2921b0SApple OSS Distributions for cpuid in range(cpu_count)] 558*5c2921b0SApple OSS Distributions last_timestamp = 0 559*5c2921b0SApple OSS Distributions warned = False 560*5c2921b0SApple OSS Distributions for event in heapq.merge(*cpus): 561*5c2921b0SApple OSS Distributions if event.timestamp < last_timestamp and not warned: 562*5c2921b0SApple OSS Distributions # Human-readable output might have garbage on the rest of the line. 563*5c2921b0SApple OSS Distributions # Use a CSI escape sequence to clear it out. 564*5c2921b0SApple OSS Distributions clear_line_csi = '\033[K' 565*5c2921b0SApple OSS Distributions print( 566*5c2921b0SApple OSS Distributions 'warning: events seem to be out-of-order', 567*5c2921b0SApple OSS Distributions end=((clear_line_csi + '\n') if humanize else '\n')) 568*5c2921b0SApple OSS Distributions warned = True 569*5c2921b0SApple OSS Distributions last_timestamp = event.timestamp 570*5c2921b0SApple OSS Distributions yield event.get_kevent() 571*5c2921b0SApple OSS Distributions 572*5c2921b0SApple OSS Distributions 573*5c2921b0SApple OSS Distributions@header('{:>12s} {:>10s} {:>18s} {:>18s} {:>18s} {:>18s} {:>5s} {:>8s}'.format( 574*5c2921b0SApple OSS Distributions 'timestamp', 'debugid', 'arg1', 'arg2', 'arg3', 'arg4', 'cpuid', 575*5c2921b0SApple OSS Distributions 'tid')) 576*5c2921b0SApple OSS Distributionsdef GetKdebugEvent(event, k64, symbolicate=False, O=None): 577*5c2921b0SApple OSS Distributions """ 578*5c2921b0SApple OSS Distributions Return a string representing a kdebug trace event. 579*5c2921b0SApple OSS Distributions """ 580*5c2921b0SApple OSS Distributions if k64: 581*5c2921b0SApple OSS Distributions timestamp = event.timestamp & ((1 << 48) - 1) 582*5c2921b0SApple OSS Distributions cpuid = event.timestamp >> 48 583*5c2921b0SApple OSS Distributions else: 584*5c2921b0SApple OSS Distributions timestamp = event.timestamp 585*5c2921b0SApple OSS Distributions cpuid = event.cpuid 586*5c2921b0SApple OSS Distributions def fmt_arg(a): 587*5c2921b0SApple OSS Distributions return '0x{:016x}'.format(unsigned(a)) 588*5c2921b0SApple OSS Distributions def sym_arg(a): 589*5c2921b0SApple OSS Distributions slid_addr = kern.globals.vm_kernel_slide + unsigned(a) 590*5c2921b0SApple OSS Distributions syms = kern.SymbolicateFromAddress(slid_addr) 591*5c2921b0SApple OSS Distributions return syms[0].GetName() if syms else fmt_arg(a) 592*5c2921b0SApple OSS Distributions args = list(map( 593*5c2921b0SApple OSS Distributions sym_arg if symbolicate else fmt_arg, 594*5c2921b0SApple OSS Distributions [event.arg1, event.arg2, event.arg3, event.arg4])) 595*5c2921b0SApple OSS Distributions return O.format( 596*5c2921b0SApple OSS Distributions '{:12d} 0x{:08x} {:18s} {:18s} {:18s} {:18s} {:5d} {:8d}', 597*5c2921b0SApple OSS Distributions unsigned(timestamp), unsigned(event.debugid), 598*5c2921b0SApple OSS Distributions args[0], args[1], args[2], args[3], unsigned(cpuid), 599*5c2921b0SApple OSS Distributions unsigned(event.arg5)) 600*5c2921b0SApple OSS Distributions 601*5c2921b0SApple OSS Distributions 602*5c2921b0SApple OSS Distributions@lldb_command('showkdebugtrace', 'L:S', fancy=True) 603*5c2921b0SApple OSS Distributionsdef ShowKdebugTrace(cmd_args=None, cmd_options={}, O=None): 604*5c2921b0SApple OSS Distributions """ 605*5c2921b0SApple OSS Distributions List the events present in the kdebug trace buffers. 606*5c2921b0SApple OSS Distributions 607*5c2921b0SApple OSS Distributions (lldb) showkdebugtrace [-S] [-L <last-seconds>] 608*5c2921b0SApple OSS Distributions 609*5c2921b0SApple OSS Distributions -L <last-seconds>: only show events from the last <last-seconds> seconds 610*5c2921b0SApple OSS Distributions -S: attempt to symbolicate arguments as kernel addresses 611*5c2921b0SApple OSS Distributions 612*5c2921b0SApple OSS Distributions Caveats: 613*5c2921b0SApple OSS Distributions * Events from IOPs may be missing or cut-off -- they weren't informed 614*5c2921b0SApple OSS Distributions of this kind of buffer collection. 615*5c2921b0SApple OSS Distributions """ 616*5c2921b0SApple OSS Distributions k64 = kern.ptrsize == 8 617*5c2921b0SApple OSS Distributions last = cmd_options.get('-L', None) 618*5c2921b0SApple OSS Distributions if last: 619*5c2921b0SApple OSS Distributions try: 620*5c2921b0SApple OSS Distributions last = float(last) 621*5c2921b0SApple OSS Distributions except ValueError: 622*5c2921b0SApple OSS Distributions raise ArgumentError( 623*5c2921b0SApple OSS Distributions 'error: -L argument must be a number, not {}'.format(last)) 624*5c2921b0SApple OSS Distributions with O.table(GetKdebugEvent.header): 625*5c2921b0SApple OSS Distributions for event in IterateKdebugEvents( 626*5c2921b0SApple OSS Distributions config['verbosity'] > vHUMAN, humanize=True, last=last): 627*5c2921b0SApple OSS Distributions print(GetKdebugEvent( 628*5c2921b0SApple OSS Distributions event, k64, symbolicate='-S' in cmd_options, O=O)) 629*5c2921b0SApple OSS Distributions 630*5c2921b0SApple OSS Distributions 631*5c2921b0SApple OSS Distributionsdef binary_plist(o): 632*5c2921b0SApple OSS Distributions if PY2: 633*5c2921b0SApple OSS Distributions # Python 2 lacks a convenient binary plist writer. 634*5c2921b0SApple OSS Distributions with tempfile.NamedTemporaryFile(delete=False) as f: 635*5c2921b0SApple OSS Distributions plistlib.writePlist(o, f) 636*5c2921b0SApple OSS Distributions name = f.name 637*5c2921b0SApple OSS Distributions 638*5c2921b0SApple OSS Distributions subprocess.check_output(['plutil', '-convert', 'binary1', name]) 639*5c2921b0SApple OSS Distributions with open(name, mode='rb') as f: 640*5c2921b0SApple OSS Distributions plist = f.read() 641*5c2921b0SApple OSS Distributions 642*5c2921b0SApple OSS Distributions os.unlink(name) 643*5c2921b0SApple OSS Distributions return plist 644*5c2921b0SApple OSS Distributions else: 645*5c2921b0SApple OSS Distributions return plistlib.dumps(o, fmt=plistlib.FMT_BINARY) 646*5c2921b0SApple OSS Distributions 647*5c2921b0SApple OSS Distributions 648*5c2921b0SApple OSS Distributionsdef plist_data(d): 649*5c2921b0SApple OSS Distributions if PY2: 650*5c2921b0SApple OSS Distributions return plistlib.Data(d) 651*5c2921b0SApple OSS Distributions else: 652*5c2921b0SApple OSS Distributions return d 653*5c2921b0SApple OSS Distributions 654*5c2921b0SApple OSS Distributions 655*5c2921b0SApple OSS Distributionsdef align_next_chunk(f, offset, verbose): 656*5c2921b0SApple OSS Distributions trailing = offset % 8 657*5c2921b0SApple OSS Distributions padding = 0 658*5c2921b0SApple OSS Distributions if trailing != 0: 659*5c2921b0SApple OSS Distributions padding = 8 - trailing 660*5c2921b0SApple OSS Distributions f.write(b'\x00' * padding) 661*5c2921b0SApple OSS Distributions if verbose: 662*5c2921b0SApple OSS Distributions print('aligned next chunk with {} padding bytes'.format(padding)) 663*5c2921b0SApple OSS Distributions return padding 664*5c2921b0SApple OSS Distributions 665*5c2921b0SApple OSS Distributions 666*5c2921b0SApple OSS Distributionsdef GetKtraceMachine(): 667*5c2921b0SApple OSS Distributions """ 668*5c2921b0SApple OSS Distributions This is best effort -- several fields are only available to user space or 669*5c2921b0SApple OSS Distributions are difficult to determine from a core file. 670*5c2921b0SApple OSS Distributions """ 671*5c2921b0SApple OSS Distributions master_cpu_data = GetCpuDataForCpuID(0) 672*5c2921b0SApple OSS Distributions if kern.arch == 'x86_64': 673*5c2921b0SApple OSS Distributions cpu_family = unsigned(kern.globals.cpuid_cpu_info.cpuid_cpufamily) 674*5c2921b0SApple OSS Distributions else: 675*5c2921b0SApple OSS Distributions cpu_family = 0 # XXX 676*5c2921b0SApple OSS Distributions 677*5c2921b0SApple OSS Distributions k64 = kern.ptrsize == 8 678*5c2921b0SApple OSS Distributions page_size = 4 * 4096 if k64 else 4096 679*5c2921b0SApple OSS Distributions 680*5c2921b0SApple OSS Distributions return { 681*5c2921b0SApple OSS Distributions 'kern_version': str(kern.globals.version), 682*5c2921b0SApple OSS Distributions 'boot_args': '', # XXX 683*5c2921b0SApple OSS Distributions 'hw_memsize': unsigned(kern.globals.max_mem), 684*5c2921b0SApple OSS Distributions 'hw_pagesize': page_size, # XXX 685*5c2921b0SApple OSS Distributions 'vm_pagesize': page_size, # XXX 686*5c2921b0SApple OSS Distributions 'os_name': 'Unknown', # XXX 687*5c2921b0SApple OSS Distributions 'os_version': 'Unknown', # XXX 688*5c2921b0SApple OSS Distributions 'os_build': str(kern.globals.osversion), 689*5c2921b0SApple OSS Distributions 'arch': 'Unknown', # XXX 690*5c2921b0SApple OSS Distributions 'hw_model': 'Unknown', # XXX 691*5c2921b0SApple OSS Distributions 'cpu_type': unsigned(master_cpu_data.cpu_type), 692*5c2921b0SApple OSS Distributions 'cpu_subtype': unsigned(master_cpu_data.cpu_subtype), 693*5c2921b0SApple OSS Distributions 'cpu_family': cpu_family, 694*5c2921b0SApple OSS Distributions 'active_cpus': unsigned(kern.globals.processor_avail_count), 695*5c2921b0SApple OSS Distributions 'max_cpus': unsigned(kern.globals.machine_info.logical_cpu_max), 696*5c2921b0SApple OSS Distributions 'apple_internal': True, # XXX 697*5c2921b0SApple OSS Distributions } 698*5c2921b0SApple OSS Distributions 699*5c2921b0SApple OSS Distributions 700*5c2921b0SApple OSS DistributionsCHUNKHDR_PACK = 'IHHQ' 701*5c2921b0SApple OSS Distributions 702*5c2921b0SApple OSS Distributions 703*5c2921b0SApple OSS Distributionsdef append_chunk(f, file_offset, tag, major, minor, data, verbose): 704*5c2921b0SApple OSS Distributions f.write(struct.pack(CHUNKHDR_PACK, tag, major, minor, len(data))) 705*5c2921b0SApple OSS Distributions f.write(data) 706*5c2921b0SApple OSS Distributions offset = 16 + len(data) 707*5c2921b0SApple OSS Distributions return offset + align_next_chunk(f, file_offset + offset, verbose) 708*5c2921b0SApple OSS Distributions 709*5c2921b0SApple OSS Distributions 710*5c2921b0SApple OSS Distributions@lldb_command('savekdebugtrace', 'IL:MN:') 711*5c2921b0SApple OSS Distributionsdef SaveKdebugTrace(cmd_args=None, cmd_options={}): 712*5c2921b0SApple OSS Distributions """ 713*5c2921b0SApple OSS Distributions Save any valid ktrace events to a file. 714*5c2921b0SApple OSS Distributions 715*5c2921b0SApple OSS Distributions (lldb) savekdebugtrace [-IM] [-N <n-events> | -L <last-secs>] <output-path> 716*5c2921b0SApple OSS Distributions 717*5c2921b0SApple OSS Distributions -I: ignore coprocessor (IOP) events entirely 718*5c2921b0SApple OSS Distributions -L <last-seconds>: only save events from the <last-seconds> seconds 719*5c2921b0SApple OSS Distributions -N <n-events>: only save the last <n-events> events 720*5c2921b0SApple OSS Distributions -M: ensure output is machine-friendly 721*5c2921b0SApple OSS Distributions 722*5c2921b0SApple OSS Distributions Tips: 723*5c2921b0SApple OSS Distributions * To speed up the process, use the -I and -L options to avoid 724*5c2921b0SApple OSS Distributions processing events based on source or time. 725*5c2921b0SApple OSS Distributions 726*5c2921b0SApple OSS Distributions Caveats: 727*5c2921b0SApple OSS Distributions * Fewer than the requested number of events may end up in the file. 728*5c2921b0SApple OSS Distributions * The machine and config chunks may be missing crucial information 729*5c2921b0SApple OSS Distributions required for tools to analyze them. 730*5c2921b0SApple OSS Distributions * Events from coprocessors may be missing or cut-off -- they weren't 731*5c2921b0SApple OSS Distributions informed of this kind of buffer collection. 732*5c2921b0SApple OSS Distributions * Chunks related to post-processing, like symbolication data or a 733*5c2921b0SApple OSS Distributions catalog will need to be added manually. 734*5c2921b0SApple OSS Distributions """ 735*5c2921b0SApple OSS Distributions 736*5c2921b0SApple OSS Distributions k64 = kern.ptrsize == 8 737*5c2921b0SApple OSS Distributions 738*5c2921b0SApple OSS Distributions if len(cmd_args) != 1: 739*5c2921b0SApple OSS Distributions raise ArgumentError('error: path to trace file is required') 740*5c2921b0SApple OSS Distributions 741*5c2921b0SApple OSS Distributions last = cmd_options.get('-L', None) 742*5c2921b0SApple OSS Distributions if last and '-N' in cmd_options: 743*5c2921b0SApple OSS Distributions raise ArgumentError('error: -L and -N are mutually exclusive') 744*5c2921b0SApple OSS Distributions if last: 745*5c2921b0SApple OSS Distributions try: 746*5c2921b0SApple OSS Distributions last = float(last) 747*5c2921b0SApple OSS Distributions except ValueError: 748*5c2921b0SApple OSS Distributions raise ArgumentError( 749*5c2921b0SApple OSS Distributions 'error: -L argument must be a number, not {}'.format(last)) 750*5c2921b0SApple OSS Distributions 751*5c2921b0SApple OSS Distributions nevents = unsigned(kern.globals.kd_buffer_trace.kdb_event_count) 752*5c2921b0SApple OSS Distributions if nevents == 0: 753*5c2921b0SApple OSS Distributions print('error: kdebug buffers are not set up') 754*5c2921b0SApple OSS Distributions return 755*5c2921b0SApple OSS Distributions 756*5c2921b0SApple OSS Distributions limit_nevents = nevents 757*5c2921b0SApple OSS Distributions if '-N' in cmd_options: 758*5c2921b0SApple OSS Distributions limit_nevents = unsigned(cmd_options['-N']) 759*5c2921b0SApple OSS Distributions if limit_nevents > nevents: 760*5c2921b0SApple OSS Distributions limit_nevents = nevents 761*5c2921b0SApple OSS Distributions verbose = config['verbosity'] > vHUMAN 762*5c2921b0SApple OSS Distributions humanize = '-M' not in cmd_options 763*5c2921b0SApple OSS Distributions 764*5c2921b0SApple OSS Distributions file_offset = 0 765*5c2921b0SApple OSS Distributions with open(cmd_args[0], 'w+b') as f: 766*5c2921b0SApple OSS Distributions FILE_MAGIC = 0x55aa0300 767*5c2921b0SApple OSS Distributions EVENTS_TAG = 0x00001e00 768*5c2921b0SApple OSS Distributions SSHOT_TAG = 0x8002 769*5c2921b0SApple OSS Distributions CONFIG_TAG = 0x8006 770*5c2921b0SApple OSS Distributions MACHINE_TAG = 0x8c00 771*5c2921b0SApple OSS Distributions CHUNKHDR_PACK = 'IHHQ' 772*5c2921b0SApple OSS Distributions FILEHDR_PACK = CHUNKHDR_PACK + 'IIQQIIII' 773*5c2921b0SApple OSS Distributions FILEHDR_SIZE = 40 774*5c2921b0SApple OSS Distributions FUTURE_SIZE = 8 775*5c2921b0SApple OSS Distributions 776*5c2921b0SApple OSS Distributions numer, denom = GetTimebaseInfo() 777*5c2921b0SApple OSS Distributions 778*5c2921b0SApple OSS Distributions # XXX The kernel doesn't have a solid concept of the wall time. 779*5c2921b0SApple OSS Distributions wall_abstime = 0 780*5c2921b0SApple OSS Distributions wall_secs = 0 781*5c2921b0SApple OSS Distributions wall_usecs = 0 782*5c2921b0SApple OSS Distributions 783*5c2921b0SApple OSS Distributions event_size = 64 if k64 else 32 784*5c2921b0SApple OSS Distributions 785*5c2921b0SApple OSS Distributions file_hdr = struct.pack( 786*5c2921b0SApple OSS Distributions FILEHDR_PACK, FILE_MAGIC, 0, 0, FILEHDR_SIZE, 787*5c2921b0SApple OSS Distributions numer, denom, wall_abstime, wall_secs, wall_usecs, 0, 0, 788*5c2921b0SApple OSS Distributions 0x1 if k64 else 0) 789*5c2921b0SApple OSS Distributions f.write(file_hdr) 790*5c2921b0SApple OSS Distributions header_size_offset = file_offset + 8 791*5c2921b0SApple OSS Distributions file_offset += 16 + FILEHDR_SIZE # chunk header plus file header 792*5c2921b0SApple OSS Distributions 793*5c2921b0SApple OSS Distributions if verbose: 794*5c2921b0SApple OSS Distributions print('writing machine chunk at offset 0x{:x}'.format(file_offset)) 795*5c2921b0SApple OSS Distributions machine_data = GetKtraceMachine() 796*5c2921b0SApple OSS Distributions machine_bytes = binary_plist(machine_data) 797*5c2921b0SApple OSS Distributions file_offset += append_chunk( 798*5c2921b0SApple OSS Distributions f, file_offset, MACHINE_TAG, 0, 0, machine_bytes, verbose) 799*5c2921b0SApple OSS Distributions 800*5c2921b0SApple OSS Distributions if verbose: 801*5c2921b0SApple OSS Distributions print('writing config chunk at offset 0x{:x}'.format(file_offset)) 802*5c2921b0SApple OSS Distributions config_data = GetKtraceConfig() 803*5c2921b0SApple OSS Distributions config_bytes = binary_plist(config_data) 804*5c2921b0SApple OSS Distributions file_offset += append_chunk( 805*5c2921b0SApple OSS Distributions f, file_offset, CONFIG_TAG, 0, 0, config_bytes, verbose) 806*5c2921b0SApple OSS Distributions 807*5c2921b0SApple OSS Distributions events_hdr = struct.pack( 808*5c2921b0SApple OSS Distributions CHUNKHDR_PACK, EVENTS_TAG, 0, 0, 0) # size will be filled in later 809*5c2921b0SApple OSS Distributions f.write(events_hdr) 810*5c2921b0SApple OSS Distributions file_offset += 16 # header size 811*5c2921b0SApple OSS Distributions event_size_offset = file_offset - FUTURE_SIZE 812*5c2921b0SApple OSS Distributions # Future events timestamp -- doesn't need to be set for merged events. 813*5c2921b0SApple OSS Distributions f.write(struct.pack('Q', 0)) 814*5c2921b0SApple OSS Distributions file_offset += FUTURE_SIZE 815*5c2921b0SApple OSS Distributions 816*5c2921b0SApple OSS Distributions if verbose: 817*5c2921b0SApple OSS Distributions print('events start at offset 0x{:x}'.format(file_offset)) 818*5c2921b0SApple OSS Distributions 819*5c2921b0SApple OSS Distributions process = LazyTarget().GetProcess() 820*5c2921b0SApple OSS Distributions error = lldb.SBError() 821*5c2921b0SApple OSS Distributions 822*5c2921b0SApple OSS Distributions skip_nevents = nevents - limit_nevents if limit_nevents else 0 823*5c2921b0SApple OSS Distributions if skip_nevents > 0: 824*5c2921b0SApple OSS Distributions print('omitting {} events from the beginning'.format(skip_nevents)) 825*5c2921b0SApple OSS Distributions 826*5c2921b0SApple OSS Distributions written_nevents = 0 827*5c2921b0SApple OSS Distributions seen_nevents = 0 828*5c2921b0SApple OSS Distributions start_time = time.time() 829*5c2921b0SApple OSS Distributions update_every = 1000 if humanize else 25000 830*5c2921b0SApple OSS Distributions for event in IterateKdebugEvents( 831*5c2921b0SApple OSS Distributions verbose, include_coprocessors='-I' not in cmd_options, 832*5c2921b0SApple OSS Distributions humanize=humanize, last=last): 833*5c2921b0SApple OSS Distributions seen_nevents += 1 834*5c2921b0SApple OSS Distributions if skip_nevents >= seen_nevents: 835*5c2921b0SApple OSS Distributions if seen_nevents % update_every == 0: 836*5c2921b0SApple OSS Distributions sys.stderr.write('skipped {}/{} ({:4.2f}%) events'.format( 837*5c2921b0SApple OSS Distributions seen_nevents, skip_nevents, 838*5c2921b0SApple OSS Distributions float(seen_nevents) / skip_nevents * 100.0)) 839*5c2921b0SApple OSS Distributions sys.stderr.write('\r') 840*5c2921b0SApple OSS Distributions 841*5c2921b0SApple OSS Distributions continue 842*5c2921b0SApple OSS Distributions 843*5c2921b0SApple OSS Distributions event = process.ReadMemory( 844*5c2921b0SApple OSS Distributions unsigned(event), event_size, error) 845*5c2921b0SApple OSS Distributions file_offset += event_size 846*5c2921b0SApple OSS Distributions f.write(event) 847*5c2921b0SApple OSS Distributions written_nevents += 1 848*5c2921b0SApple OSS Distributions # Periodically update the CLI with progress. 849*5c2921b0SApple OSS Distributions if written_nevents % update_every == 0: 850*5c2921b0SApple OSS Distributions sys.stderr.write('{}: wrote {}/{} ({:4.2f}%) events'.format( 851*5c2921b0SApple OSS Distributions time.strftime('%H:%M:%S'), written_nevents, 852*5c2921b0SApple OSS Distributions limit_nevents, 853*5c2921b0SApple OSS Distributions float(written_nevents) / nevents * 100.0)) 854*5c2921b0SApple OSS Distributions if humanize: 855*5c2921b0SApple OSS Distributions sys.stderr.write('\r') 856*5c2921b0SApple OSS Distributions else: 857*5c2921b0SApple OSS Distributions sys.stderr.write('\n') 858*5c2921b0SApple OSS Distributions sys.stderr.write('\n') 859*5c2921b0SApple OSS Distributions elapsed = time.time() - start_time 860*5c2921b0SApple OSS Distributions print('wrote {} ({}MB) events in {:.3f}s'.format( 861*5c2921b0SApple OSS Distributions written_nevents, written_nevents * event_size >> 20, elapsed)) 862*5c2921b0SApple OSS Distributions if verbose: 863*5c2921b0SApple OSS Distributions print('events end at offset 0x{:x}'.format(file_offset)) 864*5c2921b0SApple OSS Distributions 865*5c2921b0SApple OSS Distributions # Normally, the chunk would need to be padded to 8, but events are 866*5c2921b0SApple OSS Distributions # already aligned. 867*5c2921b0SApple OSS Distributions 868*5c2921b0SApple OSS Distributions kcdata = kern.globals.kc_panic_data 869*5c2921b0SApple OSS Distributions kcdata_addr = unsigned(kcdata.kcd_addr_begin) 870*5c2921b0SApple OSS Distributions kcdata_length = unsigned(kcdata.kcd_length) 871*5c2921b0SApple OSS Distributions if kcdata_addr != 0 and kcdata_length != 0: 872*5c2921b0SApple OSS Distributions print('writing stackshot') 873*5c2921b0SApple OSS Distributions if verbose: 874*5c2921b0SApple OSS Distributions print('stackshot is 0x{:x} bytes at offset 0x{:x}'.format( 875*5c2921b0SApple OSS Distributions kcdata_length, file_offset)) 876*5c2921b0SApple OSS Distributions ssdata = process.ReadMemory(kcdata_addr, kcdata_length, error) 877*5c2921b0SApple OSS Distributions magic = struct.unpack('I', ssdata[:4]) 878*5c2921b0SApple OSS Distributions if magic[0] == GetTypeForName('KCDATA_BUFFER_BEGIN_COMPRESSED'): 879*5c2921b0SApple OSS Distributions if verbose: 880*5c2921b0SApple OSS Distributions print('found compressed stackshot') 881*5c2921b0SApple OSS Distributions iterator = kcdata_item_iterator(ssdata) 882*5c2921b0SApple OSS Distributions for item in iterator: 883*5c2921b0SApple OSS Distributions kcdata_buffer = KCObject.FromKCItem(item) 884*5c2921b0SApple OSS Distributions if isinstance(kcdata_buffer, KCCompressedBufferObject): 885*5c2921b0SApple OSS Distributions kcdata_buffer.ReadItems(iterator) 886*5c2921b0SApple OSS Distributions decompressed = kcdata_buffer.Decompress(ssdata) 887*5c2921b0SApple OSS Distributions ssdata = decompressed 888*5c2921b0SApple OSS Distributions kcdata_length = len(ssdata) 889*5c2921b0SApple OSS Distributions if verbose: 890*5c2921b0SApple OSS Distributions print( 891*5c2921b0SApple OSS Distributions 'compressed stackshot is 0x{:x} bytes long'. 892*5c2921b0SApple OSS Distributions format(kcdata_length)) 893*5c2921b0SApple OSS Distributions 894*5c2921b0SApple OSS Distributions file_offset += append_chunk( 895*5c2921b0SApple OSS Distributions f, file_offset, SSHOT_TAG, 1, 0, ssdata, verbose) 896*5c2921b0SApple OSS Distributions if verbose: 897*5c2921b0SApple OSS Distributions print('stackshot ends at offset 0x{:x}'.format(file_offset)) 898*5c2921b0SApple OSS Distributions else: 899*5c2921b0SApple OSS Distributions print('warning: no stackshot; trace file may not be usable') 900*5c2921b0SApple OSS Distributions 901*5c2921b0SApple OSS Distributions # After the number of events is known, fix up the events chunk size. 902*5c2921b0SApple OSS Distributions events_data_size = unsigned(written_nevents * event_size) + FUTURE_SIZE 903*5c2921b0SApple OSS Distributions f.seek(event_size_offset) 904*5c2921b0SApple OSS Distributions f.write(struct.pack('Q', events_data_size)) 905*5c2921b0SApple OSS Distributions if verbose: 906*5c2921b0SApple OSS Distributions print('wrote {:x} bytes at offset 0x{:x} for event size'.format( 907*5c2921b0SApple OSS Distributions events_data_size, event_size_offset)) 908*5c2921b0SApple OSS Distributions 909*5c2921b0SApple OSS Distributions # Fix up the size of the header chunks, too. 910*5c2921b0SApple OSS Distributions f.seek(header_size_offset) 911*5c2921b0SApple OSS Distributions f.write(struct.pack('Q', FILEHDR_SIZE + 16 + len(machine_bytes))) 912*5c2921b0SApple OSS Distributions if verbose: 913*5c2921b0SApple OSS Distributions print(( 914*5c2921b0SApple OSS Distributions 'wrote 0x{:x} bytes at offset 0x{:x} for ' + 915*5c2921b0SApple OSS Distributions 'file header size').format( 916*5c2921b0SApple OSS Distributions len(machine_bytes), header_size_offset)) 917*5c2921b0SApple OSS Distributions 918*5c2921b0SApple OSS Distributions return 919*5c2921b0SApple OSS Distributions 920*5c2921b0SApple OSS Distributions# Obsolete commands. 921*5c2921b0SApple OSS Distributions 922*5c2921b0SApple OSS Distributions@lldb_command('showkerneldebugbuffercpu') 923*5c2921b0SApple OSS Distributionsdef ShowKernelDebugBufferCPU(cmd_args=None): 924*5c2921b0SApple OSS Distributions """ REMOVED: Use showkdebugtrace instead. """ 925*5c2921b0SApple OSS Distributions raise NotImplementedError("Use showkdebugtrace instead") 926*5c2921b0SApple OSS Distributions 927*5c2921b0SApple OSS Distributions 928*5c2921b0SApple OSS Distributions@lldb_command('showkerneldebugbuffer') 929*5c2921b0SApple OSS Distributionsdef ShowKernelDebugBuffer(cmd_args=None): 930*5c2921b0SApple OSS Distributions """ REMOVED: Use showkdebugtrace instead. """ 931*5c2921b0SApple OSS Distributions raise NotImplementedError("Use showkdebugtrace instead") 932*5c2921b0SApple OSS Distributions 933*5c2921b0SApple OSS Distributions 934*5c2921b0SApple OSS Distributions@lldb_command('dumprawtracefile') 935*5c2921b0SApple OSS Distributionsdef DumpRawTraceFile(cmd_args=[], cmd_options={}): 936*5c2921b0SApple OSS Distributions """ REMOVED: Use savekdebugtrace instead. """ 937*5c2921b0SApple OSS Distributions raise NotImplementedError("Use savekdebugtrace instead") 938*5c2921b0SApple OSS Distributions 939*5c2921b0SApple OSS Distributions 940