]>
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 | * | |
f427ee49 A |
193 | * Feature description: Compression |
194 | * -------------------- | |
195 | * In order to avoid keeping large amunt of memory reserved for a panic stackshot, kcdata has support | |
196 | * for compressing the buffer in a streaming fashion. New data pushed to the kcdata buffer will be | |
197 | * automatically compressed using an algorithm selected by the API user (currently, we only support | |
198 | * pass-through and zlib, in the future we plan to add WKDM support, see: 57913859). | |
199 | * | |
200 | * To start using compression, call: | |
201 | * kcdata_init_compress(kcdata_p, hdr_tag, memcpy_f, comp_type); | |
202 | * where: | |
203 | * `kcdata_p` is the kcdata buffer that will be used | |
204 | * `hdr_tag` is the usual header tag denoting what type of kcdata buffer this will be | |
205 | * `memcpy_f` a memcpy(3) function to use to copy into the buffer, optional. | |
206 | * `compy_type` is the compression type, see KCDCT_ZLIB for an example. | |
207 | * | |
208 | * Once compression is initialized: | |
209 | * (1) all self-describing APIs will automatically compress | |
210 | * (2) you can now use the following APIs to compress data into the buffer: | |
211 | * (None of the following will compress unless kcdata_init_compress() has been called) | |
212 | * | |
213 | * - kcdata_push_data(kcdata_descriptor_t data, uint32_t type, uint32_t size, const void *input_data) | |
214 | * Pushes the buffer of kctype @type at[@input_data, @input_data + @size] | |
215 | * into the kcdata buffer @data, compressing if needed. | |
216 | * | |
217 | * - kcdata_push_array(kcdata_descriptor_t data, uint32_t type_of_element, | |
218 | * uint32_t size_of_element, uint32_t count, const void *input_data) | |
219 | * Pushes the array found at @input_data, with element type @type_of_element, where | |
220 | * each element is of size @size_of_element and there are @count elements into the kcdata buffer | |
221 | * at @data. | |
222 | * | |
223 | * - kcdata_compression_window_open/close(kcdata_descriptor_t data) | |
224 | * In case the data you are trying to push to the kcdata buffer @data is difficult to predict, | |
225 | * you can open a "compression window". Between an open and a close, no compression will be done. | |
226 | * Once you clsoe the window, the underlying compression algorithm will compress the data into the buffer | |
227 | * and automatically rewind the current end marker of the kcdata buffer. | |
228 | * There is an ASCII art in kern_cdata.c to aid the reader in understanding | |
229 | * this. | |
230 | * | |
231 | * - kcdata_finish_compression(kcdata_descriptor_t data) | |
232 | * Must be called at the end to flush any underlying buffers used by the compression algorithms. | |
233 | * This function will also add some statistics about the compression to the buffer which helps with | |
234 | * decompressing later. | |
235 | * | |
236 | * Once you are done with the kcdata buffer, call kcdata_deinit_compress to | |
237 | * free any buffers that may have been allocated internal to the compression | |
238 | * algorithm. | |
39037602 A |
239 | */ |
240 | ||
241 | ||
242 | #ifndef _KCDATA_H_ | |
243 | #define _KCDATA_H_ | |
244 | ||
245 | #include <stdint.h> | |
246 | #include <string.h> | |
247 | #include <uuid/uuid.h> | |
248 | ||
249 | #define KCDATA_DESC_MAXLEN 32 /* including NULL byte at end */ | |
250 | ||
251 | #define KCDATA_FLAGS_STRUCT_PADDING_MASK 0xf | |
252 | #define KCDATA_FLAGS_STRUCT_HAS_PADDING 0x80 | |
253 | ||
254 | /* | |
255 | * kcdata aligns elements to 16 byte boundaries. | |
256 | */ | |
257 | #define KCDATA_ALIGNMENT_SIZE 0x10 | |
258 | ||
259 | struct kcdata_item { | |
260 | uint32_t type; | |
261 | uint32_t size; /* len(data) */ | |
262 | /* flags. | |
263 | * | |
264 | * For structures: | |
265 | * padding = flags & 0xf | |
266 | * has_padding = (flags & 0x80) >> 7 | |
267 | * | |
268 | * has_padding is needed to disambiguate cases such as | |
269 | * thread_snapshot_v2 and thread_snapshot_v3. Their | |
270 | * respective sizes are 0x68 and 0x70, and thread_snapshot_v2 | |
271 | * was emmitted by old kernels *before* we started recording | |
272 | * padding. Since legacy thread_snapsht_v2 and modern | |
273 | * thread_snapshot_v3 will both record 0 for the padding | |
274 | * flags, we need some other bit which will be nonzero in the | |
275 | * flags to disambiguate. | |
276 | * | |
277 | * This is why we hardcode a special case for | |
278 | * STACKSHOT_KCTYPE_THREAD_SNAPSHOT into the iterator | |
279 | * functions below. There is only a finite number of such | |
280 | * hardcodings which will ever be needed. They can occur | |
281 | * when: | |
282 | * | |
283 | * * We have a legacy structure that predates padding flags | |
284 | * | |
285 | * * which we want to extend without changing the kcdata type | |
286 | * | |
287 | * * by only so many bytes as would fit in the space that | |
288 | * was previously unused padding. | |
289 | * | |
290 | * For containers: | |
291 | * container_id = flags | |
292 | * | |
293 | * For arrays: | |
294 | * element_count = flags & UINT32_MAX | |
295 | * element_type = (flags >> 32) & UINT32_MAX | |
296 | */ | |
297 | uint64_t flags; | |
298 | char data[]; /* must be at the end */ | |
299 | }; | |
300 | ||
301 | typedef struct kcdata_item * kcdata_item_t; | |
302 | ||
303 | 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 }; | |
304 | typedef enum KCDATA_SUBTYPE_TYPES kctype_subtype_t; | |
305 | ||
306 | /* | |
307 | * A subtype description structure that defines | |
308 | * how a compound data is laid out in memory. This | |
309 | * provides on the fly definition of types and consumption | |
310 | * by the parser. | |
311 | */ | |
312 | struct kcdata_subtype_descriptor { | |
313 | uint8_t kcs_flags; | |
314 | #define KCS_SUBTYPE_FLAGS_NONE 0x0 | |
315 | #define KCS_SUBTYPE_FLAGS_ARRAY 0x1 | |
316 | /* Force struct type even if only one element. | |
317 | * | |
318 | * Normally a kcdata_type_definition is treated as a structure if it has | |
319 | * more than one subtype descriptor. Otherwise it is treated as a simple | |
320 | * type. For example libkdd will represent a simple integer 42 as simply | |
321 | * 42, but it will represent a structure containing an integer 42 as | |
322 | * {"field_name": 42}.. | |
323 | * | |
324 | * If a kcdata_type_definition has only single subtype, then it will be | |
325 | * treated as a structure iff KCS_SUBTYPE_FLAGS_STRUCT is set. If it has | |
326 | * multiple subtypes, it will always be treated as a structure. | |
327 | * | |
328 | * KCS_SUBTYPE_FLAGS_MERGE has the opposite effect. If this flag is used then | |
329 | * even if there are multiple elements, they will all be treated as individual | |
330 | * properties of the parent dictionary. | |
331 | */ | |
332 | #define KCS_SUBTYPE_FLAGS_STRUCT 0x2 /* force struct type even if only one element */ | |
333 | #define KCS_SUBTYPE_FLAGS_MERGE 0x4 /* treat as multiple elements of parents instead of struct */ | |
334 | uint8_t kcs_elem_type; /* restricted to kctype_subtype_t */ | |
335 | uint16_t kcs_elem_offset; /* offset in struct where data is found */ | |
336 | uint32_t kcs_elem_size; /* size of element (or) packed state for array type */ | |
337 | char kcs_name[KCDATA_DESC_MAXLEN]; /* max 31 bytes for name of field */ | |
338 | }; | |
339 | ||
340 | typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t; | |
341 | ||
342 | /* | |
343 | * In case of array of basic c types in kctype_subtype_t, | |
344 | * size is packed in lower 16 bits and | |
345 | * count is packed in upper 16 bits of kcs_elem_size field. | |
346 | */ | |
347 | #define KCS_SUBTYPE_PACK_SIZE(e_count, e_size) (((e_count)&0xffffu) << 16 | ((e_size)&0xffffu)) | |
348 | ||
349 | static inline uint32_t | |
350 | kcs_get_elem_size(kcdata_subtype_descriptor_t d) | |
351 | { | |
352 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { | |
353 | /* size is composed as ((count &0xffff)<<16 | (elem_size & 0xffff)) */ | |
0a7de745 | 354 | return (uint32_t)((d->kcs_elem_size & 0xffff) * ((d->kcs_elem_size & 0xffff0000) >> 16)); |
39037602 A |
355 | } |
356 | return d->kcs_elem_size; | |
357 | } | |
358 | ||
359 | static inline uint32_t | |
360 | kcs_get_elem_count(kcdata_subtype_descriptor_t d) | |
361 | { | |
0a7de745 | 362 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { |
39037602 | 363 | return (d->kcs_elem_size >> 16) & 0xffff; |
0a7de745 | 364 | } |
39037602 A |
365 | return 1; |
366 | } | |
367 | ||
368 | static inline int | |
369 | kcs_set_elem_size(kcdata_subtype_descriptor_t d, uint32_t size, uint32_t count) | |
370 | { | |
371 | if (count > 1) { | |
372 | /* means we are setting up an array */ | |
0a7de745 | 373 | if (size > 0xffff || count > 0xffff) { |
39037602 | 374 | return -1; //invalid argument |
0a7de745 | 375 | } |
39037602 | 376 | d->kcs_elem_size = ((count & 0xffff) << 16 | (size & 0xffff)); |
0a7de745 | 377 | } else { |
39037602 A |
378 | d->kcs_elem_size = size; |
379 | } | |
380 | return 0; | |
381 | } | |
382 | ||
383 | struct kcdata_type_definition { | |
384 | uint32_t kct_type_identifier; | |
385 | uint32_t kct_num_elements; | |
386 | char kct_name[KCDATA_DESC_MAXLEN]; | |
387 | struct kcdata_subtype_descriptor kct_elements[]; | |
388 | }; | |
389 | ||
390 | ||
391 | /* chunk type definitions. 0 - 0x7ff are reserved and defined here | |
392 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
393 | * in STACKSHOT_KCTYPE_* types. | |
394 | */ | |
395 | ||
396 | /* | |
397 | * Types with description value. | |
398 | * these will have KCDATA_DESC_MAXLEN-1 length string description | |
399 | * and rest of kcdata_iter_size() - KCDATA_DESC_MAXLEN bytes as data | |
400 | */ | |
401 | #define KCDATA_TYPE_INVALID 0x0u | |
402 | #define KCDATA_TYPE_STRING_DESC 0x1u | |
403 | #define KCDATA_TYPE_UINT32_DESC 0x2u | |
404 | #define KCDATA_TYPE_UINT64_DESC 0x3u | |
405 | #define KCDATA_TYPE_INT32_DESC 0x4u | |
406 | #define KCDATA_TYPE_INT64_DESC 0x5u | |
407 | #define KCDATA_TYPE_BINDATA_DESC 0x6u | |
408 | ||
409 | /* | |
410 | * Compound type definitions | |
411 | */ | |
412 | #define KCDATA_TYPE_ARRAY 0x11u /* Array of data OBSOLETE DONT USE THIS*/ | |
413 | #define KCDATA_TYPE_TYPEDEFINTION 0x12u /* Meta type that describes a type on the fly. */ | |
414 | #define KCDATA_TYPE_CONTAINER_BEGIN \ | |
415 | 0x13u /* Container type which has corresponding CONTAINER_END header. \ | |
0a7de745 A |
416 | * KCDATA_TYPE_CONTAINER_BEGIN has type in the data segment. \ |
417 | * Both headers have (uint64_t) ID for matching up nested data. \ | |
418 | */ | |
39037602 A |
419 | #define KCDATA_TYPE_CONTAINER_END 0x14u |
420 | ||
421 | #define KCDATA_TYPE_ARRAY_PAD0 0x20u /* Array of data with 0 byte of padding*/ | |
422 | #define KCDATA_TYPE_ARRAY_PAD1 0x21u /* Array of data with 1 byte of padding*/ | |
423 | #define KCDATA_TYPE_ARRAY_PAD2 0x22u /* Array of data with 2 byte of padding*/ | |
424 | #define KCDATA_TYPE_ARRAY_PAD3 0x23u /* Array of data with 3 byte of padding*/ | |
425 | #define KCDATA_TYPE_ARRAY_PAD4 0x24u /* Array of data with 4 byte of padding*/ | |
426 | #define KCDATA_TYPE_ARRAY_PAD5 0x25u /* Array of data with 5 byte of padding*/ | |
427 | #define KCDATA_TYPE_ARRAY_PAD6 0x26u /* Array of data with 6 byte of padding*/ | |
428 | #define KCDATA_TYPE_ARRAY_PAD7 0x27u /* Array of data with 7 byte of padding*/ | |
429 | #define KCDATA_TYPE_ARRAY_PAD8 0x28u /* Array of data with 8 byte of padding*/ | |
430 | #define KCDATA_TYPE_ARRAY_PAD9 0x29u /* Array of data with 9 byte of padding*/ | |
431 | #define KCDATA_TYPE_ARRAY_PADa 0x2au /* Array of data with a byte of padding*/ | |
432 | #define KCDATA_TYPE_ARRAY_PADb 0x2bu /* Array of data with b byte of padding*/ | |
433 | #define KCDATA_TYPE_ARRAY_PADc 0x2cu /* Array of data with c byte of padding*/ | |
434 | #define KCDATA_TYPE_ARRAY_PADd 0x2du /* Array of data with d byte of padding*/ | |
435 | #define KCDATA_TYPE_ARRAY_PADe 0x2eu /* Array of data with e byte of padding*/ | |
436 | #define KCDATA_TYPE_ARRAY_PADf 0x2fu /* Array of data with f byte of padding*/ | |
437 | ||
438 | /* | |
439 | * Generic data types that are most commonly used | |
440 | */ | |
441 | #define KCDATA_TYPE_LIBRARY_LOADINFO 0x30u /* struct dyld_uuid_info_32 */ | |
442 | #define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31u /* struct dyld_uuid_info_64 */ | |
443 | #define KCDATA_TYPE_TIMEBASE 0x32u /* struct mach_timebase_info */ | |
444 | #define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33u /* uint64_t */ | |
445 | #define KCDATA_TYPE_TIMEVAL 0x34u /* struct timeval64 */ | |
446 | #define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35u /* time in usecs uint64_t */ | |
447 | #define KCDATA_TYPE_PID 0x36u /* int32_t */ | |
448 | #define KCDATA_TYPE_PROCNAME 0x37u /* char * */ | |
449 | #define KCDATA_TYPE_NESTED_KCDATA 0x38u /* nested kcdata buffer */ | |
f427ee49 | 450 | #define KCDATA_TYPE_LIBRARY_AOTINFO 0x39u /* struct user64_dyld_aot_info */ |
39037602 A |
451 | |
452 | #define KCDATA_TYPE_BUFFER_END 0xF19158EDu | |
453 | ||
454 | /* MAGIC numbers defined for each class of chunked data | |
455 | * | |
456 | * To future-proof against big-endian arches, make sure none of these magic | |
457 | * numbers are byteswaps of each other | |
458 | */ | |
459 | ||
f427ee49 A |
460 | #define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157u /* owner: corpses/task_corpse.h */ |
461 | /* type-range: 0x800 - 0x8ff */ | |
462 | #define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807u /* owner: sys/stackshot.h */ | |
463 | /* type-range: 0x900 - 0x93f */ | |
464 | #define KCDATA_BUFFER_BEGIN_COMPRESSED 0x434f4d50u /* owner: sys/stackshot.h */ | |
465 | /* type-range: 0x900 - 0x93f */ | |
466 | #define KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT 0xDE17A59Au /* owner: sys/stackshot.h */ | |
467 | /* type-range: 0x940 - 0x9ff */ | |
468 | #define KCDATA_BUFFER_BEGIN_OS_REASON 0x53A20900u /* owner: sys/reason.h */ | |
469 | /* type-range: 0x1000-0x103f */ | |
470 | #define KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG 0x1e21c09fu /* owner: osfmk/tests/kernel_tests.c */ | |
471 | /* type-range: 0x1040-0x105f */ | |
39037602 A |
472 | |
473 | /* next type range number available 0x1060 */ | |
474 | /**************** definitions for XNUPOST *********************/ | |
0a7de745 | 475 | #define XNUPOST_KCTYPE_TESTCONFIG 0x1040 |
39037602 A |
476 | |
477 | /**************** definitions for stackshot *********************/ | |
478 | ||
479 | /* This value must always match IO_NUM_PRIORITIES defined in thread_info.h */ | |
0a7de745 | 480 | #define STACKSHOT_IO_NUM_PRIORITIES 4 |
39037602 | 481 | /* This value must always match MAXTHREADNAMESIZE used in bsd */ |
0a7de745 | 482 | #define STACKSHOT_MAX_THREAD_NAME_SIZE 64 |
39037602 A |
483 | |
484 | /* | |
485 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
486 | * in STACKSHOT_KCTYPE_* types. | |
487 | */ | |
cb323159 A |
488 | #define STACKSHOT_KCTYPE_IOSTATS 0x901u /* io_stats_snapshot */ |
489 | #define STACKSHOT_KCTYPE_GLOBAL_MEM_STATS 0x902u /* struct mem_and_io_snapshot */ | |
490 | #define STACKSHOT_KCCONTAINER_TASK 0x903u | |
491 | #define STACKSHOT_KCCONTAINER_THREAD 0x904u | |
492 | #define STACKSHOT_KCTYPE_TASK_SNAPSHOT 0x905u /* task_snapshot_v2 */ | |
493 | #define STACKSHOT_KCTYPE_THREAD_SNAPSHOT 0x906u /* thread_snapshot_v2, thread_snapshot_v3 */ | |
494 | #define STACKSHOT_KCTYPE_DONATING_PIDS 0x907u /* int[] */ | |
495 | #define STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO 0x908u /* same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
496 | #define STACKSHOT_KCTYPE_THREAD_NAME 0x909u /* char[] */ | |
497 | #define STACKSHOT_KCTYPE_KERN_STACKFRAME 0x90Au /* struct stack_snapshot_frame32 */ | |
498 | #define STACKSHOT_KCTYPE_KERN_STACKFRAME64 0x90Bu /* struct stack_snapshot_frame64 */ | |
499 | #define STACKSHOT_KCTYPE_USER_STACKFRAME 0x90Cu /* struct stack_snapshot_frame32 */ | |
500 | #define STACKSHOT_KCTYPE_USER_STACKFRAME64 0x90Du /* struct stack_snapshot_frame64 */ | |
501 | #define STACKSHOT_KCTYPE_BOOTARGS 0x90Eu /* boot args string */ | |
502 | #define STACKSHOT_KCTYPE_OSVERSION 0x90Fu /* os version string */ | |
503 | #define STACKSHOT_KCTYPE_KERN_PAGE_SIZE 0x910u /* kernel page size in uint32_t */ | |
504 | #define STACKSHOT_KCTYPE_JETSAM_LEVEL 0x911u /* jetsam level in uint32_t */ | |
505 | #define STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP 0x912u /* timestamp used for the delta stackshot */ | |
506 | #define STACKSHOT_KCTYPE_KERN_STACKLR 0x913u /* uint32_t */ | |
507 | #define STACKSHOT_KCTYPE_KERN_STACKLR64 0x914u /* uint64_t */ | |
508 | #define STACKSHOT_KCTYPE_USER_STACKLR 0x915u /* uint32_t */ | |
509 | #define STACKSHOT_KCTYPE_USER_STACKLR64 0x916u /* uint64_t */ | |
510 | #define STACKSHOT_KCTYPE_NONRUNNABLE_TIDS 0x917u /* uint64_t */ | |
511 | #define STACKSHOT_KCTYPE_NONRUNNABLE_TASKS 0x918u /* uint64_t */ | |
512 | #define STACKSHOT_KCTYPE_CPU_TIMES 0x919u /* struct stackshot_cpu_times or stackshot_cpu_times_v2 */ | |
513 | #define STACKSHOT_KCTYPE_STACKSHOT_DURATION 0x91au /* struct stackshot_duration */ | |
514 | #define STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS 0x91bu /* struct stackshot_fault_stats */ | |
515 | #define STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO 0x91cu /* kernelcache UUID -- same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
516 | #define STACKSHOT_KCTYPE_THREAD_WAITINFO 0x91du /* struct stackshot_thread_waitinfo */ | |
517 | #define STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT 0x91eu /* struct thread_group_snapshot or thread_group_snapshot_v2 */ | |
518 | #define STACKSHOT_KCTYPE_THREAD_GROUP 0x91fu /* uint64_t */ | |
519 | #define STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT 0x920u /* struct jetsam_coalition_snapshot */ | |
520 | #define STACKSHOT_KCTYPE_JETSAM_COALITION 0x921u /* uint64_t */ | |
521 | #define STACKSHOT_KCTYPE_THREAD_POLICY_VERSION 0x922u /* THREAD_POLICY_INTERNAL_STRUCT_VERSION in uint32 */ | |
522 | #define STACKSHOT_KCTYPE_INSTRS_CYCLES 0x923u /* struct instrs_cycles_snapshot */ | |
523 | #define STACKSHOT_KCTYPE_USER_STACKTOP 0x924u /* struct stack_snapshot_stacktop */ | |
524 | #define STACKSHOT_KCTYPE_ASID 0x925u /* uint32_t */ | |
525 | #define STACKSHOT_KCTYPE_PAGE_TABLES 0x926u /* uint64_t */ | |
526 | #define STACKSHOT_KCTYPE_SYS_SHAREDCACHE_LAYOUT 0x927u /* same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
527 | #define STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL 0x928u /* dispatch queue label */ | |
528 | #define STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO 0x929u /* struct stackshot_thread_turnstileinfo */ | |
f427ee49 A |
529 | #define STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE 0x92au /* struct stackshot_cpu_architecture */ |
530 | #define STACKSHOT_KCTYPE_LATENCY_INFO 0x92bu /* struct stackshot_latency_collection */ | |
531 | #define STACKSHOT_KCTYPE_LATENCY_INFO_TASK 0x92cu /* struct stackshot_latency_task */ | |
532 | #define STACKSHOT_KCTYPE_LATENCY_INFO_THREAD 0x92du /* struct stackshot_latency_thread */ | |
533 | #define STACKSHOT_KCTYPE_LOADINFO64_TEXT_EXEC 0x92eu /* TEXT_EXEC load info -- same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ | |
534 | #define STACKSHOT_KCTYPE_AOTCACHE_LOADINFO 0x92fu /* struct dyld_aot_cache_uuid_info */ | |
39037602 A |
535 | |
536 | #define STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT 0x940u /* task_delta_snapshot_v2 */ | |
a39ff7e2 | 537 | #define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v* */ |
39037602 | 538 | |
39037602 A |
539 | struct stack_snapshot_frame32 { |
540 | uint32_t lr; | |
541 | uint32_t sp; | |
542 | }; | |
543 | ||
544 | struct stack_snapshot_frame64 { | |
0a7de745 A |
545 | uint64_t lr; |
546 | uint64_t sp; | |
39037602 A |
547 | }; |
548 | ||
549 | struct dyld_uuid_info_32 { | |
0a7de745 A |
550 | uint32_t imageLoadAddress; /* base address image is mapped at */ |
551 | uuid_t imageUUID; | |
39037602 A |
552 | }; |
553 | ||
554 | struct dyld_uuid_info_64 { | |
0a7de745 A |
555 | uint64_t imageLoadAddress; /* XXX image slide */ |
556 | uuid_t imageUUID; | |
39037602 A |
557 | }; |
558 | ||
559 | struct dyld_uuid_info_64_v2 { | |
0a7de745 A |
560 | uint64_t imageLoadAddress; /* XXX image slide */ |
561 | uuid_t imageUUID; | |
562 | /* end of version 1 of dyld_uuid_info_64. sizeof v1 was 24 */ | |
563 | uint64_t imageSlidBaseAddress; /* slid base address of image */ | |
39037602 A |
564 | }; |
565 | ||
f427ee49 A |
566 | struct dyld_aot_cache_uuid_info { |
567 | uint64_t x86SlidBaseAddress; /* slid base address of x86 shared cache */ | |
568 | uuid_t x86UUID; /* UUID of x86 shared cache */ | |
569 | uint64_t aotSlidBaseAddress; /* slide base address of aot cache */ | |
570 | uuid_t aotUUID; /* UUID of aot shared cache */ | |
571 | }; | |
572 | ||
39037602 | 573 | struct user32_dyld_uuid_info { |
0a7de745 A |
574 | uint32_t imageLoadAddress; /* base address image is mapped into */ |
575 | uuid_t imageUUID; /* UUID of image */ | |
39037602 A |
576 | }; |
577 | ||
578 | struct user64_dyld_uuid_info { | |
0a7de745 A |
579 | uint64_t imageLoadAddress; /* base address image is mapped into */ |
580 | uuid_t imageUUID; /* UUID of image */ | |
39037602 A |
581 | }; |
582 | ||
f427ee49 A |
583 | #define DYLD_AOT_IMAGE_KEY_SIZE 32 |
584 | ||
585 | struct user64_dyld_aot_info { | |
586 | uint64_t x86LoadAddress; | |
587 | uint64_t aotLoadAddress; | |
588 | uint64_t aotImageSize; | |
589 | uint8_t aotImageKey[DYLD_AOT_IMAGE_KEY_SIZE]; | |
590 | }; | |
591 | ||
39037602 | 592 | enum task_snapshot_flags { |
cb323159 | 593 | /* k{User,Kernel}64_p (values 0x1 and 0x2) are defined in generic_snapshot_flags */ |
39037602 A |
594 | kTaskRsrcFlagged = 0x4, // In the EXC_RESOURCE danger zone? |
595 | kTerminatedSnapshot = 0x8, | |
596 | kPidSuspended = 0x10, // true for suspended task | |
597 | kFrozen = 0x20, // true for hibernated task (along with pidsuspended) | |
598 | kTaskDarwinBG = 0x40, | |
599 | kTaskExtDarwinBG = 0x80, | |
600 | kTaskVisVisible = 0x100, | |
601 | kTaskVisNonvisible = 0x200, | |
602 | kTaskIsForeground = 0x400, | |
603 | kTaskIsBoosted = 0x800, | |
604 | kTaskIsSuppressed = 0x1000, | |
605 | kTaskIsTimerThrottled = 0x2000, /* deprecated */ | |
606 | kTaskIsImpDonor = 0x4000, | |
607 | kTaskIsLiveImpDonor = 0x8000, | |
608 | kTaskIsDirty = 0x10000, | |
609 | kTaskWqExceededConstrainedThreadLimit = 0x20000, | |
610 | kTaskWqExceededTotalThreadLimit = 0x40000, | |
611 | kTaskWqFlagsAvailable = 0x80000, | |
612 | kTaskUUIDInfoFaultedIn = 0x100000, /* successfully faulted in some UUID info */ | |
613 | kTaskUUIDInfoMissing = 0x200000, /* some UUID info was paged out */ | |
614 | kTaskUUIDInfoTriedFault = 0x400000, /* tried to fault in UUID info */ | |
615 | kTaskSharedRegionInfoUnavailable = 0x800000, /* shared region info unavailable */ | |
d9a64523 A |
616 | kTaskTALEngaged = 0x1000000, |
617 | /* 0x2000000 unused */ | |
618 | kTaskIsDirtyTracked = 0x4000000, | |
619 | kTaskAllowIdleExit = 0x8000000, | |
f427ee49 | 620 | kTaskIsTranslated = 0x10000000, |
39037602 A |
621 | }; |
622 | ||
623 | enum thread_snapshot_flags { | |
cb323159 | 624 | /* k{User,Kernel}64_p (values 0x1 and 0x2) are defined in generic_snapshot_flags */ |
39037602 A |
625 | kHasDispatchSerial = 0x4, |
626 | kStacksPCOnly = 0x8, /* Stack traces have no frame pointers. */ | |
627 | kThreadDarwinBG = 0x10, /* Thread is darwinbg */ | |
628 | kThreadIOPassive = 0x20, /* Thread uses passive IO */ | |
629 | kThreadSuspended = 0x40, /* Thread is suspended */ | |
630 | kThreadTruncatedBT = 0x80, /* Unmapped pages caused truncated backtrace */ | |
631 | kGlobalForcedIdle = 0x100, /* Thread performs global forced idle */ | |
632 | kThreadFaultedBT = 0x200, /* Some thread stack pages were faulted in as part of BT */ | |
633 | kThreadTriedFaultBT = 0x400, /* We tried to fault in thread stack pages as part of BT */ | |
634 | kThreadOnCore = 0x800, /* Thread was on-core when we entered debugger context */ | |
635 | kThreadIdleWorker = 0x1000, /* Thread is an idle libpthread worker thread */ | |
5ba3f43e | 636 | kThreadMain = 0x2000, /* Thread is the main thread */ |
39037602 A |
637 | }; |
638 | ||
639 | struct mem_and_io_snapshot { | |
0a7de745 A |
640 | uint32_t snapshot_magic; |
641 | uint32_t free_pages; | |
642 | uint32_t active_pages; | |
643 | uint32_t inactive_pages; | |
644 | uint32_t purgeable_pages; | |
645 | uint32_t wired_pages; | |
646 | uint32_t speculative_pages; | |
647 | uint32_t throttled_pages; | |
648 | uint32_t filebacked_pages; | |
649 | uint32_t compressions; | |
650 | uint32_t decompressions; | |
651 | uint32_t compressor_size; | |
652 | int32_t busy_buffer_count; | |
653 | uint32_t pages_wanted; | |
654 | uint32_t pages_reclaimed; | |
655 | uint8_t pages_wanted_reclaimed_valid; // did mach_vm_pressure_monitor succeed? | |
39037602 A |
656 | } __attribute__((packed)); |
657 | ||
658 | /* SS_TH_* macros are for ths_state */ | |
659 | #define SS_TH_WAIT 0x01 /* queued for waiting */ | |
660 | #define SS_TH_SUSP 0x02 /* stopped or requested to stop */ | |
661 | #define SS_TH_RUN 0x04 /* running or on runq */ | |
662 | #define SS_TH_UNINT 0x08 /* waiting uninteruptibly */ | |
663 | #define SS_TH_TERMINATE 0x10 /* halted at termination */ | |
664 | #define SS_TH_TERMINATE2 0x20 /* added to termination queue */ | |
665 | #define SS_TH_IDLE 0x80 /* idling processor */ | |
666 | ||
667 | struct thread_snapshot_v2 { | |
668 | uint64_t ths_thread_id; | |
669 | uint64_t ths_wait_event; | |
670 | uint64_t ths_continuation; | |
671 | uint64_t ths_total_syscalls; | |
672 | uint64_t ths_voucher_identifier; | |
673 | uint64_t ths_dqserialnum; | |
674 | uint64_t ths_user_time; | |
675 | uint64_t ths_sys_time; | |
676 | uint64_t ths_ss_flags; | |
677 | uint64_t ths_last_run_time; | |
678 | uint64_t ths_last_made_runnable_time; | |
679 | uint32_t ths_state; | |
680 | uint32_t ths_sched_flags; | |
681 | int16_t ths_base_priority; | |
682 | int16_t ths_sched_priority; | |
683 | uint8_t ths_eqos; | |
684 | uint8_t ths_rqos; | |
685 | uint8_t ths_rqos_override; | |
686 | uint8_t ths_io_tier; | |
687 | } __attribute__((packed)); | |
688 | ||
689 | struct thread_snapshot_v3 { | |
690 | uint64_t ths_thread_id; | |
691 | uint64_t ths_wait_event; | |
692 | uint64_t ths_continuation; | |
693 | uint64_t ths_total_syscalls; | |
694 | uint64_t ths_voucher_identifier; | |
695 | uint64_t ths_dqserialnum; | |
696 | uint64_t ths_user_time; | |
697 | uint64_t ths_sys_time; | |
698 | uint64_t ths_ss_flags; | |
699 | uint64_t ths_last_run_time; | |
700 | uint64_t ths_last_made_runnable_time; | |
701 | uint32_t ths_state; | |
702 | uint32_t ths_sched_flags; | |
703 | int16_t ths_base_priority; | |
704 | int16_t ths_sched_priority; | |
705 | uint8_t ths_eqos; | |
706 | uint8_t ths_rqos; | |
707 | uint8_t ths_rqos_override; | |
708 | uint8_t ths_io_tier; | |
709 | uint64_t ths_thread_t; | |
710 | } __attribute__((packed)); | |
711 | ||
5ba3f43e A |
712 | |
713 | struct thread_snapshot_v4 { | |
714 | uint64_t ths_thread_id; | |
715 | uint64_t ths_wait_event; | |
716 | uint64_t ths_continuation; | |
717 | uint64_t ths_total_syscalls; | |
718 | uint64_t ths_voucher_identifier; | |
719 | uint64_t ths_dqserialnum; | |
720 | uint64_t ths_user_time; | |
721 | uint64_t ths_sys_time; | |
722 | uint64_t ths_ss_flags; | |
723 | uint64_t ths_last_run_time; | |
724 | uint64_t ths_last_made_runnable_time; | |
725 | uint32_t ths_state; | |
726 | uint32_t ths_sched_flags; | |
727 | int16_t ths_base_priority; | |
728 | int16_t ths_sched_priority; | |
729 | uint8_t ths_eqos; | |
730 | uint8_t ths_rqos; | |
731 | uint8_t ths_rqos_override; | |
732 | uint8_t ths_io_tier; | |
733 | uint64_t ths_thread_t; | |
734 | uint64_t ths_requested_policy; | |
735 | uint64_t ths_effective_policy; | |
736 | } __attribute__((packed)); | |
737 | ||
738 | ||
739 | struct thread_group_snapshot { | |
740 | uint64_t tgs_id; | |
741 | char tgs_name[16]; | |
742 | } __attribute__((packed)); | |
743 | ||
5c9f4661 A |
744 | enum thread_group_flags { |
745 | kThreadGroupEfficient = 0x1, | |
746 | kThreadGroupUIApp = 0x2 | |
747 | }; | |
748 | ||
749 | struct thread_group_snapshot_v2 { | |
750 | uint64_t tgs_id; | |
751 | char tgs_name[16]; | |
752 | uint64_t tgs_flags; | |
753 | } __attribute__((packed)); | |
754 | ||
5ba3f43e A |
755 | enum coalition_flags { |
756 | kCoalitionTermRequested = 0x1, | |
757 | kCoalitionTerminated = 0x2, | |
758 | kCoalitionReaped = 0x4, | |
759 | kCoalitionPrivileged = 0x8, | |
760 | }; | |
761 | ||
762 | struct jetsam_coalition_snapshot { | |
763 | uint64_t jcs_id; | |
764 | uint64_t jcs_flags; | |
765 | uint64_t jcs_thread_group; | |
766 | uint64_t jcs_leader_task_uniqueid; | |
767 | } __attribute__((packed)); | |
768 | ||
769 | struct instrs_cycles_snapshot { | |
770 | uint64_t ics_instructions; | |
771 | uint64_t ics_cycles; | |
772 | } __attribute__((packed)); | |
773 | ||
39037602 A |
774 | struct thread_delta_snapshot_v2 { |
775 | uint64_t tds_thread_id; | |
776 | uint64_t tds_voucher_identifier; | |
777 | uint64_t tds_ss_flags; | |
778 | uint64_t tds_last_made_runnable_time; | |
779 | uint32_t tds_state; | |
780 | uint32_t tds_sched_flags; | |
781 | int16_t tds_base_priority; | |
782 | int16_t tds_sched_priority; | |
783 | uint8_t tds_eqos; | |
784 | uint8_t tds_rqos; | |
785 | uint8_t tds_rqos_override; | |
786 | uint8_t tds_io_tier; | |
787 | } __attribute__ ((packed)); | |
788 | ||
a39ff7e2 A |
789 | struct thread_delta_snapshot_v3 { |
790 | uint64_t tds_thread_id; | |
791 | uint64_t tds_voucher_identifier; | |
792 | uint64_t tds_ss_flags; | |
793 | uint64_t tds_last_made_runnable_time; | |
794 | uint32_t tds_state; | |
795 | uint32_t tds_sched_flags; | |
796 | int16_t tds_base_priority; | |
797 | int16_t tds_sched_priority; | |
798 | uint8_t tds_eqos; | |
799 | uint8_t tds_rqos; | |
800 | uint8_t tds_rqos_override; | |
801 | uint8_t tds_io_tier; | |
802 | uint64_t tds_requested_policy; | |
803 | uint64_t tds_effective_policy; | |
804 | } __attribute__ ((packed)); | |
805 | ||
0a7de745 | 806 | struct io_stats_snapshot { |
39037602 A |
807 | /* |
808 | * I/O Statistics | |
809 | * XXX: These fields must be together. | |
810 | */ | |
811 | uint64_t ss_disk_reads_count; | |
812 | uint64_t ss_disk_reads_size; | |
813 | uint64_t ss_disk_writes_count; | |
814 | uint64_t ss_disk_writes_size; | |
815 | uint64_t ss_io_priority_count[STACKSHOT_IO_NUM_PRIORITIES]; | |
816 | uint64_t ss_io_priority_size[STACKSHOT_IO_NUM_PRIORITIES]; | |
817 | uint64_t ss_paging_count; | |
818 | uint64_t ss_paging_size; | |
819 | uint64_t ss_non_paging_count; | |
820 | uint64_t ss_non_paging_size; | |
821 | uint64_t ss_data_count; | |
822 | uint64_t ss_data_size; | |
823 | uint64_t ss_metadata_count; | |
824 | uint64_t ss_metadata_size; | |
825 | /* XXX: I/O Statistics end */ | |
39037602 A |
826 | } __attribute__ ((packed)); |
827 | ||
828 | struct task_snapshot_v2 { | |
829 | uint64_t ts_unique_pid; | |
830 | uint64_t ts_ss_flags; | |
831 | uint64_t ts_user_time_in_terminated_threads; | |
832 | uint64_t ts_system_time_in_terminated_threads; | |
833 | uint64_t ts_p_start_sec; | |
834 | uint64_t ts_task_size; | |
835 | uint64_t ts_max_resident_size; | |
836 | uint32_t ts_suspend_count; | |
837 | uint32_t ts_faults; | |
838 | uint32_t ts_pageins; | |
839 | uint32_t ts_cow_faults; | |
840 | uint32_t ts_was_throttled; | |
841 | uint32_t ts_did_throttle; | |
842 | uint32_t ts_latency_qos; | |
843 | int32_t ts_pid; | |
844 | char ts_p_comm[32]; | |
845 | } __attribute__ ((packed)); | |
846 | ||
847 | struct task_delta_snapshot_v2 { | |
848 | uint64_t tds_unique_pid; | |
849 | uint64_t tds_ss_flags; | |
850 | uint64_t tds_user_time_in_terminated_threads; | |
851 | uint64_t tds_system_time_in_terminated_threads; | |
852 | uint64_t tds_task_size; | |
853 | uint64_t tds_max_resident_size; | |
854 | uint32_t tds_suspend_count; | |
855 | uint32_t tds_faults; | |
856 | uint32_t tds_pageins; | |
857 | uint32_t tds_cow_faults; | |
858 | uint32_t tds_was_throttled; | |
859 | uint32_t tds_did_throttle; | |
860 | uint32_t tds_latency_qos; | |
861 | } __attribute__ ((packed)); | |
862 | ||
863 | struct stackshot_cpu_times { | |
864 | uint64_t user_usec; | |
865 | uint64_t system_usec; | |
866 | } __attribute__((packed)); | |
867 | ||
d9a64523 A |
868 | struct stackshot_cpu_times_v2 { |
869 | uint64_t user_usec; | |
870 | uint64_t system_usec; | |
871 | uint64_t runnable_usec; | |
872 | } __attribute__((packed)); | |
873 | ||
39037602 A |
874 | struct stackshot_duration { |
875 | uint64_t stackshot_duration; | |
876 | uint64_t stackshot_duration_outer; | |
877 | } __attribute__((packed)); | |
878 | ||
879 | struct stackshot_fault_stats { | |
880 | uint32_t sfs_pages_faulted_in; /* number of pages faulted in using KDP fault path */ | |
881 | uint64_t sfs_time_spent_faulting; /* MATUs spent faulting */ | |
882 | uint64_t sfs_system_max_fault_time; /* MATUs fault time limit per stackshot */ | |
883 | uint8_t sfs_stopped_faulting; /* we stopped decompressing because we hit the limit */ | |
884 | } __attribute__((packed)); | |
885 | ||
813fb2f6 | 886 | typedef struct stackshot_thread_waitinfo { |
0a7de745 A |
887 | uint64_t owner; /* The thread that owns the object */ |
888 | uint64_t waiter; /* The thread that's waiting on the object */ | |
889 | uint64_t context; /* A context uniquely identifying the object */ | |
890 | uint8_t wait_type; /* The type of object that the thread is waiting on */ | |
813fb2f6 A |
891 | } __attribute__((packed)) thread_waitinfo_t; |
892 | ||
cb323159 A |
893 | typedef struct stackshot_thread_turnstileinfo { |
894 | uint64_t waiter; /* The thread that's waiting on the object */ | |
895 | uint64_t turnstile_context; /* Associated data (either thread id, or workq addr) */ | |
896 | uint8_t turnstile_priority; | |
897 | uint8_t number_of_hops; | |
f427ee49 A |
898 | #define STACKSHOT_TURNSTILE_STATUS_UNKNOWN 0x01 /* The final inheritor is unknown (bug?) */ |
899 | #define STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ 0x02 /* A waitq was found to be locked */ | |
900 | #define STACKSHOT_TURNSTILE_STATUS_WORKQUEUE 0x04 /* The final inheritor is a workqueue */ | |
901 | #define STACKSHOT_TURNSTILE_STATUS_THREAD 0x08 /* The final inheritor is a thread */ | |
902 | #define STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK 0x10 /* blocked on task, dind't find thread */ | |
903 | #define STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK 0x20 /* the ip_lock was held */ | |
cb323159 A |
904 | uint64_t turnstile_flags; |
905 | } __attribute__((packed)) thread_turnstileinfo_t; | |
906 | ||
813fb2f6 A |
907 | #define STACKSHOT_WAITOWNER_KERNEL (UINT64_MAX - 1) |
908 | #define STACKSHOT_WAITOWNER_PORT_LOCKED (UINT64_MAX - 2) | |
909 | #define STACKSHOT_WAITOWNER_PSET_LOCKED (UINT64_MAX - 3) | |
910 | #define STACKSHOT_WAITOWNER_INTRANSIT (UINT64_MAX - 4) | |
911 | #define STACKSHOT_WAITOWNER_MTXSPIN (UINT64_MAX - 5) | |
5ba3f43e A |
912 | #define STACKSHOT_WAITOWNER_THREQUESTED (UINT64_MAX - 6) /* workloop waiting for a new worker thread */ |
913 | #define STACKSHOT_WAITOWNER_SUSPENDED (UINT64_MAX - 7) /* workloop is suspended */ | |
813fb2f6 | 914 | |
f427ee49 A |
915 | struct stackshot_cpu_architecture { |
916 | int32_t cputype; | |
917 | int32_t cpusubtype; | |
918 | } __attribute__((packed)); | |
813fb2f6 | 919 | |
d9a64523 A |
920 | struct stack_snapshot_stacktop { |
921 | uint64_t sp; | |
922 | uint8_t stack_contents[8]; | |
923 | }; | |
924 | ||
f427ee49 A |
925 | /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ |
926 | struct stackshot_latency_collection { | |
927 | uint64_t latency_version; | |
928 | uint64_t setup_latency; | |
929 | uint64_t total_task_iteration_latency; | |
930 | uint64_t total_terminated_task_iteration_latency; | |
931 | } __attribute__((packed)); | |
932 | ||
933 | /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ | |
934 | struct stackshot_latency_task { | |
935 | uint64_t task_uniqueid; | |
936 | uint64_t setup_latency; | |
937 | uint64_t task_thread_count_loop_latency; | |
938 | uint64_t task_thread_data_loop_latency; | |
939 | uint64_t cur_tsnap_latency; | |
940 | uint64_t pmap_latency; | |
941 | uint64_t bsd_proc_ids_latency; | |
942 | uint64_t misc_latency; | |
943 | uint64_t misc2_latency; | |
944 | uint64_t end_latency; | |
945 | } __attribute__((packed)); | |
946 | ||
947 | /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ | |
948 | struct stackshot_latency_thread { | |
949 | uint64_t thread_id; | |
950 | uint64_t cur_thsnap1_latency; | |
951 | uint64_t dispatch_serial_latency; | |
952 | uint64_t dispatch_label_latency; | |
953 | uint64_t cur_thsnap2_latency; | |
954 | uint64_t thread_name_latency; | |
955 | uint64_t sur_times_latency; | |
956 | uint64_t user_stack_latency; | |
957 | uint64_t kernel_stack_latency; | |
958 | uint64_t misc_latency; | |
959 | } __attribute__((packed)); | |
960 | ||
d9a64523 | 961 | |
39037602 A |
962 | /**************** definitions for crashinfo *********************/ |
963 | ||
964 | /* | |
965 | * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes | |
966 | * in TASK_CRASHINFO_* types. | |
967 | */ | |
968 | ||
969 | /* FIXME some of these types aren't clean (fixed width, packed, and defined *here*) */ | |
970 | ||
a39ff7e2 | 971 | struct crashinfo_proc_uniqidentifierinfo { |
0a7de745 A |
972 | uint8_t p_uuid[16]; /* UUID of the main executable */ |
973 | uint64_t p_uniqueid; /* 64 bit unique identifier for process */ | |
974 | uint64_t p_puniqueid; /* unique identifier for process's parent */ | |
975 | uint64_t p_reserve2; /* reserved for future use */ | |
976 | uint64_t p_reserve3; /* reserved for future use */ | |
977 | uint64_t p_reserve4; /* reserved for future use */ | |
a39ff7e2 A |
978 | } __attribute__((packed)); |
979 | ||
39037602 A |
980 | #define TASK_CRASHINFO_BEGIN KCDATA_BUFFER_BEGIN_CRASHINFO |
981 | #define TASK_CRASHINFO_STRING_DESC KCDATA_TYPE_STRING_DESC | |
982 | #define TASK_CRASHINFO_UINT32_DESC KCDATA_TYPE_UINT32_DESC | |
983 | #define TASK_CRASHINFO_UINT64_DESC KCDATA_TYPE_UINT64_DESC | |
984 | ||
985 | #define TASK_CRASHINFO_EXTMODINFO 0x801 | |
a39ff7e2 | 986 | #define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct crashinfo_proc_uniqidentifierinfo */ |
39037602 A |
987 | #define TASK_CRASHINFO_TASKDYLD_INFO 0x803 |
988 | #define TASK_CRASHINFO_UUID 0x804 | |
989 | #define TASK_CRASHINFO_PID 0x805 | |
990 | #define TASK_CRASHINFO_PPID 0x806 | |
991 | #define TASK_CRASHINFO_RUSAGE 0x807 /* struct rusage DEPRECATED do not use. | |
0a7de745 | 992 | * This struct has longs in it */ |
39037602 A |
993 | #define TASK_CRASHINFO_RUSAGE_INFO 0x808 /* struct rusage_info_v3 from resource.h */ |
994 | #define TASK_CRASHINFO_PROC_NAME 0x809 /* char * */ | |
995 | #define TASK_CRASHINFO_PROC_STARTTIME 0x80B /* struct timeval64 */ | |
996 | #define TASK_CRASHINFO_USERSTACK 0x80C /* uint64_t */ | |
997 | #define TASK_CRASHINFO_ARGSLEN 0x80D | |
998 | #define TASK_CRASHINFO_EXCEPTION_CODES 0x80E /* mach_exception_data_t */ | |
999 | #define TASK_CRASHINFO_PROC_PATH 0x80F /* string of len MAXPATHLEN */ | |
1000 | #define TASK_CRASHINFO_PROC_CSFLAGS 0x810 /* uint32_t */ | |
1001 | #define TASK_CRASHINFO_PROC_STATUS 0x811 /* char */ | |
1002 | #define TASK_CRASHINFO_UID 0x812 /* uid_t */ | |
1003 | #define TASK_CRASHINFO_GID 0x813 /* gid_t */ | |
1004 | #define TASK_CRASHINFO_PROC_ARGC 0x814 /* int */ | |
1005 | #define TASK_CRASHINFO_PROC_FLAGS 0x815 /* unsigned int */ | |
1006 | #define TASK_CRASHINFO_CPUTYPE 0x816 /* cpu_type_t */ | |
1007 | #define TASK_CRASHINFO_WORKQUEUEINFO 0x817 /* struct proc_workqueueinfo */ | |
1008 | #define TASK_CRASHINFO_RESPONSIBLE_PID 0x818 /* pid_t */ | |
1009 | #define TASK_CRASHINFO_DIRTY_FLAGS 0x819 /* int */ | |
1010 | #define TASK_CRASHINFO_CRASHED_THREADID 0x81A /* uint64_t */ | |
1011 | #define TASK_CRASHINFO_COALITION_ID 0x81B /* uint64_t */ | |
1012 | #define TASK_CRASHINFO_UDATA_PTRS 0x81C /* uint64_t */ | |
1013 | #define TASK_CRASHINFO_MEMORY_LIMIT 0x81D /* uint64_t */ | |
1014 | ||
d9a64523 A |
1015 | #define TASK_CRASHINFO_LEDGER_INTERNAL 0x81E /* uint64_t */ |
1016 | #define TASK_CRASHINFO_LEDGER_INTERNAL_COMPRESSED 0x81F /* uint64_t */ | |
1017 | #define TASK_CRASHINFO_LEDGER_IOKIT_MAPPED 0x820 /* uint64_t */ | |
1018 | #define TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING 0x821 /* uint64_t */ | |
1019 | #define TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING_COMPRESSED 0x822 /* uint64_t */ | |
1020 | #define TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE 0x823 /* uint64_t */ | |
1021 | #define TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE_COMPRESSED 0x824 /* uint64_t */ | |
1022 | #define TASK_CRASHINFO_LEDGER_PAGE_TABLE 0x825 /* uint64_t */ | |
1023 | #define TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT 0x826 /* uint64_t */ | |
1024 | #define TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT_LIFETIME_MAX 0x827 /* uint64_t */ | |
1025 | #define TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE 0x828 /* uint64_t */ | |
1026 | #define TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE_COMPRESSED 0x829 /* uint64_t */ | |
1027 | #define TASK_CRASHINFO_LEDGER_WIRED_MEM 0x82A /* uint64_t */ | |
cb323159 A |
1028 | #define TASK_CRASHINFO_PROC_PERSONA_ID 0x82B /* uid_t */ |
1029 | #define TASK_CRASHINFO_MEMORY_LIMIT_INCREASE 0x82C /* uint32_t */ | |
f427ee49 A |
1030 | #define TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT 0x82D /* uint64_t */ |
1031 | #define TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT_COMPRESSED 0x82E /* uint64_t */ | |
1032 | #define TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT 0x82F /* uint64_t */ | |
1033 | #define TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT_COMPRESSED 0x830 /* uint64_t */ | |
1034 | #define TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT 0x831 /* uint64_t */ | |
1035 | #define TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT_COMPRESSED 0x832 /* uint64_t */ | |
1036 | #define TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT 0x833 /* uint64_t */ | |
1037 | #define TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT_COMPRESSED 0x834 /* uint64_t */ | |
1038 | #define TASK_CRASHINFO_MEMORYSTATUS_EFFECTIVE_PRIORITY 0x835 /* int32_t */ | |
d9a64523 | 1039 | |
39037602 A |
1040 | #define TASK_CRASHINFO_END KCDATA_TYPE_BUFFER_END |
1041 | ||
1042 | /**************** definitions for os reasons *********************/ | |
1043 | ||
1044 | #define EXIT_REASON_SNAPSHOT 0x1001 | |
1045 | #define EXIT_REASON_USER_DESC 0x1002 /* string description of reason */ | |
1046 | #define EXIT_REASON_USER_PAYLOAD 0x1003 /* user payload data */ | |
1047 | #define EXIT_REASON_CODESIGNING_INFO 0x1004 | |
5ba3f43e A |
1048 | #define EXIT_REASON_WORKLOOP_ID 0x1005 |
1049 | #define EXIT_REASON_DISPATCH_QUEUE_NO 0x1006 | |
39037602 A |
1050 | |
1051 | struct exit_reason_snapshot { | |
0a7de745 A |
1052 | uint32_t ers_namespace; |
1053 | uint64_t ers_code; | |
1054 | /* end of version 1 of exit_reason_snapshot. sizeof v1 was 12 */ | |
1055 | uint64_t ers_flags; | |
39037602 A |
1056 | } __attribute__((packed)); |
1057 | ||
1058 | #define EXIT_REASON_CODESIG_PATH_MAX 1024 | |
1059 | ||
1060 | struct codesigning_exit_reason_info { | |
1061 | uint64_t ceri_virt_addr; | |
1062 | uint64_t ceri_file_offset; | |
1063 | char ceri_pathname[EXIT_REASON_CODESIG_PATH_MAX]; | |
1064 | char ceri_filename[EXIT_REASON_CODESIG_PATH_MAX]; | |
1065 | uint64_t ceri_codesig_modtime_secs; | |
1066 | uint64_t ceri_codesig_modtime_nsecs; | |
1067 | uint64_t ceri_page_modtime_secs; | |
1068 | uint64_t ceri_page_modtime_nsecs; | |
1069 | uint8_t ceri_path_truncated; | |
1070 | uint8_t ceri_object_codesigned; | |
1071 | uint8_t ceri_page_codesig_validated; | |
1072 | uint8_t ceri_page_codesig_tainted; | |
1073 | uint8_t ceri_page_codesig_nx; | |
1074 | uint8_t ceri_page_wpmapped; | |
1075 | uint8_t ceri_page_slid; | |
1076 | uint8_t ceri_page_dirty; | |
1077 | uint32_t ceri_page_shadow_depth; | |
1078 | } __attribute__((packed)); | |
1079 | ||
1080 | #define EXIT_REASON_USER_DESC_MAX_LEN 1024 | |
1081 | #define EXIT_REASON_PAYLOAD_MAX_LEN 2048 | |
1082 | /**************** safe iterators *********************/ | |
1083 | ||
1084 | typedef struct kcdata_iter { | |
1085 | kcdata_item_t item; | |
1086 | void *end; | |
1087 | } kcdata_iter_t; | |
1088 | ||
1089 | ||
1090 | static inline | |
0a7de745 A |
1091 | kcdata_iter_t |
1092 | kcdata_iter(void *buffer, unsigned long size) | |
1093 | { | |
39037602 A |
1094 | kcdata_iter_t iter; |
1095 | iter.item = (kcdata_item_t) buffer; | |
1096 | iter.end = (void*) (((uintptr_t)buffer) + size); | |
1097 | return iter; | |
1098 | } | |
1099 | ||
1100 | static inline | |
1101 | kcdata_iter_t kcdata_iter_unsafe(void *buffer) __attribute__((deprecated)); | |
1102 | ||
1103 | static inline | |
0a7de745 A |
1104 | kcdata_iter_t |
1105 | kcdata_iter_unsafe(void *buffer) | |
1106 | { | |
39037602 A |
1107 | kcdata_iter_t iter; |
1108 | iter.item = (kcdata_item_t) buffer; | |
1109 | iter.end = (void*) (uintptr_t) ~0; | |
1110 | return iter; | |
1111 | } | |
1112 | ||
cb323159 | 1113 | static const kcdata_iter_t kcdata_invalid_iter = { .item = NULL, .end = NULL }; |
39037602 A |
1114 | |
1115 | static inline | |
0a7de745 A |
1116 | int |
1117 | kcdata_iter_valid(kcdata_iter_t iter) | |
1118 | { | |
39037602 | 1119 | return |
0a7de745 A |
1120 | ((uintptr_t)iter.item + sizeof(struct kcdata_item) <= (uintptr_t)iter.end) && |
1121 | ((uintptr_t)iter.item + sizeof(struct kcdata_item) + iter.item->size <= (uintptr_t)iter.end); | |
39037602 A |
1122 | } |
1123 | ||
1124 | ||
1125 | static inline | |
0a7de745 A |
1126 | kcdata_iter_t |
1127 | kcdata_iter_next(kcdata_iter_t iter) | |
1128 | { | |
39037602 A |
1129 | iter.item = (kcdata_item_t) (((uintptr_t)iter.item) + sizeof(struct kcdata_item) + (iter.item->size)); |
1130 | return iter; | |
1131 | } | |
1132 | ||
1133 | static inline uint32_t | |
1134 | kcdata_iter_type(kcdata_iter_t iter) | |
1135 | { | |
0a7de745 | 1136 | if ((iter.item->type & ~0xfu) == KCDATA_TYPE_ARRAY_PAD0) { |
39037602 | 1137 | return KCDATA_TYPE_ARRAY; |
0a7de745 | 1138 | } else { |
39037602 | 1139 | return iter.item->type; |
0a7de745 | 1140 | } |
39037602 A |
1141 | } |
1142 | ||
1143 | static inline uint32_t | |
1144 | kcdata_calc_padding(uint32_t size) | |
1145 | { | |
d9a64523 | 1146 | /* calculate number of bytes to add to size to get something divisible by 16 */ |
39037602 A |
1147 | return (-size) & 0xf; |
1148 | } | |
1149 | ||
1150 | static inline uint32_t | |
1151 | kcdata_flags_get_padding(uint64_t flags) | |
1152 | { | |
1153 | return flags & KCDATA_FLAGS_STRUCT_PADDING_MASK; | |
1154 | } | |
1155 | ||
1156 | /* see comment above about has_padding */ | |
1157 | static inline int | |
1158 | kcdata_iter_is_legacy_item(kcdata_iter_t iter, uint32_t legacy_size) | |
1159 | { | |
1160 | uint32_t legacy_size_padded = legacy_size + kcdata_calc_padding(legacy_size); | |
0a7de745 A |
1161 | return iter.item->size == legacy_size_padded && |
1162 | (iter.item->flags & (KCDATA_FLAGS_STRUCT_PADDING_MASK | KCDATA_FLAGS_STRUCT_HAS_PADDING)) == 0; | |
39037602 A |
1163 | } |
1164 | ||
1165 | static inline uint32_t | |
1166 | kcdata_iter_size(kcdata_iter_t iter) | |
1167 | { | |
1168 | uint32_t legacy_size = 0; | |
1169 | ||
1170 | switch (kcdata_iter_type(iter)) { | |
1171 | case KCDATA_TYPE_ARRAY: | |
1172 | case KCDATA_TYPE_CONTAINER_BEGIN: | |
1173 | return iter.item->size; | |
1174 | case STACKSHOT_KCTYPE_THREAD_SNAPSHOT: { | |
1175 | legacy_size = sizeof(struct thread_snapshot_v2); | |
1176 | if (kcdata_iter_is_legacy_item(iter, legacy_size)) { | |
1177 | return legacy_size; | |
1178 | } | |
1179 | ||
1180 | goto not_legacy; | |
1181 | } | |
1182 | case STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO: { | |
1183 | legacy_size = sizeof(struct dyld_uuid_info_64); | |
1184 | if (kcdata_iter_is_legacy_item(iter, legacy_size)) { | |
1185 | return legacy_size; | |
1186 | } | |
1187 | ||
1188 | goto not_legacy; | |
1189 | } | |
1190 | not_legacy: | |
1191 | default: | |
0a7de745 | 1192 | if (iter.item->size < kcdata_flags_get_padding(iter.item->flags)) { |
39037602 | 1193 | return 0; |
0a7de745 | 1194 | } else { |
39037602 | 1195 | return iter.item->size - kcdata_flags_get_padding(iter.item->flags); |
0a7de745 | 1196 | } |
39037602 A |
1197 | } |
1198 | } | |
1199 | ||
1200 | static inline uint64_t | |
1201 | kcdata_iter_flags(kcdata_iter_t iter) | |
1202 | { | |
1203 | return iter.item->flags; | |
1204 | } | |
1205 | ||
1206 | static inline | |
0a7de745 A |
1207 | void * |
1208 | kcdata_iter_payload(kcdata_iter_t iter) | |
1209 | { | |
39037602 A |
1210 | return &iter.item->data; |
1211 | } | |
1212 | ||
1213 | ||
1214 | static inline | |
0a7de745 A |
1215 | uint32_t |
1216 | kcdata_iter_array_elem_type(kcdata_iter_t iter) | |
1217 | { | |
39037602 A |
1218 | return (iter.item->flags >> 32) & UINT32_MAX; |
1219 | } | |
1220 | ||
1221 | static inline | |
0a7de745 A |
1222 | uint32_t |
1223 | kcdata_iter_array_elem_count(kcdata_iter_t iter) | |
1224 | { | |
39037602 A |
1225 | return (iter.item->flags) & UINT32_MAX; |
1226 | } | |
1227 | ||
1228 | /* KCDATA_TYPE_ARRAY is ambiguous about the size of the array elements. Size is | |
1229 | * calculated as total_size / elements_count, but total size got padded out to a | |
1230 | * 16 byte alignment. New kernels will generate KCDATA_TYPE_ARRAY_PAD* instead | |
1231 | * to explicitly tell us how much padding was used. Here we have a fixed, never | |
1232 | * to be altered list of the sizes of array elements that were used before I | |
1233 | * discovered this issue. If you find a KCDATA_TYPE_ARRAY that is not one of | |
1234 | * these types, treat it as invalid data. */ | |
1235 | ||
1236 | static inline | |
1237 | uint32_t | |
0a7de745 A |
1238 | kcdata_iter_array_size_switch(kcdata_iter_t iter) |
1239 | { | |
1240 | switch (kcdata_iter_array_elem_type(iter)) { | |
39037602 A |
1241 | case KCDATA_TYPE_LIBRARY_LOADINFO: |
1242 | return sizeof(struct dyld_uuid_info_32); | |
1243 | case KCDATA_TYPE_LIBRARY_LOADINFO64: | |
1244 | return sizeof(struct dyld_uuid_info_64); | |
1245 | case STACKSHOT_KCTYPE_KERN_STACKFRAME: | |
1246 | case STACKSHOT_KCTYPE_USER_STACKFRAME: | |
1247 | return sizeof(struct stack_snapshot_frame32); | |
1248 | case STACKSHOT_KCTYPE_KERN_STACKFRAME64: | |
1249 | case STACKSHOT_KCTYPE_USER_STACKFRAME64: | |
1250 | return sizeof(struct stack_snapshot_frame64); | |
1251 | case STACKSHOT_KCTYPE_DONATING_PIDS: | |
1252 | return sizeof(int32_t); | |
1253 | case STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT: | |
1254 | return sizeof(struct thread_delta_snapshot_v2); | |
0a7de745 A |
1255 | // This one is only here to make some unit tests work. It should be OK to |
1256 | // remove. | |
39037602 A |
1257 | case TASK_CRASHINFO_CRASHED_THREADID: |
1258 | return sizeof(uint64_t); | |
1259 | default: | |
1260 | return 0; | |
1261 | } | |
1262 | } | |
1263 | ||
1264 | static inline | |
0a7de745 A |
1265 | int |
1266 | kcdata_iter_array_valid(kcdata_iter_t iter) | |
1267 | { | |
1268 | if (!kcdata_iter_valid(iter)) { | |
39037602 | 1269 | return 0; |
0a7de745 A |
1270 | } |
1271 | if (kcdata_iter_type(iter) != KCDATA_TYPE_ARRAY) { | |
39037602 | 1272 | return 0; |
0a7de745 A |
1273 | } |
1274 | if (kcdata_iter_array_elem_count(iter) == 0) { | |
39037602 | 1275 | return iter.item->size == 0; |
0a7de745 | 1276 | } |
39037602 A |
1277 | if (iter.item->type == KCDATA_TYPE_ARRAY) { |
1278 | uint32_t elem_size = kcdata_iter_array_size_switch(iter); | |
0a7de745 | 1279 | if (elem_size == 0) { |
39037602 | 1280 | return 0; |
0a7de745 | 1281 | } |
39037602 A |
1282 | /* sizes get aligned to the nearest 16. */ |
1283 | return | |
0a7de745 A |
1284 | kcdata_iter_array_elem_count(iter) <= iter.item->size / elem_size && |
1285 | iter.item->size % kcdata_iter_array_elem_count(iter) < 16; | |
39037602 A |
1286 | } else { |
1287 | return | |
0a7de745 A |
1288 | (iter.item->type & 0xf) <= iter.item->size && |
1289 | kcdata_iter_array_elem_count(iter) <= iter.item->size - (iter.item->type & 0xf) && | |
1290 | (iter.item->size - (iter.item->type & 0xf)) % kcdata_iter_array_elem_count(iter) == 0; | |
39037602 A |
1291 | } |
1292 | } | |
1293 | ||
1294 | ||
1295 | static inline | |
0a7de745 A |
1296 | uint32_t |
1297 | kcdata_iter_array_elem_size(kcdata_iter_t iter) | |
1298 | { | |
1299 | if (iter.item->type == KCDATA_TYPE_ARRAY) { | |
39037602 | 1300 | return kcdata_iter_array_size_switch(iter); |
0a7de745 A |
1301 | } |
1302 | if (kcdata_iter_array_elem_count(iter) == 0) { | |
39037602 | 1303 | return 0; |
0a7de745 | 1304 | } |
39037602 A |
1305 | return (iter.item->size - (iter.item->type & 0xf)) / kcdata_iter_array_elem_count(iter); |
1306 | } | |
1307 | ||
1308 | static inline | |
0a7de745 A |
1309 | int |
1310 | kcdata_iter_container_valid(kcdata_iter_t iter) | |
1311 | { | |
39037602 | 1312 | return |
0a7de745 A |
1313 | kcdata_iter_valid(iter) && |
1314 | kcdata_iter_type(iter) == KCDATA_TYPE_CONTAINER_BEGIN && | |
1315 | iter.item->size >= sizeof(uint32_t); | |
39037602 A |
1316 | } |
1317 | ||
1318 | static inline | |
0a7de745 A |
1319 | uint32_t |
1320 | kcdata_iter_container_type(kcdata_iter_t iter) | |
1321 | { | |
1322 | return *(uint32_t *) kcdata_iter_payload(iter); | |
39037602 A |
1323 | } |
1324 | ||
1325 | static inline | |
0a7de745 A |
1326 | uint64_t |
1327 | kcdata_iter_container_id(kcdata_iter_t iter) | |
1328 | { | |
39037602 A |
1329 | return iter.item->flags; |
1330 | } | |
1331 | ||
1332 | ||
1333 | #define KCDATA_ITER_FOREACH(iter) for(; kcdata_iter_valid(iter) && iter.item->type != KCDATA_TYPE_BUFFER_END; iter = kcdata_iter_next(iter)) | |
1334 | #define KCDATA_ITER_FOREACH_FAILED(iter) (!kcdata_iter_valid(iter) || (iter).item->type != KCDATA_TYPE_BUFFER_END) | |
1335 | ||
1336 | static inline | |
1337 | kcdata_iter_t | |
1338 | kcdata_iter_find_type(kcdata_iter_t iter, uint32_t type) | |
1339 | { | |
1340 | KCDATA_ITER_FOREACH(iter) | |
1341 | { | |
0a7de745 | 1342 | if (kcdata_iter_type(iter) == type) { |
39037602 | 1343 | return iter; |
0a7de745 | 1344 | } |
39037602 A |
1345 | } |
1346 | return kcdata_invalid_iter; | |
1347 | } | |
1348 | ||
1349 | static inline | |
0a7de745 A |
1350 | int |
1351 | kcdata_iter_data_with_desc_valid(kcdata_iter_t iter, uint32_t minsize) | |
1352 | { | |
39037602 | 1353 | return |
0a7de745 A |
1354 | kcdata_iter_valid(iter) && |
1355 | kcdata_iter_size(iter) >= KCDATA_DESC_MAXLEN + minsize && | |
1356 | ((char*)kcdata_iter_payload(iter))[KCDATA_DESC_MAXLEN - 1] == 0; | |
39037602 A |
1357 | } |
1358 | ||
1359 | static inline | |
0a7de745 A |
1360 | char * |
1361 | kcdata_iter_string(kcdata_iter_t iter, uint32_t offset) | |
1362 | { | |
39037602 A |
1363 | if (offset > kcdata_iter_size(iter)) { |
1364 | return NULL; | |
1365 | } | |
1366 | uint32_t maxlen = kcdata_iter_size(iter) - offset; | |
1367 | char *s = ((char*)kcdata_iter_payload(iter)) + offset; | |
1368 | if (strnlen(s, maxlen) < maxlen) { | |
1369 | return s; | |
1370 | } else { | |
1371 | return NULL; | |
1372 | } | |
1373 | } | |
1374 | ||
0a7de745 A |
1375 | static inline void |
1376 | kcdata_iter_get_data_with_desc(kcdata_iter_t iter, char **desc_ptr, void **data_ptr, uint32_t *size_ptr) | |
1377 | { | |
1378 | if (desc_ptr) { | |
39037602 | 1379 | *desc_ptr = (char *)kcdata_iter_payload(iter); |
0a7de745 A |
1380 | } |
1381 | if (data_ptr) { | |
39037602 | 1382 | *data_ptr = (void *)((uintptr_t)kcdata_iter_payload(iter) + KCDATA_DESC_MAXLEN); |
0a7de745 A |
1383 | } |
1384 | if (size_ptr) { | |
39037602 | 1385 | *size_ptr = kcdata_iter_size(iter) - KCDATA_DESC_MAXLEN; |
0a7de745 | 1386 | } |
39037602 A |
1387 | } |
1388 | ||
1389 | #endif |