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