xref: /xnu-8020.121.3/tools/lldbmacros/kcdata.py (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
1#!/usr/bin/env python3
2from __future__ import absolute_import, print_function, division
3import sys
4import struct
5import mmap
6import json
7import copy
8import re
9import base64
10import argparse
11import 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    'STACKSHOT_KCCONTAINER_PORTLABEL' : 0x934,
121    'STACKSHOT_KCTYPE_PORTLABEL' : 0x935,
122    'STACKSHOT_KCTYPE_PORTLABEL_NAME' : 0x936,
123    'STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT': 0x940,
124    'STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT': 0x941,
125
126    'KCDATA_TYPE_BUFFER_END':      0xF19158ED,
127
128    'TASK_CRASHINFO_EXTMODINFO':           0x801,
129    'TASK_CRASHINFO_BSDINFOWITHUNIQID':    0x802,
130    'TASK_CRASHINFO_TASKDYLD_INFO':        0x803,
131    'TASK_CRASHINFO_UUID':                 0x804,
132    'TASK_CRASHINFO_PID':                  0x805,
133    'TASK_CRASHINFO_PPID':                 0x806,
134
135    # Don't want anyone using this.  It's struct rusage from whatever machine generated the data
136    #'TASK_CRASHINFO_RUSAGE':               0x807,
137    'Type_0x807':               0x807,
138
139    'TASK_CRASHINFO_RUSAGE_INFO':          0x808,
140    'TASK_CRASHINFO_PROC_NAME':            0x809,
141    'TASK_CRASHINFO_PROC_STARTTIME':       0x80B,
142    'TASK_CRASHINFO_USERSTACK':            0x80C,
143    'TASK_CRASHINFO_ARGSLEN':              0x80D,
144    'TASK_CRASHINFO_EXCEPTION_CODES':      0x80E,
145    'TASK_CRASHINFO_PROC_PATH':            0x80F,
146    'TASK_CRASHINFO_PROC_CSFLAGS':         0x810,
147    'TASK_CRASHINFO_PROC_STATUS':          0x811,
148    'TASK_CRASHINFO_UID':                  0x812,
149    'TASK_CRASHINFO_GID':                  0x813,
150    'TASK_CRASHINFO_PROC_ARGC':            0x814,
151    'TASK_CRASHINFO_PROC_FLAGS':           0x815,
152    'TASK_CRASHINFO_CPUTYPE':              0x816,
153    'TASK_CRASHINFO_WORKQUEUEINFO':        0x817,
154    'TASK_CRASHINFO_RESPONSIBLE_PID':      0x818,
155    'TASK_CRASHINFO_DIRTY_FLAGS':          0x819,
156    'TASK_CRASHINFO_CRASHED_THREADID':     0x81A,
157    'TASK_CRASHINFO_COALITION_ID':         0x81B,
158    'EXIT_REASON_SNAPSHOT':                0x1001,
159    'EXIT_REASON_USER_DESC':               0x1002,
160    'EXIT_REASON_USER_PAYLOAD':            0x1003,
161    'EXIT_REASON_CODESIGNING_INFO':        0x1004,
162    'EXIT_REASON_WORKLOOP_ID':             0x1005,
163    'EXIT_REASON_DISPATCH_QUEUE_NO':       0x1006,
164    'KCDATA_BUFFER_BEGIN_CRASHINFO':       0xDEADF157,
165    'KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT': 0xDE17A59A,
166    'KCDATA_BUFFER_BEGIN_STACKSHOT':       0x59a25807,
167    'KCDATA_BUFFER_BEGIN_COMPRESSED':      0x434f4d50,
168    'KCDATA_BUFFER_BEGIN_OS_REASON':       0x53A20900,
169    'KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG':  0x1E21C09F
170}
171kcdata_type_def_rev = dict((v, k) for k, v in iter(kcdata_type_def.items()))
172
173KNOWN_TYPES_COLLECTION = {}
174
175KNOWN_TOPLEVEL_CONTAINER_TYPES = ()
176
177def enum(**args):
178    return type('enum', (), args)
179
180#
181# Decode bytes as UTF-8, using surrogateescape if there are invalid UTF-8
182# sequences; see PEP-383
183#
184def BytesToString(b):
185    if isinstance(b, six.string_types):
186        return b
187    return b.decode('utf-8', errors="surrogateescape")
188
189# important keys
190SC_SLID_FIRSTMAPPING_KEY = 'sharedCacheSlidFirstMapping'
191
192# important builtin types
193KCSUBTYPE_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)
194
195
196LEGAL_OLD_STYLE_ARRAY_TYPE_NAMES = ['KCDATA_TYPE_LIBRARY_LOADINFO',
197                                    'KCDATA_TYPE_LIBRARY_LOADINFO64',
198                                    'STACKSHOT_KCTYPE_KERN_STACKFRAME',
199                                    'STACKSHOT_KCTYPE_USER_STACKFRAME',
200                                    'STACKSHOT_KCTYPE_KERN_STACKFRAME64',
201                                    'STACKSHOT_KCTYPE_USER_STACKFRAME64',
202                                    'STACKSHOT_KCTYPE_DONATING_PIDS',
203                                    'STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT']
204
205KCDATA_FLAGS_STRUCT_PADDING_MASK = 0xf
206KCDATA_FLAGS_STRUCT_HAS_PADDING = 0x80
207
208class KCSubTypeElement(object):
209    """convert kcdata_subtype_descriptor to """
210    _unpack_formats = (None, 'c', 'b', 'B', 'h', 'H', 'i', 'I', 'q', 'Q')
211    _ctypes = ('Unknown', 'char', 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', 'uint32_t', 'int64_t', 'uint64_t')
212
213    def __init__(self, st_name, st_type, st_size, st_offset=0, st_flag=0, custom_repr=None):
214        self.name = st_name
215        self.offset = st_offset
216        self.type_id = st_type
217        if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
218            raise ValueError("Invalid type passed %d" % st_type)
219        self.unpack_fmt = KCSubTypeElement._unpack_formats[self.type_id]
220        self.size = st_size
221        self.totalsize = st_size
222        self.count = 1
223        self.is_array_type = False
224        self.custom_JsonRepr = custom_repr
225        if (st_flag & 0x1) == 0x1:
226            self.is_array_type = True
227            self.size = st_size & 0xffff
228            self.count = (st_size >> 16) & 0xffff
229            self.totalsize = self.size * self.count
230
231    @staticmethod
232    def GetSizeForArray(el_count, el_size):
233        return ((el_count & 0xffff) << 16) | (el_size & 0xffff)
234
235    @staticmethod
236    def FromBinaryTypeData(byte_data):
237        (st_flag, st_type, st_offset, st_size, st_name) = struct.unpack_from('=BBHI32s', byte_data)
238        st_name = BytesToString(st_name).rstrip('\0')
239        return KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag)
240
241    @staticmethod
242    def FromBasicCtype(st_name, st_type, st_offset=0, legacy_size=None):
243        if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64:
244            raise ValueError("Invalid type passed %d" % st_type)
245        st_size = struct.calcsize(KCSubTypeElement._unpack_formats[st_type])
246        st_flag = 0
247        retval = KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag, KCSubTypeElement._get_naked_element_value)
248        if legacy_size:
249            retval.legacy_size = legacy_size
250        return retval
251
252    @staticmethod
253    def FromKCSubTypeElement(other, name_override=''):
254        _copy = copy.copy(other)
255        if name_override:
256            _copy.name = name_override
257        return copy
258
259    def GetName(self):
260        return self.name
261
262    def GetTotalSize(self):
263        return self.totalsize
264
265    def GetValueAsString(self, base_data, array_pos=0):
266        v = self.GetValue(base_data, array_pos)
267        if isinstance(v, bytes):
268            return BytesToString(v)
269        return str(v)
270
271    def GetValue(self, base_data, array_pos=0):
272        return struct.unpack_from(self.unpack_fmt, base_data[self.offset + (array_pos * self.size):])[0]
273
274    @staticmethod
275    def _get_naked_element_value(elementValue, elementName):
276        return json.dumps(elementValue)
277
278    def __str__(self):
279        if self.is_array_type:
280            return '[%d,%d] %s  %s[%d];' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name, self.count)
281        return '[%d,%d] %s  %s;' % (self.offset, self.totalsize, self.GetCTypeDesc(), self.name)
282
283    def __repr__(self):
284        return str(self)
285
286    def GetCTypeDesc(self):
287        return KCSubTypeElement._ctypes[self.type_id]
288
289    def GetStringRepr(self, base_data):
290        if not self.is_array_type:
291            return self.GetValueAsString(base_data)
292        if self.type_id == KCSUBTYPE_TYPE.KC_ST_CHAR:
293            str_len = self.count
294            if len(base_data) < str_len:
295                str_len = len(base_data)
296            str_arr = []
297            for i in range(str_len):
298                _v = self.GetValue(base_data, i)
299                if ord(_v) == 0:
300                    break
301                str_arr.append(self.GetValueAsString(base_data, i))
302            return json.dumps(''.join(str_arr))
303
304        count = self.count
305        if count > len(base_data)//self.size:
306            count = len(base_data)//self.size
307
308        o = '[' + ','.join([self.GetValueAsString(base_data, i) for i in range(count)]) + ']'
309
310        return o
311
312    def GetJsonRepr(self, base_data, flags=0):
313        if (flags & (KCDATA_FLAGS_STRUCT_HAS_PADDING | KCDATA_FLAGS_STRUCT_PADDING_MASK)) != 0:
314            padding = (flags & KCDATA_FLAGS_STRUCT_PADDING_MASK)
315            if padding:
316                base_data = base_data[:-padding]
317        if self.custom_JsonRepr:
318            if self.is_array_type:
319                e_data = [self.GetValue(base_data, i) for i in range(self.count)]
320            else:
321                e_data = self.GetValue(base_data)
322            return self.custom_JsonRepr(e_data, self.name)
323        return self.GetStringRepr(base_data)
324
325    def sizeof(self):
326        return self.totalsize
327
328    def ShouldSkip(self, data):
329        return len(data) < self.offset + self.totalsize
330
331    def ShouldMerge(self):
332        return False
333
334
335class KCTypeDescription(object):
336    def __init__(self, t_type_id, t_elements=[], t_name='anon', custom_repr=None, legacy_size=None, merge=False, naked=False):
337        self.type_id = t_type_id
338        self.elements = t_elements
339        self.name = t_name
340        self.totalsize = 0
341        self.custom_JsonRepr = custom_repr
342        if legacy_size:
343            self.legacy_size = legacy_size
344        self.merge = merge
345        self.naked = naked
346        for e in self.elements:
347            self.totalsize += e.GetTotalSize()
348
349    def ValidateData(self, base_data):
350        if len(base_data) >= self.totalsize:
351            return True
352        return False
353
354    def GetTypeID(self):
355        return self.type_id
356
357    def GetName(self):
358        return self.name
359
360    def __str__(self):
361        o = '%s {\n\t' % self.name + "\n\t".join([str(e) for e in self.elements]) + '\n};'
362        return o
363
364    @staticmethod
365    def FromKCTypeDescription(other, t_type_id, t_name):
366        retval = KCTypeDescription(t_type_id, other.elements, t_name, other.custom_JsonRepr,
367                                   legacy_size=getattr(other, 'legacy_size', None))
368        return retval
369
370    def ShouldMerge(self):
371        return self.merge
372
373    def GetJsonRepr(self, base_data, flags):
374        if (flags & (KCDATA_FLAGS_STRUCT_HAS_PADDING | KCDATA_FLAGS_STRUCT_PADDING_MASK)) != 0:
375            padding = (flags & KCDATA_FLAGS_STRUCT_PADDING_MASK)
376            if padding:
377                base_data = base_data[:-padding]
378        elif hasattr(self, 'legacy_size') and len(base_data) == self.legacy_size + ((-self.legacy_size) & 0xf):
379            base_data = base_data[:self.legacy_size]
380        if self.custom_JsonRepr:
381            return self.custom_JsonRepr([e.GetValue(base_data) for e in self.elements])
382        if self.naked:
383            o = ", ".join([e.GetJsonRepr(base_data) for e in self.elements if not e.ShouldSkip(base_data)])
384        else:
385            o = ", ".join(['"%s": %s' % (e.GetName(), e.GetJsonRepr(base_data)) for e in self.elements if not e.ShouldSkip(base_data)])
386        if not self.merge:
387            o = '{' + o + '}'
388        return o
389
390    def sizeof(self):
391        return max(st.totalsize + st.offset for st in self.elements)
392
393
394def GetTypeNameForKey(k):
395    retval = "0x%x" % k
396    if k in KNOWN_TYPES_COLLECTION:
397        retval = KNOWN_TYPES_COLLECTION[k].GetName()
398    elif k in kcdata_type_def_rev:
399        retval = kcdata_type_def_rev[k]
400    return retval
401
402
403def GetTypeForName(n):
404    ret = 0
405    if n in kcdata_type_def:
406        ret = kcdata_type_def[n]
407    return ret
408
409
410LEGAL_OLD_STYLE_ARRAY_TYPES = list(map(GetTypeForName, LEGAL_OLD_STYLE_ARRAY_TYPE_NAMES))
411
412kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_STACKSHOT')] = 'kcdata_stackshot'
413kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT')] = 'kcdata_delta_stackshot'
414kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_CRASHINFO')] = 'kcdata_crashinfo'
415kcdata_type_def_rev[GetTypeForName('KCDATA_BUFFER_BEGIN_OS_REASON')] = 'kcdata_reason'
416kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_TASK')] = 'task_snapshots'
417kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_TRANSITIONING_TASK')] = 'transitioning_task_snapshots'
418kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_THREAD')] = 'thread_snapshots'
419kcdata_type_def_rev[GetTypeForName('STACKSHOT_KCCONTAINER_PORTLABEL')] = 'portlabels'
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                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 25),
1113                        KCSubTypeElement.FromBasicCtype('wait_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 27)
1114            ),
1115            'thread_waitinfo')
1116
1117KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO'),
1118            (
1119                        KCSubTypeElement.FromBasicCtype('waiter', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1120                        KCSubTypeElement.FromBasicCtype('turnstile_context', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1121                        KCSubTypeElement.FromBasicCtype('turnstile_priority', KCSUBTYPE_TYPE.KC_ST_UINT8, 16),
1122                        KCSubTypeElement.FromBasicCtype('number_of_hops', KCSUBTYPE_TYPE.KC_ST_UINT8, 17),
1123                        KCSubTypeElement.FromBasicCtype('turnstile_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 18),
1124                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 26),
1125            ),
1126            'thread_turnstileinfo')
1127
1128KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL'),
1129            (
1130                        KCSubTypeElement.FromBasicCtype('portlabel_id', KCSUBTYPE_TYPE.KC_ST_INT16, 0),
1131                        KCSubTypeElement.FromBasicCtype('portlabel_flags', KCSUBTYPE_TYPE.KC_ST_UINT16, 2),
1132                        KCSubTypeElement.FromBasicCtype('portlabel_domain', KCSUBTYPE_TYPE.KC_ST_UINT8, 4),
1133            ),
1134            'portlabel_info', merge=True)
1135
1136KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PORTLABEL_NAME')] = (
1137    KCSubTypeElement("portlabel_name", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1138
1139KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP'),
1140            (
1141                        KCSubTypeElement.FromBasicCtype('tgs_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1142                        KCSubTypeElement('tgs_name', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(16, 1),
1143                            8, 1),
1144                        KCSubTypeElement.FromBasicCtype('tgs_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1145                        KCSubTypeElement('tgs_name_cont', KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(16, 1),
1146                            32, 1),
1147            ),
1148            'thread_group_snapshot')
1149
1150
1151KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_THREAD_GROUP')] = KCSubTypeElement('thread_group', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1152
1153KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT'),
1154            (
1155                        KCSubTypeElement.FromBasicCtype('jcs_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1156                        KCSubTypeElement.FromBasicCtype('jcs_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1157                        KCSubTypeElement.FromBasicCtype('jcs_thread_group', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1158                        KCSubTypeElement.FromBasicCtype('jcs_leader_task_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1159            ),
1160            'jetsam_coalition_snapshot')
1161
1162KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_JETSAM_COALITION')] = KCSubTypeElement('jetsam_coalition', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value)
1163
1164KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_INSTRS_CYCLES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_INSTRS_CYCLES'),
1165            (
1166                        KCSubTypeElement.FromBasicCtype('ics_instructions', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1167                        KCSubTypeElement.FromBasicCtype('ics_cycles', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)
1168            ),
1169            'instrs_cycles_snapshot')
1170
1171KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE'),
1172            (
1173                        KCSubTypeElement.FromBasicCtype('cputype', KCSUBTYPE_TYPE.KC_ST_INT32, 0),
1174                        KCSubTypeElement.FromBasicCtype('cpusubtype', KCSUBTYPE_TYPE.KC_ST_INT32, 4)
1175            ),
1176            'task_cpu_architecture')
1177
1178KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO'),
1179            (
1180                        KCSubTypeElement.FromBasicCtype('latency_version', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1181                        KCSubTypeElement.FromBasicCtype('setup_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1182                        KCSubTypeElement.FromBasicCtype('total_task_iteration_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1183                        KCSubTypeElement.FromBasicCtype('total_terminated_task_iteration', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1184            ),
1185            'stackshot_latency_collection')
1186
1187KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_TASK')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_TASK'),
1188            (
1189                        KCSubTypeElement.FromBasicCtype('task_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1190                        KCSubTypeElement.FromBasicCtype('setup_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1191                        KCSubTypeElement.FromBasicCtype('task_thread_count_loop_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1192                        KCSubTypeElement.FromBasicCtype('task_thread_data_loop_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1193                        KCSubTypeElement.FromBasicCtype('cur_tsnap_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1194                        KCSubTypeElement.FromBasicCtype('pmap_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1195                        KCSubTypeElement.FromBasicCtype('bsd_proc_ids_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1196                        KCSubTypeElement.FromBasicCtype('misc_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1197                        KCSubTypeElement.FromBasicCtype('misc2_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1198                        KCSubTypeElement.FromBasicCtype('end_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 72)
1199            ),
1200            'stackshot_latency_task')
1201
1202KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_THREAD')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_LATENCY_INFO_THREAD'),
1203            (
1204                        KCSubTypeElement.FromBasicCtype('thread_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1205                        KCSubTypeElement.FromBasicCtype('cur_thsnap1_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1206                        KCSubTypeElement.FromBasicCtype('dispatch_serial_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1207                        KCSubTypeElement.FromBasicCtype('dispatch_label_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1208                        KCSubTypeElement.FromBasicCtype('cur_thsnap2_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1209                        KCSubTypeElement.FromBasicCtype('thread_name_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1210                        KCSubTypeElement.FromBasicCtype('sur_times_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1211                        KCSubTypeElement.FromBasicCtype('user_stack_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1212                        KCSubTypeElement.FromBasicCtype('kernel_stack_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1213                        KCSubTypeElement.FromBasicCtype('misc_latency', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
1214            ),
1215            'stackshot_latency_thread')
1216
1217def set_type(name, *args):
1218    typ = GetTypeForName(name)
1219    KNOWN_TYPES_COLLECTION[typ] = KCTypeDescription(GetTypeForName(typ), *args)
1220
1221
1222set_type('STACKSHOT_KCTYPE_USER_STACKTOP',
1223         (
1224             KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1225             KCSubTypeElement('stack_contents', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(8, 1), 8, 1),
1226         ),
1227         'user_stacktop')
1228
1229#KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement('donating_pids', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0, KCSubTypeElement._get_naked_element_value)
1230KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PID')] = KCSubTypeElement('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1231KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PPID')] = KCSubTypeElement('ppid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1232KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_NAME')] = KCSubTypeElement('p_comm', KCSUBTYPE_TYPE.KC_ST_CHAR,
1233                           KCSubTypeElement.GetSizeForArray(32, 1), 0, 1)
1234KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_USERSTACK')] = KCSubTypeElement('userstack_ptr', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1235KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_ARGSLEN')] = KCSubTypeElement('p_argslen', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1236
1237KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_PATH')] = KCSubTypeElement('p_path', KCSUBTYPE_TYPE.KC_ST_CHAR,
1238                           KCSubTypeElement.GetSizeForArray(1024, 1), 0, 1)
1239KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_CSFLAGS')] = KCSubTypeElement('p_csflags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1240KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_UID')] = KCSubTypeElement('uid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1241KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_GID')] = KCSubTypeElement('gid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1242KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_ARGC')] = KCSubTypeElement('argc', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1243KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_FLAGS')] = KCSubTypeElement('p_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1244KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CPUTYPE')] = KCSubTypeElement('cputype', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1245KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RESPONSIBLE_PID')] = KCSubTypeElement('responsible_pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1246KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_DIRTY_FLAGS')] = KCSubTypeElement('dirty_flags', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0)
1247KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_CRASHED_THREADID')] = KCSubTypeElement('crashed_threadid', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1248KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_COALITION_ID')] = KCSubTypeElement('coalition_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0)
1249
1250KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_STATUS')] = KCSubTypeElement('p_status', KCSUBTYPE_TYPE.KC_ST_UINT8, 1, 0, 0)
1251
1252KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_BSDINFOWITHUNIQID'),
1253    (   KCSubTypeElement('p_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
1254        KCSubTypeElement.FromBasicCtype('p_uniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1255        KCSubTypeElement.FromBasicCtype('p_puniqueid', KCSUBTYPE_TYPE.KC_ST_UINT64, 24)
1256    ),
1257    'proc_uniqidentifierinfo')
1258
1259KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_EXCEPTION_CODES')] = (
1260    KCTypeDescription(GetTypeForName('TASK_CRASHINFO_EXCEPTION_CODES'),
1261                      (KCSubTypeElement.FromBasicCtype('code_0', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1262                       KCSubTypeElement.FromBasicCtype('code_1', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)),
1263                      'mach_exception_data_t'))
1264
1265
1266KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_PROC_STARTTIME')] = (
1267    KCTypeDescription(GetTypeForName('TASK_CRASHINFO_PROC_STARTTIME'),
1268                      (KCSubTypeElement.FromBasicCtype('tv_sec', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1269                       KCSubTypeElement.FromBasicCtype('tv_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 8)),
1270                      'proc_starttime'))
1271
1272
1273KNOWN_TYPES_COLLECTION[GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO')] = KCTypeDescription(GetTypeForName('TASK_CRASHINFO_RUSAGE_INFO'),
1274    (
1275        KCSubTypeElement('ri_uuid', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 0, 1),
1276            KCSubTypeElement.FromBasicCtype('ri_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1277            KCSubTypeElement.FromBasicCtype('ri_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 24),
1278            KCSubTypeElement.FromBasicCtype('ri_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 32),
1279            KCSubTypeElement.FromBasicCtype('ri_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 40),
1280            KCSubTypeElement.FromBasicCtype('ri_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 48),
1281            KCSubTypeElement.FromBasicCtype('ri_wired_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 56),
1282            KCSubTypeElement.FromBasicCtype('ri_resident_size', KCSUBTYPE_TYPE.KC_ST_UINT64, 64),
1283            KCSubTypeElement.FromBasicCtype('ri_phys_footprint', KCSUBTYPE_TYPE.KC_ST_UINT64, 72),
1284            KCSubTypeElement.FromBasicCtype('ri_proc_start_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 80),
1285            KCSubTypeElement.FromBasicCtype('ri_proc_exit_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 88),
1286            KCSubTypeElement.FromBasicCtype('ri_child_user_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 96),
1287            KCSubTypeElement.FromBasicCtype('ri_child_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 104),
1288            KCSubTypeElement.FromBasicCtype('ri_child_pkg_idle_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 112),
1289            KCSubTypeElement.FromBasicCtype('ri_child_interrupt_wkups', KCSUBTYPE_TYPE.KC_ST_UINT64, 120),
1290            KCSubTypeElement.FromBasicCtype('ri_child_pageins', KCSUBTYPE_TYPE.KC_ST_UINT64, 128),
1291            KCSubTypeElement.FromBasicCtype('ri_child_elapsed_abstime', KCSUBTYPE_TYPE.KC_ST_UINT64, 136),
1292            KCSubTypeElement.FromBasicCtype('ri_diskio_bytesread', KCSUBTYPE_TYPE.KC_ST_UINT64, 144),
1293            KCSubTypeElement.FromBasicCtype('ri_diskio_byteswritten', KCSUBTYPE_TYPE.KC_ST_UINT64, 152),
1294            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_default', KCSUBTYPE_TYPE.KC_ST_UINT64, 160),
1295            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_maintenance', KCSUBTYPE_TYPE.KC_ST_UINT64, 168),
1296            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_background', KCSUBTYPE_TYPE.KC_ST_UINT64, 176),
1297            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_utility', KCSUBTYPE_TYPE.KC_ST_UINT64, 184),
1298            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_legacy', KCSUBTYPE_TYPE.KC_ST_UINT64, 192),
1299            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_initiated', KCSUBTYPE_TYPE.KC_ST_UINT64, 200),
1300            KCSubTypeElement.FromBasicCtype('ri_cpu_time_qos_user_interactiv', KCSUBTYPE_TYPE.KC_ST_UINT64, 208),
1301            KCSubTypeElement.FromBasicCtype('ri_billed_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 216),
1302            KCSubTypeElement.FromBasicCtype('ri_serviced_system_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 224)
1303    ),
1304    'rusage_info')
1305
1306KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_CPU_TIMES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_CPU_TIMES'),
1307    (
1308        KCSubTypeElement.FromBasicCtype('user_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1309        KCSubTypeElement.FromBasicCtype('system_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1310        KCSubTypeElement.FromBasicCtype('runnable_usec', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1311    ), 'cpu_times')
1312
1313KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_DURATION')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_STACKSHOT_DURATION'),
1314    (
1315        KCSubTypeElement.FromBasicCtype('stackshot_duration', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1316        KCSubTypeElement.FromBasicCtype('stackshot_duration_outer', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1317        KCSubTypeElement.FromBasicCtype('stackshot_duration_prior', KCSUBTYPE_TYPE.KC_ST_UINT64, 16),
1318    ), 'stackshot_duration', merge=True
1319)
1320
1321KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_PROCNAME')] = (
1322    KCSubTypeElement("proc_name", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1323
1324KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_PID')] = (
1325    KCSubTypeElement('pid', KCSUBTYPE_TYPE.KC_ST_INT32, 4, 0, 0))
1326
1327KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_AOTINFO')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_AOTINFO'),
1328    (
1329        KCSubTypeElement('x86LoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0),
1330        KCSubTypeElement('aotLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 8, 0),
1331        KCSubTypeElement('aotImageSize', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 16, 0),
1332        KCSubTypeElement('aotImageKey', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(32, 1), 24, 1),
1333    ), 'dyld_aot_info')
1334
1335KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_SNAPSHOT')] = KCTypeDescription(GetTypeForName('EXIT_REASON_SNAPSHOT'),
1336    (
1337        KCSubTypeElement.FromBasicCtype('ers_namespace', KCSUBTYPE_TYPE.KC_ST_UINT32, 0),
1338        KCSubTypeElement.FromBasicCtype('ers_code', KCSUBTYPE_TYPE.KC_ST_UINT64, 4),
1339        KCSubTypeElement.FromBasicCtype('ers_flags', KCSUBTYPE_TYPE.KC_ST_UINT64, 12),
1340    ), 'exit_reason_basic_info')
1341
1342KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_USER_DESC')] = (
1343    KCSubTypeElement("exit_reason_user_description", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1))
1344
1345KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_USER_PAYLOAD')] = KCSubTypeElement('exit_reason_user_payload',
1346        KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(-1, 1), 0, 1)
1347
1348KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_CODESIGNING_INFO')] = KCTypeDescription(GetTypeForName('EXIT_REASON_CODESIGNING_INFO'),
1349    (
1350        KCSubTypeElement.FromBasicCtype('ceri_virt_addr', KCSUBTYPE_TYPE.KC_ST_UINT64, 0),
1351        KCSubTypeElement.FromBasicCtype('ceri_file_offset', KCSUBTYPE_TYPE.KC_ST_UINT64, 8),
1352        KCSubTypeElement("ceri_pathname", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(1024, 1), 16, 1),
1353        KCSubTypeElement("ceri_filename", KCSUBTYPE_TYPE.KC_ST_CHAR, KCSubTypeElement.GetSizeForArray(1024, 1), 1040, 1),
1354        KCSubTypeElement.FromBasicCtype('ceri_codesig_modtime_secs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2064),
1355        KCSubTypeElement.FromBasicCtype('ceri_codesig_modtime_nsecs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2072),
1356        KCSubTypeElement.FromBasicCtype('ceri_page_modtime_secs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2080),
1357        KCSubTypeElement.FromBasicCtype('ceri_page_modtime_nsecs', KCSUBTYPE_TYPE.KC_ST_UINT64, 2088),
1358        KCSubTypeElement.FromBasicCtype('ceri_path_truncated', KCSUBTYPE_TYPE.KC_ST_UINT8, 2096),
1359        KCSubTypeElement.FromBasicCtype('ceri_object_codesigned', KCSUBTYPE_TYPE.KC_ST_UINT8, 2097),
1360        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_validated', KCSUBTYPE_TYPE.KC_ST_UINT8, 2098),
1361        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_tainted', KCSUBTYPE_TYPE.KC_ST_UINT8, 2099),
1362        KCSubTypeElement.FromBasicCtype('ceri_page_codesig_nx', KCSUBTYPE_TYPE.KC_ST_UINT8, 2100),
1363        KCSubTypeElement.FromBasicCtype('ceri_page_wpmapped', KCSUBTYPE_TYPE.KC_ST_UINT8, 2101),
1364        KCSubTypeElement.FromBasicCtype('ceri_page_slid', KCSUBTYPE_TYPE.KC_ST_UINT8, 2102),
1365        KCSubTypeElement.FromBasicCtype('ceri_page_dirty', KCSUBTYPE_TYPE.KC_ST_UINT8, 2103),
1366        KCSubTypeElement.FromBasicCtype('ceri_page_shadow_depth', KCSUBTYPE_TYPE.KC_ST_UINT32, 2104),
1367    ), 'exit_reason_codesigning_info')
1368
1369KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_WORKLOOP_ID')] = (
1370        KCSubTypeElement('exit_reason_workloop_id', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value))
1371
1372KNOWN_TYPES_COLLECTION[GetTypeForName('EXIT_REASON_DISPATCH_QUEUE_NO')] = (
1373        KCSubTypeElement('exit_reason_dispatch_queue_no', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value))
1374
1375KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_ASID')] = (
1376    KCSubTypeElement('ts_asid', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0))
1377
1378KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_PAGE_TABLES')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_PAGE_TABLES'), (
1379    KCSubTypeElement(None, KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value), ),
1380    'ts_pagetable',
1381    merge=True,
1382    naked=True
1383)
1384
1385def GetSecondsFromMATime(mat, tb):
1386    return (float(long(mat) * tb['numer']) / tb['denom']) / 1e9
1387
1388def GetLongForAddress(address):
1389    if isinstance(address, six.string_types):
1390        if '0x' in address.lower():
1391            address = long(address, 16)
1392        else:
1393            address = long(address)
1394    return address
1395
1396def FindLibraryForAddress(liblist, address):
1397    current_lib = None
1398    for l in liblist:
1399        l_addr = GetLongForAddress(l[1])
1400        if address >= l_addr:
1401            current_lib = l
1402    return current_lib
1403
1404def FindIndexOfLibInCatalog(catalog, lib):
1405    index = None
1406    i = 0
1407    for l in catalog:
1408        if l[0] == lib[0] and l[1] == lib[1]:
1409            index = i
1410            break
1411        i += 1
1412
1413    if index is None:
1414        catalog.append(lib)
1415        index = len(catalog) - 1
1416
1417    return index
1418
1419def GetOffsetOfAddressForLib(lib, address):
1420    return (address - GetLongForAddress(lib[1]))
1421
1422def GetSymbolInfoForFrame(catalog, liblist, address):
1423    address = GetLongForAddress(address)
1424    lib = FindLibraryForAddress(liblist, address)
1425    if not lib:
1426        lib = ["00000000000000000000000000000000",0,"A"]
1427    offset = GetOffsetOfAddressForLib(lib, address)
1428    index = FindIndexOfLibInCatalog(catalog, lib)
1429    return [index, offset]
1430
1431def GetStateDescription(s):
1432    retval = []
1433    TH_WAIT = 0x01
1434    TH_SUSP = 0x02
1435    TH_RUN = 0x04
1436    TH_UNINT = 0x08
1437    TH_TERMINATE = 0x10
1438    TH_TERMINATE2 = 0x20
1439    TH_WAIT_REPORT = 0x40
1440    TH_IDLE = 0x80
1441    if (s & TH_WAIT):
1442        retval.append("TH_WAIT")
1443    if (s & TH_SUSP):
1444        retval.append("TH_SUSP")
1445    if (s & TH_RUN):
1446        retval.append("TH_RUN")
1447    if (s & TH_UNINT):
1448        retval.append("TH_UNINT")
1449    if (s & TH_TERMINATE):
1450        retval.append("TH_TERMINATE")
1451    if (s & TH_TERMINATE2):
1452        retval.append("TH_TERMINATE2")
1453    if (s & TH_WAIT_REPORT):
1454        retval.append("TH_WAIT_REPORT")
1455    if (s & TH_IDLE):
1456        retval.append("TH_IDLE")
1457    return retval
1458
1459
1460def format_uuid(elementValues):
1461    # sometimes we get string like "25A926D8-F742-3E5E..."
1462    if isinstance(elementValues, six.string_types):
1463        return elementValues
1464    return ''.join("%02x" % i for i in elementValues)
1465
1466kThreadWaitNone			= 0x00
1467kThreadWaitKernelMutex          = 0x01
1468kThreadWaitPortReceive          = 0x02
1469kThreadWaitPortSetReceive       = 0x03
1470kThreadWaitPortSend             = 0x04
1471kThreadWaitPortSendInTransit    = 0x05
1472kThreadWaitSemaphore            = 0x06
1473kThreadWaitKernelRWLockRead     = 0x07
1474kThreadWaitKernelRWLockWrite    = 0x08
1475kThreadWaitKernelRWLockUpgrade  = 0x09
1476kThreadWaitUserLock             = 0x0a
1477kThreadWaitPThreadMutex         = 0x0b
1478kThreadWaitPThreadRWLockRead    = 0x0c
1479kThreadWaitPThreadRWLockWrite   = 0x0d
1480kThreadWaitPThreadCondVar       = 0x0e
1481kThreadWaitParkedWorkQueue      = 0x0f
1482kThreadWaitWorkloopSyncWait     = 0x10
1483kThreadWaitOnProcess            = 0x11
1484kThreadWaitSleepWithInheritor   = 0x12
1485kThreadWaitEventlink            = 0x13
1486kThreadWaitCompressor           = 0x14
1487
1488
1489UINT64_MAX = 0xffffffffffffffff
1490STACKSHOT_WAITOWNER_KERNEL      = (UINT64_MAX - 1)
1491STACKSHOT_WAITOWNER_PORT_LOCKED = (UINT64_MAX - 2)
1492STACKSHOT_WAITOWNER_PSET_LOCKED = (UINT64_MAX - 3)
1493STACKSHOT_WAITOWNER_INTRANSIT   = (UINT64_MAX - 4)
1494STACKSHOT_WAITOWNER_MTXSPIN     = (UINT64_MAX - 5)
1495STACKSHOT_WAITOWNER_THREQUESTED = (UINT64_MAX - 6)
1496STACKSHOT_WAITOWNER_SUSPENDED   = (UINT64_MAX - 7)
1497
1498STACKSHOT_TURNSTILE_STATUS_UNKNOWN         = 0x01
1499STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ    = 0x02
1500STACKSHOT_TURNSTILE_STATUS_WORKQUEUE       = 0x04
1501STACKSHOT_TURNSTILE_STATUS_THREAD          = 0x08
1502STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK = 0x10
1503STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK     = 0x20
1504STACKSHOT_TURNSTILE_STATUS_SENDPORT        = 0x40
1505STACKSHOT_TURNSTILE_STATUS_RECEIVEPORT     = 0x80
1506
1507#
1508# These come from xpc_domain_type_t in <xpc/launch_private.h>
1509PORTLABEL_DOMAINS = {
1510    1: 'system',        # XPC_DOMAIN_SYSTEM
1511    2: 'user',          # XPC_DOMAIN_USER
1512    5: 'pid',           # XPC_DOMAIN_PID
1513    7: 'port',          # XPC_DOMAIN_PORT
1514}
1515def portlabel_domain(x):
1516    if x is None:
1517        return "unknown"
1518    return PORTLABEL_DOMAINS.get(x, "unknown.{}".format(x))
1519
1520STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY = 0x1
1521
1522def formatPortLabelID(portlabel_id, portlabels):
1523    if portlabel_id > 0:
1524        portlabel = {}
1525        if portlabels is not None:
1526            portlabel = portlabels.get(str(portlabel_id), {})
1527        portlabel_name = portlabel_domain(portlabel.get('portlabel_domain')) + " "
1528        portlabel_name += portlabel.get("portlabel_name", "!!!unknown, ID {} !!!".format(portlabel_id));
1529        return " {" + portlabel_name + "}"
1530    if portlabel_id < 0:
1531        return" {labeled, info trucated}"
1532    return ""
1533
1534def formatWaitInfo(info, wantHex, portlabels):
1535    base='#x' if wantHex else 'd'
1536    s = 'thread {0:{base}}: '.format(info['waiter'], base=base)
1537    type = info['wait_type']
1538    context = info['context']
1539    owner = info['owner']
1540    ownerThread = "{0:{base}}".format(owner, base=base)
1541    portlabel_id = info.get('portlabel_id', 0)
1542    flags = info.get('wait_flags', 0)
1543
1544    if type == kThreadWaitKernelMutex:
1545        s += 'kernel mutex %x' % context
1546        if owner == STACKSHOT_WAITOWNER_MTXSPIN:
1547            s += " in spin mode"
1548        elif owner:
1549            s += " owned by thread %s" % ownerThread
1550        else:
1551            s += "with unknown owner"
1552    elif type == kThreadWaitPortReceive:
1553        s += "mach_msg receive on "
1554        if flags & STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY:
1555            s += "REPLY "
1556            flags = flags - STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY
1557        if owner == STACKSHOT_WAITOWNER_PORT_LOCKED:
1558            s += "locked port %x" % context
1559        elif owner == STACKSHOT_WAITOWNER_INTRANSIT:
1560            s += "intransit port %x" % context
1561        elif owner:
1562            s += "port %x name %x" % (context, owner)
1563        else:
1564            s += "port %x" % context
1565    elif type == kThreadWaitPortSetReceive:
1566        if owner == STACKSHOT_WAITOWNER_PSET_LOCKED:
1567            s += "mach_msg receive on locked port set %x" % context
1568        else:
1569            s += "mach_msg receive on port set %x" % context
1570    elif type == kThreadWaitPortSend:
1571        s += "mach_msg send on "
1572        if owner == STACKSHOT_WAITOWNER_PORT_LOCKED:
1573            s += "locked port %x" % context
1574        elif owner == STACKSHOT_WAITOWNER_INTRANSIT:
1575            s += "intransit port %x" % context
1576        elif owner == STACKSHOT_WAITOWNER_KERNEL:
1577            s += "port %x owned by kernel" % context
1578        elif owner:
1579            s += "port %x owned by pid %d" % (context, owner)
1580        else:
1581            s += "port %x with unknown owner" % context
1582    elif type == kThreadWaitPortSendInTransit:
1583        s += "mach_msg send on port %x in transit to " % context
1584        if owner:
1585            s += "port %x" % owner
1586        else:
1587            s += "unknown port"
1588    elif type == kThreadWaitSemaphore:
1589        s += "semaphore port %x " % context
1590        if owner:
1591            s += "owned by pid %d" % owner
1592        else:
1593            s += "with unknown owner"
1594    elif type == kThreadWaitKernelRWLockRead:
1595        s += "krwlock %x for reading" % context
1596        if owner:
1597            s += " owned by thread %s" % ownerThread
1598    elif type == kThreadWaitKernelRWLockWrite:
1599        s += "krwlock %x for writing" % context
1600        if owner:
1601            s += " owned by thread %s" % ownerThread
1602    elif type == kThreadWaitKernelRWLockUpgrade:
1603        s += "krwlock %x for upgrading" % context
1604        if owner:
1605            s += " owned by thread %s" % ownerThread
1606    elif type == kThreadWaitUserLock:
1607        if owner:
1608            s += "unfair lock %x owned by thread %s" % (context, ownerThread)
1609        else:
1610            s += "spin lock %x" % context
1611    elif type == kThreadWaitPThreadMutex:
1612        s += "pthread mutex %x" % context
1613        if owner:
1614            s += " owned by thread %s" % ownerThread
1615        else:
1616            s += " with unknown owner"
1617    elif type == kThreadWaitPThreadRWLockRead:
1618        s += "pthread rwlock %x for reading" % context
1619    elif type == kThreadWaitPThreadRWLockWrite:
1620        s += "pthread rwlock %x for writing" % context
1621    elif type == kThreadWaitPThreadCondVar:
1622        s += "pthread condvar %x" % context
1623    elif type == kThreadWaitWorkloopSyncWait:
1624        s += "workloop sync wait"
1625        if owner == STACKSHOT_WAITOWNER_SUSPENDED:
1626            s += ", suspended"
1627        elif owner == STACKSHOT_WAITOWNER_THREQUESTED:
1628            s += ", thread requested"
1629        elif owner != 0:
1630            s += ", owned by thread %s" % ownerThread
1631        else:
1632            s += ", unknown owner"
1633        s += ", workloop id %x" % context
1634    elif type == kThreadWaitOnProcess:
1635        if owner == 2**64-1:
1636            s += "waitpid, for any children"
1637        elif 2**32 <= owner and owner < 2**64-1:
1638            s += "waitpid, for process group %d" % abs(owner - 2**64)
1639        else:
1640            s += "waitpid, for pid %d" % owner
1641    elif type == kThreadWaitSleepWithInheritor:
1642        if owner == 0:
1643            s += "turnstile, held waitq"
1644        else:
1645            s += "turnstile, pushing thread %s" % ownerThread
1646    elif type == kThreadWaitEventlink:
1647        if owner == 0:
1648            s += "eventlink, held waitq"
1649        else:
1650            s += "eventlink, signaled by thread %s" % ownerThread
1651    elif type == kThreadWaitCompressor:
1652        s += "in compressor segment %x, busy for thread %s" % (context, ownerThread)
1653
1654    else:
1655        s += "unknown type %d (owner %s, context %x)" % (type, ownerThread, context)
1656
1657    s += formatPortLabelID(portlabel_id, portlabels)
1658
1659    if flags != 0:
1660        s += "flags {}".format(hex(flags))
1661    return s
1662
1663def formatTurnstileInfo(ti, wi_portlabel_id, portlabels):
1664    if ti is None:
1665        return " [no turnstile]"
1666
1667    ts_flags = int(ti['turnstile_flags'])
1668    ctx = int(ti['turnstile_context'])
1669    hop = int(ti['number_of_hops'])
1670    prio = int(ti['turnstile_priority'])
1671    portlabel_id = ti.get("portlabel_id", 0)
1672
1673    portlabel_summary = ""
1674    if portlabel_id != 0 and portlabel_id != wi_portlabel_id:
1675        portlabel_summary += formatPortLabelID(portlabel_id, portlabels)
1676
1677    if ts_flags & STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK:
1678        return " [turnstile blocked on task, but ip_lock was held]" + portlabel_summary
1679    if ts_flags & STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK:
1680        return " [turnstile blocked on task pid %d, hops: %d, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1681    if ts_flags & STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ:
1682        return " [turnstile was in process of being updated]" + portlabel_summary
1683    if ts_flags & STACKSHOT_TURNSTILE_STATUS_WORKQUEUE:
1684        return " [blocked on workqueue: 0x%x, hops: %x, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1685    if ts_flags & STACKSHOT_TURNSTILE_STATUS_THREAD:
1686        return " [blocked on: %d, hops: %x, priority: %d]%s" % (ctx, hop, prio, portlabel_summary)
1687    if ts_flags & STACKSHOT_TURNSTILE_STATUS_UNKNOWN:
1688        return " [turnstile with unknown inheritor]" + portlabel_summary
1689
1690    return " [unknown turnstile status!]" + portlabel_summary
1691
1692def formatWaitInfoWithTurnstiles(waitinfos, tsinfos, portlabels):
1693    wis_tis = []
1694    for w in waitinfos:
1695        found_pair = False
1696        for t in tsinfos:
1697            if int(w['waiter']) == int(t['waiter']):
1698                wis_tis.append((w, t))
1699                found_pair = True
1700                break
1701        if not found_pair:
1702            wis_tis.append((w, None))
1703
1704    return [formatWaitInfo(wi, False, portlabels) + formatTurnstileInfo(ti, wi.get('portlabel_id', 0), portlabels) for (wi, ti) in wis_tis]
1705
1706def SaveStackshotReport(j, outfile_name, incomplete):
1707    import time
1708    from operator import itemgetter, attrgetter
1709    ss = j.get('kcdata_stackshot')
1710    if not ss:
1711        print("No KCDATA_BUFFER_BEGIN_STACKSHOT object found. Skipping writing report.")
1712        return
1713
1714    timestamp = ss.get('usecs_since_epoch')
1715    try:
1716        timestamp = time.strftime("%Y-%m-%d %H:%M:%S +0000",time.gmtime(timestamp // 1000000 if timestamp else None))
1717    except ValueError as e:
1718        print("couldn't convert timestamp:", str(e))
1719        timestamp = None
1720
1721    os_version = ss.get('osversion', 'Unknown')
1722    timebase = ss.get('mach_timebase_info', {"denom": 1, "numer": 1})
1723
1724    sc_note = None
1725    extra_note = None
1726    dsc_common = None
1727    shared_cache_info = ss.get('shared_cache_dyld_load_info')
1728    if shared_cache_info:
1729        shared_cache_base_addr = shared_cache_info['imageSlidBaseAddress']
1730        # If we have a slidFirstMapping and it's >= base_address, use that.
1731        #
1732        # Otherwise we're processing a stackshot from before the slidFirstMapping
1733        # field was introduced and corrected.  On ARM the SlidBaseAddress is the
1734        # same, but on x86 it's off by 0x20000000.  We use 'X86_64' in the
1735        # kernel version string plus checking kern_page_size == 4k' as
1736        # proxy for x86_64, and only adjust SlidBaseAddress if the unslid
1737        # address is precisely the expected incorrect value.
1738        #
1739        is_intel = ('X86_64' in ss.get('osversion', "") and
1740           ss.get('kernel_page_size', 0) == 4096)
1741        slidFirstMapping = shared_cache_info.get(SC_SLID_FIRSTMAPPING_KEY, -1);
1742        if slidFirstMapping >= shared_cache_base_addr:
1743            shared_cache_base_addr = slidFirstMapping
1744            sc_note = "base-accurate"
1745
1746        elif is_intel:
1747            sc_slide = shared_cache_info['imageLoadAddress']
1748            if (shared_cache_base_addr - sc_slide) == 0x7fff00000000:
1749                shared_cache_base_addr += 0x20000000
1750                sc_note = "base-x86-adjusted"
1751                extra_note = "Shared cache base adjusted for x86. "
1752            else:
1753                sc_note = "base-x86-unknown"
1754
1755        dsc_common = [format_uuid(shared_cache_info['imageUUID']),
1756                shared_cache_base_addr, "S" ]
1757        print("Shared cache UUID found from the binary data is <%s> " % str(dsc_common[0]))
1758
1759    dsc_layout = ss.get('system_shared_cache_layout')
1760
1761    dsc_libs = []
1762    if dsc_layout:
1763        print("Found in memory system shared cache layout with {} images".format(len(dsc_layout)))
1764        slide = ss.get('shared_cache_dyld_load_info')['imageLoadAddress']
1765
1766        for image in dsc_layout:
1767            dsc_libs.append([format_uuid(image['imageUUID']), image['imageLoadAddress'] + slide, "C"])
1768
1769    AllImageCatalog = []
1770    obj = {}
1771    obj["kernel"] = os_version
1772    if timestamp is not None:
1773        obj["date"] = timestamp
1774    obj["reason"] = "kernel panic stackshot"
1775    obj["incident"] = "ABCDEFGH-1234-56IJ-789K-0LMNOPQRSTUV"
1776    obj["crashReporterKey"] = "12ab34cd45aabbccdd6712ab34cd45aabbccdd67"
1777    obj["bootArgs"] = ss.get('boot_args','')
1778    obj["frontmostPids"] = [0]
1779    obj["exception"] = "0xDEADF157"
1780    obj["processByPid"] = {}
1781    if sc_note is not None:
1782        obj["sharedCacheNote"] = sc_note
1783
1784    if incomplete:
1785        obj["reason"] = "!!!INCOMPLETE!!! kernel panic stackshot"
1786        obj["notes"] = "Generated by xnu kcdata.py from incomplete data!   Some information is missing! "
1787    else:
1788        obj["notes"] = "Generated by xnu kcdata.py. "
1789
1790    if extra_note is not None:
1791        obj["notes"] = obj["notes"] + extra_note
1792
1793    processByPid = obj["processByPid"]
1794    ssplist = ss.get('task_snapshots', {})
1795    ssplist.update(ss.get('transitioning_task_snapshots', {}))
1796    kern_load_info = []
1797    if "0" in ssplist:
1798        kc_uuid = ssplist["0"].get('kernelcache_load_info', None)
1799        if kc_uuid:
1800            kernelcache_uuid = [format_uuid(kc_uuid['imageUUID']), kc_uuid['imageLoadAddress'], "U" ]
1801            kern_load_info.append(kernelcache_uuid)
1802
1803        kl_infos = ssplist["0"].get("dyld_load_info", [])
1804        for dlinfo in kl_infos:
1805            kern_load_info.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], "K"])
1806
1807        kl_infos_text_exec = ssplist["0"].get("dyld_load_info_text_exec", [])
1808        for dlinfo in kl_infos_text_exec:
1809            kern_load_info.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], "T"])
1810
1811    for pid,piddata in list(ssplist.items()):
1812        processByPid[str(pid)] = {}
1813        tsnap = processByPid[str(pid)]
1814        pr_lib_dsc = dsc_common
1815
1816        # see if there's an alternate shared cache
1817        scd = piddata.get('shared_cache_dyld_load_info')
1818        if scd is not None:
1819            if 'imageSlidBaseAddress' not in scd:
1820                print("Specific task shared cache format does not include slid shared cache base address. Skipping writing report.")
1821                return
1822
1823            scd_uuid = format_uuid(scd['imageUUID'])
1824            scd_base_addr = scd['imageSlidBaseAddress']
1825            pr_lib_dsc = [scd_uuid, scd_base_addr, "S"]
1826
1827        pr_libs = []
1828        if len(dsc_libs) == 0 and pr_lib_dsc:
1829            pr_libs.append(pr_lib_dsc)
1830        _lib_type = "P"
1831        if int(pid) == 0:
1832            _lib_type = "K"
1833            pr_libs = []
1834        else:
1835            for dlinfo in piddata.get('dyld_load_info',[]):
1836                pr_libs.append([format_uuid(dlinfo['imageUUID']), dlinfo['imageLoadAddress'], _lib_type])
1837
1838        pr_libs.extend(kern_load_info)
1839        pr_libs.extend(dsc_libs)
1840
1841        pr_libs.sort(key=itemgetter(1))
1842
1843        ttsnap = piddata.get('transitioning_task_snapshot', None)
1844        if ttsnap is not None:
1845            # Transitioning task snapshots have "tts_" prefixes; change them to
1846            # "ts_".
1847            ttsnap = { key[1:] : value for key,value in ttsnap.items() }
1848            # Add a note to let people know
1849            obj["notes"] = obj["notes"] + "PID {} is a transitioning (exiting) task. ".format(pid)
1850        tasksnap = piddata.get('task_snapshot', ttsnap);
1851        if tasksnap is None:
1852            continue;
1853        tsnap["pid"] = tasksnap["ts_pid"]
1854        if 'ts_asid' in piddata:
1855            tsnap["asid"] = piddata["ts_asid"]
1856
1857        if 'ts_pagetable' in piddata:
1858            pagetables = []
1859            for tte in piddata["ts_pagetable"]:
1860                pagetables.append(tte)
1861            tsnap["pageTables"] = pagetables
1862
1863        # Some fields are missing from transitioning_task snapshots.
1864        if ttsnap is None:
1865            tsnap["residentMemoryBytes"] = tasksnap["ts_task_size"]
1866            tsnap["timesDidThrottle"] = tasksnap["ts_did_throttle"]
1867            tsnap["systemTimeTask"] = GetSecondsFromMATime(tasksnap["ts_system_time_in_terminated_th"], timebase)
1868            tsnap["pageIns"] = tasksnap["ts_pageins"]
1869            tsnap["pageFaults"] = tasksnap["ts_faults"]
1870            tsnap["userTimeTask"] = GetSecondsFromMATime(tasksnap["ts_user_time_in_terminated_thre"], timebase)
1871        tsnap["procname"] = tasksnap["ts_p_comm"]
1872        if ttsnap is None:
1873            tsnap["copyOnWriteFaults"] = tasksnap["ts_cow_faults"]
1874            tsnap["timesThrottled"] = tasksnap["ts_was_throttled"]
1875        tsnap["threadById"] = {}
1876        threadByID = tsnap["threadById"]
1877        thlist = piddata.get('thread_snapshots', {})
1878        for tid,thdata in list(thlist.items()):
1879            threadByID[str(tid)] = {}
1880            thsnap = threadByID[str(tid)]
1881            if "thread_snapshot" not in thdata:
1882                print("Found broken thread state for thread ID: %s." % tid)
1883                break
1884            threadsnap = thdata["thread_snapshot"]
1885            thsnap["userTime"] = GetSecondsFromMATime(threadsnap["ths_user_time"], timebase)
1886            thsnap["id"] = threadsnap["ths_thread_id"]
1887            thsnap["basePriority"] = threadsnap["ths_base_priority"]
1888            thsnap["systemTime"] = GetSecondsFromMATime(threadsnap["ths_sys_time"], timebase)
1889            thsnap["schedPriority"] = threadsnap["ths_sched_priority"]
1890            thsnap["state"] = GetStateDescription(threadsnap['ths_state'])
1891            thsnap["qosEffective"] = threadsnap["ths_eqos"]
1892            thsnap["qosRequested"] = threadsnap["ths_rqos"]
1893
1894            if "pth_name" in thdata:
1895                thsnap["name"] = thdata["pth_name"];
1896
1897            if threadsnap['ths_continuation']:
1898                thsnap["continuation"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['ths_continuation'])
1899            if "kernel_stack_frames" in thdata:
1900                kuserframes = []
1901                for f in thdata["kernel_stack_frames"]:
1902                    kuserframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
1903                thsnap["kernelFrames"] = kuserframes
1904
1905            if "user_stack_frames" in thdata:
1906                uframes = []
1907                for f in thdata["user_stack_frames"]:
1908                    uframes.append(GetSymbolInfoForFrame(AllImageCatalog, pr_libs, f['lr']))
1909                thsnap["userFrames"] = uframes
1910
1911            if "user_stacktop" in thdata:
1912                (address,) = struct.unpack("<Q", struct.pack("B"*8, *thdata["user_stacktop"]["stack_contents"]))
1913                thsnap["userStacktop"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, address)
1914
1915            if threadsnap['ths_wait_event']:
1916                thsnap["waitEvent"] = GetSymbolInfoForFrame(AllImageCatalog, pr_libs, threadsnap['ths_wait_event'])
1917
1918        if 'thread_waitinfo' in piddata and 'thread_turnstileinfo' in piddata:
1919            tsnap['waitInfo'] = formatWaitInfoWithTurnstiles(piddata['thread_waitinfo'], piddata['thread_turnstileinfo'], piddata.get('portlabels', None))
1920        elif 'thread_waitinfo' in piddata:
1921            portlabels = ss.get('portlabels', None)
1922            tsnap['waitInfo'] = [formatWaitInfo(x, False, portlabels) for x in piddata['thread_waitinfo']]
1923    obj['binaryImages'] = AllImageCatalog
1924    if outfile_name == '-':
1925        fh = sys.stdout
1926    else:
1927        fh = open(outfile_name, "w")
1928
1929    header = {}
1930    header['bug_type'] = 288
1931    if timestamp is not None:
1932        header['timestamp'] = timestamp
1933    header['os_version'] = os_version
1934    fh.write(json.dumps(header))
1935    fh.write("\n")
1936
1937    fh.write(json.dumps(obj, sort_keys=False, indent=2, separators=(',', ': ')))
1938    fh.close()
1939
1940## Base utils for interacting with shell ##
1941def RunCommand(bash_cmd_string, get_stderr = True):
1942    """
1943        returns: (int,str) : exit_code and output_str
1944    """
1945    print("RUNNING: %s" % bash_cmd_string)
1946    cmd_args = shlex.split(bash_cmd_string)
1947    output_str = ""
1948    exit_code = 0
1949    try:
1950        if get_stderr:
1951            output_str = subprocess.check_output(cmd_args, stderr=subprocess.STDOUT)
1952        else:
1953            output_str = subprocess.check_output(cmd_args, stderr=None)
1954    except subprocess.CalledProcessError as e:
1955        exit_code = e.returncode
1956    finally:
1957        return (exit_code, output_str)
1958
1959
1960@contextlib.contextmanager
1961def data_from_stream(stream):
1962    try:
1963        fmap = mmap.mmap(stream.fileno(), 0, mmap.MAP_SHARED, mmap.PROT_READ)
1964    except:
1965        yield stream.read()
1966    else:
1967        try:
1968            yield fmap
1969        finally:
1970            fmap.close()
1971
1972def iterate_kcdatas(kcdata_file):
1973    with data_from_stream(kcdata_file) as data:
1974        iterator = kcdata_item_iterator(data)
1975        kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1976
1977        if isinstance(kcdata_buffer, KCCompressedBufferObject):
1978            kcdata_buffer.ReadItems(iterator)
1979            decompressed = kcdata_buffer.Decompress(data)
1980            iterator = kcdata_item_iterator(decompressed)
1981            kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1982
1983        if not isinstance(kcdata_buffer, KCBufferObject):
1984            # ktrace stackshot chunk
1985            iterator = kcdata_item_iterator(data[16:])
1986            kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1987
1988        if not isinstance(kcdata_buffer, KCBufferObject):
1989            try:
1990                decoded = base64.b64decode(data)
1991            except:
1992                pass
1993            else:
1994                iterator = kcdata_item_iterator(decoded)
1995                kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
1996        if not isinstance(kcdata_buffer, KCBufferObject):
1997            import gzip
1998            from io import BytesIO
1999            try:
2000                decompressed = gzip.GzipFile(fileobj=BytesIO(data[:])).read()
2001            except:
2002                pass
2003            else:
2004                iterator = kcdata_item_iterator(decompressed)
2005                kcdata_buffer = KCObject.FromKCItem(six.next(iterator))
2006
2007        if not isinstance(kcdata_buffer, KCBufferObject):
2008            raise Exception("unknown file type")
2009
2010
2011        kcdata_buffer.ReadItems(iterator)
2012        yield kcdata_buffer
2013
2014        for magic in iterator:
2015            kcdata_buffer = KCObject.FromKCItem(magic)
2016            if kcdata_buffer.i_type == 0:
2017                continue
2018            if not isinstance(kcdata_buffer, KCBufferObject):
2019                raise Exception("unknown file type")
2020            kcdata_buffer.ReadItems(iterator)
2021            yield kcdata_buffer
2022
2023#
2024# Values for various flag fields.  Each entry's key is the key seen in the
2025# processed kcdata, the value is an array of bits, from low (0x1) to high, with
2026# either a string flag name or None for unused holes.
2027#
2028# Only put flags in here which are stable - this is run against stackshots
2029# of all different versions.  For anything unstable, we'll need a decoder ring
2030# added to the stackshot.
2031#
2032PRETTIFY_FLAGS = {
2033    'jcs_flags': [
2034       'kCoalitionTermRequested',
2035       'kCoalitionTerminated',
2036       'kCoalitionReaped',
2037       'kCoalitionPrivileged',
2038    ],
2039    'stackshot_in_flags': [ # STACKSHOT_*, also stackshot_out_flags
2040        'get_dq',
2041        'save_loadinfo',
2042        'get_global_mem_stats',
2043        'save_kext_loadinfo',
2044        None,
2045        None,
2046        None,
2047        None,
2048        'active_kernel_threads_only',
2049        'get_boot_profile',
2050        'do_compress',
2051        None,
2052        None,
2053        'save_imp_donation_pids',
2054        'save_in_kernel_buffer',
2055        'retrieve_existing_buffer',
2056        'kcdata_format',
2057        'enable_bt_faulting',
2058        'collect_delta_snapshot',
2059        'collect_sharedcache_layout',
2060        'trylock',
2061        'enable_uuid_faulting',
2062        'from_panic',
2063        'no_io_stats',
2064        'thread_waitinfo',
2065        'thread_group',
2066        'save_jetsam_coalitions',
2067        'instrs_cycles',
2068        'asid',
2069        'page_tables',
2070        'disable_latency_info',
2071    ],
2072    'system_state_flags': [
2073        'kUser64_p',
2074        'kKern64_p',
2075    ],
2076    'tgs_flags': [
2077        'kThreadGroupEfficient',
2078        'kThreadGroupUIApp',
2079    ],
2080    'ths_ss_flags': [
2081        'kUser64_p',
2082        'kKern64_p',
2083        'kHasDispatchSerial',
2084        'kStacksPCOnly',
2085        'kThreadDarwinBG',
2086        'kThreadIOPassive',
2087        'kThreadSuspended',
2088        'kThreadTruncatedBT',
2089        'kGlobalForcedIdle',
2090        'kThreadFaultedBT',
2091        'kThreadTriedFaultBT',
2092        'kThreadOnCore',
2093        'kThreadIdleWorker',
2094        'kThreadMain',
2095        'kThreadTruncKernBT',
2096        'kThreadTruncUserBT',
2097        'kThreadTruncUserAsyncBT',
2098    ],
2099    'ths_state': [
2100        'TH_WAIT',
2101        'TH_SUSP',
2102        'TH_RUN',
2103        'TH_UNINT',
2104        'TH_TERMINATE',
2105        'TH_TERMINATE2',
2106        'TH_WAIT_REPORT',
2107        'TH_IDLE',
2108    ],
2109    'ts_ss_flags': [
2110        'kUser64_p',
2111        'kKern64_p',
2112        'kTaskRsrcFlagged',
2113        'kTerminatedSnapshot',
2114        'kPidSuspended',
2115        'kFrozen',
2116        'kTaskDarwinBG',
2117        'kTaskExtDarwinBG',
2118        'kTaskVisVisible',
2119        'kTaskVisNonvisible',
2120        'kTaskIsForeground',
2121        'kTaskIsBoosted',
2122        'kTaskIsSuppressed',
2123        'kTaskIsTimerThrottled',
2124        'kTaskIsImpDonor',
2125        'kTaskIsLiveImpDonor',
2126        'kTaskIsDirty',
2127        'kTaskWqExceededConstrainedThreadLimit',
2128        'kTaskWqExceededTotalThreadLimit',
2129        'kTaskWqFlagsAvailable',
2130        'kTaskUUIDInfoFaultedIn',
2131        'kTaskUUIDInfoMissing',
2132        'kTaskUUIDInfoTriedFault',
2133        'kTaskSharedRegionInfoUnavailable',
2134        'kTaskTALEngaged',
2135        None,
2136        'kTaskIsDirtyTracked',
2137        'kTaskAllowIdleExit',
2138        'kTaskIsTranslated',
2139        'kTaskSharedRegionNone',
2140        'kTaskSharedRegionSystem',
2141        'kTaskSharedRegionOther',
2142    ],
2143    'turnstile_flags': [
2144        'turnstile_status_unknown',
2145        'turnstile_status_locked_waitq',
2146        'turnstile_status_workqueue',
2147        'turnstile_status_thread',
2148        'turnstile_status_blocked_on_task',
2149        'turnstile_status_held_iplock',
2150    ],
2151}
2152PRETTIFY_FLAGS['stackshot_out_flags'] = PRETTIFY_FLAGS['stackshot_in_flags']
2153PRETTIFY_FLAGS['tts_ss_flags'] = PRETTIFY_FLAGS['ts_ss_flags']
2154
2155# Fields which should never be hexified
2156PRETTIFY_DONTHEX = {
2157    'stackshot_in_pid': True,
2158    'tts_pid': True,
2159    'ts_pid': True,
2160    'donating_pids': True,
2161    'ppid': True,
2162}
2163
2164# Only hex() the value if it is multiple digits
2165def prettify_hex(v):
2166    if v < -9 or v > 9:
2167        return hex(v)
2168    return str(v)
2169
2170def prettify_flags(v, flags):
2171    output=""
2172    seen = 0
2173    if v == 0:
2174        return "0"
2175    for (s, n) in zip(range(len(flags)),flags):
2176        if n is None:
2177            continue
2178        if (v & (2 ** s)):
2179            output += "|" + n
2180            seen |= 2 ** s
2181    if output == "":
2182        return prettify_hex(v)
2183    rest = (v & ~seen)
2184    if (rest != 0):
2185        output += "|" + prettify_hex(rest)
2186    return prettify_hex(v) + " (" + output[1:] + ")"
2187
2188def prettify_core(data, mosthex, key, portlabels):
2189    if key == 'stack_contents':
2190        (address,) = struct.unpack("<Q", struct.pack("B"*8, *data))
2191        return '0x%X' % address
2192
2193    elif isinstance(data, list):
2194        if 'uuid' in key.lower() and len(data) == 16:
2195            return '%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X' % tuple(data)
2196
2197        return [prettify_core(x, mosthex, key, portlabels) for x in data]
2198
2199    elif key == 'thread_waitinfo':
2200        return formatWaitInfo(data, mosthex, portlabels)
2201
2202    elif isinstance(data, dict):
2203        if 'portlabels' in data:
2204            portlabels = data['portlabels']
2205        newdata = dict()
2206        for key, value in data.items():
2207            if mosthex and key != 'task_snapshots' and len(key) > 0 and key.isnumeric():
2208                key = prettify_hex(int(key))
2209            newdata[key] = prettify_core(value, mosthex, key, portlabels)
2210        return newdata
2211
2212    elif 'address' in key.lower() and isinstance(data, (int, long)):
2213        return '0x%X' % data
2214    elif key == 'lr' or key == SC_SLID_FIRSTMAPPING_KEY:
2215        return '0x%X' % data
2216    elif key in PRETTIFY_FLAGS and isinstance(data, (int, long)):
2217        return prettify_flags(data, PRETTIFY_FLAGS[key])
2218    elif key.endswith('_flags') and isinstance(data, (int, long)):
2219        return prettify_hex(data)
2220
2221    elif mosthex and not PRETTIFY_DONTHEX.get(key, False):
2222        if isinstance(data, (int, long)):
2223            return prettify_hex(data)
2224        elif isinstance(data, six.string_types) and len(data) > 0 and data.isnumeric():
2225            return prettify_hex(int(data))
2226        return data
2227
2228    else:
2229        return data
2230
2231def prettify(data, mosthex):
2232    return prettify_core(data, mosthex, "", None)
2233
2234if __name__ == '__main__':
2235    parser = argparse.ArgumentParser(description="Decode a kcdata binary file.")
2236    parser.add_argument("-l", "--listtypes", action="store_true", required=False, default=False,
2237                        help="List all known types",
2238                        dest="list_known_types")
2239
2240    parser.add_argument("-s", "--stackshot", required=False, default=False,
2241                        help="Generate a stackshot report file",
2242                        dest="stackshot_file")
2243
2244    parser.add_argument("--multiple", help="look for multiple stackshots in a single file", action='store_true')
2245
2246    parser.add_argument("-p", "--plist", required=False, default=False,
2247                        help="output as plist", action="store_true")
2248
2249    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")
2250    parser.add_argument("-P", "--pretty", default=False, action='store_true', help="make the output a little more human readable")
2251    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")
2252    parser.add_argument("--incomplete", action='store_true', help="accept incomplete data")
2253    parser.add_argument("kcdata_file", type=argparse.FileType('r'), help="Path to a kcdata binary file.")
2254
2255    class VerboseAction(argparse.Action):
2256        def __call__(self, parser, namespace, values, option_string=None):
2257            logging.basicConfig(level=logging.INFO, stream=sys.stderr, format='%(message)s')
2258    parser.add_argument('-v', "--verbose", action=VerboseAction, nargs=0)
2259
2260    args = parser.parse_args()
2261
2262    if args.multiple and args.stackshot_file:
2263        raise NotImplementedError
2264
2265    if args.list_known_types:
2266        for (n, t) in KNOWN_TYPES_COLLECTION.items():
2267            print("%d : %s " % (n, str(t)))
2268        sys.exit(1)
2269
2270    if args.incomplete or args.stackshot_file:
2271        G.accept_incomplete_data = True
2272
2273    for i,kcdata_buffer in enumerate(iterate_kcdatas(args.kcdata_file)):
2274        if i > 0 and not args.multiple:
2275            break
2276
2277        str_data = "{" + kcdata_buffer.GetJsonRepr() + "}"
2278        str_data = str_data.replace("\t", "    ")
2279
2280        try:
2281            json_obj = json.loads(str_data)
2282        except:
2283            print("JSON reparsing failed!  Printing string data!\n", file=sys.stderr)
2284            import textwrap
2285            print(textwrap.fill(str_data, 100))
2286            raise
2287
2288        if args.prettyhex:
2289            json_obj = prettify(json_obj, True)
2290        elif args.pretty:
2291            json_obj = prettify(json_obj, False)
2292
2293        if args.stackshot_file:
2294            SaveStackshotReport(json_obj, args.stackshot_file, G.data_was_incomplete)
2295        elif args.plist:
2296            import Foundation
2297            plist = Foundation.NSPropertyListSerialization.dataWithPropertyList_format_options_error_(
2298                json_obj, Foundation.NSPropertyListXMLFormat_v1_0, 0, None)[0].bytes().tobytes()
2299            #sigh.  on some pythons long integers are getting output with L's in the plist.
2300            plist = re.sub(r'^(\s*<integer>\d+)L(</integer>\s*)$', r"\1\2", BytesToString(plist), flags=re.MULTILINE)
2301            print(plist,)
2302        else:
2303            print(json.dumps(json_obj, sort_keys=True, indent=4, separators=(',', ': ')))
2304