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