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