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