]>
Commit | Line | Data |
---|---|---|
39037602 A |
1 | /* |
2 | * Copyright (c) 2015 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | ||
30 | /* | |
31 | * | |
32 | * THE KCDATA MANIFESTO | |
33 | * | |
34 | * Kcdata is a self-describing data serialization format. It is meant to get | |
35 | * nested data structures out of xnu with minimum fuss, but also for that data | |
36 | * to be easy to parse. It is also meant to allow us to add new fields and | |
37 | * evolve the data format without breaking old parsers. | |
38 | * | |
39 | * Kcdata is a permanent data format suitable for long-term storage including | |
40 | * in files. It is very important that we continue to be able to parse old | |
41 | * versions of kcdata-based formats. To this end, there are several | |
42 | * invariants you MUST MAINTAIN if you alter this file. | |
43 | * | |
44 | * * None of the magic numbers should ever be a byteswap of themselves or | |
45 | * of any of the other magic numbers. | |
46 | * | |
47 | * * Never remove any type. | |
48 | * | |
49 | * * All kcdata structs must be packed, and must exclusively use fixed-size | |
50 | * types. | |
51 | * | |
52 | * * Never change the definition of any type, except to add new fields to | |
53 | * the end. | |
54 | * | |
55 | * * If you do add new fields to the end of a type, do not actually change | |
56 | * the definition of the old structure. Instead, define a new structure | |
57 | * with the new fields. See thread_snapshot_v3 as an example. This | |
58 | * provides source compatibility for old readers, and also documents where | |
59 | * the potential size cutoffs are. | |
60 | * | |
61 | * * If you change libkdd, or kcdata.py run the unit tests under libkdd. | |
62 | * | |
63 | * * If you add a type or extend an existing one, add a sample test to | |
64 | * libkdd/tests so future changes to libkdd will always parse your struct | |
65 | * correctly. | |
66 | * | |
67 | * For example to add a field to this: | |
68 | * | |
69 | * struct foobar { | |
70 | * uint32_t baz; | |
71 | * uint32_t quux; | |
72 | * } __attribute__ ((packed)); | |
73 | * | |
74 | * Make it look like this: | |
75 | * | |
76 | * struct foobar { | |
77 | * uint32_t baz; | |
78 | * uint32_t quux; | |
79 | * ///////// end version 1 of foobar. sizeof(struct foobar) was 8 //////// | |
80 | * uint32_t frozzle; | |
81 | * } __attribute__ ((packed)); | |
82 | * | |
83 | * If you are parsing kcdata formats, you MUST | |
84 | * | |
85 | * * Check the length field of each struct, including array elements. If the | |
86 | * struct is longer than you expect, you must ignore the extra data. | |
87 | * | |
88 | * * Ignore any data types you do not understand. | |
89 | * | |
90 | * Additionally, we want to be as forward compatible as we can. Meaning old | |
91 | * tools should still be able to use new data whenever possible. To this end, | |
92 | * you should: | |
93 | * | |
94 | * * Try not to add new versions of types that supplant old ones. Instead | |
95 | * extend the length of existing types or add supplemental types. | |
96 | * | |
97 | * * Try not to remove information from existing kcdata formats, unless | |
98 | * removal was explicitly asked for. For example it is fine to add a | |
99 | * stackshot flag to remove unwanted information, but you should not | |
100 | * remove it from the default stackshot if the new flag is absent. | |
101 | * | |
102 | * * (TBD) If you do break old readers by removing information or | |
103 | * supplanting old structs, then increase the major version number. | |
104 | * | |
105 | * | |
106 | * | |
107 | * The following is a description of the kcdata format. | |
108 | * | |
109 | * | |
110 | * The format for data is setup in a generic format as follows | |
111 | * | |
112 | * Layout of data structure: | |
113 | * | |
114 | * | 8 - bytes | | |
115 | * | type = MAGIC | LENGTH | | |
116 | * | 0 | | |
117 | * | type | size | | |
118 | * | flags | | |
119 | * | data | | |
120 | * |___________data____________| | |
121 | * | type | size | | |
122 | * | flags | | |
123 | * |___________data____________| | |
124 | * | type = END | size=0 | | |
125 | * | 0 | | |
126 | * | |
127 | * | |
128 | * The type field describes what kind of data is passed. For example type = TASK_CRASHINFO_UUID means the following data is a uuid. | |
129 | * These types need to be defined in task_corpses.h for easy consumption by userspace inspection tools. | |
130 | * | |
131 | * Some range of types is reserved for special types like ints, longs etc. A cool new functionality made possible with this | |
132 | * extensible data format is that kernel can decide to put more information as required without requiring user space tools to | |
133 | * re-compile to be compatible. The case of rusage struct versions could be introduced without breaking existing tools. | |
134 | * | |
135 | * Feature description: Generic data with description | |
136 | * ------------------- | |
137 | * Further more generic data with description is very much possible now. For example | |
138 | * | |
139 | * - kcdata_add_uint64_with_description(cdatainfo, 0x700, "NUM MACH PORTS"); | |
140 | * - and more functions that allow adding description. | |
141 | * The userspace tools can then look at the description and print the data even if they are not compiled with knowledge of the field apriori. | |
142 | * | |
143 | * Example data: | |
144 | * 0000 57 f1 ad de 00 00 00 00 00 00 00 00 00 00 00 00 W............... | |
145 | * 0010 01 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 ........0....... | |
146 | * 0020 50 49 44 00 00 00 00 00 00 00 00 00 00 00 00 00 PID............. | |
147 | * 0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | |
148 | * 0040 9c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | |
149 | * 0050 01 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 ........0....... | |
150 | * 0060 50 41 52 45 4e 54 20 50 49 44 00 00 00 00 00 00 PARENT PID...... | |
151 | * 0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | |
152 | * 0080 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | |
153 | * 0090 ed 58 91 f1 | |
154 | * | |
155 | * Feature description: Container markers for compound data | |
156 | * ------------------ | |
157 | * If a given kernel data type is complex and requires adding multiple optional fields inside a container | |
158 | * object for a consumer to understand arbitrary data, we package it using container markers. | |
159 | * | |
160 | * For example, the stackshot code gathers information and describes the state of a given task with respect | |
161 | * to many subsystems. It includes data such as io stats, vm counters, process names/flags and syscall counts. | |
162 | * | |
163 | * kcdata_add_container_marker(kcdata_p, KCDATA_TYPE_CONTAINER_BEGIN, STACKSHOT_KCCONTAINER_TASK, task_uniqueid); | |
164 | * // add multiple data, or add_<type>_with_description()s here | |
165 | * | |
166 | * kcdata_add_container_marker(kcdata_p, KCDATA_TYPE_CONTAINER_END, STACKSHOT_KCCONTAINER_TASK, task_uniqueid); | |
167 | * | |
168 | * Feature description: Custom Data formats on demand | |
169 | * -------------------- | |
170 | * With the self describing nature of format, the kernel provider can describe a data type (uniquely identified by a number) and use | |
171 | * it in the buffer for sending data. The consumer can parse the type information and have knowledge of describing incoming data. | |
172 | * Following is an example of how we can describe a kernel specific struct sample_disk_io_stats in buffer. | |
173 | * | |
174 | * struct sample_disk_io_stats { | |
175 | * uint64_t disk_reads_count; | |
176 | * uint64_t disk_reads_size; | |
177 | * uint64_t io_priority_count[4]; | |
178 | * uint64_t io_priority_size; | |
179 | * } __attribute__ ((packed)); | |
180 | * | |
181 | * | |
182 | * struct kcdata_subtype_descriptor disk_io_stats_def[] = { | |
183 | * {KCS_SUBTYPE_FLAGS_NONE, KC_ST_UINT64, 0 * sizeof(uint64_t), sizeof(uint64_t), "disk_reads_count"}, | |
184 | * {KCS_SUBTYPE_FLAGS_NONE, KC_ST_UINT64, 1 * sizeof(uint64_t), sizeof(uint64_t), "disk_reads_size"}, | |
185 | * {KCS_SUBTYPE_FLAGS_ARRAY, KC_ST_UINT64, 2 * sizeof(uint64_t), KCS_SUBTYPE_PACK_SIZE(4, sizeof(uint64_t)), "io_priority_count"}, | |
186 | * {KCS_SUBTYPE_FLAGS_ARRAY, KC_ST_UINT64, (2 + 4) * sizeof(uint64_t), sizeof(uint64_t), "io_priority_size"}, | |
187 | * }; | |
188 | * | |
189 | * Now you can add this custom type definition into the buffer as | |
190 | * kcdata_add_type_definition(kcdata_p, KCTYPE_SAMPLE_DISK_IO_STATS, "sample_disk_io_stats", | |
191 | * &disk_io_stats_def[0], sizeof(disk_io_stats_def)/sizeof(struct kcdata_subtype_descriptor)); | |
192 | * | |
193 | */ | |
194 | ||
195 | ||
196 | #ifndef _KCDATA_H_ | |
197 | #define _KCDATA_H_ | |
198 | ||
199 | #include <stdint.h> | |
200 | #include <string.h> | |
201 | #include <uuid/uuid.h> | |
202 | ||
203 | #define KCDATA_DESC_MAXLEN 32 /* including NULL byte at end */ | |
204 | ||
205 | #define KCDATA_FLAGS_STRUCT_PADDING_MASK 0xf | |
206 | #define KCDATA_FLAGS_STRUCT_HAS_PADDING 0x80 | |
207 | ||
208 | /* | |
209 | * kcdata aligns elements to 16 byte boundaries. | |
210 | */ | |
211 | #define KCDATA_ALIGNMENT_SIZE 0x10 | |
212 | ||
213 | struct kcdata_item { | |
214 | uint32_t type; | |
215 | uint32_t size; /* len(data) */ | |
216 | /* flags. | |
217 | * | |
218 | * For structures: | |
219 | * padding = flags & 0xf | |
220 | * has_padding = (flags & 0x80) >> 7 | |
221 | * | |
222 | * has_padding is needed to disambiguate cases such as | |
223 | * thread_snapshot_v2 and thread_snapshot_v3. Their | |
224 | * respective sizes are 0x68 and 0x70, and thread_snapshot_v2 | |
225 | * was emmitted by old kernels *before* we started recording | |
226 | * padding. Since legacy thread_snapsht_v2 and modern | |
227 | * thread_snapshot_v3 will both record 0 for the padding | |
228 | * flags, we need some other bit which will be nonzero in the | |
229 | * flags to disambiguate. | |
230 | * | |
231 | * This is why we hardcode a special case for | |
232 | * STACKSHOT_KCTYPE_THREAD_SNAPSHOT into the iterator | |
233 | * functions below. There is only a finite number of such | |
234 | * hardcodings which will ever be needed. They can occur | |
235 | * when: | |
236 | * | |
237 | * * We have a legacy structure that predates padding flags | |
238 | * | |
239 | * * which we want to extend without changing the kcdata type | |
240 | * | |
241 | * * by only so many bytes as would fit in the space that | |
242 | * was previously unused padding. | |
243 | * | |
244 | * For containers: | |
245 | * container_id = flags | |
246 | * | |
247 | * For arrays: | |
248 | * element_count = flags & UINT32_MAX | |
249 | * element_type = (flags >> 32) & UINT32_MAX | |
250 | */ | |
251 | uint64_t flags; | |
252 | char data[]; /* must be at the end */ | |
253 | }; | |
254 | ||
255 | typedef struct kcdata_item * kcdata_item_t; | |
256 | ||
257 | enum KCDATA_SUBTYPE_TYPES { KC_ST_CHAR = 1, KC_ST_INT8, KC_ST_UINT8, KC_ST_INT16, KC_ST_UINT16, KC_ST_INT32, KC_ST_UINT32, KC_ST_INT64, KC_ST_UINT64 }; | |
258 | typedef enum KCDATA_SUBTYPE_TYPES kctype_subtype_t; | |
259 | ||
260 | /* | |
261 | * A subtype description structure that defines | |
262 | * how a compound data is laid out in memory. This | |
263 | * provides on the fly definition of types and consumption | |
264 | * by the parser. | |
265 | */ | |
266 | struct kcdata_subtype_descriptor { | |
267 | uint8_t kcs_flags; | |
268 | #define KCS_SUBTYPE_FLAGS_NONE 0x0 | |
269 | #define KCS_SUBTYPE_FLAGS_ARRAY 0x1 | |
270 | /* Force struct type even if only one element. | |
271 | * | |
272 | * Normally a kcdata_type_definition is treated as a structure if it has | |
273 | * more than one subtype descriptor. Otherwise it is treated as a simple | |
274 | * type. For example libkdd will represent a simple integer 42 as simply | |
275 | * 42, but it will represent a structure containing an integer 42 as | |
276 | * {"field_name": 42}.. | |
277 | * | |
278 | * If a kcdata_type_definition has only single subtype, then it will be | |
279 | * treated as a structure iff KCS_SUBTYPE_FLAGS_STRUCT is set. If it has | |
280 | * multiple subtypes, it will always be treated as a structure. | |
281 | * | |
282 | * KCS_SUBTYPE_FLAGS_MERGE has the opposite effect. If this flag is used then | |
283 | * even if there are multiple elements, they will all be treated as individual | |
284 | * properties of the parent dictionary. | |
285 | */ | |
286 | #define KCS_SUBTYPE_FLAGS_STRUCT 0x2 /* force struct type even if only one element */ | |
287 | #define KCS_SUBTYPE_FLAGS_MERGE 0x4 /* treat as multiple elements of parents instead of struct */ | |
288 | uint8_t kcs_elem_type; /* restricted to kctype_subtype_t */ | |
289 | uint16_t kcs_elem_offset; /* offset in struct where data is found */ | |
290 | uint32_t kcs_elem_size; /* size of element (or) packed state for array type */ | |
291 | char kcs_name[KCDATA_DESC_MAXLEN]; /* max 31 bytes for name of field */ | |
292 | }; | |
293 | ||
294 | typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t; | |
295 | ||
296 | /* | |
297 | * In case of array of basic c types in kctype_subtype_t, | |
298 | * size is packed in lower 16 bits and | |
299 | * count is packed in upper 16 bits of kcs_elem_size field. | |
300 | */ | |
301 | #define KCS_SUBTYPE_PACK_SIZE(e_count, e_size) (((e_count)&0xffffu) << 16 | ((e_size)&0xffffu)) | |
302 | ||
303 | static inline uint32_t | |
304 | kcs_get_elem_size(kcdata_subtype_descriptor_t d) | |
305 | { | |
306 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { | |
307 | /* size is composed as ((count &0xffff)<<16 | (elem_size & 0xffff)) */ | |
308 | return (uint32_t)((d->kcs_elem_size & 0xffff) * ((d->kcs_elem_size & 0xffff0000)>>16)); | |
309 | } | |
310 | return d->kcs_elem_size; | |
311 | } | |
312 | ||
313 | static inline uint32_t | |
314 | kcs_get_elem_count(kcdata_subtype_descriptor_t d) | |
315 | { | |
316 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) | |
317 | return (d->kcs_elem_size >> 16) & 0xffff; | |
318 | return 1; | |
319 | } | |
320 | ||
321 | static inline int | |
322 | kcs_set_elem_size(kcdata_subtype_descriptor_t d, uint32_t size, uint32_t count) | |
323 | { | |
324 | if (count > 1) { | |
325 | /* means we are setting up an array */ | |
326 | if (size > 0xffff || count > 0xffff) | |
327 | return -1; //invalid argument | |
328 | d->kcs_elem_size = ((count & 0xffff) << 16 | (size & 0xffff)); | |
329 | } | |
330 | else | |
331 | { | |
332 | d->kcs_elem_size = size; | |
333 | } | |
334 | return 0; | |
335 | } | |
336 | ||
337 | struct kcdata_type_definition { | |
338 | uint32_t kct_type_identifier; | |
339 | uint32_t kct_num_elements; | |
340 | char kct_name[KCDATA_DESC_MAXLEN]; | |
341 | struct kcdata_subtype_descriptor kct_elements[]; | |
342 | }; | |
343 | ||
344 | ||
345 | /* chunk type definitions. 0 - 0x7ff are reserved and defined here | |
346 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
347 | * in STACKSHOT_KCTYPE_* types. | |
348 | */ | |
349 | ||
350 | /* | |
351 | * Types with description value. | |
352 | * these will have KCDATA_DESC_MAXLEN-1 length string description | |
353 | * and rest of kcdata_iter_size() - KCDATA_DESC_MAXLEN bytes as data | |
354 | */ | |
355 | #define KCDATA_TYPE_INVALID 0x0u | |
356 | #define KCDATA_TYPE_STRING_DESC 0x1u | |
357 | #define KCDATA_TYPE_UINT32_DESC 0x2u | |
358 | #define KCDATA_TYPE_UINT64_DESC 0x3u | |
359 | #define KCDATA_TYPE_INT32_DESC 0x4u | |
360 | #define KCDATA_TYPE_INT64_DESC 0x5u | |
361 | #define KCDATA_TYPE_BINDATA_DESC 0x6u | |
362 | ||
363 | /* | |
364 | * Compound type definitions | |
365 | */ | |
366 | #define KCDATA_TYPE_ARRAY 0x11u /* Array of data OBSOLETE DONT USE THIS*/ | |
367 | #define KCDATA_TYPE_TYPEDEFINTION 0x12u /* Meta type that describes a type on the fly. */ | |
368 | #define KCDATA_TYPE_CONTAINER_BEGIN \ | |
369 | 0x13u /* Container type which has corresponding CONTAINER_END header. \ | |
370 | * KCDATA_TYPE_CONTAINER_BEGIN has type in the data segment. \ | |
371 | * Both headers have (uint64_t) ID for matching up nested data. \ | |
372 | */ | |
373 | #define KCDATA_TYPE_CONTAINER_END 0x14u | |
374 | ||
375 | #define KCDATA_TYPE_ARRAY_PAD0 0x20u /* Array of data with 0 byte of padding*/ | |
376 | #define KCDATA_TYPE_ARRAY_PAD1 0x21u /* Array of data with 1 byte of padding*/ | |
377 | #define KCDATA_TYPE_ARRAY_PAD2 0x22u /* Array of data with 2 byte of padding*/ | |
378 | #define KCDATA_TYPE_ARRAY_PAD3 0x23u /* Array of data with 3 byte of padding*/ | |
379 | #define KCDATA_TYPE_ARRAY_PAD4 0x24u /* Array of data with 4 byte of padding*/ | |
380 | #define KCDATA_TYPE_ARRAY_PAD5 0x25u /* Array of data with 5 byte of padding*/ | |
381 | #define KCDATA_TYPE_ARRAY_PAD6 0x26u /* Array of data with 6 byte of padding*/ | |
382 | #define KCDATA_TYPE_ARRAY_PAD7 0x27u /* Array of data with 7 byte of padding*/ | |
383 | #define KCDATA_TYPE_ARRAY_PAD8 0x28u /* Array of data with 8 byte of padding*/ | |
384 | #define KCDATA_TYPE_ARRAY_PAD9 0x29u /* Array of data with 9 byte of padding*/ | |
385 | #define KCDATA_TYPE_ARRAY_PADa 0x2au /* Array of data with a byte of padding*/ | |
386 | #define KCDATA_TYPE_ARRAY_PADb 0x2bu /* Array of data with b byte of padding*/ | |
387 | #define KCDATA_TYPE_ARRAY_PADc 0x2cu /* Array of data with c byte of padding*/ | |
388 | #define KCDATA_TYPE_ARRAY_PADd 0x2du /* Array of data with d byte of padding*/ | |
389 | #define KCDATA_TYPE_ARRAY_PADe 0x2eu /* Array of data with e byte of padding*/ | |
390 | #define KCDATA_TYPE_ARRAY_PADf 0x2fu /* Array of data with f byte of padding*/ | |
391 | ||
392 | /* | |
393 | * Generic data types that are most commonly used | |
394 | */ | |
395 | #define KCDATA_TYPE_LIBRARY_LOADINFO 0x30u /* struct dyld_uuid_info_32 */ | |
396 | #define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31u /* struct dyld_uuid_info_64 */ | |
397 | #define KCDATA_TYPE_TIMEBASE 0x32u /* struct mach_timebase_info */ | |
398 | #define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33u /* uint64_t */ | |
399 | #define KCDATA_TYPE_TIMEVAL 0x34u /* struct timeval64 */ | |
400 | #define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35u /* time in usecs uint64_t */ | |
401 | #define KCDATA_TYPE_PID 0x36u /* int32_t */ | |
402 | #define KCDATA_TYPE_PROCNAME 0x37u /* char * */ | |
403 | #define KCDATA_TYPE_NESTED_KCDATA 0x38u /* nested kcdata buffer */ | |
404 | ||
405 | #define KCDATA_TYPE_BUFFER_END 0xF19158EDu | |
406 | ||
407 | /* MAGIC numbers defined for each class of chunked data | |
408 | * | |
409 | * To future-proof against big-endian arches, make sure none of these magic | |
410 | * numbers are byteswaps of each other | |
411 | */ | |
412 | ||
413 | #define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157u /* owner: corpses/task_corpse.h */ | |
414 | /* type-range: 0x800 - 0x8ff */ | |
415 | #define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807u /* owner: sys/stackshot.h */ | |
416 | /* type-range: 0x900 - 0x93f */ | |
417 | #define KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT 0xDE17A59Au /* owner: sys/stackshot.h */ | |
418 | /* type-range: 0x940 - 0x9ff */ | |
419 | #define KCDATA_BUFFER_BEGIN_OS_REASON 0x53A20900u /* owner: sys/reason.h */ | |
420 | /* type-range: 0x1000-0x103f */ | |
421 | #define KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG 0x1e21c09fu /* owner: osfmk/tests/kernel_tests.c */ | |
422 | /* type-range: 0x1040-0x105f */ | |
423 | ||
424 | /* next type range number available 0x1060 */ | |
425 | /**************** definitions for XNUPOST *********************/ | |
426 | #define XNUPOST_KCTYPE_TESTCONFIG 0x1040 | |
427 | ||
428 | /**************** definitions for stackshot *********************/ | |
429 | ||
430 | /* This value must always match IO_NUM_PRIORITIES defined in thread_info.h */ | |
431 | #define STACKSHOT_IO_NUM_PRIORITIES 4 | |
432 | /* This value must always match MAXTHREADNAMESIZE used in bsd */ | |
433 | #define STACKSHOT_MAX_THREAD_NAME_SIZE 64 | |
434 | ||
435 | /* | |
436 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
437 | * in STACKSHOT_KCTYPE_* types. | |
438 | */ | |
439 | #define STACKSHOT_KCTYPE_IOSTATS 0x901u /* io_stats_snapshot */ | |
440 | #define STACKSHOT_KCTYPE_GLOBAL_MEM_STATS 0x902u /* struct mem_and_io_snapshot */ | |
441 | #define STACKSHOT_KCCONTAINER_TASK 0x903u | |
442 | #define STACKSHOT_KCCONTAINER_THREAD 0x904u | |
443 | #define STACKSHOT_KCTYPE_TASK_SNAPSHOT 0x905u /* task_snapshot_v2 */ | |
444 | #define STACKSHOT_KCTYPE_THREAD_SNAPSHOT 0x906u /* thread_snapshot_v2, thread_snapshot_v3 */ | |
445 | #define STACKSHOT_KCTYPE_DONATING_PIDS 0x907u /* int[] */ | |
446 | #define STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO 0x908u /* same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
447 | #define STACKSHOT_KCTYPE_THREAD_NAME 0x909u /* char[] */ | |
448 | #define STACKSHOT_KCTYPE_KERN_STACKFRAME 0x90Au /* struct stack_snapshot_frame32 */ | |
449 | #define STACKSHOT_KCTYPE_KERN_STACKFRAME64 0x90Bu /* struct stack_snapshot_frame64 */ | |
450 | #define STACKSHOT_KCTYPE_USER_STACKFRAME 0x90Cu /* struct stack_snapshot_frame32 */ | |
451 | #define STACKSHOT_KCTYPE_USER_STACKFRAME64 0x90Du /* struct stack_snapshot_frame64 */ | |
452 | #define STACKSHOT_KCTYPE_BOOTARGS 0x90Eu /* boot args string */ | |
453 | #define STACKSHOT_KCTYPE_OSVERSION 0x90Fu /* os version string */ | |
454 | #define STACKSHOT_KCTYPE_KERN_PAGE_SIZE 0x910u /* kernel page size in uint32_t */ | |
455 | #define STACKSHOT_KCTYPE_JETSAM_LEVEL 0x911u /* jetsam level in uint32_t */ | |
456 | #define STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP 0x912u /* timestamp used for the delta stackshot */ | |
457 | ||
458 | #define STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT 0x940u /* task_delta_snapshot_v2 */ | |
459 | #define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v2 */ | |
460 | ||
461 | #define STACKSHOT_KCTYPE_KERN_STACKLR 0x913u /* uint32_t */ | |
462 | #define STACKSHOT_KCTYPE_KERN_STACKLR64 0x914u /* uint64_t */ | |
463 | #define STACKSHOT_KCTYPE_USER_STACKLR 0x915u /* uint32_t */ | |
464 | #define STACKSHOT_KCTYPE_USER_STACKLR64 0x916u /* uint64_t */ | |
465 | #define STACKSHOT_KCTYPE_NONRUNNABLE_TIDS 0x917u /* uint64_t */ | |
466 | #define STACKSHOT_KCTYPE_NONRUNNABLE_TASKS 0x918u /* uint64_t */ | |
467 | #define STACKSHOT_KCTYPE_CPU_TIMES 0x919u /* struct stackshot_cpu_times */ | |
468 | #define STACKSHOT_KCTYPE_STACKSHOT_DURATION 0x91au /* struct stackshot_duration */ | |
469 | #define STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS 0x91bu /* struct stackshot_fault_stats */ | |
470 | #define STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO 0x91cu /* kernelcache UUID -- same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
813fb2f6 | 471 | #define STACKSHOT_KCTYPE_THREAD_WAITINFO 0x91du /* struct stackshot_thread_waitinfo */ |
5c9f4661 | 472 | #define STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT 0x91eu /* struct thread_group_snapshot or thread_group_snapshot_v2 */ |
5ba3f43e A |
473 | #define STACKSHOT_KCTYPE_THREAD_GROUP 0x91fu /* uint64_t */ |
474 | #define STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT 0x920u /* struct jetsam_coalition_snapshot */ | |
475 | #define STACKSHOT_KCTYPE_JETSAM_COALITION 0x921u /* uint64_t */ | |
476 | #define STACKSHOT_KCTYPE_INSTRS_CYCLES 0x923u /* struct instrs_cycles_snapshot */ | |
477 | ||
478 | #define STACKSHOT_KCTYPE_THREAD_POLICY_VERSION 0x922u /* THREAD_POLICY_INTERNAL_STRUCT_VERSION in uint32 */ | |
39037602 A |
479 | |
480 | struct stack_snapshot_frame32 { | |
481 | uint32_t lr; | |
482 | uint32_t sp; | |
483 | }; | |
484 | ||
485 | struct stack_snapshot_frame64 { | |
486 | uint64_t lr; | |
487 | uint64_t sp; | |
488 | }; | |
489 | ||
490 | struct dyld_uuid_info_32 { | |
491 | uint32_t imageLoadAddress; /* base address image is mapped at */ | |
492 | uuid_t imageUUID; | |
493 | }; | |
494 | ||
495 | struct dyld_uuid_info_64 { | |
496 | uint64_t imageLoadAddress; /* XXX image slide */ | |
497 | uuid_t imageUUID; | |
498 | }; | |
499 | ||
500 | struct dyld_uuid_info_64_v2 { | |
501 | uint64_t imageLoadAddress; /* XXX image slide */ | |
502 | uuid_t imageUUID; | |
503 | /* end of version 1 of dyld_uuid_info_64. sizeof v1 was 24 */ | |
504 | uint64_t imageSlidBaseAddress; /* slid base address of image */ | |
505 | }; | |
506 | ||
507 | struct user32_dyld_uuid_info { | |
508 | uint32_t imageLoadAddress; /* base address image is mapped into */ | |
509 | uuid_t imageUUID; /* UUID of image */ | |
510 | }; | |
511 | ||
512 | struct user64_dyld_uuid_info { | |
513 | uint64_t imageLoadAddress; /* base address image is mapped into */ | |
514 | uuid_t imageUUID; /* UUID of image */ | |
515 | }; | |
516 | ||
517 | enum task_snapshot_flags { | |
518 | kTaskRsrcFlagged = 0x4, // In the EXC_RESOURCE danger zone? | |
519 | kTerminatedSnapshot = 0x8, | |
520 | kPidSuspended = 0x10, // true for suspended task | |
521 | kFrozen = 0x20, // true for hibernated task (along with pidsuspended) | |
522 | kTaskDarwinBG = 0x40, | |
523 | kTaskExtDarwinBG = 0x80, | |
524 | kTaskVisVisible = 0x100, | |
525 | kTaskVisNonvisible = 0x200, | |
526 | kTaskIsForeground = 0x400, | |
527 | kTaskIsBoosted = 0x800, | |
528 | kTaskIsSuppressed = 0x1000, | |
529 | kTaskIsTimerThrottled = 0x2000, /* deprecated */ | |
530 | kTaskIsImpDonor = 0x4000, | |
531 | kTaskIsLiveImpDonor = 0x8000, | |
532 | kTaskIsDirty = 0x10000, | |
533 | kTaskWqExceededConstrainedThreadLimit = 0x20000, | |
534 | kTaskWqExceededTotalThreadLimit = 0x40000, | |
535 | kTaskWqFlagsAvailable = 0x80000, | |
536 | kTaskUUIDInfoFaultedIn = 0x100000, /* successfully faulted in some UUID info */ | |
537 | kTaskUUIDInfoMissing = 0x200000, /* some UUID info was paged out */ | |
538 | kTaskUUIDInfoTriedFault = 0x400000, /* tried to fault in UUID info */ | |
539 | kTaskSharedRegionInfoUnavailable = 0x800000, /* shared region info unavailable */ | |
540 | }; | |
541 | ||
542 | enum thread_snapshot_flags { | |
543 | kHasDispatchSerial = 0x4, | |
544 | kStacksPCOnly = 0x8, /* Stack traces have no frame pointers. */ | |
545 | kThreadDarwinBG = 0x10, /* Thread is darwinbg */ | |
546 | kThreadIOPassive = 0x20, /* Thread uses passive IO */ | |
547 | kThreadSuspended = 0x40, /* Thread is suspended */ | |
548 | kThreadTruncatedBT = 0x80, /* Unmapped pages caused truncated backtrace */ | |
549 | kGlobalForcedIdle = 0x100, /* Thread performs global forced idle */ | |
550 | kThreadFaultedBT = 0x200, /* Some thread stack pages were faulted in as part of BT */ | |
551 | kThreadTriedFaultBT = 0x400, /* We tried to fault in thread stack pages as part of BT */ | |
552 | kThreadOnCore = 0x800, /* Thread was on-core when we entered debugger context */ | |
553 | kThreadIdleWorker = 0x1000, /* Thread is an idle libpthread worker thread */ | |
5ba3f43e | 554 | kThreadMain = 0x2000, /* Thread is the main thread */ |
39037602 A |
555 | }; |
556 | ||
557 | struct mem_and_io_snapshot { | |
558 | uint32_t snapshot_magic; | |
559 | uint32_t free_pages; | |
560 | uint32_t active_pages; | |
561 | uint32_t inactive_pages; | |
562 | uint32_t purgeable_pages; | |
563 | uint32_t wired_pages; | |
564 | uint32_t speculative_pages; | |
565 | uint32_t throttled_pages; | |
566 | uint32_t filebacked_pages; | |
567 | uint32_t compressions; | |
568 | uint32_t decompressions; | |
569 | uint32_t compressor_size; | |
570 | int32_t busy_buffer_count; | |
571 | uint32_t pages_wanted; | |
572 | uint32_t pages_reclaimed; | |
573 | uint8_t pages_wanted_reclaimed_valid; // did mach_vm_pressure_monitor succeed? | |
574 | } __attribute__((packed)); | |
575 | ||
576 | /* SS_TH_* macros are for ths_state */ | |
577 | #define SS_TH_WAIT 0x01 /* queued for waiting */ | |
578 | #define SS_TH_SUSP 0x02 /* stopped or requested to stop */ | |
579 | #define SS_TH_RUN 0x04 /* running or on runq */ | |
580 | #define SS_TH_UNINT 0x08 /* waiting uninteruptibly */ | |
581 | #define SS_TH_TERMINATE 0x10 /* halted at termination */ | |
582 | #define SS_TH_TERMINATE2 0x20 /* added to termination queue */ | |
583 | #define SS_TH_IDLE 0x80 /* idling processor */ | |
584 | ||
585 | struct thread_snapshot_v2 { | |
586 | uint64_t ths_thread_id; | |
587 | uint64_t ths_wait_event; | |
588 | uint64_t ths_continuation; | |
589 | uint64_t ths_total_syscalls; | |
590 | uint64_t ths_voucher_identifier; | |
591 | uint64_t ths_dqserialnum; | |
592 | uint64_t ths_user_time; | |
593 | uint64_t ths_sys_time; | |
594 | uint64_t ths_ss_flags; | |
595 | uint64_t ths_last_run_time; | |
596 | uint64_t ths_last_made_runnable_time; | |
597 | uint32_t ths_state; | |
598 | uint32_t ths_sched_flags; | |
599 | int16_t ths_base_priority; | |
600 | int16_t ths_sched_priority; | |
601 | uint8_t ths_eqos; | |
602 | uint8_t ths_rqos; | |
603 | uint8_t ths_rqos_override; | |
604 | uint8_t ths_io_tier; | |
605 | } __attribute__((packed)); | |
606 | ||
607 | struct thread_snapshot_v3 { | |
608 | uint64_t ths_thread_id; | |
609 | uint64_t ths_wait_event; | |
610 | uint64_t ths_continuation; | |
611 | uint64_t ths_total_syscalls; | |
612 | uint64_t ths_voucher_identifier; | |
613 | uint64_t ths_dqserialnum; | |
614 | uint64_t ths_user_time; | |
615 | uint64_t ths_sys_time; | |
616 | uint64_t ths_ss_flags; | |
617 | uint64_t ths_last_run_time; | |
618 | uint64_t ths_last_made_runnable_time; | |
619 | uint32_t ths_state; | |
620 | uint32_t ths_sched_flags; | |
621 | int16_t ths_base_priority; | |
622 | int16_t ths_sched_priority; | |
623 | uint8_t ths_eqos; | |
624 | uint8_t ths_rqos; | |
625 | uint8_t ths_rqos_override; | |
626 | uint8_t ths_io_tier; | |
627 | uint64_t ths_thread_t; | |
628 | } __attribute__((packed)); | |
629 | ||
5ba3f43e A |
630 | |
631 | struct thread_snapshot_v4 { | |
632 | uint64_t ths_thread_id; | |
633 | uint64_t ths_wait_event; | |
634 | uint64_t ths_continuation; | |
635 | uint64_t ths_total_syscalls; | |
636 | uint64_t ths_voucher_identifier; | |
637 | uint64_t ths_dqserialnum; | |
638 | uint64_t ths_user_time; | |
639 | uint64_t ths_sys_time; | |
640 | uint64_t ths_ss_flags; | |
641 | uint64_t ths_last_run_time; | |
642 | uint64_t ths_last_made_runnable_time; | |
643 | uint32_t ths_state; | |
644 | uint32_t ths_sched_flags; | |
645 | int16_t ths_base_priority; | |
646 | int16_t ths_sched_priority; | |
647 | uint8_t ths_eqos; | |
648 | uint8_t ths_rqos; | |
649 | uint8_t ths_rqos_override; | |
650 | uint8_t ths_io_tier; | |
651 | uint64_t ths_thread_t; | |
652 | uint64_t ths_requested_policy; | |
653 | uint64_t ths_effective_policy; | |
654 | } __attribute__((packed)); | |
655 | ||
656 | ||
657 | struct thread_group_snapshot { | |
658 | uint64_t tgs_id; | |
659 | char tgs_name[16]; | |
660 | } __attribute__((packed)); | |
661 | ||
5c9f4661 A |
662 | enum thread_group_flags { |
663 | kThreadGroupEfficient = 0x1, | |
664 | kThreadGroupUIApp = 0x2 | |
665 | }; | |
666 | ||
667 | struct thread_group_snapshot_v2 { | |
668 | uint64_t tgs_id; | |
669 | char tgs_name[16]; | |
670 | uint64_t tgs_flags; | |
671 | } __attribute__((packed)); | |
672 | ||
5ba3f43e A |
673 | enum coalition_flags { |
674 | kCoalitionTermRequested = 0x1, | |
675 | kCoalitionTerminated = 0x2, | |
676 | kCoalitionReaped = 0x4, | |
677 | kCoalitionPrivileged = 0x8, | |
678 | }; | |
679 | ||
680 | struct jetsam_coalition_snapshot { | |
681 | uint64_t jcs_id; | |
682 | uint64_t jcs_flags; | |
683 | uint64_t jcs_thread_group; | |
684 | uint64_t jcs_leader_task_uniqueid; | |
685 | } __attribute__((packed)); | |
686 | ||
687 | struct instrs_cycles_snapshot { | |
688 | uint64_t ics_instructions; | |
689 | uint64_t ics_cycles; | |
690 | } __attribute__((packed)); | |
691 | ||
39037602 A |
692 | struct thread_delta_snapshot_v2 { |
693 | uint64_t tds_thread_id; | |
694 | uint64_t tds_voucher_identifier; | |
695 | uint64_t tds_ss_flags; | |
696 | uint64_t tds_last_made_runnable_time; | |
697 | uint32_t tds_state; | |
698 | uint32_t tds_sched_flags; | |
699 | int16_t tds_base_priority; | |
700 | int16_t tds_sched_priority; | |
701 | uint8_t tds_eqos; | |
702 | uint8_t tds_rqos; | |
703 | uint8_t tds_rqos_override; | |
704 | uint8_t tds_io_tier; | |
705 | } __attribute__ ((packed)); | |
706 | ||
707 | struct io_stats_snapshot | |
708 | { | |
709 | /* | |
710 | * I/O Statistics | |
711 | * XXX: These fields must be together. | |
712 | */ | |
713 | uint64_t ss_disk_reads_count; | |
714 | uint64_t ss_disk_reads_size; | |
715 | uint64_t ss_disk_writes_count; | |
716 | uint64_t ss_disk_writes_size; | |
717 | uint64_t ss_io_priority_count[STACKSHOT_IO_NUM_PRIORITIES]; | |
718 | uint64_t ss_io_priority_size[STACKSHOT_IO_NUM_PRIORITIES]; | |
719 | uint64_t ss_paging_count; | |
720 | uint64_t ss_paging_size; | |
721 | uint64_t ss_non_paging_count; | |
722 | uint64_t ss_non_paging_size; | |
723 | uint64_t ss_data_count; | |
724 | uint64_t ss_data_size; | |
725 | uint64_t ss_metadata_count; | |
726 | uint64_t ss_metadata_size; | |
727 | /* XXX: I/O Statistics end */ | |
728 | ||
729 | } __attribute__ ((packed)); | |
730 | ||
731 | struct task_snapshot_v2 { | |
732 | uint64_t ts_unique_pid; | |
733 | uint64_t ts_ss_flags; | |
734 | uint64_t ts_user_time_in_terminated_threads; | |
735 | uint64_t ts_system_time_in_terminated_threads; | |
736 | uint64_t ts_p_start_sec; | |
737 | uint64_t ts_task_size; | |
738 | uint64_t ts_max_resident_size; | |
739 | uint32_t ts_suspend_count; | |
740 | uint32_t ts_faults; | |
741 | uint32_t ts_pageins; | |
742 | uint32_t ts_cow_faults; | |
743 | uint32_t ts_was_throttled; | |
744 | uint32_t ts_did_throttle; | |
745 | uint32_t ts_latency_qos; | |
746 | int32_t ts_pid; | |
747 | char ts_p_comm[32]; | |
748 | } __attribute__ ((packed)); | |
749 | ||
750 | struct task_delta_snapshot_v2 { | |
751 | uint64_t tds_unique_pid; | |
752 | uint64_t tds_ss_flags; | |
753 | uint64_t tds_user_time_in_terminated_threads; | |
754 | uint64_t tds_system_time_in_terminated_threads; | |
755 | uint64_t tds_task_size; | |
756 | uint64_t tds_max_resident_size; | |
757 | uint32_t tds_suspend_count; | |
758 | uint32_t tds_faults; | |
759 | uint32_t tds_pageins; | |
760 | uint32_t tds_cow_faults; | |
761 | uint32_t tds_was_throttled; | |
762 | uint32_t tds_did_throttle; | |
763 | uint32_t tds_latency_qos; | |
764 | } __attribute__ ((packed)); | |
765 | ||
766 | struct stackshot_cpu_times { | |
767 | uint64_t user_usec; | |
768 | uint64_t system_usec; | |
769 | } __attribute__((packed)); | |
770 | ||
771 | struct stackshot_duration { | |
772 | uint64_t stackshot_duration; | |
773 | uint64_t stackshot_duration_outer; | |
774 | } __attribute__((packed)); | |
775 | ||
776 | struct stackshot_fault_stats { | |
777 | uint32_t sfs_pages_faulted_in; /* number of pages faulted in using KDP fault path */ | |
778 | uint64_t sfs_time_spent_faulting; /* MATUs spent faulting */ | |
779 | uint64_t sfs_system_max_fault_time; /* MATUs fault time limit per stackshot */ | |
780 | uint8_t sfs_stopped_faulting; /* we stopped decompressing because we hit the limit */ | |
781 | } __attribute__((packed)); | |
782 | ||
813fb2f6 A |
783 | typedef struct stackshot_thread_waitinfo { |
784 | uint64_t owner; /* The thread that owns the object */ | |
785 | uint64_t waiter; /* The thread that's waiting on the object */ | |
786 | uint64_t context; /* A context uniquely identifying the object */ | |
787 | uint8_t wait_type; /* The type of object that the thread is waiting on */ | |
788 | } __attribute__((packed)) thread_waitinfo_t; | |
789 | ||
790 | #define STACKSHOT_WAITOWNER_KERNEL (UINT64_MAX - 1) | |
791 | #define STACKSHOT_WAITOWNER_PORT_LOCKED (UINT64_MAX - 2) | |
792 | #define STACKSHOT_WAITOWNER_PSET_LOCKED (UINT64_MAX - 3) | |
793 | #define STACKSHOT_WAITOWNER_INTRANSIT (UINT64_MAX - 4) | |
794 | #define STACKSHOT_WAITOWNER_MTXSPIN (UINT64_MAX - 5) | |
5ba3f43e A |
795 | #define STACKSHOT_WAITOWNER_THREQUESTED (UINT64_MAX - 6) /* workloop waiting for a new worker thread */ |
796 | #define STACKSHOT_WAITOWNER_SUSPENDED (UINT64_MAX - 7) /* workloop is suspended */ | |
813fb2f6 A |
797 | |
798 | ||
39037602 A |
799 | /**************** definitions for crashinfo *********************/ |
800 | ||
801 | /* | |
802 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
803 | * in TASK_CRASHINFO_* types. | |
804 | */ | |
805 | ||
806 | /* FIXME some of these types aren't clean (fixed width, packed, and defined *here*) */ | |
807 | ||
808 | #define TASK_CRASHINFO_BEGIN KCDATA_BUFFER_BEGIN_CRASHINFO | |
809 | #define TASK_CRASHINFO_STRING_DESC KCDATA_TYPE_STRING_DESC | |
810 | #define TASK_CRASHINFO_UINT32_DESC KCDATA_TYPE_UINT32_DESC | |
811 | #define TASK_CRASHINFO_UINT64_DESC KCDATA_TYPE_UINT64_DESC | |
812 | ||
813 | #define TASK_CRASHINFO_EXTMODINFO 0x801 | |
814 | #define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct proc_uniqidentifierinfo */ | |
815 | #define TASK_CRASHINFO_TASKDYLD_INFO 0x803 | |
816 | #define TASK_CRASHINFO_UUID 0x804 | |
817 | #define TASK_CRASHINFO_PID 0x805 | |
818 | #define TASK_CRASHINFO_PPID 0x806 | |
819 | #define TASK_CRASHINFO_RUSAGE 0x807 /* struct rusage DEPRECATED do not use. | |
820 | This struct has longs in it */ | |
821 | #define TASK_CRASHINFO_RUSAGE_INFO 0x808 /* struct rusage_info_v3 from resource.h */ | |
822 | #define TASK_CRASHINFO_PROC_NAME 0x809 /* char * */ | |
823 | #define TASK_CRASHINFO_PROC_STARTTIME 0x80B /* struct timeval64 */ | |
824 | #define TASK_CRASHINFO_USERSTACK 0x80C /* uint64_t */ | |
825 | #define TASK_CRASHINFO_ARGSLEN 0x80D | |
826 | #define TASK_CRASHINFO_EXCEPTION_CODES 0x80E /* mach_exception_data_t */ | |
827 | #define TASK_CRASHINFO_PROC_PATH 0x80F /* string of len MAXPATHLEN */ | |
828 | #define TASK_CRASHINFO_PROC_CSFLAGS 0x810 /* uint32_t */ | |
829 | #define TASK_CRASHINFO_PROC_STATUS 0x811 /* char */ | |
830 | #define TASK_CRASHINFO_UID 0x812 /* uid_t */ | |
831 | #define TASK_CRASHINFO_GID 0x813 /* gid_t */ | |
832 | #define TASK_CRASHINFO_PROC_ARGC 0x814 /* int */ | |
833 | #define TASK_CRASHINFO_PROC_FLAGS 0x815 /* unsigned int */ | |
834 | #define TASK_CRASHINFO_CPUTYPE 0x816 /* cpu_type_t */ | |
835 | #define TASK_CRASHINFO_WORKQUEUEINFO 0x817 /* struct proc_workqueueinfo */ | |
836 | #define TASK_CRASHINFO_RESPONSIBLE_PID 0x818 /* pid_t */ | |
837 | #define TASK_CRASHINFO_DIRTY_FLAGS 0x819 /* int */ | |
838 | #define TASK_CRASHINFO_CRASHED_THREADID 0x81A /* uint64_t */ | |
839 | #define TASK_CRASHINFO_COALITION_ID 0x81B /* uint64_t */ | |
840 | #define TASK_CRASHINFO_UDATA_PTRS 0x81C /* uint64_t */ | |
841 | #define TASK_CRASHINFO_MEMORY_LIMIT 0x81D /* uint64_t */ | |
842 | ||
843 | #define TASK_CRASHINFO_END KCDATA_TYPE_BUFFER_END | |
844 | ||
845 | /**************** definitions for os reasons *********************/ | |
846 | ||
847 | #define EXIT_REASON_SNAPSHOT 0x1001 | |
848 | #define EXIT_REASON_USER_DESC 0x1002 /* string description of reason */ | |
849 | #define EXIT_REASON_USER_PAYLOAD 0x1003 /* user payload data */ | |
850 | #define EXIT_REASON_CODESIGNING_INFO 0x1004 | |
5ba3f43e A |
851 | #define EXIT_REASON_WORKLOOP_ID 0x1005 |
852 | #define EXIT_REASON_DISPATCH_QUEUE_NO 0x1006 | |
39037602 A |
853 | |
854 | struct exit_reason_snapshot { | |
855 | uint32_t ers_namespace; | |
856 | uint64_t ers_code; | |
857 | /* end of version 1 of exit_reason_snapshot. sizeof v1 was 12 */ | |
858 | uint64_t ers_flags; | |
859 | } __attribute__((packed)); | |
860 | ||
861 | #define EXIT_REASON_CODESIG_PATH_MAX 1024 | |
862 | ||
863 | struct codesigning_exit_reason_info { | |
864 | uint64_t ceri_virt_addr; | |
865 | uint64_t ceri_file_offset; | |
866 | char ceri_pathname[EXIT_REASON_CODESIG_PATH_MAX]; | |
867 | char ceri_filename[EXIT_REASON_CODESIG_PATH_MAX]; | |
868 | uint64_t ceri_codesig_modtime_secs; | |
869 | uint64_t ceri_codesig_modtime_nsecs; | |
870 | uint64_t ceri_page_modtime_secs; | |
871 | uint64_t ceri_page_modtime_nsecs; | |
872 | uint8_t ceri_path_truncated; | |
873 | uint8_t ceri_object_codesigned; | |
874 | uint8_t ceri_page_codesig_validated; | |
875 | uint8_t ceri_page_codesig_tainted; | |
876 | uint8_t ceri_page_codesig_nx; | |
877 | uint8_t ceri_page_wpmapped; | |
878 | uint8_t ceri_page_slid; | |
879 | uint8_t ceri_page_dirty; | |
880 | uint32_t ceri_page_shadow_depth; | |
881 | } __attribute__((packed)); | |
882 | ||
883 | #define EXIT_REASON_USER_DESC_MAX_LEN 1024 | |
884 | #define EXIT_REASON_PAYLOAD_MAX_LEN 2048 | |
885 | /**************** safe iterators *********************/ | |
886 | ||
887 | typedef struct kcdata_iter { | |
888 | kcdata_item_t item; | |
889 | void *end; | |
890 | } kcdata_iter_t; | |
891 | ||
892 | ||
893 | static inline | |
894 | kcdata_iter_t kcdata_iter(void *buffer, unsigned long size) { | |
895 | kcdata_iter_t iter; | |
896 | iter.item = (kcdata_item_t) buffer; | |
897 | iter.end = (void*) (((uintptr_t)buffer) + size); | |
898 | return iter; | |
899 | } | |
900 | ||
901 | static inline | |
902 | kcdata_iter_t kcdata_iter_unsafe(void *buffer) __attribute__((deprecated)); | |
903 | ||
904 | static inline | |
905 | kcdata_iter_t kcdata_iter_unsafe(void *buffer) { | |
906 | kcdata_iter_t iter; | |
907 | iter.item = (kcdata_item_t) buffer; | |
908 | iter.end = (void*) (uintptr_t) ~0; | |
909 | return iter; | |
910 | } | |
911 | ||
912 | static const kcdata_iter_t kcdata_invalid_iter = { .item = 0, .end = 0 }; | |
913 | ||
914 | static inline | |
915 | int kcdata_iter_valid(kcdata_iter_t iter) { | |
916 | return | |
917 | ( (uintptr_t)iter.item + sizeof(struct kcdata_item) <= (uintptr_t)iter.end ) && | |
918 | ( (uintptr_t)iter.item + sizeof(struct kcdata_item) + iter.item->size <= (uintptr_t)iter.end); | |
919 | } | |
920 | ||
921 | ||
922 | static inline | |
923 | kcdata_iter_t kcdata_iter_next(kcdata_iter_t iter) { | |
924 | iter.item = (kcdata_item_t) (((uintptr_t)iter.item) + sizeof(struct kcdata_item) + (iter.item->size)); | |
925 | return iter; | |
926 | } | |
927 | ||
928 | static inline uint32_t | |
929 | kcdata_iter_type(kcdata_iter_t iter) | |
930 | { | |
931 | if ((iter.item->type & ~0xfu) == KCDATA_TYPE_ARRAY_PAD0) | |
932 | return KCDATA_TYPE_ARRAY; | |
933 | else | |
934 | return iter.item->type; | |
935 | } | |
936 | ||
937 | static inline uint32_t | |
938 | kcdata_calc_padding(uint32_t size) | |
939 | { | |
940 | /* calculate number of bits to add to size to get something divisible by 16 */ | |
941 | return (-size) & 0xf; | |
942 | } | |
943 | ||
944 | static inline uint32_t | |
945 | kcdata_flags_get_padding(uint64_t flags) | |
946 | { | |
947 | return flags & KCDATA_FLAGS_STRUCT_PADDING_MASK; | |
948 | } | |
949 | ||
950 | /* see comment above about has_padding */ | |
951 | static inline int | |
952 | kcdata_iter_is_legacy_item(kcdata_iter_t iter, uint32_t legacy_size) | |
953 | { | |
954 | uint32_t legacy_size_padded = legacy_size + kcdata_calc_padding(legacy_size); | |
955 | return (iter.item->size == legacy_size_padded && | |
956 | (iter.item->flags & (KCDATA_FLAGS_STRUCT_PADDING_MASK | KCDATA_FLAGS_STRUCT_HAS_PADDING)) == 0); | |
957 | ||
958 | } | |
959 | ||
960 | static inline uint32_t | |
961 | kcdata_iter_size(kcdata_iter_t iter) | |
962 | { | |
963 | uint32_t legacy_size = 0; | |
964 | ||
965 | switch (kcdata_iter_type(iter)) { | |
966 | case KCDATA_TYPE_ARRAY: | |
967 | case KCDATA_TYPE_CONTAINER_BEGIN: | |
968 | return iter.item->size; | |
969 | case STACKSHOT_KCTYPE_THREAD_SNAPSHOT: { | |
970 | legacy_size = sizeof(struct thread_snapshot_v2); | |
971 | if (kcdata_iter_is_legacy_item(iter, legacy_size)) { | |
972 | return legacy_size; | |
973 | } | |
974 | ||
975 | goto not_legacy; | |
976 | } | |
977 | case STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO: { | |
978 | legacy_size = sizeof(struct dyld_uuid_info_64); | |
979 | if (kcdata_iter_is_legacy_item(iter, legacy_size)) { | |
980 | return legacy_size; | |
981 | } | |
982 | ||
983 | goto not_legacy; | |
984 | } | |
985 | not_legacy: | |
986 | default: | |
987 | if (iter.item->size < kcdata_flags_get_padding(iter.item->flags)) | |
988 | return 0; | |
989 | else | |
990 | return iter.item->size - kcdata_flags_get_padding(iter.item->flags); | |
991 | } | |
992 | } | |
993 | ||
994 | static inline uint64_t | |
995 | kcdata_iter_flags(kcdata_iter_t iter) | |
996 | { | |
997 | return iter.item->flags; | |
998 | } | |
999 | ||
1000 | static inline | |
1001 | void * kcdata_iter_payload(kcdata_iter_t iter) { | |
1002 | return &iter.item->data; | |
1003 | } | |
1004 | ||
1005 | ||
1006 | static inline | |
1007 | uint32_t kcdata_iter_array_elem_type(kcdata_iter_t iter) { | |
1008 | return (iter.item->flags >> 32) & UINT32_MAX; | |
1009 | } | |
1010 | ||
1011 | static inline | |
1012 | uint32_t kcdata_iter_array_elem_count(kcdata_iter_t iter) { | |
1013 | return (iter.item->flags) & UINT32_MAX; | |
1014 | } | |
1015 | ||
1016 | /* KCDATA_TYPE_ARRAY is ambiguous about the size of the array elements. Size is | |
1017 | * calculated as total_size / elements_count, but total size got padded out to a | |
1018 | * 16 byte alignment. New kernels will generate KCDATA_TYPE_ARRAY_PAD* instead | |
1019 | * to explicitly tell us how much padding was used. Here we have a fixed, never | |
1020 | * to be altered list of the sizes of array elements that were used before I | |
1021 | * discovered this issue. If you find a KCDATA_TYPE_ARRAY that is not one of | |
1022 | * these types, treat it as invalid data. */ | |
1023 | ||
1024 | static inline | |
1025 | uint32_t | |
1026 | kcdata_iter_array_size_switch(kcdata_iter_t iter) { | |
1027 | switch(kcdata_iter_array_elem_type(iter)) { | |
1028 | case KCDATA_TYPE_LIBRARY_LOADINFO: | |
1029 | return sizeof(struct dyld_uuid_info_32); | |
1030 | case KCDATA_TYPE_LIBRARY_LOADINFO64: | |
1031 | return sizeof(struct dyld_uuid_info_64); | |
1032 | case STACKSHOT_KCTYPE_KERN_STACKFRAME: | |
1033 | case STACKSHOT_KCTYPE_USER_STACKFRAME: | |
1034 | return sizeof(struct stack_snapshot_frame32); | |
1035 | case STACKSHOT_KCTYPE_KERN_STACKFRAME64: | |
1036 | case STACKSHOT_KCTYPE_USER_STACKFRAME64: | |
1037 | return sizeof(struct stack_snapshot_frame64); | |
1038 | case STACKSHOT_KCTYPE_DONATING_PIDS: | |
1039 | return sizeof(int32_t); | |
1040 | case STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT: | |
1041 | return sizeof(struct thread_delta_snapshot_v2); | |
1042 | // This one is only here to make some unit tests work. It should be OK to | |
1043 | // remove. | |
1044 | case TASK_CRASHINFO_CRASHED_THREADID: | |
1045 | return sizeof(uint64_t); | |
1046 | default: | |
1047 | return 0; | |
1048 | } | |
1049 | } | |
1050 | ||
1051 | static inline | |
1052 | int kcdata_iter_array_valid(kcdata_iter_t iter) { | |
1053 | if (!kcdata_iter_valid(iter)) | |
1054 | return 0; | |
1055 | if (kcdata_iter_type(iter) != KCDATA_TYPE_ARRAY) | |
1056 | return 0; | |
1057 | if (kcdata_iter_array_elem_count(iter) == 0) | |
1058 | return iter.item->size == 0; | |
1059 | if (iter.item->type == KCDATA_TYPE_ARRAY) { | |
1060 | uint32_t elem_size = kcdata_iter_array_size_switch(iter); | |
1061 | if (elem_size == 0) | |
1062 | return 0; | |
1063 | /* sizes get aligned to the nearest 16. */ | |
1064 | return | |
1065 | kcdata_iter_array_elem_count(iter) <= iter.item->size / elem_size && | |
1066 | iter.item->size % kcdata_iter_array_elem_count(iter) < 16; | |
1067 | } else { | |
1068 | return | |
1069 | (iter.item->type & 0xf) <= iter.item->size && | |
1070 | kcdata_iter_array_elem_count(iter) <= iter.item->size - (iter.item->type & 0xf) && | |
1071 | (iter.item->size - (iter.item->type & 0xf)) % kcdata_iter_array_elem_count(iter) == 0; | |
1072 | } | |
1073 | } | |
1074 | ||
1075 | ||
1076 | static inline | |
1077 | uint32_t kcdata_iter_array_elem_size(kcdata_iter_t iter) { | |
1078 | if (iter.item->type == KCDATA_TYPE_ARRAY) | |
1079 | return kcdata_iter_array_size_switch(iter); | |
1080 | if (kcdata_iter_array_elem_count(iter) == 0) | |
1081 | return 0; | |
1082 | return (iter.item->size - (iter.item->type & 0xf)) / kcdata_iter_array_elem_count(iter); | |
1083 | } | |
1084 | ||
1085 | static inline | |
1086 | int kcdata_iter_container_valid(kcdata_iter_t iter) { | |
1087 | return | |
1088 | kcdata_iter_valid(iter) && | |
1089 | kcdata_iter_type(iter) == KCDATA_TYPE_CONTAINER_BEGIN && | |
1090 | iter.item->size >= sizeof(uint32_t); | |
1091 | } | |
1092 | ||
1093 | static inline | |
1094 | uint32_t kcdata_iter_container_type(kcdata_iter_t iter) { | |
1095 | return * (uint32_t *) kcdata_iter_payload(iter); | |
1096 | } | |
1097 | ||
1098 | static inline | |
1099 | uint64_t kcdata_iter_container_id(kcdata_iter_t iter) { | |
1100 | return iter.item->flags; | |
1101 | } | |
1102 | ||
1103 | ||
1104 | #define KCDATA_ITER_FOREACH(iter) for(; kcdata_iter_valid(iter) && iter.item->type != KCDATA_TYPE_BUFFER_END; iter = kcdata_iter_next(iter)) | |
1105 | #define KCDATA_ITER_FOREACH_FAILED(iter) (!kcdata_iter_valid(iter) || (iter).item->type != KCDATA_TYPE_BUFFER_END) | |
1106 | ||
1107 | static inline | |
1108 | kcdata_iter_t | |
1109 | kcdata_iter_find_type(kcdata_iter_t iter, uint32_t type) | |
1110 | { | |
1111 | KCDATA_ITER_FOREACH(iter) | |
1112 | { | |
1113 | if (kcdata_iter_type(iter) == type) | |
1114 | return iter; | |
1115 | } | |
1116 | return kcdata_invalid_iter; | |
1117 | } | |
1118 | ||
1119 | static inline | |
1120 | int kcdata_iter_data_with_desc_valid(kcdata_iter_t iter, uint32_t minsize) { | |
1121 | return | |
1122 | kcdata_iter_valid(iter) && | |
1123 | kcdata_iter_size(iter) >= KCDATA_DESC_MAXLEN + minsize && | |
1124 | ((char*)kcdata_iter_payload(iter))[KCDATA_DESC_MAXLEN-1] == 0; | |
1125 | } | |
1126 | ||
1127 | static inline | |
1128 | char *kcdata_iter_string(kcdata_iter_t iter, uint32_t offset) { | |
1129 | if (offset > kcdata_iter_size(iter)) { | |
1130 | return NULL; | |
1131 | } | |
1132 | uint32_t maxlen = kcdata_iter_size(iter) - offset; | |
1133 | char *s = ((char*)kcdata_iter_payload(iter)) + offset; | |
1134 | if (strnlen(s, maxlen) < maxlen) { | |
1135 | return s; | |
1136 | } else { | |
1137 | return NULL; | |
1138 | } | |
1139 | } | |
1140 | ||
1141 | static inline void kcdata_iter_get_data_with_desc(kcdata_iter_t iter, char **desc_ptr, void **data_ptr, uint32_t *size_ptr) { | |
1142 | if (desc_ptr) | |
1143 | *desc_ptr = (char *)kcdata_iter_payload(iter); | |
1144 | if (data_ptr) | |
1145 | *data_ptr = (void *)((uintptr_t)kcdata_iter_payload(iter) + KCDATA_DESC_MAXLEN); | |
1146 | if (size_ptr) | |
1147 | *size_ptr = kcdata_iter_size(iter) - KCDATA_DESC_MAXLEN; | |
1148 | } | |
1149 | ||
1150 | #endif |