]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/kcdata.py
xnu-3247.1.106.tar.gz
[apple/xnu.git] / tools / lldbmacros / kcdata.py
1 #!/usr/bin/env python
2 import sys
3 import struct
4 import mmap
5 import json
6 import cgitb
7 import copy
8 import re
9 import base64
10 import argparse
11 import os
12 import shlex
13 import subprocess
14
15 cgitb.enable(format='text')
16
17 kcdata_type_def = {
18 'KCDATA_TYPE_INVALID': 0x0,
19 'KCDATA_TYPE_STRING_DESC': 0x1,
20 'KCDATA_TYPE_UINT32_DESC': 0x2,
21 'KCDATA_TYPE_UINT64_DESC': 0x3,
22 'KCDATA_TYPE_INT32_DESC': 0x4,
23 'KCDATA_TYPE_INT64_DESC': 0x5,
24 'KCDATA_TYPE_BINDATA_DESC': 0x6,
25 'KCDATA_TYPE_ARRAY': 0x11,
26 'KCDATA_TYPE_TYPEDEFINTION': 0x12,
27 'KCDATA_TYPE_CONTAINER_BEGIN': 0x13,
28 'KCDATA_TYPE_CONTIANER_END': 0x14,
29 'KCDATA_TYPE_LIBRARY_LOADINFO': 0x30,
30 'KCDATA_TYPE_LIBRARY_LOADINFO64': 0x31,
31 'KCDATA_TYPE_TIMEBASE': 0x32,
32 #'KCDATA_TYPE_MACH_ABSOLUTE_TIME': 0x33,
33 'KCDATA_TYPE_TIMEVAL': 0x34,
34 'KCDATA_TYPE_USECS_SINCE_EPOCH': 0x35,
35 'STACKSHOT_KCCONTAINER_TASK': 0x903,
36 'STACKSHOT_KCCONTAINER_THREAD': 0x904,
37 'STACKSHOT_KCTYPE_KERN_STACKFRAME': 0x90A,
38 'STACKSHOT_KCTYPE_KERN_STACKFRAME64': 0x90B,
39 'STACKSHOT_KCTYPE_USER_STACKFRAME': 0x90C,
40 'STACKSHOT_KCTYPE_USER_STACKFRAME64': 0x90D,
41 'STACKSHOT_KCTYPE_BOOTARGS': 0x90E,
42 'STACKSHOT_KCTYPE_OSVERSION': 0x90F,
43 'STACKSHOT_KCTYPE_KERN_PAGE_SIZE': 0x910,
44 'STACKSHOT_KCTYPE_JETSAM_LEVEL': 0x911,
45 'KCDATA_TYPE_BUFFER_END': 0xF19158ED,
46
47
48 'TASK_CRASHINFO_EXTMODINFO': 0x801,
49 'TASK_CRASHINFO_BSDINFOWITHUNIQID': 0x802,
50 'TASK_CRASHINFO_TASKDYLD_INFO': 0x803,
51 'TASK_CRASHINFO_UUID': 0x804,
52 'TASK_CRASHINFO_PID': 0x805,
53 'TASK_CRASHINFO_PPID': 0x806,
54 'TASK_CRASHINFO_RUSAGE': 0x807,
55 'TASK_CRASHINFO_RUSAGE_INFO': 0x808,
56 'TASK_CRASHINFO_PROC_NAME': 0x809,
57 'TASK_CRASHINFO_PROC_STARTTIME': 0x80B,
58 'TASK_CRASHINFO_USERSTACK': 0x80C,
59 'TASK_CRASHINFO_ARGSLEN': 0x80D,
60 'TASK_CRASHINFO_EXCEPTION_CODES': 0x80E,
61 'TASK_CRASHINFO_PROC_PATH': 0x80F,
62 'TASK_CRASHINFO_PROC_CSFLAGS': 0x810,
63 'TASK_CRASHINFO_PROC_STATUS': 0x811,
64 'TASK_CRASHINFO_UID': 0x812,
65 'TASK_CRASHINFO_GID': 0x813,
66 'TASK_CRASHINFO_PROC_ARGC': 0x814,
67 'TASK_CRASHINFO_PROC_FLAGS': 0x815,
68 'TASK_CRASHINFO_CPUTYPE': 0x816,
69 'TASK_CRASHINFO_WORKQUEUEINFO': 0x817,
70 'TASK_CRASHINFO_RESPONSIBLE_PID': 0x818,
71 'TASK_CRASHINFO_DIRTY_FLAGS': 0x819,
72 'TASK_CRASHINFO_CRASHED_THREADID': 0x81A,
73
74 'KCDATA_BUFFER_BEGIN_CRASHINFO': 0xDEADF157,
75 'KCDATA_BUFFER_BEGIN_STACKSHOT': 0x59a25807
76 }
77 kcdata_type_def_rev = dict((v, k) for k, v in kcdata_type_def.iteritems())
78
79 KNOWN_TYPES_COLLECTION = {}
80
81
82 def enum(**args):
83 return type('enum', (), args)
84
85 KCSUBTYPE_TYPE = enum(KC_ST_CHAR=1, KC_ST_INT8=2, KC_ST_UINT8=3, KC_ST_INT16=4, KC_ST_UINT16=5, KC_ST_INT32=6, KC_ST_UINT32=7, KC_ST_INT64=8, KC_ST_UINT64=9)
86
87
88 class KCSubTypeElement(object):
89 """convert kcdata_subtype_descriptor to """
90 _unpack_formats = (None, 'c', 'b', 'B', 'h', 'H', 'i', 'I', 'q', 'Q')
91 _ctypes = ('Unknown', 'char', 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', 'uint32_t', 'int64_t', 'uint64_t')
92
93 def __init__(self, st_name, st_type, st_size, st_offset=0, st_flag=0, custom_repr=None):
94 self.name = st_name
95 self.offset = st_offset
96 self.type_id = st_type
97 if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
98 raise ValueError("Invalid type passed %d" % st_type)
99 self.unpack_fmt = KCSubTypeElement._unpack_formats[self.type_id]
100 self.size = st_size
101 self.totalsize = st_size
102 self.count = 1
103 self.is_array_type = False
104 self.custom_JsonRepr = custom_repr
105 if (st_flag & 0x1) == 0x1:
106 self.is_array_type = True
107 self.size = st_size & 0xffff
108 self.count = (st_size >> 16) & 0xffff
109 self.totalsize = self.size * self.count
110
111 @staticmethod
112 def GetSizeForArray(el_count, el_size):
113 return ((el_count & 0xffff) << 16) | (el_size & 0xffff)
114
115 @staticmethod
116 def FromBinaryTypeData(byte_data):
117 (st_flag, st_type, st_offset, st_size, st_name) = struct.unpack_from('=BBHI32s', byte_data)
118 st_name = st_name.rstrip('\x00')
119 return KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag)
120
121 @staticmethod
122 def FromBasicCtype(st_name, st_type, st_offset=0):
123 if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
124 raise ValueError("Invalid type passed %d" % st_type)
125 st_size = struct.calcsize(KCSubTypeElement._unpack_formats[st_type])
126 st_flag = 0
127 retval = KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag, KCSubTypeElement._get_naked_element_value)
128 return retval
129
130 @staticmethod
131 def FromKCSubTypeElement(other, name_override=''):
132 _copy = copy.copy(other)
133 if name_override:
134 _copy.name = name_override
135 return copy
136
137 def GetName(self):
138 return self.name
139
140 def GetTotalSize(self):
141 return self.totalsize
142
143 def GetValueAsString(self, base_data, array_pos=0):
144 return str(self.GetValue(base_data, array_pos))
145
146 def GetValue(self, base_data, array_pos=0):
147 return struct.unpack_from(self.unpack_fmt, base_data[self.offset + (array_pos * self.size):])[0]
148
149 @staticmethod
150 def _get_naked_element_value(elementValue, elementName):
151 return json.dumps(elementValue)
152
153 def __str__(self):
154 if self.is_array_type:
155 return '[%d,%d] %s %s[%d];' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name, self.count)
156 return '[%d,%d] %s %s;' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name)
157
158 def __repr__(self):
159 return str(self)
160
161 def GetCTypeDesc(self):
162 return KCSubTypeElement._ctypes[self.type_id]
163
164 def GetStringRepr(self, base_data):
165 if not self.is_array_type:
166 return self.GetValueAsString(base_data)
167 if self.type_id == KCSUBTYPE_TYPE.KC_ST_CHAR:
168 str_len = self.count
169 if len(base_data) < str_len:
170 str_len = len(base_data)
171 str_arr = []
172 for i in range(str_len):
173 _v = self.GetValue(base_data, i)
174 if ord(_v) == 0:
175 break
176 str_arr.append(self.GetValueAsString(base_data, i))
177
178 return '"' + ''.join(str_arr) + '"'
179 o = '[' + ','.join([self.GetValueAsString(base_data, i) for i in range(self.count)]) + ']'
180 return o
181
182 def GetJsonRepr(self, base_data):
183 if self.custom_JsonRepr:
184 if self.is_array_type:
185 e_data = [self.GetValue(base_data, i) for i in range(self.count)]
186 else:
187 e_data = self.GetValue(base_data)
188 return self.custom_JsonRepr(e_data, self.name)
189 return self.GetStringRepr(base_data)
190
191
192 class KCTypeDescription(object):
193 def __init__(self, t_type_id, t_elements=[], t_name='anon', custom_repr=None):
194 self.type_id = t_type_id
195 self.elements = t_elements
196 self.name = t_name
197 self.totalsize = 0
198 self.custom_JsonRepr = custom_repr
199 for e in self.elements:
200 self.totalsize += e.GetTotalSize()
201
202 def ValidateData(self, base_data):
203 if len(base_data) >= self.totalsize:
204 return True
205 return False
206
207 def GetTypeID(self):
208 return self.type_id
209
210 def GetName(self):
211 return self.name
212
213 def __str__(self):
214 o = '%s {\n\t' % self.name + "\n\t".join([str(e) for e in self.elements]) + '\n};'
215 return o
216
217 @staticmethod
218 def FromKCTypeDescription(other, t_type_id, t_name):
219 retval = KCTypeDescription(t_type_id, other.elements, t_name, other.custom_JsonRepr)
220 return retval
221
222 def GetJsonRepr(self, base_data):
223 if self.custom_JsonRepr:
224 return self.custom_JsonRepr([e.GetValue(base_data) for e in self.elements])
225 o = '{' + ", ".join(['"%s": %s' % (e.GetName(), e.GetJsonRepr(base_data)) for e in self.elements]) + '}'
226 return o
227
228
229 def GetTypeNameForKey(k):
230 retval = "0x%x" % k
231 if k in KNOWN_TYPES_COLLECTION:
232 retval = KNOWN_TYPES_COLLECTION[k].GetName()
233 elif k in kcdata_type_def_rev:
234 retval = kcdata_type_def_rev[k]
235 return retval
236
237
238 def GetTypeForName(n):
239 ret = 0
240 if n in kcdata_type_def:
241 ret = kcdata_type_def[n]
242 return ret
243
244
245 class KCObject(object):
246 """
247 """
248 def __init__(self, type_code, data, flags=0, field_name=''):
249 self.i_type = type_code
250 self.i_data = data
251 self.i_size = len(data)
252 self.i_name = field_name
253 self.i_flags = flags
254 self.obj_collection = []
255 self.obj = {}
256 self.is_container_type = False
257 self.is_array_type = False
258 self.is_naked_type = False
259 if not field_name:
260 self.i_name = GetTypeNameForKey(type_code)
261 self.ParseData()
262
263 @staticmethod
264 def FromKCItem(kcitem):
265 return KCObject(kcitem.i_type, kcitem.i_data, kcitem.i_flags)
266
267 def IsContainerType(self):
268 return self.is_container_type
269
270 def IsContainerEnd(self):
271 if self.i_type in (GetTypeForName('KCDATA_TYPE_CONTIANER_END'), GetTypeForName('KCDATA_TYPE_BUFFER_END')):
272 return True
273 return False
274
275 def GetJsonRepr(self):
276 if self.is_array_type:
277 return '[' + ', '.join([i.GetJsonRepr() for i in self.obj_collection]) + ']'
278 #if self.is_array_type:
279 # return '"%s" : [' % self.i_name + ', '.join([i.GetJsonRepr() for i in self.obj_collection]) + ']'
280 if self.is_container_type:
281 raise NotImplementedError("Containter types should not have come here")
282 if self.i_type in KNOWN_TYPES_COLLECTION:
283 return KNOWN_TYPES_COLLECTION[self.i_type].GetJsonRepr(self.i_data)
284 if self.is_naked_type:
285 return json.dumps(self.obj)
286
287 raise NotImplementedError("Broken GetJsonRepr implementation")
288
289 def ParseData(self):
290 if self.i_type == GetTypeForName('KCDATA_TYPE_CONTAINER_BEGIN'):
291 self.is_container_type = True
292 self.obj['uniqID'] = self.i_flags
293 self.i_name = str(self.obj['uniqID'])
294 self.obj['typeID'] = struct.unpack_from('I', self.i_data)[0]
295
296 elif self.i_type in (GetTypeForName('KCDATA_BUFFER_BEGIN_CRASHINFO'), GetTypeForName('KCDATA_BUFFER_BEGIN_STACKSHOT')):
297 self.is_container_type = True
298 self.obj['uniqID'] = self.i_name
299 self.obj['typeID'] = self.i_type
300
301 elif self.i_type == GetTypeForName('KCDATA_TYPE_CONTIANER_END'):
302 self.obj['uniqID'] = self.i_flags
303
304 elif self.i_type == GetTypeForName('KCDATA_TYPE_BUFFER_END'):
305 self.obj = ''
306
307 elif self.i_type == GetTypeForName('KCDATA_TYPE_UINT32_DESC'):
308 self.is_naked_type = True
309 u_d = struct.unpack_from('32sI', self.i_data)
310 self.i_name = u_d[0].strip(chr(0))
311 self.obj = u_d[1]
312
313 elif self.i_type == GetTypeForName('KCDATA_TYPE_UINT64_DESC'):
314 self.is_naked_type = True
315 u_d = struct.unpack_from('32sQ', self.i_data)
316 self.i_name = u_d[0].strip(chr(0))
317 self.obj = u_d[1]
318
319 elif self.i_type == GetTypeForName('KCDATA_TYPE_TYPEDEFINTION'):
320 self.is_naked_type = True
321 u_d = struct.unpack_from('II32s', self.i_data)
322 self.obj['name'] = u_d[2].strip(chr(0))
323 self.i_name = "typedef<%s>" % self.obj['name']
324 self.obj['typeID'] = u_d[0]
325 self.obj['numOfFields'] = u_d[1]
326 element_arr = []
327 for i in range(u_d[1]):
328 e = KCSubTypeElement.FromBinaryTypeData(self.i_data[40+(i*40):])
329 #print str(e)
330 element_arr.append(e)
331 type_desc = KCTypeDescription(u_d[0], element_arr, self.obj['name'])
332 #print str(type_desc)
333 self.obj['fields'] = [str(e) for e in element_arr]
334 KNOWN_TYPES_COLLECTION[type_desc.GetTypeID()] = type_desc
335
336 elif self.i_type == GetTypeForName('KCDATA_TYPE_ARRAY'):
337 self.is_array_type = True
338 e_t = (self.i_flags >> 32) & 0xffffffff
339 e_c = self.i_flags & 0xffffffff
340 e_s = self.i_size / e_c
341 self.obj['typeID'] = e_t
342 self.i_name = GetTypeNameForKey(e_t)
343 self.i_type = e_t
344 self.obj['numOfElements'] = e_c
345 self.obj['sizeOfElement'] = e_s
346 #populate the array here by recursive creation of KCObject
347 for _i in range(e_c):
348 _o = KCObject(e_t, self.i_data[(_i * e_s):(_i * e_s) + e_s])
349 self.obj_collection.append(_o)
350 elif self.i_type in KNOWN_TYPES_COLLECTION:
351 self.i_name = KNOWN_TYPES_COLLECTION[self.i_type].GetName()
352 self.is_naked_type = True
353 else:
354 self.is_naked_type = True
355 #self.obj = "data of len %d" % len(self.i_data)
356 #self.obj = ''.join(["%x" % ki for ki in struct.unpack('%dB' % len(self.i_data), self.i_data)])
357 self.obj = base64.b64encode(self.i_data)
358
359
360 class KCContainerObject(KCObject):
361 def __init__(self, *args, **kwargs):
362 KCObject.__init__(self, *args, **kwargs)
363 self.obj_container_dict = {}
364 self.obj_nested_objs = {}
365
366 def GetJsonRepr(self):
367 o = '"%s"' % self.obj['uniqID'] + ' : { "typeID" : %d ,' % self.obj['typeID']
368 for (k, v) in self.obj_container_dict.items():
369 if v.IsContainerType():
370 o += v.GetJsonRepr() + ","
371 else:
372 o += ' "%s" : ' % k + v.GetJsonRepr() + ","
373
374 for (k, v) in self.obj_nested_objs.items():
375 o += '"%s" : {' % k + ",".join([vi.GetJsonRepr() for vi in v.values()]) + "} ,"
376
377 o = o.rstrip(',') + "}"
378
379 return o
380
381 def AddObject(self, kco):
382 if kco.IsContainerEnd():
383 return
384 if kco.IsContainerType():
385 type_name = GetTypeNameForKey(kco.obj['typeID'])
386 if type_name not in self.obj_nested_objs:
387 self.obj_nested_objs[type_name] = {}
388 self.obj_nested_objs[type_name][kco.i_name] = kco
389 return
390 self.obj_container_dict[kco.i_name] = kco
391
392
393 class KCData_item:
394 """ a basic kcdata_item type object.
395 """
396 header_size = 16 # (uint32_t + uint32_t + uint64_t)
397
398 def __init__(self, item_type, item_size, item_flags, item_data):
399 self.i_type = item_type
400 self.i_size = item_size
401 self.i_flags = item_flags
402 self.i_data = item_data
403 self._buf_pos = None
404
405 def __init__(self, barray, pos=0):
406 """ create an object by parsing data from bytes array
407 returns : obj - if data is readable
408 raises ValueError if something is not ok.
409 """
410 self.i_type = struct.unpack('I', barray[pos:pos+4])[0] # int.from_bytes(barray[pos:pos+4])
411 self.i_size = struct.unpack('I', barray[pos+4:pos+8])[0] # int.from_bytes(barray[pos+4:pos+8])
412 self.i_flags = struct.unpack('Q', barray[pos+8:pos+16])[0] # int.from_bytes(barray[pos+8:pos+16])
413 self.i_data = barray[pos+16: (pos + 16 + self.i_size)]
414 self._buf_pos = pos
415
416 def __len__(self):
417 return self.i_size + KCData_item.header_size
418
419 def GetHeaderDescription(self):
420 outs = "type: 0x%x size: 0x%x flags: 0x%x" % (self.i_type, self.i_size, self.i_flags)
421 if not self._buf_pos is None:
422 outs = "pos: 0x%x" % self._buf_pos + outs
423 return outs
424
425 def __str__(self):
426 return self.GetHeaderDescription()
427
428
429 def kcdata_item_iterator(filename):
430 if not filename:
431 return
432 with open(filename, "r+b") as f:
433 fmap = mmap.mmap(f.fileno(), 0)
434 file_len = len(fmap)
435 curpos = 0
436 while curpos < file_len:
437 item = KCData_item(fmap, curpos)
438 yield item
439 curpos += len(item)
440 fmap.close()
441
442
443 def _get_data_element(elementValues):
444 return json.dumps(elementValues[-1])
445
446 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_UINT32_DESC')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_UINT32_DESC'), (
447 KCSubTypeElement('desc', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 0, 1),
448 KCSubTypeElement('data', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 32, 0)
449 ),
450 'KCDATA_TYPE_UINT32_DESC',
451 _get_data_element
452 )
453
454 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_UINT64_DESC')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_UINT64_DESC'), (
455 KCSubTypeElement('desc', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 0, 1),
456 KCSubTypeElement('data', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 32, 0)
457 ),
458 'KCDATA_TYPE_UINT64_DESC',
459 _get_data_element
460 )
461
462 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_TIMEBASE')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_TIMEBASE'), (
463 KCSubTypeElement('numerator', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0),
464 KCSubTypeElement('denominator', KCSUBTYPE_TYPE.KC_ST_UINT32, 8, 4, 0)
465 ),
466 'timebase_info'
467 )
468
469
470 STACKSHOT_IO_NUM_PRIORITIES = 4
471 KNOWN_TYPES_COLLECTION[0x901] = KCTypeDescription(0x901, (
472 KCSubTypeElement.FromBasicCtype('disk_reads_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
473 KCSubTypeElement.FromBasicCtype('disk_reads_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
474 KCSubTypeElement.FromBasicCtype('disk_writes_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
475 KCSubTypeElement.FromBasicCtype('disk_writes_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
476 KCSubTypeElement('io_priority_count', KCSUBTYPE_TYPE.KC_ST_UINT64, KCSubTypeElement.GetSizeForArray(STACKSHOT_IO_NUM_PRIORITIES, 8), 32, 1),
477 KCSubTypeElement('io_priority_size', KCSUBTYPE_TYPE.KC_ST_UINT64, KCSubTypeElement.GetSizeForArray(STACKSHOT_IO_NUM_PRIORITIES, 8), 32 + (STACKSHOT_IO_NUM_PRIORITIES * 8), 1),
478 KCSubTypeElement.FromBasicCtype('paging_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 32 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
479 KCSubTypeElement.FromBasicCtype('paging_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 40 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
480 KCSubTypeElement.FromBasicCtype('non_paging_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 48 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
481 KCSubTypeElement.FromBasicCtype('non_paging_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 56 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
482 KCSubTypeElement.FromBasicCtype('data_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 64 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
483 KCSubTypeElement.FromBasicCtype('data_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 72 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
484 KCSubTypeElement.FromBasicCtype('metadata_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 80 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
485 KCSubTypeElement.FromBasicCtype('metadata_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 88 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8))
486 ),
487 'io_statistics'
488 )
489
490 KNOWN_TYPES_COLLECTION[0x902] = KCTypeDescription(0x902, (
491 KCSubTypeElement('snapshot_magic', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 0, 0),
492 KCSubTypeElement('free_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 1, 0),
493 KCSubTypeElement('active_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 2, 0),
494 KCSubTypeElement('inactive_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 3, 0),
495 KCSubTypeElement('purgeable_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 4, 0),
496 KCSubTypeElement('wired_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 5, 0),
497 KCSubTypeElement('speculative_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 6, 0),
498 KCSubTypeElement('throttled_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 7, 0),
499 KCSubTypeElement('filebacked_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 8, 0),
500 KCSubTypeElement('compressions', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 9, 0),
501 KCSubTypeElement('decompressions', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 10, 0),
502 KCSubTypeElement('compressor_size', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 11, 0),
503 KCSubTypeElement('busy_buffer_count', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 4 * 12, 0),
504 KCSubTypeElement('pages_wanted', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 13, 0),
505 KCSubTypeElement('pages_reclaimed', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 14, 0),
506 KCSubTypeElement('pages_wanted_reclaimed_valid', KCSUBTYPE_TYPE.KC_ST_UINT8, 1, 4 * 15, 0)
507 ),
508 'mem_and_io_snapshot'
509 )
510
511
512 KNOWN_TYPES_COLLECTION[0x905] = KCTypeDescription(0x905, (
513 KCSubTypeElement.FromBasicCtype('unique_pid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
514 KCSubTypeElement.FromBasicCtype('ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
515 KCSubTypeElement.FromBasicCtype('user_time_in_terminated_threads', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
516 KCSubTypeElement.FromBasicCtype('system_time_in_terminated_threads', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
517 KCSubTypeElement.FromBasicCtype('p_start_sec', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
518 KCSubTypeElement.FromBasicCtype('task_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
519 KCSubTypeElement.FromBasicCtype('task_max_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
520 KCSubTypeElement.FromBasicCtype('suspend_count', KCSUBTYPE_TYPE.KC_ST_UINT32, 56),
521 KCSubTypeElement.FromBasicCtype('faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 60),
522 KCSubTypeElement.FromBasicCtype('pageins', KCSUBTYPE_TYPE.KC_ST_UINT32, 64),
523 KCSubTypeElement.FromBasicCtype('cow_faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 68),
524 KCSubTypeElement.FromBasicCtype('was_throttled', KCSUBTYPE_TYPE.KC_ST_UINT32, 72),
525 KCSubTypeElement.FromBasicCtype('did_throttle', KCSUBTYPE_TYPE.KC_ST_UINT32, 76),
526 KCSubTypeElement.FromBasicCtype('latency_qos', KCSUBTYPE_TYPE.KC_ST_UINT32, 80),
527 KCSubTypeElement.FromBasicCtype('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 84),
528 KCSubTypeElement('p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 88, 1)
529 ),
530 'task_snapshot_v2'
531 )
532
533 KNOWN_TYPES_COLLECTION[0x906] = KCTypeDescription(0x906, (
534 KCSubTypeElement.FromBasicCtype('thread_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
535 KCSubTypeElement.FromBasicCtype('wait_event', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
536 KCSubTypeElement.FromBasicCtype('continuation', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
537 KCSubTypeElement.FromBasicCtype('total_syscalls', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
538 KCSubTypeElement.FromBasicCtype('voucher_identifier', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
539 KCSubTypeElement.FromBasicCtype('dqserialnum', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
540 KCSubTypeElement.FromBasicCtype('user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
541 KCSubTypeElement.FromBasicCtype('sys_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
542 KCSubTypeElement.FromBasicCtype('ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
543 KCSubTypeElement.FromBasicCtype('last_run_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
544 KCSubTypeElement.FromBasicCtype('last_made_runnable_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 80),
545 KCSubTypeElement.FromBasicCtype('state', KCSUBTYPE_TYPE.KC_ST_UINT32, 88),
546 KCSubTypeElement.FromBasicCtype('sched_flags', KCSUBTYPE_TYPE.KC_ST_UINT32, 92),
547 KCSubTypeElement.FromBasicCtype('base_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 96),
548 KCSubTypeElement.FromBasicCtype('sched_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 98),
549 KCSubTypeElement.FromBasicCtype('ts_eqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 100),
550 KCSubTypeElement.FromBasicCtype('ts_rqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 101),
551 KCSubTypeElement.FromBasicCtype('ts_rqos_override', KCSUBTYPE_TYPE.KC_ST_UINT8, 102),
552 KCSubTypeElement.FromBasicCtype('io_tier', KCSUBTYPE_TYPE.KC_ST_UINT8, 103),
553 ),
554 'thread_snapshot_v2'
555 )
556
557 KNOWN_TYPES_COLLECTION[0x909] = KCSubTypeElement('pth_name', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(64, 1), 0, 1)
558
559
560 def _get_uuid_json_data(elementValues, elementName):
561 return '"<%s>"' % ''.join("%02x" % i for i in elementValues)
562
563 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO64')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO64'), (
564 KCSubTypeElement('loadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
565 KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1, _get_uuid_json_data)
566 ),
567 'dyld_load_info'
568 )
569
570 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO'), (
571 KCSubTypeElement('loadAddress', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0),
572 KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 4, 1, _get_uuid_json_data)
573 ),
574 'dyld_load_info'
575 )
576
577 KNOWN_TYPES_COLLECTION[0x908] = KCTypeDescription.FromKCTypeDescription(KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO64')], 0x908, 'shared_cache_dyld_info')
578
579 KNOWN_TYPES_COLLECTION[0x33] = KCSubTypeElement('mach_absolute_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
580 KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement.FromBasicCtype('donating_pids', KCSUBTYPE_TYPE.KC_ST_INT32)
581
582 KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_USECS_SINCE_EPOCH')] = KCSubTypeElement('usecs_since_epoch', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
583
584 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME'), (
585 KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT32),
586 KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT32, 4)
587 ),
588 'kernel_stack_frames'
589 )
590
591 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME')] = KCTypeDescription.FromKCTypeDescription(
592 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME')],
593 GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME'),
594 'user_stack_frames'
595 )
596
597 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64'), (
598 KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT64),
599 KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)
600 ),
601 'kernel_stack_frames'
602 )
603
604 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME64')] = KCTypeDescription.FromKCTypeDescription(
605 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64')],
606 GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME64'),
607 'user_stack_frames'
608 )
609
610 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_OSVERSION')] = KCSubTypeElement('osversion', KCSUBTYPE_TYPE.KC_ST_CHAR,
611 KCSubTypeElement.GetSizeForArray(256, 1), 0, 1)
612
613 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_BOOTARGS')] = KCSubTypeElement('bootargs', KCSUBTYPE_TYPE.KC_ST_CHAR,
614 KCSubTypeElement.GetSizeForArray(256, 1), 0, 1)
615
616 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_PAGE_SIZE')] = KCSubTypeElement('kernel_page_size', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
617
618 KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_LEVEL')] = KCSubTypeElement('jetsam_level', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
619
620
621 #KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement('donating_pids', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
622 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PID')] = KCSubTypeElement('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
623 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PPID')] = KCSubTypeElement('ppid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
624 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_NAME')] = KCSubTypeElement('p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR,
625 KCSubTypeElement.GetSizeForArray(32, 1), 0, 1)
626 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_USERSTACK')] = KCSubTypeElement('userstack_ptr', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
627 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_ARGSLEN')] = KCSubTypeElement('p_argslen', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
628
629 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_PATH')] = KCSubTypeElement('p_path', KCSUBTYPE_TYPE.KC_ST_CHAR,
630 KCSubTypeElement.GetSizeForArray(1024, 1), 0, 1)
631 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_CSFLAGS')] = KCSubTypeElement('p_csflags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
632 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_UID')] = KCSubTypeElement('uid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
633 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_GID')] = KCSubTypeElement('gid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
634 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_ARGC')] = KCSubTypeElement('argc', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
635 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_FLAGS')] = KCSubTypeElement('p_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
636 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CPUTYPE')] = KCSubTypeElement('cputype', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
637 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RESPONSIBLE_PID')] = KCSubTypeElement('responsible_pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
638 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_DIRTY_FLAGS')] = KCSubTypeElement('dirty_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
639 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CRASHED_THREADID')] = KCSubTypeElement('crashed_threadid', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
640
641 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_STATUS')] = KCSubTypeElement('p_status', KCSUBTYPE_TYPE.KC_ST_UINT8, 1, 0, 0)
642
643 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID'),
644 ( KCSubTypeElement('p_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
645 KCSubTypeElement.FromBasicCtype('p_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
646 KCSubTypeElement.FromBasicCtype('p_puniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
647 ),
648 'proc_uniqidentifierinfo')
649
650 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_EXCEPTION_CODES')] = KCSubTypeElement('TASK_CRASHINFO_EXCEPTION_CODES', KCSUBTYPE_TYPE.KC_ST_INT64,
651 KCSubTypeElement.GetSizeForArray(2,8), 0, 1)
652
653 KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO'),
654 (
655 KCSubTypeElement('ri_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
656 KCSubTypeElement.FromBasicCtype('ri_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
657 KCSubTypeElement.FromBasicCtype('ri_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
658 KCSubTypeElement.FromBasicCtype('ri_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
659 KCSubTypeElement.FromBasicCtype('ri_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
660 KCSubTypeElement.FromBasicCtype('ri_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
661 KCSubTypeElement.FromBasicCtype('ri_wired_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
662 KCSubTypeElement.FromBasicCtype('ri_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
663 KCSubTypeElement.FromBasicCtype('ri_phys_footprint', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
664 KCSubTypeElement.FromBasicCtype('ri_proc_start_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 80),
665 KCSubTypeElement.FromBasicCtype('ri_proc_exit_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 88),
666 KCSubTypeElement.FromBasicCtype('ri_child_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 96),
667 KCSubTypeElement.FromBasicCtype('ri_child_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 104),
668 KCSubTypeElement.FromBasicCtype('ri_child_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 112),
669 KCSubTypeElement.FromBasicCtype('ri_child_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 120),
670 KCSubTypeElement.FromBasicCtype('ri_child_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 128),
671 KCSubTypeElement.FromBasicCtype('ri_child_elapsed_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 136),
672 KCSubTypeElement.FromBasicCtype('ri_diskio_bytesread', KCSUBTYPE_TYPE.KC_ST_UINT64, 144),
673 KCSubTypeElement.FromBasicCtype('ri_diskio_byteswritten', KCSUBTYPE_TYPE.KC_ST_UINT64, 152),
674 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_default', KCSUBTYPE_TYPE.KC_ST_UINT64, 160),
675 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_maintenance', KCSUBTYPE_TYPE.KC_ST_UINT64, 168),
676 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_background', KCSUBTYPE_TYPE.KC_ST_UINT64, 176),
677 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_utility', KCSUBTYPE_TYPE.KC_ST_UINT64, 184),
678 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_legacy', KCSUBTYPE_TYPE.KC_ST_UINT64, 192),
679 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_initiated', KCSUBTYPE_TYPE.KC_ST_UINT64, 200),
680 KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_interactive', KCSUBTYPE_TYPE.KC_ST_UINT64, 208),
681 KCSubTypeElement.FromBasicCtype('ri_billed_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 216),
682 KCSubTypeElement.FromBasicCtype('ri_serviced_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 224)
683 ),
684 'rusage_info_v3')
685
686 def GetSecondsFromMATime(mat, tb):
687 return (float(mat) * tb['numerator']) / tb['denominator']
688
689 def FindLibraryForAddress(liblist, address):
690 current_lib = None
691 for l in liblist:
692 if address >= l[1]:
693 current_lib = l
694 return current_lib
695
696 def FindIndexOfLibInCatalog(catalog, lib):
697 index = None
698 i = 0
699 for l in catalog:
700 if l[0] == lib[0] and l[1] == lib[1]:
701 index = i
702 break
703 i += 1
704
705 if index is None:
706 catalog.append(lib)
707 index = len(catalog) - 1
708
709 return index
710
711 def GetOffsetOfAddressForLib(lib, address):
712 return (address - lib[1])
713
714 def GetSymbolInfoForFrame(catalog, liblist, address):
715 lib = FindLibraryForAddress(liblist, address)
716 if not lib:
717 lib = ["00000000000000000000000000000000",0,"A"]
718 offset = GetOffsetOfAddressForLib(lib, address)
719 index = FindIndexOfLibInCatalog(catalog, lib)
720 return [index, offset]
721
722 def GetStateDescription(s):
723 retval = []
724 TH_WAIT = 0x01
725 TH_SUSP = 0x02
726 TH_RUN = 0x04
727 TH_UNINT = 0x08
728 TH_TERMINATE = 0x10
729 TH_TERMINATE2 = 0x20
730 TH_IDLE = 0x80
731 if (s & TH_WAIT):
732 retval.append("TH_WAIT")
733 if (s & TH_SUSP):
734 retval.append("TH_SUSP")
735 if (s & TH_RUN):
736 retval.append("TH_RUN")
737 if (s & TH_UNINT):
738 retval.append("TH_UNINT")
739 if (s & TH_TERMINATE):
740 retval.append("TH_TERMINATE")
741 if (s & TH_TERMINATE2):
742 retval.append("TH_TERMINATE2")
743 if (s & TH_IDLE):
744 retval.append("TH_IDLE")
745 return retval
746
747 def SaveStackshotReport(j, outfile_name, dsc_uuid, dsc_libs_arr):
748 import time
749 from operator import itemgetter, attrgetter
750 ss = j.get('KCDATA_BUFFER_BEGIN_STACKSHOT')
751 if not ss:
752 print "No KCDATA_BUFFER_BEGIN_STACKSHOT object found. Skipping writing report."
753 return
754 timestamp = ss.get('usecs_since_epoch', int(time.time()))
755 timestamp = time.strftime("%Y-%m-%d %H:%M:%S %z",time.gmtime(timestamp))
756 os_version = ss.get('osversion', 'Unknown')
757 timebase = ss.get('timebase_info', {"denominator": 1, "numerator": 1})
758 dsc_common = [ss.get('shared_cache_dyld_info')['imageUUID'].strip('<>'),
759 ss.get('shared_cache_dyld_info')['loadAddress'],
760 "C"
761 ]
762
763 dsc_libs = []
764 if dsc_common[0].replace('-', '').lower() == dsc_uuid:
765 print "SUCCESS: Found Matching dyld shared cache uuid. Loading library load addresses from layout provided."
766 _load_addr = dsc_common[1]
767 #print _load_addr
768 #print dsc_libs_arr
769 for i in dsc_libs_arr:
770 _uuid = i[2].lower().replace('-','').strip()
771 _addr = int(i[0], 16) + _load_addr
772 dsc_libs.append([_uuid, _addr, "P"])
773 #print "adding ", [_uuid, _addr, "C"]
774
775 AllImageCatalog = []
776 obj = {}
777 obj["kernel"] = os_version
778 obj["date"] = timestamp
779 obj["reason"] = "kernel panic stackshot"
780 obj["incident"] = "ABCDEFGH-1234-56IJ-789K-0LMNOPQRSTUV"
781 obj["crashReporterKey"] = "12ab34cd45aabbccdd6712ab34cd45aabbccdd67"
782 obj["bootArgs"] = ss.get('bootargs','')
783 obj["frontmostPids"] = [0]
784 obj["exception"] = "0xDEADF157"
785 obj["processByPid"] = {}
786 processByPid = obj["processByPid"]
787 ssplist = ss.get('STACKSHOT_KCCONTAINER_TASK', {})
788 kern_load_info = []
789 if "0" in ssplist:
790 kl_infos = ssplist["0"].get("dyld_load_info", [])
791 for dlinfo in kl_infos:
792 kern_load_info.append([dlinfo['imageUUID'].strip('<>'), dlinfo['loadAddress'], "K"])
793 for pid,piddata in ssplist.iteritems():
794 processByPid[str(pid)] = {}
795 tsnap = processByPid[str(pid)]
796 pr_lib_dsc = dsc_common
797 if 'shared_cache_dyld_info' in tsnap:
798 pr_lib_dsc = [tsnap.get('shared_cache_dyld_info')['imageUUID'].strip('<>'),
799 tsnap.get('shared_cache_dyld_info')['loadAddress'],
800 "C"
801 ]
802
803 pr_libs = []
804 if len(dsc_libs) == 0:
805 pr_libs.append(pr_lib_dsc)
806 _lib_type = "P"
807 if int(pid) == 0:
808 _lib_type = "K"
809 pr_libs = []
810 else:
811 for dlinfo in piddata.get('dyld_load_info',[]):
812 pr_libs.append([dlinfo['imageUUID'].strip('<>'), dlinfo['loadAddress'], _lib_type])
813
814 pr_libs.extend(kern_load_info)
815 pr_libs.extend(dsc_libs)
816
817 pr_libs.sort(key=itemgetter(1))
818
819 tasksnap = piddata['task_snapshot_v2']
820 tsnap["pid"] = tasksnap["pid"]
821 tsnap["residentMemoryBytes"] = tasksnap["task_size"]
822 tsnap["timesDidThrottle"] = tasksnap["did_throttle"]
823 tsnap["systemTimeTask"] = GetSecondsFromMATime(tasksnap["system_time_in_terminated_threads"], timebase)
824 tsnap["pageIns"] = tasksnap["pageins"]
825 tsnap["pageFaults"] = tasksnap["faults"]
826 tsnap["userTimeTask"] = GetSecondsFromMATime(tasksnap["user_time_in_terminated_threads"], timebase)
827 tsnap["procname"] = tasksnap["p_comm"]
828 tsnap["copyOnWriteFaults"] = tasksnap["cow_faults"]
829 tsnap["timesThrottled"] = tasksnap["was_throttled"]
830 tsnap["threadById"] = {}
831 threadByID = tsnap["threadById"]
832 thlist = piddata.get('STACKSHOT_KCCONTAINER_THREAD', {})
833 for tid,thdata in thlist.iteritems():
834 threadByID[str(tid)] = {}
835 thsnap = threadByID[str(tid)]
836 threadsnap = thdata["thread_snapshot_v2"]
837 thsnap["userTime"] = GetSecondsFromMATime(threadsnap["user_time"], timebase)
838 thsnap["id"] = threadsnap["thread_id"]
839 thsnap["basePriority"] = threadsnap["base_priority"]
840 thsnap["systemTime"] = threadsnap["sys_time"]
841 thsnap["schedPriority"] = threadsnap["sched_priority"]
842 thsnap["state"] = GetStateDescription(threadsnap['state'])
843 thsnap["qosEffective"] = threadsnap["ts_eqos"]
844 thsnap["qosRequested"] = threadsnap["ts_rqos"]
845
846 if threadsnap['continuation']:
847 thsnap["continuation"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['continuation'])
848 if "kernel_stack_frames" in thdata:
849 kuserframes = []
850 for f in thdata["kernel_stack_frames"]:
851 kuserframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
852 thsnap["kernelFrames"] = kuserframes
853
854 if "user_stack_frames" in thdata:
855 uframes = []
856 for f in thdata["user_stack_frames"]:
857 uframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
858 thsnap["userFrames"] = uframes
859 if threadsnap['wait_event']:
860 thsnap["waitEvent"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['wait_event'])
861
862 obj['binaryImages'] = AllImageCatalog
863 fh = open(outfile_name, "w")
864 fh.write('{"bug_type":"288", "timestamp":"'+ timestamp +'", "os_version":"'+ os_version +'"}\n')
865 fh.write(json.dumps(obj, sort_keys=False, indent=2, separators=(',', ': ')))
866 fh.close()
867
868 ## Base utils for interacting with shell ##
869 def RunCommand(bash_cmd_string, get_stderr = True):
870 """
871 returns: (int,str) : exit_code and output_str
872 """
873 print "RUNNING: %s" % bash_cmd_string
874 cmd_args = shlex.split(bash_cmd_string)
875 output_str = ""
876 exit_code = 0
877 try:
878 if get_stderr:
879 output_str = subprocess.check_output(cmd_args, stderr=subprocess.STDOUT)
880 else:
881 output_str = subprocess.check_output(cmd_args, stderr=None)
882 except subprocess.CalledProcessError, e:
883 exit_code = e.returncode
884 finally:
885 return (exit_code, output_str)
886
887 def ProcessDyldSharedCacheFile(shared_cache_file_path, sdk_str=""):
888 """ returns (uuid, text_info) output from shared_cache_util.
889 In case of error None is returned and err message is printed to stdout.
890 """
891 if not os.path.exists(shared_cache_file_path):
892 print "File path: %s does not exists" % shared_cache_file_path
893 return None
894 if sdk_str:
895 sdk_str = ' -sdk "%s" ' % sdk_str
896 (c, so) = RunCommand("xcrun {} -find dyld_shared_cache_util".format(sdk_str))
897 if c:
898 print "Failed to find path to dyld_shared_cache_util. Exit code: %d , message: %s" % (c,so)
899 return None
900 dyld_shared_cache_util = so.strip()
901 (c, so) = RunCommand("{} -info {}".format(dyld_shared_cache_util, shared_cache_file_path))
902 if c:
903 print "Failed to get uuid info from %s" % shared_cache_file_path
904 print so
905 return None
906
907 uuid = so.splitlines()[0].split(": ")[-1].strip().replace("-","").lower()
908
909 (c, so) = RunCommand("{} -text_info {}".format(dyld_shared_cache_util, shared_cache_file_path))
910 if c:
911 print "Failed to get text_info from %s" % shared_cache_file_path
912 print so
913 return None
914
915 print "Found %s uuid: %s" % (shared_cache_file_path, uuid)
916 text_info = so
917
918 return (uuid, so)
919
920 parser = argparse.ArgumentParser(description="Decode a kcdata binary file.")
921 parser.add_argument("-l", "--listtypes", action="store_true", required=False, default=False,
922 help="List all known types",
923 dest="list_known_types")
924
925 parser.add_argument("-s", "--stackshot", required=False, default=False,
926 help="Generate a stackshot report file",
927 dest="stackshot_file")
928
929 parser.add_argument("-U", "--uuid", required=False, default="", help="UUID of dyld shared cache to be analysed and filled in libs of stackshot report", dest="uuid")
930 parser.add_argument("-L", "--layout", required=False, type=argparse.FileType("r"), help="Path to layout file for DyldSharedCache. You can generate one by doing \n\tbash$xcrun -sdk <sdk> dyld_shared_cache_util -text_info </path/to/dyld_shared_cache> ", dest="layout")
931 parser.add_argument("-S", "--sdk", required=False, default="", help="sdk property passed to xcrun command to find the required tools. Default is empty string.", dest="sdk")
932 parser.add_argument("-D", "--dyld_shared_cache", required=False, default="", help="Path to dyld_shared_cache built by B&I", dest="dsc")
933 parser.add_argument("kcdata_file", type=argparse.FileType('r'), help="Path to a kcdata binary file.")
934
935
936
937 if __name__ == '__main__':
938 args = parser.parse_args()
939
940 if args.list_known_types:
941 for (n, t) in KNOWN_TYPES_COLLECTION.items():
942 print "%d : %s " % (n, str(t))
943 sys.exit(1)
944
945 file_name = args.kcdata_file.name
946 master_objs = []
947 master_container = None
948 current_container = None
949 for i in kcdata_item_iterator(file_name):
950 #print "processed " + str(i)
951 o = KCObject.FromKCItem(i)
952 if o.IsContainerType():
953 o = KCContainerObject(i.i_type, i.i_data, i.i_flags)
954
955 if current_container is None:
956 master_objs.append(o)
957 current_container = o
958 master_container = o
959 else:
960 current_container.AddObject(o)
961
962 if o.IsContainerType():
963 master_objs.append(current_container)
964 current_container = o
965
966 if o.IsContainerEnd():
967 current_container = master_objs.pop()
968 str_data = "{" + master_container.GetJsonRepr() + "}"
969 try:
970 json_obj = json.loads(str_data)
971 dsc_uuid = None
972 dsc_libs_arr = []
973 libs_re = re.compile("^\s*(0x[a-fA-F0-9]+)\s->\s(0x[a-fA-F0-9]+)\s+<([a-fA-F0-9\-]+)>\s+.*$", re.MULTILINE)
974 if args.uuid and args.layout:
975 dsc_uuid = args.uuid.strip().replace("-",'').lower()
976 dsc_libs_arr = libs_re.findall(args.layout.read())
977
978 if args.dsc:
979 _ret = ProcessDyldSharedCacheFile(args.dsc, args.sdk)
980 if _ret:
981 dsc_uuid = _ret[0]
982 dsc_libs_arr = libs_re.findall(_ret[1])
983
984 if args.stackshot_file:
985 SaveStackshotReport(json_obj, args.stackshot_file, dsc_uuid, dsc_libs_arr)
986 else:
987 print json.dumps(json_obj, sort_keys=True, indent=4, separators=(',', ': '))
988
989 except Exception, e:
990 raise
991 print e
992 print "--------------------------------------------"*3
993 print str_data