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