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