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