xref: /xnu-8792.61.2/tools/lldbmacros/kcdata.py (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
1#!/usr/bin/env python3
2from __future__ import absolute_import, print_function, division
3import sys
4import struct
5import mmap
6import json
7import copy
8import re
9import base64
10import argparse
11import logging
12import contextlib
13import base64
14import zlib
15import six
16
17if six.PY3:
18    long = int
19else:
20    # can be removed once we move to Python3.1+
21    from future.utils.surrogateescape import register_surrogateescape
22    register_surrogateescape()
23
24class Globals(object):
25    pass
26G = Globals()
27G.accept_incomplete_data = False
28G.data_was_incomplete = False
29
30kcdata_type_def = {
31    'KCDATA_TYPE_INVALID':              0x0,
32    'KCDATA_TYPE_STRING_DESC':          0x1,
33    'KCDATA_TYPE_UINT32_DESC':          0x2,
34    'KCDATA_TYPE_UINT64_DESC':          0x3,
35    'KCDATA_TYPE_INT32_DESC':           0x4,
36    'KCDATA_TYPE_INT64_DESC':           0x5,
37    'KCDATA_TYPE_BINDATA_DESC':         0x6,
38    'KCDATA_TYPE_ARRAY':                0x11,
39    'KCDATA_TYPE_TYPEDEFINITION':       0x12,
40    'KCDATA_TYPE_CONTAINER_BEGIN':      0x13,
41    'KCDATA_TYPE_CONTAINER_END':        0x14,
42
43    'KCDATA_TYPE_ARRAY_PAD0':           0x20,
44    'KCDATA_TYPE_ARRAY_PAD1':           0x21,
45    'KCDATA_TYPE_ARRAY_PAD2':           0x22,
46    'KCDATA_TYPE_ARRAY_PAD3':           0x23,
47    'KCDATA_TYPE_ARRAY_PAD4':           0x24,
48    'KCDATA_TYPE_ARRAY_PAD5':           0x25,
49    'KCDATA_TYPE_ARRAY_PAD6':           0x26,
50    'KCDATA_TYPE_ARRAY_PAD7':           0x27,
51    'KCDATA_TYPE_ARRAY_PAD8':           0x28,
52    'KCDATA_TYPE_ARRAY_PAD9':           0x29,
53    'KCDATA_TYPE_ARRAY_PADa':           0x2a,
54    'KCDATA_TYPE_ARRAY_PADb':           0x2b,
55    'KCDATA_TYPE_ARRAY_PADc':           0x2c,
56    'KCDATA_TYPE_ARRAY_PADd':           0x2d,
57    'KCDATA_TYPE_ARRAY_PADe':           0x2e,
58    'KCDATA_TYPE_ARRAY_PADf':           0x2f,
59
60    'KCDATA_TYPE_LIBRARY_LOADINFO':     0x30,
61    'KCDATA_TYPE_LIBRARY_LOADINFO64':   0x31,
62    'KCDATA_TYPE_TIMEBASE':             0x32,
63    'KCDATA_TYPE_MACH_ABSOLUTE_TIME':   0x33,
64    'KCDATA_TYPE_TIMEVAL':              0x34,
65    'KCDATA_TYPE_USECS_SINCE_EPOCH':    0x35,
66    'KCDATA_TYPE_PID':                  0x36,
67    'KCDATA_TYPE_PROCNAME':             0x37,
68    'KCDATA_TYPE_NESTED_KCDATA':        0x38,
69    'KCDATA_TYPE_LIBRARY_AOTINFO':      0x39,
70
71    'STACKSHOT_KCCONTAINER_TASK':       0x903,
72    'STACKSHOT_KCCONTAINER_THREAD':     0x904,
73    'STACKSHOT_KCTYPE_DONATING_PIDS':   0x907,
74    'STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO': 0x908,
75    'STACKSHOT_KCTYPE_THREAD_NAME':     0x909,
76    'STACKSHOT_KCTYPE_KERN_STACKFRAME': 0x90A,
77    'STACKSHOT_KCTYPE_KERN_STACKFRAME64': 0x90B,
78    'STACKSHOT_KCTYPE_USER_STACKFRAME': 0x90C,
79    'STACKSHOT_KCTYPE_USER_STACKFRAME64': 0x90D,
80    'STACKSHOT_KCTYPE_BOOTARGS':        0x90E,
81    'STACKSHOT_KCTYPE_OSVERSION':       0x90F,
82    'STACKSHOT_KCTYPE_KERN_PAGE_SIZE':  0x910,
83    'STACKSHOT_KCTYPE_JETSAM_LEVEL':    0x911,
84    'STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP': 0x912,
85    'STACKSHOT_KCTYPE_KERN_STACKLR':  0x913,
86    'STACKSHOT_KCTYPE_KERN_STACKLR64':  0x914,
87    'STACKSHOT_KCTYPE_USER_STACKLR':  0x915,
88    'STACKSHOT_KCTYPE_USER_STACKLR64':  0x916,
89    'STACKSHOT_KCTYPE_NONRUNNABLE_TIDS':  0x917,
90    'STACKSHOT_KCTYPE_NONRUNNABLE_TASKS':  0x918,
91    'STACKSHOT_KCTYPE_CPU_TIMES': 0x919,
92    'STACKSHOT_KCTYPE_STACKSHOT_DURATION': 0x91a,
93    'STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS': 0x91b,
94    'STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO': 0x91c,
95    'STACKSHOT_KCTYPE_THREAD_WAITINFO' : 0x91d,
96    'STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT' : 0x91e,
97    'STACKSHOT_KCTYPE_THREAD_GROUP' : 0x91f,
98    'STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT' : 0x920,
99    'STACKSHOT_KCTYPE_JETSAM_COALITION' : 0x921,
100    'STACKSHOT_KCTYPE_THREAD_POLICY_VERSION': 0x922,
101    'STACKSHOT_KCTYPE_INSTRS_CYCLES' : 0x923,
102    'STACKSHOT_KCTYPE_USER_STACKTOP' : 0x924,
103    'STACKSHOT_KCTYPE_ASID' : 0x925,
104    'STACKSHOT_KCTYPE_PAGE_TABLES' : 0x926,
105    'STACKSHOT_KCTYPE_SYS_SHAREDCACHE_LAYOUT' : 0x927,
106    'STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL' : 0x928,
107    'STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO' : 0x929,
108    'STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE' : 0x92a,
109    'STACKSHOT_KCTYPE_LATENCY_INFO' : 0x92b,
110    'STACKSHOT_KCTYPE_LATENCY_INFO_TASK' : 0x92c,
111    'STACKSHOT_KCTYPE_LATENCY_INFO_THREAD' : 0x92d,
112    'STACKSHOT_KCTYPE_LOADINFO64_TEXT_EXEC' : 0x92e,
113    'STACKSHOT_KCTYPE_AOTCACHE_LOADINFO' : 0x92f,
114    'STACKSHOT_KCTYPE_TRANSITIONING_TASK_SNAPSHOT' : 0x930,
115    'STACKSHOT_KCCONTAINER_TRANSITIONING_TASK' : 0x931,
116    'STACKSHOT_KCTYPE_USER_ASYNC_START_INDEX' : 0x932,
117    'STACKSHOT_KCTYPE_USER_ASYNC_STACKLR64' : 0x933,
118    'STACKSHOT_KCCONTAINER_PORTLABEL' : 0x934,
119    'STACKSHOT_KCTYPE_PORTLABEL' : 0x935,
120    'STACKSHOT_KCTYPE_PORTLABEL_NAME' : 0x936,
121    'STACKSHOT_KCTYPE_DYLD_COMPACTINFO' : 0x937,
122    'STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT': 0x940,
123    'STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT': 0x941,
124    'STACKSHOT_KCCONTAINER_SHAREDCACHE' : 0x942,
125    'STACKSHOT_KCTYPE_SHAREDCACHE_INFO' : 0x943,
126    'STACKSHOT_KCTYPE_SHAREDCACHE_AOTINFO' : 0x944,
127    'STACKSHOT_KCTYPE_SHAREDCACHE_ID' : 0x945,
128
129    'KCDATA_TYPE_BUFFER_END':      0xF19158ED,
130
131    'TASK_CRASHINFO_EXTMODINFO':           0x801,
132    'TASK_CRASHINFO_BSDINFOWITHUNIQID':    0x802,
133    'TASK_CRASHINFO_TASKDYLD_INFO':        0x803,
134    'TASK_CRASHINFO_UUID':                 0x804,
135    'TASK_CRASHINFO_PID':                  0x805,
136    'TASK_CRASHINFO_PPID':                 0x806,
137
138    # Don't want anyone using this.  It's struct rusage from whatever machine generated the data
139    #'TASK_CRASHINFO_RUSAGE':               0x807,
140    'Type_0x807':               0x807,
141
142    'TASK_CRASHINFO_RUSAGE_INFO':          0x808,
143    'TASK_CRASHINFO_PROC_NAME':            0x809,
144    'TASK_CRASHINFO_PROC_STARTTIME':       0x80B,
145    'TASK_CRASHINFO_USERSTACK':            0x80C,
146    'TASK_CRASHINFO_ARGSLEN':              0x80D,
147    'TASK_CRASHINFO_EXCEPTION_CODES':      0x80E,
148    'TASK_CRASHINFO_PROC_PATH':            0x80F,
149    'TASK_CRASHINFO_PROC_CSFLAGS':         0x810,
150    'TASK_CRASHINFO_PROC_STATUS':          0x811,
151    'TASK_CRASHINFO_UID':                  0x812,
152    'TASK_CRASHINFO_GID':                  0x813,
153    'TASK_CRASHINFO_PROC_ARGC':            0x814,
154    'TASK_CRASHINFO_PROC_FLAGS':           0x815,
155    'TASK_CRASHINFO_CPUTYPE':              0x816,
156    'TASK_CRASHINFO_WORKQUEUEINFO':        0x817,
157    'TASK_CRASHINFO_RESPONSIBLE_PID':      0x818,
158    'TASK_CRASHINFO_DIRTY_FLAGS':          0x819,
159    'TASK_CRASHINFO_CRASHED_THREADID':     0x81A,
160    'TASK_CRASHINFO_COALITION_ID':         0x81B,
161    'EXIT_REASON_SNAPSHOT':                0x1001,
162    'EXIT_REASON_USER_DESC':               0x1002,
163    'EXIT_REASON_USER_PAYLOAD':            0x1003,
164    'EXIT_REASON_CODESIGNING_INFO':        0x1004,
165    'EXIT_REASON_WORKLOOP_ID':             0x1005,
166    'EXIT_REASON_DISPATCH_QUEUE_NO':       0x1006,
167    'KCDATA_BUFFER_BEGIN_CRASHINFO':       0xDEADF157,
168    'KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT': 0xDE17A59A,
169    'KCDATA_BUFFER_BEGIN_STACKSHOT':       0x59a25807,
170    'KCDATA_BUFFER_BEGIN_COMPRESSED':      0x434f4d50,
171    'KCDATA_BUFFER_BEGIN_OS_REASON':       0x53A20900,
172    'KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG':  0x1E21C09F
173}
174kcdata_type_def_rev = dict((v, k) for k, v in iter(kcdata_type_def.items()))
175
176KNOWN_TYPES_COLLECTION = {}
177
178KNOWN_TOPLEVEL_CONTAINER_TYPES = ()
179
180def enum(**args):
181    return type('enum', (), args)
182
183#
184# Decode bytes as UTF-8, using surrogateescape if there are invalid UTF-8
185# sequences; see PEP-383
186#
187def BytesToString(b):
188    if isinstance(b, six.string_types):
189        return b
190    return b.decode('utf-8', errors="surrogateescape")
191
192# important keys
193SC_SLID_FIRSTMAPPING_KEY = 'sharedCacheSlidFirstMapping'
194
195# important builtin types
196KCSUBTYPE_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)
197
198
199LEGAL_OLD_STYLE_ARRAY_TYPE_NAMES = ['KCDATA_TYPE_LIBRARY_LOADINFO',
200                                    'KCDATA_TYPE_LIBRARY_LOADINFO64',
201                                    'STACKSHOT_KCTYPE_KERN_STACKFRAME',
202                                    'STACKSHOT_KCTYPE_USER_STACKFRAME',
203                                    'STACKSHOT_KCTYPE_KERN_STACKFRAME64',
204                                    'STACKSHOT_KCTYPE_USER_STACKFRAME64',
205                                    'STACKSHOT_KCTYPE_DONATING_PIDS',
206                                    'STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT']
207
208KCDATA_FLAGS_STRUCT_PADDING_MASK = 0xf
209KCDATA_FLAGS_STRUCT_HAS_PADDING = 0x80
210
211class KCSubTypeElement(object):
212    """convert kcdata_subtype_descriptor to """
213    _unpack_formats = (None, 'c', 'b', 'B', 'h', 'H', 'i', 'I', 'q', 'Q')
214    _ctypes = ('Unknown', 'char', 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', 'uint32_t', 'int64_t', 'uint64_t')
215
216    def __init__(self, st_name, st_type, st_size, st_offset=0, st_flag=0, custom_repr=None):
217        self.name = st_name
218        self.offset = st_offset
219        self.type_id = st_type
220        if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
221            raise ValueError("Invalid type passed %d" % st_type)
222        self.unpack_fmt = KCSubTypeElement._unpack_formats[self.type_id]
223        self.size = st_size
224        self.totalsize = st_size
225        self.count = 1
226        self.is_array_type = False
227        self.custom_JsonRepr = custom_repr
228        if (st_flag & 0x1) == 0x1:
229            self.is_array_type = True
230            self.size = st_size & 0xffff
231            self.count = (st_size >> 16) & 0xffff
232            self.totalsize = self.size * self.count
233
234    @staticmethod
235    def GetSizeForArray(el_count, el_size):
236        return ((el_count & 0xffff) << 16) | (el_size & 0xffff)
237
238    @staticmethod
239    def FromBinaryTypeData(byte_data):
240        (st_flag, st_type, st_offset, st_size, st_name) = struct.unpack_from('=BBHI32s', byte_data)
241        st_name = BytesToString(st_name).rstrip('\0')
242        return KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag)
243
244    @staticmethod
245    def FromBasicCtype(st_name, st_type, st_offset=0, legacy_size=None):
246        if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
247            raise ValueError("Invalid type passed %d" % st_type)
248        st_size = struct.calcsize(KCSubTypeElement._unpack_formats[st_type])
249        st_flag = 0
250        retval = KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag, KCSubTypeElement._get_naked_element_value)
251        if legacy_size:
252            retval.legacy_size = legacy_size
253        return retval
254
255    @staticmethod
256    def FromKCSubTypeElement(other, name_override=''):
257        _copy = copy.copy(other)
258        if name_override:
259            _copy.name = name_override
260        return copy
261
262    def GetName(self):
263        return self.name
264
265    def GetTotalSize(self):
266        return self.totalsize
267
268    def GetValueAsString(self, base_data, array_pos=0):
269        v = self.GetValue(base_data, array_pos)
270        if isinstance(v, bytes):
271            return BytesToString(v)
272        return str(v)
273
274    def GetValue(self, base_data, array_pos=0):
275        return struct.unpack_from(self.unpack_fmt, base_data[self.offset + (array_pos * self.size):])[0]
276
277    @staticmethod
278    def _get_naked_element_value(elementValue, elementName):
279        return json.dumps(elementValue)
280
281    def __str__(self):
282        if self.is_array_type:
283            return '[%d,%d] %s  %s[%d];' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name, self.count)
284        return '[%d,%d] %s  %s;' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name)
285
286    def __repr__(self):
287        return str(self)
288
289    def GetCTypeDesc(self):
290        return KCSubTypeElement._ctypes[self.type_id]
291
292    def GetStringRepr(self, base_data):
293        if not self.is_array_type:
294            return self.GetValueAsString(base_data)
295        if self.type_id == KCSUBTYPE_TYPE.KC_ST_CHAR:
296            str_len = self.count
297            if len(base_data) < str_len:
298                str_len = len(base_data)
299            str_arr = []
300            for i in range(str_len):
301                _v = self.GetValue(base_data, i)
302                if ord(_v) == 0:
303                    break
304                str_arr.append(self.GetValueAsString(base_data, i))
305            return json.dumps(''.join(str_arr))
306
307        count = self.count
308        if count > len(base_data)//self.size:
309            count = len(base_data)//self.size
310
311        o = '[' + ','.join([self.GetValueAsString(base_data, i) for i in range(count)]) + ']'
312
313        return o
314
315    def GetJsonRepr(self, base_data, flags=0):
316        if (flags & (KCDATA_FLAGS_STRUCT_HAS_PADDING | KCDATA_FLAGS_STRUCT_PADDING_MASK)) != 0:
317            padding = (flags & KCDATA_FLAGS_STRUCT_PADDING_MASK)
318            if padding:
319                base_data = base_data[:-padding]
320        if self.custom_JsonRepr:
321            if self.is_array_type:
322                e_data = [self.GetValue(base_data, i) for i in range(self.count)]
323            else:
324                e_data = self.GetValue(base_data)
325            return self.custom_JsonRepr(e_data, self.name)
326        return self.GetStringRepr(base_data)
327
328    def sizeof(self):
329        return self.totalsize
330
331    def ShouldSkip(self, data):
332        return len(data) < self.offset + self.totalsize
333
334    def ShouldMerge(self):
335        return False
336
337
338class KCTypeDescription(object):
339    def __init__(self, t_type_id, t_elements=[], t_name='anon', custom_repr=None, legacy_size=None, merge=False, naked=False):
340        self.type_id = t_type_id
341        self.elements = t_elements
342        self.name = t_name
343        self.totalsize = 0
344        self.custom_JsonRepr = custom_repr
345        if legacy_size:
346            self.legacy_size = legacy_size
347        self.merge = merge
348        self.naked = naked
349        for e in self.elements:
350            self.totalsize += e.GetTotalSize()
351
352    def ValidateData(self, base_data):
353        if len(base_data) >= self.totalsize:
354            return True
355        return False
356
357    def GetTypeID(self):
358        return self.type_id
359
360    def GetName(self):
361        return self.name
362
363    def __str__(self):
364        o = '%s {\n\t' % self.name + "\n\t".join([str(e) for e in self.elements]) + '\n};'
365        return o
366
367    @staticmethod
368    def FromKCTypeDescription(other, t_type_id, t_name):
369        retval = KCTypeDescription(t_type_id, other.elements, t_name, other.custom_JsonRepr,
370                                   legacy_size=getattr(other, 'legacy_size', None))
371        return retval
372
373    def ShouldMerge(self):
374        return self.merge
375
376    def GetJsonRepr(self, base_data, flags):
377        if (flags & (KCDATA_FLAGS_STRUCT_HAS_PADDING | KCDATA_FLAGS_STRUCT_PADDING_MASK)) != 0:
378            padding = (flags & KCDATA_FLAGS_STRUCT_PADDING_MASK)
379            if padding:
380                base_data = base_data[:-padding]
381        elif hasattr(self, 'legacy_size') and len(base_data) == self.legacy_size + ((-self.legacy_size) & 0xf):
382            base_data = base_data[:self.legacy_size]
383        if self.custom_JsonRepr:
384            return self.custom_JsonRepr([e.GetValue(base_data) for e in self.elements])
385        if self.naked:
386            o = ", ".join([e.GetJsonRepr(base_data) for e in self.elements if not e.ShouldSkip(base_data)])
387        else:
388            o = ", ".join(['"%s": %s' % (e.GetName(), e.GetJsonRepr(base_data)) for e in self.elements if not e.ShouldSkip(base_data)])
389        if not self.merge:
390            o = '{' + o + '}'
391        return o
392
393    def sizeof(self):
394        return max(st.totalsize + st.offset for st in self.elements)
395
396
397def GetTypeNameForKey(k):
398    retval = "0x%x" % k
399    if k in KNOWN_TYPES_COLLECTION:
400        retval = KNOWN_TYPES_COLLECTION[k].GetName()
401    elif k in kcdata_type_def_rev:
402        retval = kcdata_type_def_rev[k]
403    return retval
404
405
406def GetTypeForName(n):
407    ret = 0
408    if n in kcdata_type_def:
409        ret = kcdata_type_def[n]
410    return ret
411
412
413LEGAL_OLD_STYLE_ARRAY_TYPES = list(map(GetTypeForName, LEGAL_OLD_STYLE_ARRAY_TYPE_NAMES))
414
415kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_STACKSHOT')] = 'kcdata_stackshot'
416kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT')] = 'kcdata_delta_stackshot'
417kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_CRASHINFO')] = 'kcdata_crashinfo'
418kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_OS_REASON')] = 'kcdata_reason'
419kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_TASK')] = 'task_snapshots'
420kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_TRANSITIONING_TASK')] = 'transitioning_task_snapshots'
421kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_THREAD')] = 'thread_snapshots'
422kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_PORTLABEL')] = 'portlabels'
423kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_SHAREDCACHE')] = 'shared_caches'
424kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG')] = 'xnupost_testconfig'
425
426class Indent(object):
427    def __init__(self):
428        self.n = 0
429    def __call__(self, end=False):
430        if end:
431            return " " * (self.n-4)
432        else:
433            return " " * self.n
434    @contextlib.contextmanager
435    def indent(self):
436        self.n += 4
437        try:
438            yield
439        finally:
440            self.n -= 4
441
442INDENT = Indent()
443
444class KCObject(object):
445
446    def __init__(self, type_code, data, offset, flags=0):
447
448        self.i_type = type_code
449        self.i_data = data
450        self.offset = offset
451        self.i_size = len(data)
452        self.i_flags = flags
453        self.obj_collection = []
454        self.obj = {}
455        self.is_container_type = False
456        self.is_array_type = False
457        self.is_naked_type = False
458        self.nested_kcdata = None
459        self.i_name = GetTypeNameForKey(type_code)
460
461        self.ParseData()
462
463        if self.i_type == GetTypeForName('KCDATA_TYPE_CONTAINER_BEGIN'):
464            self.__class__ = KCContainerObject
465        elif self.i_type == GetTypeForName('KCDATA_BUFFER_BEGIN_COMPRESSED'):
466            self.__class__ = KCCompressedBufferObject
467        elif self.i_type in KNOWN_TOPLEVEL_CONTAINER_TYPES:
468            self.__class__ = KCBufferObject
469
470        self.InitAfterParse()
471
472    def __str__(self):
473        return "<KCObject at 0x%x>" % self.offset
474
475    def InitAfterParse(self):
476        pass
477
478    @staticmethod
479    def FromKCItem(kcitem):
480        return KCObject(kcitem.i_type, kcitem.i_data, kcitem.i_offset, kcitem.i_flags)
481
482    def IsContainerEnd(self):
483        return self.i_type == GetTypeForName('KCDATA_TYPE_CONTAINER_END')
484
485    def IsBufferEnd(self):
486        return self.i_type == GetTypeForName('KCDATA_TYPE_BUFFER_END')
487
488    def IsArray(self):
489        return self.is_array_type
490
491    def ShouldMerge(self):
492        if self.nested_kcdata:
493            return True
494        elif not self.is_array_type and self.i_type in KNOWN_TYPES_COLLECTION:
495            return KNOWN_TYPES_COLLECTION[self.i_type].ShouldMerge()
496        else:
497            return False
498
499    def GetJsonRepr(self):
500        if self.is_array_type:
501            return '[' + ', '.join([i.GetJsonRepr() for i in self.obj_collection]) + ']'
502        if self.i_type in KNOWN_TYPES_COLLECTION:
503            return KNOWN_TYPES_COLLECTION[self.i_type].GetJsonRepr(self.i_data, self.i_flags)
504        if self.is_naked_type:
505            return json.dumps(self.obj)
506        if self.nested_kcdata:
507            return self.nested_kcdata.GetJsonRepr()
508
509        raise NotImplementedError("Broken GetJsonRepr implementation")
510
511    def ParseData(self):
512
513
514        if self.i_type == GetTypeForName('KCDATA_TYPE_CONTAINER_BEGIN'):
515            self.obj['uniqID'] = self.i_flags
516            self.i_name = str(self.obj['uniqID'])
517            self.obj['typeID'] = struct.unpack_from('I', self.i_data)[0]
518            logging.info("0x%08x: %sCONTAINER: %s(%x)" % (self.offset, INDENT(), GetTypeNameForKey(self.obj['typeID']), self.i_flags))
519
520        elif self.i_type in (KNOWN_TOPLEVEL_CONTAINER_TYPES):
521            self.obj['uniqID'] = self.i_name
522            self.obj['typeID'] = self.i_type
523            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
524
525        elif self.i_type == GetTypeForName('KCDATA_TYPE_CONTAINER_END'):
526            self.obj['uniqID'] = self.i_flags
527            logging.info("0x%08x: %sEND" % (self.offset, INDENT(end=True)))
528
529        elif self.i_type == GetTypeForName('KCDATA_TYPE_BUFFER_END'):
530            self.obj = ''
531            logging.info("0x%08x: %sEND_BUFFER" % (self.offset, INDENT(end=True)))
532
533        elif self.i_type == GetTypeForName('KCDATA_TYPE_UINT32_DESC'):
534            self.is_naked_type = True
535            u_d = struct.unpack_from('32sI', self.i_data)
536            self.i_name = BytesToString(u_d[0]).rstrip('\0')
537            self.obj = u_d[1]
538            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
539
540        elif self.i_type == GetTypeForName('KCDATA_TYPE_UINT64_DESC'):
541            self.is_naked_type = True
542            u_d = struct.unpack_from('32sQ', self.i_data)
543            self.i_name = BytesToString(u_d[0]).rstrip('\0')
544            self.obj = u_d[1]
545            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
546
547        elif self.i_type == GetTypeForName('KCDATA_TYPE_TYPEDEFINITION'):
548            self.is_naked_type = True
549            u_d = struct.unpack_from('II32s', self.i_data)
550            self.obj['name'] = BytesToString(u_d[2]).split(chr(0))[0]
551            self.i_name = "typedef[%s]" % self.obj['name']
552            self.obj['typeID'] = u_d[0]
553            self.obj['numOfFields'] = u_d[1]
554            element_arr = []
555            for i in range(u_d[1]):
556                e = KCSubTypeElement.FromBinaryTypeData(self.i_data[40+(i*40):])
557                element_arr.append(e)
558            type_desc = KCTypeDescription(u_d[0], element_arr, self.obj['name'])
559            self.obj['fields'] = [str(e) for e in element_arr]
560            KNOWN_TYPES_COLLECTION[type_desc.GetTypeID()] = type_desc
561            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
562
563        elif self.i_type == GetTypeForName('KCDATA_TYPE_ARRAY'):
564            self.is_array_type = True
565            e_t = (self.i_flags >> 32) & 0xffffffff
566            if e_t not in LEGAL_OLD_STYLE_ARRAY_TYPES:
567                raise Exception("illegal old-style array type: %s (0x%x)" % (GetTypeNameForKey(e_t), e_t))
568            e_c = self.i_flags & 0xffffffff
569            e_s = KNOWN_TYPES_COLLECTION[e_t].legacy_size
570            if e_s * e_c > self.i_size:
571                raise Exception("array too small for its count")
572            self.obj['typeID'] = e_t
573            self.i_name = GetTypeNameForKey(e_t)
574            self.i_type = e_t
575            self.obj['numOfElements'] = e_c
576            self.obj['sizeOfElement'] = e_s
577            logging.info("0x%08x: %sARRAY: %s" % (self.offset, INDENT(), self.i_name))
578            #populate the array here by recursive creation of KCObject
579            with INDENT.indent():
580                for _i in range(e_c):
581                    _o = KCObject(e_t, self.i_data[(_i * e_s):(_i * e_s) + e_s], self.offset + _i*e_s)
582                    self.obj_collection.append(_o)
583
584        elif self.i_type >= GetTypeForName('KCDATA_TYPE_ARRAY_PAD0') and self.i_type <= GetTypeForName('KCDATA_TYPE_ARRAY_PADf'):
585            self.is_array_type = True
586            e_t = (self.i_flags >> 32) & 0xffffffff
587            e_c = self.i_flags & 0xffffffff
588            e_s = (self.i_size - (self.i_type & 0xf)) // e_c if e_c != 0 else None
589            self.obj['typeID'] = e_t
590            self.i_name = GetTypeNameForKey(e_t)
591            self.i_type = e_t
592            self.obj['numOfElements'] = e_c
593            self.obj['sizeOfElement'] = e_s
594            logging.info("0x%08x: %sARRAY: %s" % (self.offset, INDENT(), self.i_name))
595            #populate the array here by recursive creation of KCObject
596            with INDENT.indent():
597                for _i in range(e_c):
598                    _o = KCObject(e_t, self.i_data[(_i * e_s):(_i * e_s) + e_s], self.offset + _i*e_s)
599                    self.obj_collection.append(_o)
600
601        elif self.i_type == GetTypeForName('KCDATA_TYPE_NESTED_KCDATA'):
602            logging.info("0x%08x: %sNESTED_KCDATA" % (self.offset, INDENT()))
603            with INDENT.indent():
604                nested_iterator = kcdata_item_iterator(self.i_data[:self.i_size])
605                nested_buffer = KCObject.FromKCItem(six.next(nested_iterator))
606                if not isinstance(nested_buffer, KCBufferObject):
607                    raise Exception("nested buffer isn't a KCBufferObject")
608                nested_buffer.ReadItems(nested_iterator)
609            self.nested_kcdata = nested_buffer
610
611        elif self.i_type in KNOWN_TYPES_COLLECTION:
612            self.i_name = KNOWN_TYPES_COLLECTION[self.i_type].GetName()
613            self.is_naked_type = True
614            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
615        else:
616            self.is_naked_type = True
617            #self.obj = "data of len %d" % len(self.i_data)
618            #self.obj = ''.join(["%x" % ki for ki in struct.unpack('%dB' % len(self.i_data), self.i_data)])
619            if isinstance(self.i_data, six.string_types):
620                self.obj = list(map(ord, BytesToString(self.i_data)))
621            else:
622                self.obj = [i for i in self.i_data]
623            logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name))
624
625
626class KCContainerObject(KCObject):
627    def __init__(self, *args, **kwargs):
628        assert False
629
630    def InitAfterParse(self):
631        self.obj_container_dict = {}
632        self.obj_nested_objs = {}
633
634    def ShouldMerge(self):
635        return True
636
637    def GetJsonRepr(self):
638        # o = '"%s"' % self.obj['uniqID'] + ' : { "typeID" : %d ,' % self.obj['typeID']
639        o = '"%s"' % self.obj['uniqID'] + ' : { '
640        for (k, v) in self.obj_container_dict.items():
641            if v.ShouldMerge():
642                o += v.GetJsonRepr() + ","
643            else:
644                o += ' "%s" : ' % k + v.GetJsonRepr() + ","
645
646        for (k, v) in self.obj_nested_objs.items():
647            o += '"%s" : {' % k + ",".join([vi.GetJsonRepr() for vi in v.values()]) + "} ,"
648
649        o = o.rstrip(',') + "}"
650
651        return o
652
653    def AddObject(self, kco):
654        assert not kco.IsContainerEnd()
655        if isinstance(kco, KCContainerObject):
656            type_name = GetTypeNameForKey(kco.obj['typeID'])
657            if type_name not in self.obj_nested_objs:
658                self.obj_nested_objs[type_name] = {}
659            self.obj_nested_objs[type_name][kco.i_name] = kco
660            return
661        if kco.i_name in self.obj_container_dict:
662            if kco.IsArray() and self.obj_container_dict[kco.i_name].IsArray():
663                self.obj_container_dict[kco.i_name].obj_collection.extend( kco.obj_collection )
664        else:
665            self.obj_container_dict[kco.i_name] = kco
666
667    def IsEndMarker(self, o):
668        if not o.IsContainerEnd():
669            return False
670        if o.i_flags != self.i_flags:
671            raise Exception("container end marker doesn't match")
672        return True
673
674    no_end_message = "could not find container end marker"
675
676    def ReadItems(self, iterator):
677        found_end = False
678        with INDENT.indent():
679            for i in iterator:
680                o = KCObject.FromKCItem(i)
681                if self.IsEndMarker(o):
682                    found_end = True
683                    break
684                if o.IsBufferEnd():
685                    break
686                if isinstance(o, KCContainerObject):
687                    o.ReadItems(iterator)
688                self.AddObject(o)
689        if not found_end:
690            if G.accept_incomplete_data:
691                if not G.data_was_incomplete:
692                    print("kcdata.py WARNING: data is incomplete!", file=sys.stderr)
693                    G.data_was_incomplete = True
694            else:
695                raise Exception(self.no_end_message)
696
697
698
699class KCBufferObject(KCContainerObject):
700
701    def IsEndMarker(self,o):
702        if o.IsContainerEnd():
703            raise Exception("container end marker at the toplevel")
704        return o.IsBufferEnd()
705
706    no_end_message = "could not find buffer end marker"
707
708class KCCompressedBufferObject(KCContainerObject):
709
710    def ReadItems(self, iterator):
711        self.header = dict()
712        with INDENT.indent():
713            for i in iterator:
714                o = KCObject.FromKCItem(i)
715                if self.IsEndMarker(o):
716                    self.compressed_type = o.i_type
717                    self.blob_start = o.offset + 16
718                    break
719                o.ParseData()
720                self.header[o.i_name] = o.obj
721
722    def IsEndMarker(self, o):
723        return o.i_type in KNOWN_TOPLEVEL_CONTAINER_TYPES
724
725    def GetCompressedBlob(self, data):
726        if self.header['kcd_c_type'] != 1:
727            raise NotImplementedError
728        blob = data[self.blob_start:self.blob_start+self.header['kcd_c_totalout']]
729        if len(blob) != self.header['kcd_c_totalout']:
730            raise ValueError
731        return blob
732
733    def Decompress(self, data):
734        start_marker = struct.pack('<IIII', self.compressed_type, 0, 0, 0)
735        end_marker = struct.pack('<IIII', GetTypeForName('KCDATA_TYPE_BUFFER_END'), 0, 0, 0)
736        decompressed = zlib.decompress(self.GetCompressedBlob(data))
737        if len(decompressed) != self.header['kcd_c_totalin']:
738            raise ValueError("length of decompressed: %d vs expected %d" % (len(decompressed), self.header['kcd_c_totalin']))
739        alignbytes = b'\x00' * (-len(decompressed) % 16)
740        return start_marker + decompressed + alignbytes + end_marker
741
742
743class KCData_item:
744    """ a basic kcdata_item type object.
745    """
746    header_size = 16  # (uint32_t + uint32_t + uint64_t)
747
748    def __init__(self, item_type, item_size, item_flags, item_data):
749        self.i_type = item_type
750        self.i_size = item_size
751        self.i_flags = item_flags
752        self.i_data = item_data
753        self.i_offset = None
754
755    def __init__(self, barray, pos=0):
756        """ create an object by parsing data from bytes array
757            returns : obj - if data is readable
758                      raises ValueError if something is not ok.
759        """
760        self.i_type = struct.unpack('I', barray[pos:pos+4])[0]     # int.from_bytes(barray[pos:pos+4])
761        self.i_size = struct.unpack('I', barray[pos+4:pos+8])[0]   # int.from_bytes(barray[pos+4:pos+8])
762        self.i_flags = struct.unpack('Q', barray[pos+8:pos+16])[0]  # int.from_bytes(barray[pos+8:pos+16])
763        self.i_data = barray[pos+16: (pos + 16 + self.i_size)]
764        self.i_offset = pos
765
766    def __len__(self):
767        return self.i_size + KCData_item.header_size
768
769    def GetHeaderDescription(self):
770        outs = "type: 0x%x size: 0x%x flags: 0x%x  (%s)" % (self.i_type, self.i_size, self.i_flags, GetTypeNameForKey(self.i_type))
771        if not self.i_offset is None:
772            outs = "pos: 0x%x" % self.i_offset + outs
773        return outs
774
775    def __str__(self):
776        return self.GetHeaderDescription()
777
778def kcdata_item_iterator(data):
779    file_len = len(data)
780    curpos = 0
781    while curpos < file_len:
782        item = KCData_item(data, curpos)
783        yield item
784        curpos += len(item)
785
786def _get_data_element(elementValues):
787    return json.dumps(elementValues[-1])
788
789KNOWN_TOPLEVEL_CONTAINER_TYPES = list(map(GetTypeForName, ('KCDATA_BUFFER_BEGIN_COMPRESSED', 'KCDATA_BUFFER_BEGIN_CRASHINFO', 'KCDATA_BUFFER_BEGIN_STACKSHOT', 'KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT', 'KCDATA_BUFFER_BEGIN_OS_REASON','KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG')))
790
791KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_UINT32_DESC')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_UINT32_DESC'), (
792    KCSubTypeElement('desc', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 0, 1),
793    KCSubTypeElement('data', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 32, 0)
794),
795    'KCDATA_TYPE_UINT32_DESC',
796    _get_data_element
797)
798
799KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_UINT64_DESC')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_UINT64_DESC'), (
800    KCSubTypeElement('desc', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 0, 1),
801    KCSubTypeElement('data', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 32, 0)
802),
803    'KCDATA_TYPE_UINT64_DESC',
804    _get_data_element
805)
806
807KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_TIMEBASE')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_TIMEBASE'), (
808    KCSubTypeElement('numer', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0),
809    KCSubTypeElement('denom', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4, 0)
810),
811    'mach_timebase_info'
812)
813
814
815STACKSHOT_IO_NUM_PRIORITIES = 4
816KNOWN_TYPES_COLLECTION[0x901] = KCTypeDescription(0x901, (
817    KCSubTypeElement.FromBasicCtype('ss_disk_reads_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
818    KCSubTypeElement.FromBasicCtype('ss_disk_reads_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
819    KCSubTypeElement.FromBasicCtype('ss_disk_writes_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
820    KCSubTypeElement.FromBasicCtype('ss_disk_writes_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
821    KCSubTypeElement('ss_io_priority_count', KCSUBTYPE_TYPE.KC_ST_UINT64, KCSubTypeElement.GetSizeForArray(STACKSHOT_IO_NUM_PRIORITIES, 8), 32, 1),
822    KCSubTypeElement('ss_io_priority_size', KCSUBTYPE_TYPE.KC_ST_UINT64, KCSubTypeElement.GetSizeForArray(STACKSHOT_IO_NUM_PRIORITIES, 8), 32 + (STACKSHOT_IO_NUM_PRIORITIES * 8), 1),
823    KCSubTypeElement.FromBasicCtype('ss_paging_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 32 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
824    KCSubTypeElement.FromBasicCtype('ss_paging_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 40 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
825    KCSubTypeElement.FromBasicCtype('ss_non_paging_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 48 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
826    KCSubTypeElement.FromBasicCtype('ss_non_paging_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 56 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
827    KCSubTypeElement.FromBasicCtype('ss_data_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 64 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
828    KCSubTypeElement.FromBasicCtype('ss_data_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 72 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
829    KCSubTypeElement.FromBasicCtype('ss_metadata_count', KCSUBTYPE_TYPE.KC_ST_UINT64, 80 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8)),
830    KCSubTypeElement.FromBasicCtype('ss_metadata_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 88 + 2 * (STACKSHOT_IO_NUM_PRIORITIES * 8))
831),
832    'io_statistics'
833)
834
835KNOWN_TYPES_COLLECTION[0x902] = KCTypeDescription(0x902, (
836    KCSubTypeElement('snapshot_magic', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 0, 0),
837    KCSubTypeElement('free_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 1, 0),
838    KCSubTypeElement('active_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 2, 0),
839    KCSubTypeElement('inactive_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 3, 0),
840    KCSubTypeElement('purgeable_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 4, 0),
841    KCSubTypeElement('wired_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 5, 0),
842    KCSubTypeElement('speculative_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 6, 0),
843    KCSubTypeElement('throttled_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 7, 0),
844    KCSubTypeElement('filebacked_pages', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 8, 0),
845    KCSubTypeElement('compressions', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 9, 0),
846    KCSubTypeElement('decompressions', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 10, 0),
847    KCSubTypeElement('compressor_size', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 11, 0),
848    KCSubTypeElement('busy_buffer_count', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 4 * 12, 0),
849    KCSubTypeElement('pages_wanted', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 13, 0),
850    KCSubTypeElement('pages_reclaimed', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 4 * 14, 0),
851    KCSubTypeElement('pages_wanted_reclaimed_valid', KCSUBTYPE_TYPE.KC_ST_UINT8, 1, 4 * 15, 0)
852),
853    'mem_and_io_snapshot'
854)
855
856
857KNOWN_TYPES_COLLECTION[0x930] = KCTypeDescription(0x930, (
858    KCSubTypeElement.FromBasicCtype('tts_unique_pid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
859    KCSubTypeElement.FromBasicCtype('tts_ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
860    KCSubTypeElement.FromBasicCtype('tts_transition_type', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
861    KCSubTypeElement.FromBasicCtype('tts_pid', KCSUBTYPE_TYPE.KC_ST_INT32, 24),
862    KCSubTypeElement('tts_p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 28, 1)
863),
864    'transitioning_task_snapshot'
865)
866
867KNOWN_TYPES_COLLECTION[0x905] = KCTypeDescription(0x905, (
868    KCSubTypeElement.FromBasicCtype('ts_unique_pid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
869    KCSubTypeElement.FromBasicCtype('ts_ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
870    KCSubTypeElement.FromBasicCtype('ts_user_time_in_terminated_thre', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
871    KCSubTypeElement.FromBasicCtype('ts_system_time_in_terminated_th', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
872    KCSubTypeElement.FromBasicCtype('ts_p_start_sec', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
873    KCSubTypeElement.FromBasicCtype('ts_task_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
874    KCSubTypeElement.FromBasicCtype('ts_max_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
875    KCSubTypeElement.FromBasicCtype('ts_suspend_count', KCSUBTYPE_TYPE.KC_ST_UINT32, 56),
876    KCSubTypeElement.FromBasicCtype('ts_faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 60),
877    KCSubTypeElement.FromBasicCtype('ts_pageins', KCSUBTYPE_TYPE.KC_ST_UINT32, 64),
878    KCSubTypeElement.FromBasicCtype('ts_cow_faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 68),
879    KCSubTypeElement.FromBasicCtype('ts_was_throttled', KCSUBTYPE_TYPE.KC_ST_UINT32, 72),
880    KCSubTypeElement.FromBasicCtype('ts_did_throttle', KCSUBTYPE_TYPE.KC_ST_UINT32, 76),
881    KCSubTypeElement.FromBasicCtype('ts_latency_qos', KCSUBTYPE_TYPE.KC_ST_UINT32, 80),
882    KCSubTypeElement.FromBasicCtype('ts_pid', KCSUBTYPE_TYPE.KC_ST_INT32, 84),
883    KCSubTypeElement('ts_p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(32, 1), 88, 1)
884),
885    'task_snapshot'
886)
887
888KNOWN_TYPES_COLLECTION[0x906] = KCTypeDescription(0x906, (
889    KCSubTypeElement.FromBasicCtype('ths_thread_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
890    KCSubTypeElement.FromBasicCtype('ths_wait_event', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
891    KCSubTypeElement.FromBasicCtype('ths_continuation', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
892    KCSubTypeElement.FromBasicCtype('ths_total_syscalls', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
893    KCSubTypeElement.FromBasicCtype('ths_voucher_identifier', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
894    KCSubTypeElement.FromBasicCtype('ths_dqserialnum', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
895    KCSubTypeElement.FromBasicCtype('ths_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
896    KCSubTypeElement.FromBasicCtype('ths_sys_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
897    KCSubTypeElement.FromBasicCtype('ths_ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
898    KCSubTypeElement.FromBasicCtype('ths_last_run_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
899    KCSubTypeElement.FromBasicCtype('ths_last_made_runnable_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 80),
900    KCSubTypeElement.FromBasicCtype('ths_state', KCSUBTYPE_TYPE.KC_ST_UINT32, 88),
901    KCSubTypeElement.FromBasicCtype('ths_sched_flags', KCSUBTYPE_TYPE.KC_ST_UINT32, 92),
902    KCSubTypeElement.FromBasicCtype('ths_base_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 96),
903    KCSubTypeElement.FromBasicCtype('ths_sched_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 98),
904    KCSubTypeElement.FromBasicCtype('ths_eqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 100),
905    KCSubTypeElement.FromBasicCtype('ths_rqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 101),
906    KCSubTypeElement.FromBasicCtype('ths_rqos_override', KCSUBTYPE_TYPE.KC_ST_UINT8, 102),
907    KCSubTypeElement.FromBasicCtype('ths_io_tier', KCSUBTYPE_TYPE.KC_ST_UINT8, 103),
908    KCSubTypeElement.FromBasicCtype('ths_thread_t', KCSUBTYPE_TYPE.KC_ST_UINT64, 104),
909    KCSubTypeElement.FromBasicCtype('ths_requested_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 112),
910    KCSubTypeElement.FromBasicCtype('ths_effective_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 120),
911),
912    'thread_snapshot',
913    legacy_size = 0x68
914)
915
916KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL')] = KCSubTypeElement('dispatch_queue_label', KCSUBTYPE_TYPE.KC_ST_CHAR,
917                          KCSubTypeElement.GetSizeForArray(64, 1), 0, 1)
918
919KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT'), (
920    KCSubTypeElement.FromBasicCtype('tds_thread_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
921    KCSubTypeElement.FromBasicCtype('tds_voucher_identifier', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
922    KCSubTypeElement.FromBasicCtype('tds_ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
923    KCSubTypeElement.FromBasicCtype('tds_last_made_runnable_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
924    KCSubTypeElement.FromBasicCtype('tds_state', KCSUBTYPE_TYPE.KC_ST_UINT32, 32),
925    KCSubTypeElement.FromBasicCtype('tds_sched_flags', KCSUBTYPE_TYPE.KC_ST_UINT32, 36),
926    KCSubTypeElement.FromBasicCtype('tds_base_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 40),
927    KCSubTypeElement.FromBasicCtype('tds_sched_priority', KCSUBTYPE_TYPE.KC_ST_INT16, 42),
928    KCSubTypeElement.FromBasicCtype('tds_eqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 44),
929    KCSubTypeElement.FromBasicCtype('tds_rqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 45),
930    KCSubTypeElement.FromBasicCtype('tds_rqos_override', KCSUBTYPE_TYPE.KC_ST_UINT8, 46),
931    KCSubTypeElement.FromBasicCtype('tds_io_tier', KCSUBTYPE_TYPE.KC_ST_UINT8, 47),
932    KCSubTypeElement.FromBasicCtype('tds_requested_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
933    KCSubTypeElement.FromBasicCtype('tds_effective_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
934),
935    'thread_delta_snapshot',
936    legacy_size = 48
937)
938
939KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT'), (
940    KCSubTypeElement.FromBasicCtype('tds_unique_pid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
941    KCSubTypeElement.FromBasicCtype('tds_ss_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
942    KCSubTypeElement.FromBasicCtype('tds_user_time_in_terminated_thr', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
943    KCSubTypeElement.FromBasicCtype('tds_system_time_in_terminated_t', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
944    KCSubTypeElement.FromBasicCtype('tds_task_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
945    KCSubTypeElement.FromBasicCtype('tds_max_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
946    KCSubTypeElement.FromBasicCtype('tds_suspend_count', KCSUBTYPE_TYPE.KC_ST_UINT32, 48),
947    KCSubTypeElement.FromBasicCtype('tds_faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 52),
948    KCSubTypeElement.FromBasicCtype('tds_pageins', KCSUBTYPE_TYPE.KC_ST_UINT32, 56),
949    KCSubTypeElement.FromBasicCtype('tds_cow_faults', KCSUBTYPE_TYPE.KC_ST_UINT32, 60),
950    KCSubTypeElement.FromBasicCtype('tds_was_throttled', KCSUBTYPE_TYPE.KC_ST_UINT32, 64),
951    KCSubTypeElement.FromBasicCtype('tds_did_throttle', KCSUBTYPE_TYPE.KC_ST_UINT32, 68),
952    KCSubTypeElement.FromBasicCtype('tds_latency_qos', KCSUBTYPE_TYPE.KC_ST_UINT32, 72),
953),
954    'task_delta_snapshot'
955)
956
957
958KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_NAME')] = KCSubTypeElement('pth_name', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(64, 1), 0, 1)
959
960KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SYS_SHAREDCACHE_LAYOUT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_SYS_SHAREDCACHE_LAYOUT'), (
961    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
962    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1)
963),
964    'system_shared_cache_layout'
965)
966
967KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO64')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO64'), (
968    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
969    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1)
970),
971    'dyld_load_info',
972    legacy_size = 24
973)
974
975KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO'), (
976    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0),
977    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 4, 1)
978),
979    'dyld_load_info',
980    legacy_size = 20
981)
982
983KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LOADINFO64_TEXT_EXEC')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LOADINFO64_TEXT_EXEC'), (
984    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
985    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1),
986),
987    'dyld_load_info_text_exec'
988)
989
990KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_AOTCACHE_LOADINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_AOTCACHE_LOADINFO'), (
991    KCSubTypeElement('x86SlidBaseAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
992    KCSubTypeElement('x86UUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1),
993    KCSubTypeElement('aotSlidBaseAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 24, 0),
994    KCSubTypeElement('aotUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 32, 1),
995),
996    'dyld_aot_cache_uuid_info'
997)
998KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_AOTINFO')] = KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_AOTCACHE_LOADINFO')]
999
1000KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO'), (
1001    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
1002    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1),
1003    KCSubTypeElement('imageSlidBaseAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 24, 0),
1004    KCSubTypeElement('sharedCacheSlidFirstMapping', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 32, 0),
1005),
1006    'shared_cache_dyld_load_info',
1007    legacy_size = 0x18
1008)
1009
1010KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_INFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_INFO'), (
1011    KCSubTypeElement('sharedCacheSlide', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
1012    KCSubTypeElement('sharedCacheUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1),
1013    KCSubTypeElement('sharedCacheUnreliableSlidBaseAd', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 24, 0),
1014    KCSubTypeElement('sharedCacheSlidFirstMapping', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 32, 0),
1015    KCSubTypeElement('sharedCacheID', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 40, 0),
1016    KCSubTypeElement('sharedCacheFlags', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 44, 0),
1017),
1018    'shared_cache_dyld_load_info',
1019)
1020
1021KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO'), (
1022    KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
1023    KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1),
1024),
1025    'kernelcache_load_info'
1026)
1027
1028KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_ID')] = KCSubTypeElement('sharedCacheID', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
1029
1030KNOWN_TYPES_COLLECTION[0x33] = KCSubTypeElement('mach_absolute_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1031KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement.FromBasicCtype('donating_pids', KCSUBTYPE_TYPE.KC_ST_INT32, legacy_size=4)
1032
1033KNOWN_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)
1034
1035KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME'), (
1036    KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT32),
1037    KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT32, 4)
1038),
1039    'kernel_stack_frames',
1040    legacy_size = 8
1041)
1042
1043KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR'), (
1044    KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT32),
1045),
1046    'kernel_stack_frames'
1047)
1048
1049
1050KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME')] = KCTypeDescription.FromKCTypeDescription(
1051    KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME')],
1052    GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME'),
1053    'user_stack_frames'
1054)
1055
1056KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKLR')] = KCTypeDescription.FromKCTypeDescription(
1057    KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR')],
1058    GetTypeForName('STACKSHOT_KCTYPE_USER_STACKLR'),
1059    'user_stack_frames'
1060)
1061
1062KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64'), (
1063    KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT64),
1064    KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)
1065),
1066    'kernel_stack_frames',
1067    legacy_size = 16
1068)
1069
1070KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME64')] = KCTypeDescription.FromKCTypeDescription(
1071    KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKFRAME64')],
1072    GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME64'),
1073    'user_stack_frames'
1074)
1075
1076
1077KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR64')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR64'), (
1078    KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT64),
1079),
1080    'kernel_stack_frames'
1081)
1082
1083KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKLR64')] = KCTypeDescription.FromKCTypeDescription(
1084    KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR64')],
1085    GetTypeForName('STACKSHOT_KCTYPE_USER_STACKLR64'),
1086    'user_stack_frames'
1087)
1088
1089KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_ASYNC_START_INDEX')] = KCSubTypeElement.FromBasicCtype('user_async_start_index', KCSUBTYPE_TYPE.KC_ST_UINT32)
1090
1091KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_ASYNC_STACKLR64')] = KCTypeDescription.FromKCTypeDescription(
1092    KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR64')],
1093    GetTypeForName('STACKSHOT_KCTYPE_USER_ASYNC_STACKLR64'),
1094    'user_async_stack_frames'
1095)
1096
1097KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_NONRUNNABLE_TIDS')] = KCSubTypeElement.FromBasicCtype('nonrunnable_threads', KCSUBTYPE_TYPE.KC_ST_INT64)
1098
1099KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_NONRUNNABLE_TASKS')] = KCSubTypeElement.FromBasicCtype('nonrunnable_tasks', KCSUBTYPE_TYPE.KC_ST_INT64)
1100
1101KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_OSVERSION')] = KCSubTypeElement('osversion', KCSUBTYPE_TYPE.KC_ST_CHAR,
1102                          KCSubTypeElement.GetSizeForArray(256, 1), 0, 1)
1103
1104KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_BOOTARGS')] = KCSubTypeElement('boot_args', KCSUBTYPE_TYPE.KC_ST_CHAR,
1105                           KCSubTypeElement.GetSizeForArray(256, 1), 0, 1)
1106
1107KNOWN_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)
1108
1109KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_POLICY_VERSION')] = KCSubTypeElement('thread_policy_version', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
1110
1111KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_LEVEL')] = KCSubTypeElement('jetsam_level', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
1112
1113KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP')] = KCSubTypeElement("stackshot_delta_since_timestamp", KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1114
1115KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS'),
1116            (
1117                        KCSubTypeElement.FromBasicCtype('sfs_pages_faulted_in', KCSUBTYPE_TYPE.KC_ST_UINT32, 0),
1118                        KCSubTypeElement.FromBasicCtype('sfs_time_spent_faulting', KCSUBTYPE_TYPE.KC_ST_UINT64, 4),
1119                        KCSubTypeElement.FromBasicCtype('sfs_system_max_fault_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 12),
1120                        KCSubTypeElement.FromBasicCtype('sfs_stopped_faulting', KCSUBTYPE_TYPE.KC_ST_UINT8, 20)
1121            ),
1122            'stackshot_fault_stats')
1123
1124KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_WAITINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_WAITINFO'),
1125            (
1126                        KCSubTypeElement.FromBasicCtype('owner', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1127                        KCSubTypeElement.FromBasicCtype('waiter', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1128                        KCSubTypeElement.FromBasicCtype('context', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1129                        KCSubTypeElement.FromBasicCtype('wait_type', KCSUBTYPE_TYPE.KC_ST_UINT8, 24),
1130                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 25),
1131                        KCSubTypeElement.FromBasicCtype('wait_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 27)
1132            ),
1133            'thread_waitinfo')
1134
1135KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO'),
1136            (
1137                        KCSubTypeElement.FromBasicCtype('waiter', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1138                        KCSubTypeElement.FromBasicCtype('turnstile_context', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1139                        KCSubTypeElement.FromBasicCtype('turnstile_priority', KCSUBTYPE_TYPE.KC_ST_UINT8, 16),
1140                        KCSubTypeElement.FromBasicCtype('number_of_hops', KCSUBTYPE_TYPE.KC_ST_UINT8, 17),
1141                        KCSubTypeElement.FromBasicCtype('turnstile_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 18),
1142                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 26),
1143            ),
1144            'thread_turnstileinfo')
1145
1146KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL'),
1147            (
1148                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 0),
1149                        KCSubTypeElement.FromBasicCtype('portlabel_flags', KCSUBTYPE_TYPE.KC_ST_UINT16, 2),
1150                        KCSubTypeElement.FromBasicCtype('portlabel_domain', KCSUBTYPE_TYPE.KC_ST_UINT8, 4),
1151            ),
1152            'portlabel_info', merge=True)
1153
1154KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL_NAME')] = (
1155    KCSubTypeElement("portlabel_name", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1156
1157KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP'),
1158            (
1159                        KCSubTypeElement.FromBasicCtype('tgs_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1160                        KCSubTypeElement('tgs_name', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(16, 1),
1161                            8, 1),
1162                        KCSubTypeElement.FromBasicCtype('tgs_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1163            ),
1164            'thread_group_snapshot')
1165
1166
1167KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP')] = KCSubTypeElement('thread_group', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1168
1169KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT'),
1170            (
1171                        KCSubTypeElement.FromBasicCtype('jcs_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1172                        KCSubTypeElement.FromBasicCtype('jcs_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1173                        KCSubTypeElement.FromBasicCtype('jcs_thread_group', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1174                        KCSubTypeElement.FromBasicCtype('jcs_leader_task_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1175            ),
1176            'jetsam_coalition_snapshot')
1177
1178KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION')] = KCSubTypeElement('jetsam_coalition', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1179
1180KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_INSTRS_CYCLES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_INSTRS_CYCLES'),
1181            (
1182                        KCSubTypeElement.FromBasicCtype('ics_instructions', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1183                        KCSubTypeElement.FromBasicCtype('ics_cycles', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1184                        KCSubTypeElement.FromBasicCtype('ics_p_instructions', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1185                        KCSubTypeElement.FromBasicCtype('ics_p_cycles', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1186            ),
1187            'instrs_cycles_snapshot')
1188
1189KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE'),
1190            (
1191                        KCSubTypeElement.FromBasicCtype('cputype', KCSUBTYPE_TYPE.KC_ST_INT32, 0),
1192                        KCSubTypeElement.FromBasicCtype('cpusubtype', KCSUBTYPE_TYPE.KC_ST_INT32, 4)
1193            ),
1194            'task_cpu_architecture')
1195
1196KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO'),
1197            (
1198                        KCSubTypeElement.FromBasicCtype('latency_version', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1199                        KCSubTypeElement.FromBasicCtype('setup_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1200                        KCSubTypeElement.FromBasicCtype('total_task_iteration_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1201                        KCSubTypeElement.FromBasicCtype('total_terminated_task_iteration', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1202            ),
1203            'stackshot_latency_collection')
1204
1205KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_TASK')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_TASK'),
1206            (
1207                        KCSubTypeElement.FromBasicCtype('task_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1208                        KCSubTypeElement.FromBasicCtype('setup_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1209                        KCSubTypeElement.FromBasicCtype('task_thread_count_loop_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1210                        KCSubTypeElement.FromBasicCtype('task_thread_data_loop_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1211                        KCSubTypeElement.FromBasicCtype('cur_tsnap_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1212                        KCSubTypeElement.FromBasicCtype('pmap_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1213                        KCSubTypeElement.FromBasicCtype('bsd_proc_ids_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1214                        KCSubTypeElement.FromBasicCtype('misc_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1215                        KCSubTypeElement.FromBasicCtype('misc2_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1216                        KCSubTypeElement.FromBasicCtype('end_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 72)
1217            ),
1218            'stackshot_latency_task')
1219
1220KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_THREAD')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_THREAD'),
1221            (
1222                        KCSubTypeElement.FromBasicCtype('thread_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1223                        KCSubTypeElement.FromBasicCtype('cur_thsnap1_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1224                        KCSubTypeElement.FromBasicCtype('dispatch_serial_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1225                        KCSubTypeElement.FromBasicCtype('dispatch_label_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1226                        KCSubTypeElement.FromBasicCtype('cur_thsnap2_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1227                        KCSubTypeElement.FromBasicCtype('thread_name_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1228                        KCSubTypeElement.FromBasicCtype('sur_times_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1229                        KCSubTypeElement.FromBasicCtype('user_stack_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1230                        KCSubTypeElement.FromBasicCtype('kernel_stack_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1231                        KCSubTypeElement.FromBasicCtype('misc_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
1232            ),
1233            'stackshot_latency_thread')
1234
1235def set_type(name, *args):
1236    typ = GetTypeForName(name)
1237    KNOWN_TYPES_COLLECTION[typ] = KCTypeDescription(GetTypeForName(typ), *args)
1238
1239
1240set_type('STACKSHOT_KCTYPE_USER_STACKTOP',
1241         (
1242             KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1243             KCSubTypeElement('stack_contents', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(8, 1), 8, 1),
1244         ),
1245         'user_stacktop')
1246
1247#KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement('donating_pids', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
1248KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PID')] = KCSubTypeElement('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1249KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PPID')] = KCSubTypeElement('ppid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1250KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_NAME')] = KCSubTypeElement('p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR,
1251                           KCSubTypeElement.GetSizeForArray(32, 1), 0, 1)
1252KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_USERSTACK')] = KCSubTypeElement('userstack_ptr', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1253KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_ARGSLEN')] = KCSubTypeElement('p_argslen', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1254
1255KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_PATH')] = KCSubTypeElement('p_path', KCSUBTYPE_TYPE.KC_ST_CHAR,
1256                           KCSubTypeElement.GetSizeForArray(1024, 1), 0, 1)
1257KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_CSFLAGS')] = KCSubTypeElement('p_csflags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1258KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_UID')] = KCSubTypeElement('uid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1259KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_GID')] = KCSubTypeElement('gid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1260KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_ARGC')] = KCSubTypeElement('argc', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1261KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_FLAGS')] = KCSubTypeElement('p_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1262KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CPUTYPE')] = KCSubTypeElement('cputype', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1263KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RESPONSIBLE_PID')] = KCSubTypeElement('responsible_pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1264KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_DIRTY_FLAGS')] = KCSubTypeElement('dirty_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1265KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CRASHED_THREADID')] = KCSubTypeElement('crashed_threadid', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1266KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_COALITION_ID')] = KCSubTypeElement('coalition_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1267
1268KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_STATUS')] = KCSubTypeElement('p_status', KCSUBTYPE_TYPE.KC_ST_UINT8, 1, 0, 0)
1269
1270KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID'),
1271    (   KCSubTypeElement('p_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
1272        KCSubTypeElement.FromBasicCtype('p_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1273        KCSubTypeElement.FromBasicCtype('p_puniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1274    ),
1275    'proc_uniqidentifierinfo')
1276
1277KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_EXCEPTION_CODES')] = (
1278    KCTypeDescription(GetTypeForName('TASK_CRASHINFO_EXCEPTION_CODES'),
1279                      (KCSubTypeElement.FromBasicCtype('code_0', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1280                       KCSubTypeElement.FromBasicCtype('code_1', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)),
1281                      'mach_exception_data_t'))
1282
1283
1284KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_STARTTIME')] = (
1285    KCTypeDescription(GetTypeForName('TASK_CRASHINFO_PROC_STARTTIME'),
1286                      (KCSubTypeElement.FromBasicCtype('tv_sec', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1287                       KCSubTypeElement.FromBasicCtype('tv_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)),
1288                      'proc_starttime'))
1289
1290
1291KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO'),
1292    (
1293        KCSubTypeElement('ri_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
1294            KCSubTypeElement.FromBasicCtype('ri_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1295            KCSubTypeElement.FromBasicCtype('ri_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1296            KCSubTypeElement.FromBasicCtype('ri_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1297            KCSubTypeElement.FromBasicCtype('ri_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1298            KCSubTypeElement.FromBasicCtype('ri_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1299            KCSubTypeElement.FromBasicCtype('ri_wired_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1300            KCSubTypeElement.FromBasicCtype('ri_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1301            KCSubTypeElement.FromBasicCtype('ri_phys_footprint', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
1302            KCSubTypeElement.FromBasicCtype('ri_proc_start_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 80),
1303            KCSubTypeElement.FromBasicCtype('ri_proc_exit_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 88),
1304            KCSubTypeElement.FromBasicCtype('ri_child_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 96),
1305            KCSubTypeElement.FromBasicCtype('ri_child_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 104),
1306            KCSubTypeElement.FromBasicCtype('ri_child_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 112),
1307            KCSubTypeElement.FromBasicCtype('ri_child_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 120),
1308            KCSubTypeElement.FromBasicCtype('ri_child_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 128),
1309            KCSubTypeElement.FromBasicCtype('ri_child_elapsed_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 136),
1310            KCSubTypeElement.FromBasicCtype('ri_diskio_bytesread', KCSUBTYPE_TYPE.KC_ST_UINT64, 144),
1311            KCSubTypeElement.FromBasicCtype('ri_diskio_byteswritten', KCSUBTYPE_TYPE.KC_ST_UINT64, 152),
1312            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_default', KCSUBTYPE_TYPE.KC_ST_UINT64, 160),
1313            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_maintenance', KCSUBTYPE_TYPE.KC_ST_UINT64, 168),
1314            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_background', KCSUBTYPE_TYPE.KC_ST_UINT64, 176),
1315            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_utility', KCSUBTYPE_TYPE.KC_ST_UINT64, 184),
1316            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_legacy', KCSUBTYPE_TYPE.KC_ST_UINT64, 192),
1317            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_initiated', KCSUBTYPE_TYPE.KC_ST_UINT64, 200),
1318            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_interactiv', KCSUBTYPE_TYPE.KC_ST_UINT64, 208),
1319            KCSubTypeElement.FromBasicCtype('ri_billed_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 216),
1320            KCSubTypeElement.FromBasicCtype('ri_serviced_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 224)
1321    ),
1322    'rusage_info')
1323
1324KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_CPU_TIMES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_CPU_TIMES'),
1325    (
1326        KCSubTypeElement.FromBasicCtype('user_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1327        KCSubTypeElement.FromBasicCtype('system_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1328        KCSubTypeElement.FromBasicCtype('runnable_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1329    ), 'cpu_times')
1330
1331KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_DURATION')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_DURATION'),
1332    (
1333        KCSubTypeElement.FromBasicCtype('stackshot_duration', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1334        KCSubTypeElement.FromBasicCtype('stackshot_duration_outer', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1335        KCSubTypeElement.FromBasicCtype('stackshot_duration_prior', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1336    ), 'stackshot_duration', merge=True
1337)
1338
1339KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_PROCNAME')] = (
1340    KCSubTypeElement("proc_name", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1341
1342KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_PID')] = (
1343    KCSubTypeElement('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0))
1344
1345KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_AOTINFO')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_AOTINFO'),
1346    (
1347        KCSubTypeElement('x86LoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
1348        KCSubTypeElement('aotLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 8, 0),
1349        KCSubTypeElement('aotImageSize', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 16, 0),
1350        KCSubTypeElement('aotImageKey', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(32, 1), 24, 1),
1351    ), 'dyld_aot_info')
1352
1353KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_SNAPSHOT')] = KCTypeDescription(GetTypeForName('EXIT_REASON_SNAPSHOT'),
1354    (
1355        KCSubTypeElement.FromBasicCtype('ers_namespace', KCSUBTYPE_TYPE.KC_ST_UINT32, 0),
1356        KCSubTypeElement.FromBasicCtype('ers_code', KCSUBTYPE_TYPE.KC_ST_UINT64, 4),
1357        KCSubTypeElement.FromBasicCtype('ers_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 12),
1358    ), 'exit_reason_basic_info')
1359
1360KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_USER_DESC')] = (
1361    KCSubTypeElement("exit_reason_user_description", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1362
1363KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_USER_PAYLOAD')] = KCSubTypeElement('exit_reason_user_payload',
1364        KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1)
1365
1366KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_CODESIGNING_INFO')] = KCTypeDescription(GetTypeForName('EXIT_REASON_CODESIGNING_INFO'),
1367    (
1368        KCSubTypeElement.FromBasicCtype('ceri_virt_addr', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1369        KCSubTypeElement.FromBasicCtype('ceri_file_offset', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1370        KCSubTypeElement("ceri_pathname", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(1024, 1), 16, 1),
1371        KCSubTypeElement("ceri_filename", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(1024, 1), 1040, 1),
1372        KCSubTypeElement.FromBasicCtype('ceri_codesig_modtime_secs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2064),
1373        KCSubTypeElement.FromBasicCtype('ceri_codesig_modtime_nsecs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2072),
1374        KCSubTypeElement.FromBasicCtype('ceri_page_modtime_secs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2080),
1375        KCSubTypeElement.FromBasicCtype('ceri_page_modtime_nsecs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2088),
1376        KCSubTypeElement.FromBasicCtype('ceri_path_truncated', KCSUBTYPE_TYPE.KC_ST_UINT8, 2096),
1377        KCSubTypeElement.FromBasicCtype('ceri_object_codesigned', KCSUBTYPE_TYPE.KC_ST_UINT8, 2097),
1378        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_validated', KCSUBTYPE_TYPE.KC_ST_UINT8, 2098),
1379        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_tainted', KCSUBTYPE_TYPE.KC_ST_UINT8, 2099),
1380        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_nx', KCSUBTYPE_TYPE.KC_ST_UINT8, 2100),
1381        KCSubTypeElement.FromBasicCtype('ceri_page_wpmapped', KCSUBTYPE_TYPE.KC_ST_UINT8, 2101),
1382        KCSubTypeElement.FromBasicCtype('ceri_page_slid', KCSUBTYPE_TYPE.KC_ST_UINT8, 2102),
1383        KCSubTypeElement.FromBasicCtype('ceri_page_dirty', KCSUBTYPE_TYPE.KC_ST_UINT8, 2103),
1384        KCSubTypeElement.FromBasicCtype('ceri_page_shadow_depth', KCSUBTYPE_TYPE.KC_ST_UINT32, 2104),
1385    ), 'exit_reason_codesigning_info')
1386
1387KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_WORKLOOP_ID')] = (
1388        KCSubTypeElement('exit_reason_workloop_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value))
1389
1390KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_DISPATCH_QUEUE_NO')] = (
1391        KCSubTypeElement('exit_reason_dispatch_queue_no', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value))
1392
1393KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_ASID')] = (
1394    KCSubTypeElement('ts_asid', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0))
1395
1396KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PAGE_TABLES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_PAGE_TABLES'), (
1397    KCSubTypeElement(None, KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value), ),
1398    'ts_pagetable',
1399    merge=True,
1400    naked=True
1401)
1402
1403def GetSecondsFromMATime(mat, tb):
1404    return (float(long(mat) * tb['numer']) / tb['denom']) / 1e9
1405
1406def GetLongForAddress(address):
1407    if isinstance(address, six.string_types):
1408        if '0x' in address.lower():
1409            address = long(address, 16)
1410        else:
1411            address = long(address)
1412    return address
1413
1414def FindLibraryForAddress(liblist, address):
1415    current_lib = None
1416    for l in liblist:
1417        l_addr = GetLongForAddress(l[1])
1418        if address >= l_addr:
1419            current_lib = l
1420    return current_lib
1421
1422def FindIndexOfLibInCatalog(catalog, lib):
1423    index = None
1424    i = 0
1425    for l in catalog:
1426        if l[0] == lib[0] and l[1] == lib[1]:
1427            index = i
1428            break
1429        i += 1
1430
1431    if index is None:
1432        catalog.append(lib)
1433        index = len(catalog) - 1
1434
1435    return index
1436
1437def GetOffsetOfAddressForLib(lib, address):
1438    return (address - GetLongForAddress(lib[1]))
1439
1440def GetSymbolInfoForFrame(catalog, liblist, address):
1441    address = GetLongForAddress(address)
1442    lib = FindLibraryForAddress(liblist, address)
1443    if not lib:
1444        lib = ["00000000000000000000000000000000",0,"A"]
1445    offset = GetOffsetOfAddressForLib(lib, address)
1446    index = FindIndexOfLibInCatalog(catalog, lib)
1447    return [index, offset]
1448
1449def GetStateDescription(s):
1450    retval = []
1451    TH_WAIT = 0x01
1452    TH_SUSP = 0x02
1453    TH_RUN = 0x04
1454    TH_UNINT = 0x08
1455    TH_TERMINATE = 0x10
1456    TH_TERMINATE2 = 0x20
1457    TH_WAIT_REPORT = 0x40
1458    TH_IDLE = 0x80
1459    if (s & TH_WAIT):
1460        retval.append("TH_WAIT")
1461    if (s & TH_SUSP):
1462        retval.append("TH_SUSP")
1463    if (s & TH_RUN):
1464        retval.append("TH_RUN")
1465    if (s & TH_UNINT):
1466        retval.append("TH_UNINT")
1467    if (s & TH_TERMINATE):
1468        retval.append("TH_TERMINATE")
1469    if (s & TH_TERMINATE2):
1470        retval.append("TH_TERMINATE2")
1471    if (s & TH_WAIT_REPORT):
1472        retval.append("TH_WAIT_REPORT")
1473    if (s & TH_IDLE):
1474        retval.append("TH_IDLE")
1475    return retval
1476
1477
1478def format_uuid(elementValues):
1479    # sometimes we get string like "25A926D8-F742-3E5E..."
1480    if isinstance(elementValues, six.string_types):
1481        return elementValues
1482    return ''.join("%02x" % i for i in elementValues)
1483
1484kThreadWaitNone			= 0x00
1485kThreadWaitKernelMutex          = 0x01
1486kThreadWaitPortReceive          = 0x02
1487kThreadWaitPortSetReceive       = 0x03
1488kThreadWaitPortSend             = 0x04
1489kThreadWaitPortSendInTransit    = 0x05
1490kThreadWaitSemaphore            = 0x06
1491kThreadWaitKernelRWLockRead     = 0x07
1492kThreadWaitKernelRWLockWrite    = 0x08
1493kThreadWaitKernelRWLockUpgrade  = 0x09
1494kThreadWaitUserLock             = 0x0a
1495kThreadWaitPThreadMutex         = 0x0b
1496kThreadWaitPThreadRWLockRead    = 0x0c
1497kThreadWaitPThreadRWLockWrite   = 0x0d
1498kThreadWaitPThreadCondVar       = 0x0e
1499kThreadWaitParkedWorkQueue      = 0x0f
1500kThreadWaitWorkloopSyncWait     = 0x10
1501kThreadWaitOnProcess            = 0x11
1502kThreadWaitSleepWithInheritor   = 0x12
1503kThreadWaitEventlink            = 0x13
1504kThreadWaitCompressor           = 0x14
1505
1506
1507UINT64_MAX = 0xffffffffffffffff
1508STACKSHOT_WAITOWNER_KERNEL      = (UINT64_MAX - 1)
1509STACKSHOT_WAITOWNER_PORT_LOCKED = (UINT64_MAX - 2)
1510STACKSHOT_WAITOWNER_PSET_LOCKED = (UINT64_MAX - 3)
1511STACKSHOT_WAITOWNER_INTRANSIT   = (UINT64_MAX - 4)
1512STACKSHOT_WAITOWNER_MTXSPIN     = (UINT64_MAX - 5)
1513STACKSHOT_WAITOWNER_THREQUESTED = (UINT64_MAX - 6)
1514STACKSHOT_WAITOWNER_SUSPENDED   = (UINT64_MAX - 7)
1515
1516STACKSHOT_TURNSTILE_STATUS_UNKNOWN         = 0x01
1517STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ    = 0x02
1518STACKSHOT_TURNSTILE_STATUS_WORKQUEUE       = 0x04
1519STACKSHOT_TURNSTILE_STATUS_THREAD          = 0x08
1520STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK = 0x10
1521STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK     = 0x20
1522STACKSHOT_TURNSTILE_STATUS_SENDPORT        = 0x40
1523STACKSHOT_TURNSTILE_STATUS_RECEIVEPORT     = 0x80
1524
1525#
1526# These come from xpc_domain_type_t in <xpc/launch_private.h>
1527PORTLABEL_DOMAINS = {
1528    1: 'system',        # XPC_DOMAIN_SYSTEM
1529    2: 'user',          # XPC_DOMAIN_USER
1530    5: 'pid',           # XPC_DOMAIN_PID
1531    7: 'port',          # XPC_DOMAIN_PORT
1532}
1533def portlabel_domain(x):
1534    if x is None:
1535        return "unknown"
1536    return PORTLABEL_DOMAINS.get(x, "unknown.{}".format(x))
1537
1538STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY = 0x1
1539
1540def formatPortLabelID(portlabel_id, portlabels):
1541    if portlabel_id > 0:
1542        portlabel = {}
1543        if portlabels is not None:
1544            portlabel = portlabels.get(str(portlabel_id), {})
1545        portlabel_name = portlabel_domain(portlabel.get('portlabel_domain')) + " "
1546        portlabel_name += portlabel.get("portlabel_name", "!!!unknown, ID {} !!!".format(portlabel_id));
1547        return " {" + portlabel_name + "}"
1548    if portlabel_id < 0:
1549        return" {labeled, info trucated}"
1550    return ""
1551
1552def formatWaitInfo(info, wantHex, portlabels):
1553    base='#x' if wantHex else 'd'
1554    s = 'thread {0:{base}}: '.format(info['waiter'], base=base)
1555    type = info['wait_type']
1556    context = info['context']
1557    owner = info['owner']
1558    ownerThread = "{0:{base}}".format(owner, base=base)
1559    portlabel_id = info.get('portlabel_id', 0)
1560    flags = info.get('wait_flags', 0)
1561
1562    if type == kThreadWaitKernelMutex:
1563        s += 'kernel mutex %x' % context
1564        if owner == STACKSHOT_WAITOWNER_MTXSPIN:
1565            s += " in spin mode"
1566        elif owner:
1567            s += " owned by thread %s" % ownerThread
1568        else:
1569            s += "with unknown owner"
1570    elif type == kThreadWaitPortReceive:
1571        s += "mach_msg receive on "
1572        if flags & STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY:
1573            s += "REPLY "
1574            flags = flags - STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY
1575        if owner == STACKSHOT_WAITOWNER_PORT_LOCKED:
1576            s += "locked port %x" % context
1577        elif owner == STACKSHOT_WAITOWNER_INTRANSIT:
1578            s += "intransit port %x" % context
1579        elif owner:
1580            s += "port %x name %x" % (context, owner)
1581        else:
1582            s += "port %x" % context
1583    elif type == kThreadWaitPortSetReceive:
1584        if owner == STACKSHOT_WAITOWNER_PSET_LOCKED:
1585            s += "mach_msg receive on locked port set %x" % context
1586        else:
1587            s += "mach_msg receive on port set %x" % context
1588    elif type == kThreadWaitPortSend:
1589        s += "mach_msg send on "
1590        if owner == STACKSHOT_WAITOWNER_PORT_LOCKED:
1591            s += "locked port %x" % context
1592        elif owner == STACKSHOT_WAITOWNER_INTRANSIT:
1593            s += "intransit port %x" % context
1594        elif owner == STACKSHOT_WAITOWNER_KERNEL:
1595            s += "port %x owned by kernel" % context
1596        elif owner:
1597            s += "port %x owned by pid %d" % (context, owner)
1598        else:
1599            s += "port %x with unknown owner" % context
1600    elif type == kThreadWaitPortSendInTransit:
1601        s += "mach_msg send on port %x in transit to " % context
1602        if owner:
1603            s += "port %x" % owner
1604        else:
1605            s += "unknown port"
1606    elif type == kThreadWaitSemaphore:
1607        s += "semaphore port %x " % context
1608        if owner:
1609            s += "owned by pid %d" % owner
1610        else:
1611            s += "with unknown owner"
1612    elif type == kThreadWaitKernelRWLockRead:
1613        s += "krwlock %x for reading" % context
1614        if owner:
1615            s += " owned by thread %s" % ownerThread
1616    elif type == kThreadWaitKernelRWLockWrite:
1617        s += "krwlock %x for writing" % context
1618        if owner:
1619            s += " owned by thread %s" % ownerThread
1620    elif type == kThreadWaitKernelRWLockUpgrade:
1621        s += "krwlock %x for upgrading" % context
1622        if owner:
1623            s += " owned by thread %s" % ownerThread
1624    elif type == kThreadWaitUserLock:
1625        if owner:
1626            s += "unfair lock %x owned by thread %s" % (context, ownerThread)
1627        else:
1628            s += "spin lock %x" % context
1629    elif type == kThreadWaitPThreadMutex:
1630        s += "pthread mutex %x" % context
1631        if owner:
1632            s += " owned by thread %s" % ownerThread
1633        else:
1634            s += " with unknown owner"
1635    elif type == kThreadWaitPThreadRWLockRead:
1636        s += "pthread rwlock %x for reading" % context
1637    elif type == kThreadWaitPThreadRWLockWrite:
1638        s += "pthread rwlock %x for writing" % context
1639    elif type == kThreadWaitPThreadCondVar:
1640        s += "pthread condvar %x" % context
1641    elif type == kThreadWaitWorkloopSyncWait:
1642        s += "workloop sync wait"
1643        if owner == STACKSHOT_WAITOWNER_SUSPENDED:
1644            s += ", suspended"
1645        elif owner == STACKSHOT_WAITOWNER_THREQUESTED:
1646            s += ", thread requested"
1647        elif owner != 0:
1648            s += ", owned by thread %s" % ownerThread
1649        else:
1650            s += ", unknown owner"
1651        s += ", workloop id %x" % context
1652    elif type == kThreadWaitOnProcess:
1653        if owner == 2**64-1:
1654            s += "waitpid, for any children"
1655        elif 2**32 <= owner and owner < 2**64-1:
1656            s += "waitpid, for process group %d" % abs(owner - 2**64)
1657        else:
1658            s += "waitpid, for pid %d" % owner
1659    elif type == kThreadWaitSleepWithInheritor:
1660        if owner == 0:
1661            s += "turnstile, held waitq"
1662        else:
1663            s += "turnstile, pushing thread %s" % ownerThread
1664    elif type == kThreadWaitEventlink:
1665        if owner == 0:
1666            s += "eventlink, held waitq"
1667        else:
1668            s += "eventlink, signaled by thread %s" % ownerThread
1669    elif type == kThreadWaitCompressor:
1670        s += "in compressor segment %x, busy for thread %s" % (context, ownerThread)
1671
1672    else:
1673        s += "unknown type %d (owner %s, context %x)" % (type, ownerThread, context)
1674
1675    s += formatPortLabelID(portlabel_id, portlabels)
1676
1677    if flags != 0:
1678        s += "flags {}".format(hex(flags))
1679    return s
1680
1681def formatTurnstileInfo(ti, wi_portlabel_id, portlabels):
1682    if ti is None:
1683        return " [no turnstile]"
1684
1685    ts_flags = int(ti['turnstile_flags'])
1686    ctx = int(ti['turnstile_context'])
1687    hop = int(ti['number_of_hops'])
1688    prio = int(ti['turnstile_priority'])
1689    portlabel_id = ti.get("portlabel_id", 0)
1690
1691    portlabel_summary = ""
1692    if portlabel_id != 0 and portlabel_id != wi_portlabel_id:
1693        portlabel_summary += formatPortLabelID(portlabel_id, portlabels)
1694
1695    if ts_flags & STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK:
1696        return " [turnstile blocked on task, but ip_lock was held]" + portlabel_summary
1697    if ts_flags & STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK:
1698        return " [turnstile blocked on task pid %d, hops: %d, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1699    if ts_flags & STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ:
1700        return " [turnstile was in process of being updated]" + portlabel_summary
1701    if ts_flags & STACKSHOT_TURNSTILE_STATUS_WORKQUEUE:
1702        return " [blocked on workqueue: 0x%x, hops: %x, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1703    if ts_flags & STACKSHOT_TURNSTILE_STATUS_THREAD:
1704        return " [blocked on: %d, hops: %x, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1705    if ts_flags & STACKSHOT_TURNSTILE_STATUS_UNKNOWN:
1706        return " [turnstile with unknown inheritor]" + portlabel_summary
1707
1708    return " [unknown turnstile status!]" + portlabel_summary
1709
1710def formatWaitInfoWithTurnstiles(waitinfos, tsinfos, portlabels):
1711    wis_tis = []
1712    for w in waitinfos:
1713        found_pair = False
1714        for t in tsinfos:
1715            if int(w['waiter']) == int(t['waiter']):
1716                wis_tis.append((w, t))
1717                found_pair = True
1718                break
1719        if not found_pair:
1720            wis_tis.append((w, None))
1721
1722    return [formatWaitInfo(wi, False, portlabels) + formatTurnstileInfo(ti, wi.get('portlabel_id', 0), portlabels) for (wi, ti) in wis_tis]
1723
1724def SaveStackshotReport(j, outfile_name, incomplete):
1725    import time
1726    from operator import itemgetter, attrgetter
1727    ss = j.get('kcdata_stackshot')
1728    if not ss:
1729        print("No KCDATA_BUFFER_BEGIN_STACKSHOT object found. Skipping writing report.")
1730        return
1731
1732    timestamp = ss.get('usecs_since_epoch')
1733    try:
1734        timestamp = time.strftime("%Y-%m-%d %H:%M:%S +0000",time.gmtime(timestamp // 1000000 if timestamp else None))
1735    except ValueError as e:
1736        print("couldn't convert timestamp:", str(e))
1737        timestamp = None
1738
1739    os_version = ss.get('osversion', 'Unknown')
1740    timebase = ss.get('mach_timebase_info', {"denom": 1, "numer": 1})
1741
1742    sc_note = None
1743    extra_note = None
1744    dsc_common = None
1745    shared_cache_info = ss.get('shared_cache_dyld_load_info')
1746    if shared_cache_info:
1747        shared_cache_base_addr = shared_cache_info['imageSlidBaseAddress']
1748        # If we have a slidFirstMapping and it's >= base_address, use that.
1749        #
1750        # Otherwise we're processing a stackshot from before the slidFirstMapping
1751        # field was introduced and corrected.  On ARM the SlidBaseAddress is the
1752        # same, but on x86 it's off by 0x20000000.  We use 'X86_64' in the
1753        # kernel version string plus checking kern_page_size == 4k' as
1754        # proxy for x86_64, and only adjust SlidBaseAddress if the unslid
1755        # address is precisely the expected incorrect value.
1756        #
1757        is_intel = ('X86_64' in ss.get('osversion', "") and
1758           ss.get('kernel_page_size', 0) == 4096)
1759        slidFirstMapping = shared_cache_info.get(SC_SLID_FIRSTMAPPING_KEY, -1);
1760        if slidFirstMapping >= shared_cache_base_addr:
1761            shared_cache_base_addr = slidFirstMapping
1762            sc_note = "base-accurate"
1763
1764        elif is_intel:
1765            sc_slide = shared_cache_info['imageLoadAddress']
1766            if (shared_cache_base_addr - sc_slide) == 0x7fff00000000:
1767                shared_cache_base_addr += 0x20000000
1768                sc_note = "base-x86-adjusted"
1769                extra_note = "Shared cache base adjusted for x86. "
1770            else:
1771                sc_note = "base-x86-unknown"
1772
1773        dsc_common = [format_uuid(shared_cache_info['imageUUID']),
1774                shared_cache_base_addr, "S" ]
1775        print("Shared cache UUID found from the binary data is <%s> " % str(dsc_common[0]))
1776
1777    dsc_layout = ss.get('system_shared_cache_layout')
1778
1779    dsc_libs = []
1780    if dsc_layout:
1781        print("Found in memory system shared cache layout with {} images".format(len(dsc_layout)))
1782        slide = ss.get('shared_cache_dyld_load_info')['imageLoadAddress']
1783
1784        for image in dsc_layout:
1785            dsc_libs.append([format_uuid(image['imageUUID']), image['imageLoadAddress'] + slide, "C"])
1786
1787    AllImageCatalog = []
1788    obj = {}
1789    obj["kernel"] = os_version
1790    if timestamp is not None:
1791        obj["date"] = timestamp
1792    obj["reason"] = "kernel panic stackshot"
1793    obj["incident"] = "ABCDEFGH-1234-56IJ-789K-0LMNOPQRSTUV"
1794    obj["crashReporterKey"] = "12ab34cd45aabbccdd6712ab34cd45aabbccdd67"
1795    obj["bootArgs"] = ss.get('boot_args','')
1796    obj["frontmostPids"] = [0]
1797    obj["exception"] = "0xDEADF157"
1798    obj["processByPid"] = {}
1799    if sc_note is not None:
1800        obj["sharedCacheNote"] = sc_note
1801
1802    if incomplete:
1803        obj["reason"] = "!!!INCOMPLETE!!! kernel panic stackshot"
1804        obj["notes"] = "Generated by xnu kcdata.py from incomplete data!   Some information is missing! "
1805    else:
1806        obj["notes"] = "Generated by xnu kcdata.py. "
1807
1808    if extra_note is not None:
1809        obj["notes"] = obj["notes"] + extra_note
1810
1811    processByPid = obj["processByPid"]
1812    ssplist = ss.get('task_snapshots', {})
1813    ssplist.update(ss.get('transitioning_task_snapshots', {}))
1814    kern_load_info = []
1815    if "0" in ssplist:
1816        kc_uuid = ssplist["0"].get('kernelcache_load_info', None)
1817        if kc_uuid:
1818            kernelcache_uuid = [format_uuid(kc_uuid['imageUUID']), kc_uuid['imageLoadAddress'], "U" ]
1819            kern_load_info.append(kernelcache_uuid)
1820
1821        kl_infos = ssplist["0"].get("dyld_load_info", [])
1822        for dlinfo in kl_infos:
1823            kern_load_info.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], "K"])
1824
1825        kl_infos_text_exec = ssplist["0"].get("dyld_load_info_text_exec", [])
1826        for dlinfo in kl_infos_text_exec:
1827            kern_load_info.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], "T"])
1828
1829    for pid,piddata in sorted(ssplist.items()):
1830        processByPid[str(pid)] = {}
1831        tsnap = processByPid[str(pid)]
1832        pr_lib_dsc = dsc_common
1833
1834        # see if there's an alternate shared cache
1835        scd = piddata.get('shared_cache_dyld_load_info')
1836        if scd is not None:
1837            if 'imageSlidBaseAddress' not in scd:
1838                print("Specific task shared cache format does not include slid shared cache base address. Skipping writing report.")
1839                return
1840
1841            scd_uuid = format_uuid(scd['imageUUID'])
1842            scd_base_addr = scd['imageSlidBaseAddress']
1843            pr_lib_dsc = [scd_uuid, scd_base_addr, "S"]
1844
1845        pr_libs = []
1846        if len(dsc_libs) == 0 and pr_lib_dsc:
1847            pr_libs.append(pr_lib_dsc)
1848        _lib_type = "P"
1849        if int(pid) == 0:
1850            _lib_type = "K"
1851            pr_libs = []
1852        else:
1853            for dlinfo in piddata.get('dyld_load_info',[]):
1854                pr_libs.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], _lib_type])
1855
1856        pr_libs.extend(kern_load_info)
1857        pr_libs.extend(dsc_libs)
1858
1859        pr_libs.sort(key=itemgetter(1))
1860
1861        ttsnap = piddata.get('transitioning_task_snapshot', None)
1862        if ttsnap is not None:
1863            # Transitioning task snapshots have "tts_" prefixes; change them to
1864            # "ts_".
1865            ttsnap = { key[1:] : value for key,value in ttsnap.items() }
1866            # Add a note to let people know
1867            obj["notes"] = obj["notes"] + "PID {} is a transitioning (exiting) task. ".format(pid)
1868        tasksnap = piddata.get('task_snapshot', ttsnap);
1869        if tasksnap is None:
1870            continue;
1871        tsnap["pid"] = tasksnap["ts_pid"]
1872        if 'ts_asid' in piddata:
1873            tsnap["asid"] = piddata["ts_asid"]
1874
1875        if 'ts_pagetable' in piddata:
1876            pagetables = []
1877            for tte in piddata["ts_pagetable"]:
1878                pagetables.append(tte)
1879            tsnap["pageTables"] = pagetables
1880
1881        # Some fields are missing from transitioning_task snapshots.
1882        if ttsnap is None:
1883            tsnap["residentMemoryBytes"] = tasksnap["ts_task_size"]
1884            tsnap["timesDidThrottle"] = tasksnap["ts_did_throttle"]
1885            tsnap["systemTimeTask"] = GetSecondsFromMATime(tasksnap["ts_system_time_in_terminated_th"], timebase)
1886            tsnap["pageIns"] = tasksnap["ts_pageins"]
1887            tsnap["pageFaults"] = tasksnap["ts_faults"]
1888            tsnap["userTimeTask"] = GetSecondsFromMATime(tasksnap["ts_user_time_in_terminated_thre"], timebase)
1889        tsnap["procname"] = tasksnap["ts_p_comm"]
1890        if ttsnap is None:
1891            tsnap["copyOnWriteFaults"] = tasksnap["ts_cow_faults"]
1892            tsnap["timesThrottled"] = tasksnap["ts_was_throttled"]
1893        tsnap["threadById"] = {}
1894        threadByID = tsnap["threadById"]
1895        thlist = piddata.get('thread_snapshots', {})
1896        for tid,thdata in sorted(thlist.items()):
1897            threadByID[str(tid)] = {}
1898            thsnap = threadByID[str(tid)]
1899            if "thread_snapshot" not in thdata:
1900                print("Found broken thread state for thread ID: %s." % tid)
1901                break
1902            threadsnap = thdata["thread_snapshot"]
1903            thsnap["userTime"] = GetSecondsFromMATime(threadsnap["ths_user_time"], timebase)
1904            thsnap["id"] = threadsnap["ths_thread_id"]
1905            thsnap["basePriority"] = threadsnap["ths_base_priority"]
1906            thsnap["systemTime"] = GetSecondsFromMATime(threadsnap["ths_sys_time"], timebase)
1907            thsnap["schedPriority"] = threadsnap["ths_sched_priority"]
1908            thsnap["state"] = GetStateDescription(threadsnap['ths_state'])
1909            thsnap["qosEffective"] = threadsnap["ths_eqos"]
1910            thsnap["qosRequested"] = threadsnap["ths_rqos"]
1911
1912            if "pth_name" in thdata:
1913                thsnap["name"] = thdata["pth_name"];
1914
1915            if threadsnap['ths_continuation']:
1916                thsnap["continuation"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['ths_continuation'])
1917            if "kernel_stack_frames" in thdata:
1918                kuserframes = []
1919                for f in thdata["kernel_stack_frames"]:
1920                    kuserframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
1921                thsnap["kernelFrames"] = kuserframes
1922
1923            if "user_stack_frames" in thdata:
1924                uframes = []
1925                for f in thdata["user_stack_frames"]:
1926                    uframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
1927                thsnap["userFrames"] = uframes
1928
1929            if "user_stacktop" in thdata:
1930                (address,) = struct.unpack("<Q", struct.pack("B"*8, *thdata["user_stacktop"]["stack_contents"]))
1931                thsnap["userStacktop"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, address)
1932
1933            if threadsnap['ths_wait_event']:
1934                thsnap["waitEvent"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['ths_wait_event'])
1935
1936        if 'thread_waitinfo' in piddata and 'thread_turnstileinfo' in piddata:
1937            tsnap['waitInfo'] = formatWaitInfoWithTurnstiles(piddata['thread_waitinfo'], piddata['thread_turnstileinfo'], piddata.get('portlabels', None))
1938        elif 'thread_waitinfo' in piddata:
1939            portlabels = ss.get('portlabels', None)
1940            tsnap['waitInfo'] = [formatWaitInfo(x, False, portlabels) for x in piddata['thread_waitinfo']]
1941    obj['binaryImages'] = AllImageCatalog
1942    if outfile_name == '-':
1943        fh = sys.stdout
1944    else:
1945        fh = open(outfile_name, "w")
1946
1947    header = {}
1948    header['bug_type'] = 288
1949    if timestamp is not None:
1950        header['timestamp'] = timestamp
1951    header['os_version'] = os_version
1952    fh.write(json.dumps(header, sort_keys=True))
1953    fh.write("\n")
1954
1955    fh.write(json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': ')))
1956    fh.close()
1957
1958
1959@contextlib.contextmanager
1960def data_from_stream(stream):
1961    try:
1962        fmap = mmap.mmap(stream.fileno(), 0, mmap.MAP_SHARED, mmap.PROT_READ)
1963    except:
1964        if six.PY3:
1965            yield stream.buffer.read()
1966        else:
1967            yield stream.read()
1968    else:
1969        try:
1970            yield fmap
1971        finally:
1972            fmap.close()
1973
1974def iterate_kcdatas(kcdata_file):
1975    with data_from_stream(kcdata_file) as data:
1976        iterator = kcdata_item_iterator(data)
1977        kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1978
1979        if isinstance(kcdata_buffer, KCCompressedBufferObject):
1980            kcdata_buffer.ReadItems(iterator)
1981            decompressed = kcdata_buffer.Decompress(data)
1982            iterator = kcdata_item_iterator(decompressed)
1983            kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1984
1985        if not isinstance(kcdata_buffer, KCBufferObject):
1986            # ktrace stackshot chunk
1987            iterator = kcdata_item_iterator(data[16:])
1988            kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1989
1990        if not isinstance(kcdata_buffer, KCBufferObject):
1991            try:
1992                decoded = base64.b64decode(data)
1993            except:
1994                pass
1995            else:
1996                iterator = kcdata_item_iterator(decoded)
1997                kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1998        if not isinstance(kcdata_buffer, KCBufferObject):
1999            import gzip
2000            from io import BytesIO
2001            try:
2002                decompressed = gzip.GzipFile(fileobj=BytesIO(data[:])).read()
2003            except:
2004                pass
2005            else:
2006                iterator = kcdata_item_iterator(decompressed)
2007                kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
2008
2009        if not isinstance(kcdata_buffer, KCBufferObject):
2010            raise Exception("unknown file type")
2011
2012
2013        kcdata_buffer.ReadItems(iterator)
2014        yield kcdata_buffer
2015
2016        for magic in iterator:
2017            kcdata_buffer = KCObject.FromKCItem(magic)
2018            if kcdata_buffer.i_type == 0:
2019                continue
2020            if not isinstance(kcdata_buffer, KCBufferObject):
2021                raise Exception("unknown file type")
2022            kcdata_buffer.ReadItems(iterator)
2023            yield kcdata_buffer
2024
2025#
2026# Values for various flag fields.  Each entry's key is the key seen in the
2027# processed kcdata, the value is an array of bits, from low (0x1) to high, with
2028# either a string flag name or None for unused holes.
2029#
2030# Only put flags in here which are stable - this is run against stackshots
2031# of all different versions.  For anything unstable, we'll need a decoder ring
2032# added to the stackshot.
2033#
2034PRETTIFY_FLAGS = {
2035    'jcs_flags': [
2036       'kCoalitionTermRequested',
2037       'kCoalitionTerminated',
2038       'kCoalitionReaped',
2039       'kCoalitionPrivileged',
2040    ],
2041    'sharedCacheFlags': [
2042       'kSharedCacheSystemPrimary',
2043       'kSharedCacheDriverkit'
2044       'kSharedCacheAOT',
2045    ],
2046    'stackshot_in_flags': [ # STACKSHOT_*, also stackshot_out_flags
2047        'get_dq',
2048        'save_loadinfo',
2049        'get_global_mem_stats',
2050        'save_kext_loadinfo',
2051        None,
2052        None,
2053        None,
2054        None,
2055        'active_kernel_threads_only',
2056        'get_boot_profile',
2057        'do_compress',
2058        None,
2059        None,
2060        'save_imp_donation_pids',
2061        'save_in_kernel_buffer',
2062        'retrieve_existing_buffer',
2063        'kcdata_format',
2064        'enable_bt_faulting',
2065        'collect_delta_snapshot',
2066        'collect_sharedcache_layout',
2067        'trylock',
2068        'enable_uuid_faulting',
2069        'from_panic',
2070        'no_io_stats',
2071        'thread_waitinfo',
2072        'thread_group',
2073        'save_jetsam_coalitions',
2074        'instrs_cycles',
2075        'asid',
2076        'page_tables',
2077        'disable_latency_info',
2078        'save_dyld_compactinfo',
2079        'include_driver_threads_in_kernel'
2080    ],
2081    'system_state_flags': [
2082        'kUser64_p',
2083        'kKern64_p',
2084    ],
2085    'tgs_flags': [
2086        'kThreadGroupEfficient',
2087        'kThreadGroupApplication',
2088        'kThreadGroupCritical',
2089        'kThreadGroupBestEffort',
2090        None,
2091        None,
2092        None,
2093        None,
2094        'kThreadGroupUIApplication',
2095        None,      # Redacted
2096    ],
2097    'ths_ss_flags': [
2098        'kUser64_p',
2099        'kKern64_p',
2100        'kHasDispatchSerial',
2101        'kStacksPCOnly',
2102        'kThreadDarwinBG',
2103        'kThreadIOPassive',
2104        'kThreadSuspended',
2105        'kThreadTruncatedBT',
2106        'kGlobalForcedIdle',
2107        'kThreadFaultedBT',
2108        'kThreadTriedFaultBT',
2109        'kThreadOnCore',
2110        'kThreadIdleWorker',
2111        'kThreadMain',
2112        'kThreadTruncKernBT',
2113        'kThreadTruncUserBT',
2114        'kThreadTruncUserAsyncBT',
2115    ],
2116    'ths_state': [
2117        'TH_WAIT',
2118        'TH_SUSP',
2119        'TH_RUN',
2120        'TH_UNINT',
2121        'TH_TERMINATE',
2122        'TH_TERMINATE2',
2123        'TH_WAIT_REPORT',
2124        'TH_IDLE',
2125    ],
2126    'ts_ss_flags': [
2127        'kUser64_p',
2128        'kKern64_p',
2129        'kTaskRsrcFlagged',
2130        'kTerminatedSnapshot',
2131        'kPidSuspended',
2132        'kFrozen',
2133        'kTaskDarwinBG',
2134        'kTaskExtDarwinBG',
2135        'kTaskVisVisible',
2136        'kTaskVisNonvisible',
2137        'kTaskIsForeground',
2138        'kTaskIsBoosted',
2139        'kTaskIsSuppressed',
2140        'kTaskIsTimerThrottled',
2141        'kTaskIsImpDonor',
2142        'kTaskIsLiveImpDonor',
2143        'kTaskIsDirty',
2144        'kTaskWqExceededConstrainedThreadLimit',
2145        'kTaskWqExceededTotalThreadLimit',
2146        'kTaskWqFlagsAvailable',
2147        'kTaskUUIDInfoFaultedIn',
2148        'kTaskUUIDInfoMissing',
2149        'kTaskUUIDInfoTriedFault',
2150        'kTaskSharedRegionInfoUnavailable',
2151        'kTaskTALEngaged',
2152        None,
2153        'kTaskIsDirtyTracked',
2154        'kTaskAllowIdleExit',
2155        'kTaskIsTranslated',
2156        'kTaskSharedRegionNone',
2157        'kTaskSharedRegionSystem',
2158        'kTaskSharedRegionOther',
2159        'kTaskDyldCompactInfoNone',
2160        'kTaskDyldCompactInfoTooBig',
2161        'kTaskDyldCompactInfoFaultedIn',
2162        'kTaskDyldCompactInfoMissing',
2163        'kTaskDyldCompactInfoTriedFault',
2164    ],
2165    'turnstile_flags': [
2166        'turnstile_status_unknown',
2167        'turnstile_status_locked_waitq',
2168        'turnstile_status_workqueue',
2169        'turnstile_status_thread',
2170        'turnstile_status_blocked_on_task',
2171        'turnstile_status_held_iplock',
2172    ],
2173}
2174PRETTIFY_FLAGS['stackshot_out_flags'] = PRETTIFY_FLAGS['stackshot_in_flags']
2175PRETTIFY_FLAGS['tts_ss_flags'] = PRETTIFY_FLAGS['ts_ss_flags']
2176
2177# Fields which should never be hexified
2178PRETTIFY_DONTHEX = {
2179    'stackshot_in_pid': True,
2180    'tts_pid': True,
2181    'ts_pid': True,
2182    'donating_pids': True,
2183    'ppid': True,
2184}
2185
2186# Only hex() the value if it is multiple digits
2187def prettify_hex(v):
2188    if v < -9 or v > 9:
2189        return hex(v)
2190    return str(v)
2191
2192def prettify_flags(v, flags):
2193    output=""
2194    seen = 0
2195    if v == 0:
2196        return "0"
2197    for (s, n) in zip(range(len(flags)),flags):
2198        if n is None:
2199            continue
2200        if (v & (2 ** s)):
2201            output += "|" + n
2202            seen |= 2 ** s
2203    if output == "":
2204        return prettify_hex(v)
2205    rest = (v & ~seen)
2206    if (rest != 0):
2207        output += "|" + prettify_hex(rest)
2208    return prettify_hex(v) + " (" + output[1:] + ")"
2209
2210def prettify_core(data, mosthex, key, portlabels):
2211    if key == 'stack_contents':
2212        (address,) = struct.unpack("<Q", struct.pack("B"*8, *data))
2213        return '0x%X' % address
2214
2215    elif isinstance(data, list):
2216        if 'uuid' in key.lower() and len(data) == 16:
2217            return '%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X' % tuple(data)
2218
2219        return [prettify_core(x, mosthex, key, portlabels) for x in data]
2220
2221    elif key == 'thread_waitinfo':
2222        return formatWaitInfo(data, mosthex, portlabels)
2223
2224    elif isinstance(data, dict):
2225        if 'portlabels' in data:
2226            portlabels = data['portlabels']
2227        newdata = dict()
2228        for key, value in data.items():
2229            if mosthex and key != 'task_snapshots' and len(key) > 0 and key.isnumeric():
2230                key = prettify_hex(int(key))
2231            newdata[key] = prettify_core(value, mosthex, key, portlabels)
2232        return newdata
2233
2234    elif 'address' in key.lower() and isinstance(data, (int, long)):
2235        return '0x%X' % data
2236    elif key == 'lr' or key == SC_SLID_FIRSTMAPPING_KEY:
2237        return '0x%X' % data
2238    elif key in PRETTIFY_FLAGS and isinstance(data, (int, long)):
2239        return prettify_flags(data, PRETTIFY_FLAGS[key])
2240    elif key.endswith('_flags') and isinstance(data, (int, long)):
2241        return prettify_hex(data)
2242
2243    elif mosthex and not PRETTIFY_DONTHEX.get(key, False):
2244        if isinstance(data, (int, long)):
2245            return prettify_hex(data)
2246        elif isinstance(data, six.string_types) and len(data) > 0 and data.isnumeric():
2247            return prettify_hex(int(data))
2248        return data
2249
2250    else:
2251        return data
2252
2253def prettify(data, mosthex):
2254    return prettify_core(data, mosthex, "", None)
2255
2256# N.B.: This is called directly from `xnu.py` for `panicdata -S XXX.ips`'s implementation.
2257def decode_kcdata_file(kcdata_file, stackshot_file, multiple=False, prettyhex=False, pretty=False, output_as_plist=False):
2258    for i,kcdata_buffer in enumerate(iterate_kcdatas(kcdata_file)):
2259        if i > 0 and not multiple:
2260            break
2261
2262        str_data = "{" + kcdata_buffer.GetJsonRepr() + "}"
2263        str_data = str_data.replace("\t", "    ")
2264
2265        try:
2266            json_obj = json.loads(str_data)
2267        except:
2268            print("JSON reparsing failed!  Printing string data!\n", file=sys.stderr)
2269            import textwrap
2270            print(textwrap.fill(str_data, 100))
2271            raise
2272
2273        if prettyhex:
2274            json_obj = prettify(json_obj, True)
2275        elif pretty:
2276            json_obj = prettify(json_obj, False)
2277
2278        if stackshot_file:
2279            SaveStackshotReport(json_obj, stackshot_file, G.data_was_incomplete)
2280        elif output_as_plist:
2281            import Foundation
2282            plist = Foundation.NSPropertyListSerialization.dataWithPropertyList_format_options_error_(
2283                json_obj, Foundation.NSPropertyListXMLFormat_v1_0, 0, None)[0].bytes().tobytes()
2284            #sigh.  on some pythons long integers are getting output with L's in the plist.
2285            plist = re.sub(r'^(\s*<integer>\d+)L(</integer>\s*)$', r"\1\2", BytesToString(plist), flags=re.MULTILINE)
2286            print(plist,)
2287        else:
2288            print(json.dumps(json_obj, sort_keys=True, indent=4, separators=(',', ': ')))
2289
2290if __name__ == '__main__':
2291    parser = argparse.ArgumentParser(description="Decode a kcdata binary file.")
2292    parser.add_argument("-l", "--listtypes", action="store_true", required=False, default=False,
2293                        help="List all known types",
2294                        dest="list_known_types")
2295
2296    parser.add_argument("-s", "--stackshot", required=False, default=False,
2297                        help="Generate a stackshot report file",
2298                        dest="stackshot_file")
2299
2300    parser.add_argument("--multiple", help="look for multiple stackshots in a single file", action='store_true')
2301
2302    parser.add_argument("-p", "--plist", required=False, default=False,
2303                        help="output as plist", action="store_true")
2304
2305    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")
2306    parser.add_argument("-P", "--pretty", default=False, action='store_true', help="make the output a little more human readable")
2307    parser.add_argument("-X", "--prettyhex", default=False, action='store_true', help="make the output a little more human readable, and print most things as hex")
2308    parser.add_argument("--incomplete", action='store_true', help="accept incomplete data")
2309    parser.add_argument("kcdata_file", type=argparse.FileType('r'), help="Path to a kcdata binary file.")
2310
2311    class VerboseAction(argparse.Action):
2312        def __call__(self, parser, namespace, values, option_string=None):
2313            logging.basicConfig(level=logging.INFO, stream=sys.stderr, format='%(message)s')
2314    parser.add_argument('-v', "--verbose", action=VerboseAction, nargs=0)
2315
2316    args = parser.parse_args()
2317
2318    if args.multiple and args.stackshot_file:
2319        raise NotImplementedError
2320
2321    if args.list_known_types:
2322        for (n, t) in KNOWN_TYPES_COLLECTION.items():
2323            print("%d : %s " % (n, str(t)))
2324        sys.exit(1)
2325
2326    if args.incomplete or args.stackshot_file:
2327        G.accept_incomplete_data = True
2328
2329    decode_kcdata_file(args.kcdata_file, args.stackshot_file, args.multiple, args.prettyhex, args.pretty, args.plist)
2330