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