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