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