]> git.saurik.com Git - apple/xnu.git/blame - libkdd/kcdtypes.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / libkdd / kcdtypes.c
CommitLineData
39037602
A
1/*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <kcdata.h>
25#include <sys/time.h>
26#include <stdlib.h>
27#include <stddef.h>
28#include <string.h>
29#include <assert.h>
30#include <stdio.h>
31#include <mach/mach_time.h>
32#include <sys/proc_info.h>
33
34/*!
35 * @function kcdata_get_typedescription
36 *
37 * @abstract
38 * Search the known type definitions for type with id type_id.
39 *
40 * @param type_id
41 * A unsinged int type specified by the KCDATA.
42 *
43 * @param buffer
44 * pointer to data area where type definition will be saved.
45 *
46 * @param buffer_size
47 * size of the buffer provided.
48 *
49 * @return struct kcdata_type_definition *
50 * pointer to a malloc'ed buffer holding the type definition and each subtype defintion for its fields.
51 * It may return NULL if no type with id == type_id is found.
52 * Note: The caller is responsible to free() the memory when its no longer used.
53 *
54 * @discussion
55 * This function queries the known type definitions table. If found the defintion data is returned
56 * else NULL is returned. It is advised to cache the return value from this function since the data
57 * is always going to be the same for same type_id. The definition setup requires memory on heap.
58 * The caller should make sure to free() the data once its done with using it.
59 *
60 */
61struct kcdata_type_definition * kcdata_get_typedescription(unsigned type_id, uint8_t * buffer, uint32_t buffer_size);
62
63/* forward declarations for helper routines */
64static uint32_t get_kctype_subtype_size(kctype_subtype_t type);
65static void setup_subtype_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, char * name);
66static void setup_subtype_array_description(
67 kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, uint32_t count, char * name);
68static void setup_type_definition(struct kcdata_type_definition * d, uint32_t type, uint32_t num_elems, char * name);
69
70struct kcdata_type_definition *
71kcdata_get_typedescription(unsigned type_id, uint8_t * buffer, uint32_t buffer_size)
72{
73 unsigned int i = 0;
74#define _STR_VALUE(x) #x
75#define _SUBTYPE(t, s, f) setup_subtype_description(&subtypes[i++], (t), offsetof(s, f), _STR_VALUE(f))
76#define _SUBTYPE_ARRAY(t, s, f, c) setup_subtype_array_description(&subtypes[i++], (t), offsetof(s, f), (c), _STR_VALUE(f))
77#define _STRINGTYPE(f) setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, UINT16_MAX, f)
78
79 if (buffer_size < sizeof(struct kcdata_type_definition) || buffer == NULL)
80 return NULL;
81
82 struct kcdata_type_definition * retval = (struct kcdata_type_definition *)&buffer[0];
83 kcdata_subtype_descriptor_t subtypes = (kcdata_subtype_descriptor_t)&buffer[sizeof(struct kcdata_type_definition)];
84 switch (type_id) {
85 case KCDATA_TYPE_STRING_DESC: {
86 i = 0;
87 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc");
88 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, KCDATA_DESC_MAXLEN, UINT16_MAX, "data");
89 setup_type_definition(retval, type_id, i, "string_desc");
90 break;
91 }
92
93 case KCDATA_TYPE_UINT32_DESC: {
94 i = 0;
95 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc");
96 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, KCDATA_DESC_MAXLEN, "data");
97 setup_type_definition(retval, type_id, i, "uint32_desc");
98 break;
99 }
100
101 case KCDATA_TYPE_UINT64_DESC: {
102 i = 0;
103 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc");
104 setup_subtype_description(&subtypes[i++], KC_ST_UINT64, KCDATA_DESC_MAXLEN, "data");
105 setup_type_definition(retval, type_id, i, "uint64_desc");
106 break;
107 }
108
109 case KCDATA_TYPE_INT32_DESC: {
110 i = 0;
111 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc");
112 setup_subtype_description(&subtypes[i++], KC_ST_INT32, KCDATA_DESC_MAXLEN, "data");
113 setup_type_definition(retval, type_id, i, "int32_desc");
114 break;
115 }
116
117 case KCDATA_TYPE_INT64_DESC: {
118 i = 0;
119 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc");
120 setup_subtype_description(&subtypes[i++], KC_ST_INT64, KCDATA_DESC_MAXLEN, "data");
121 setup_type_definition(retval, type_id, i, "int64_desc");
122 break;
123 }
124
125 case KCDATA_TYPE_TYPEDEFINTION: {
126 i = 0;
127 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, offsetof(struct kcdata_type_definition, kct_type_identifier), "typeID");
128 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, offsetof(struct kcdata_type_definition, kct_num_elements), "numOfFields");
129 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, offsetof(struct kcdata_type_definition, kct_name), KCDATA_DESC_MAXLEN, "name");
130 // Note "fields" is an array of run time defined length. So we populate fields at parsing time.
131 setup_type_definition(retval, type_id, i, "typedef");
132 break;
133 }
134
135 case KCDATA_TYPE_CONTAINER_BEGIN: {
136 i = 0;
137 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "kcContainerType");
138 setup_type_definition(retval, type_id, i, "container_begin");
139 break;
140 }
141
142 case KCDATA_TYPE_LIBRARY_LOADINFO: {
143 i = 0;
144 _SUBTYPE(KC_ST_UINT32, struct user32_dyld_uuid_info, imageLoadAddress);
145 _SUBTYPE_ARRAY(KC_ST_UINT8, struct user32_dyld_uuid_info, imageUUID, 16);
146 setup_type_definition(retval, type_id, i, "dyld_load_info");
147 break;
148 }
149
150 case KCDATA_TYPE_LIBRARY_LOADINFO64: {
151 i = 0;
152 _SUBTYPE(KC_ST_UINT64, struct user64_dyld_uuid_info, imageLoadAddress);
153 _SUBTYPE_ARRAY(KC_ST_UINT8, struct user64_dyld_uuid_info, imageUUID, 16);
154 setup_type_definition(retval, type_id, i, "dyld_load_info");
155 break;
156 }
157
158 case STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO: {
159 i = 0;
160 _SUBTYPE(KC_ST_UINT64, struct dyld_uuid_info_64_v2, imageLoadAddress);
161 _SUBTYPE_ARRAY(KC_ST_UINT8, struct dyld_uuid_info_64_v2, imageUUID, 16);
162 _SUBTYPE(KC_ST_UINT64, struct dyld_uuid_info_64_v2, imageSlidBaseAddress);
163 setup_type_definition(retval, type_id, i, "shared_cache_dyld_load_info");
164 break;
165 }
166
167 case STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO: {
168 i = 0;
169 _SUBTYPE(KC_ST_UINT64, struct dyld_uuid_info_64, imageLoadAddress);
170 _SUBTYPE_ARRAY(KC_ST_UINT8, struct dyld_uuid_info_64, imageUUID, 16);
171 setup_type_definition(retval, type_id, i, "kernelcache_load_info");
172 break;
173 }
174
175 case KCDATA_TYPE_TIMEBASE: {
176 i = 0;
177 _SUBTYPE(KC_ST_UINT32, struct mach_timebase_info, numer);
178 _SUBTYPE(KC_ST_UINT32, struct mach_timebase_info, denom);
179 setup_type_definition(retval, type_id, i, "mach_timebase_info");
180 break;
181 }
182
183 case KCDATA_TYPE_MACH_ABSOLUTE_TIME:
184 setup_type_definition(retval, type_id, 1, "mach_absolute_time");
185 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "mach_absolute_time");
186 break;
187
188 case KCDATA_TYPE_TIMEVAL: {
189 i = 0;
190 _SUBTYPE(KC_ST_INT64, struct timeval64, tv_sec);
191 _SUBTYPE(KC_ST_INT64, struct timeval64, tv_usec);
192 setup_type_definition(retval, type_id, i, "timeval");
193 break;
194 }
195
196 case KCDATA_TYPE_USECS_SINCE_EPOCH:
197 setup_type_definition(retval, type_id, 1, "usecs_since_epoch");
198 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "usecs_since_epoch");
199 break;
200
201 case KCDATA_TYPE_PID:
202 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "pid");
203 setup_type_definition(retval, type_id, 1, "pid");
204 break;
205
206 case KCDATA_TYPE_PROCNAME:
207 i = 0;
208 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, 64, "proc_name");
209 setup_type_definition(retval, type_id, i, "proc_name");
210 break;
211
212 /* stackshot specific types */
213 case STACKSHOT_KCTYPE_IOSTATS: {
214 i = 0;
215 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_reads_count);
216 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_reads_size);
217 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_writes_count);
218 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_writes_size);
219 _SUBTYPE_ARRAY(KC_ST_UINT64, struct io_stats_snapshot, ss_io_priority_count, STACKSHOT_IO_NUM_PRIORITIES);
220 _SUBTYPE_ARRAY(KC_ST_UINT64, struct io_stats_snapshot, ss_io_priority_size, STACKSHOT_IO_NUM_PRIORITIES);
221 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_paging_count);
222 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_paging_size);
223 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_non_paging_count);
224 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_non_paging_size);
225 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_data_count);
226 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_data_size);
227 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_metadata_count);
228 _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_metadata_size);
229
230 setup_type_definition(retval, type_id, i, "io_statistics");
231 break;
232 }
233
234 case STACKSHOT_KCTYPE_GLOBAL_MEM_STATS: {
235 i = 0;
236 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, snapshot_magic);
237 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, free_pages);
238 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, active_pages);
239 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, inactive_pages);
240 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, purgeable_pages);
241 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, wired_pages);
242 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, speculative_pages);
243 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, throttled_pages);
244 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, filebacked_pages);
245 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, compressions);
246 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, decompressions);
247 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, compressor_size);
248 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, busy_buffer_count);
249 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, pages_wanted);
250 _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, pages_reclaimed);
251 _SUBTYPE(KC_ST_UINT8, struct mem_and_io_snapshot, pages_wanted_reclaimed_valid);
252 setup_type_definition(retval, type_id, i, "mem_and_io_snapshot");
253 break;
254 }
255
256 case STACKSHOT_KCCONTAINER_TASK:
257 setup_type_definition(retval, type_id, 0, "task_snapshots");
258 break;
259
260 case STACKSHOT_KCCONTAINER_THREAD:
261 setup_type_definition(retval, type_id, 0, "thread_snapshots");
262 break;
263
264 case STACKSHOT_KCTYPE_TASK_SNAPSHOT: {
265 i = 0;
266 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_unique_pid);
267 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_ss_flags);
268 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_user_time_in_terminated_threads);
269 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_system_time_in_terminated_threads);
270 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_p_start_sec);
271 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_task_size);
272 _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_max_resident_size);
273 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_suspend_count);
274 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_faults);
275 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_pageins);
276 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_cow_faults);
277 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_was_throttled);
278 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_did_throttle);
279 _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_latency_qos);
280 _SUBTYPE(KC_ST_INT32, struct task_snapshot_v2, ts_pid);
281 _SUBTYPE_ARRAY(KC_ST_CHAR, struct task_snapshot_v2, ts_p_comm, 32);
282 setup_type_definition(retval, type_id, i, "task_snapshot");
283 break;
284 }
285
286 case STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT: {
287 i = 0;
288 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_unique_pid);
289 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_ss_flags);
290 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_user_time_in_terminated_threads);
291 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_system_time_in_terminated_threads);
292 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_task_size);
293 _SUBTYPE(KC_ST_UINT64, struct task_delta_snapshot_v2, tds_max_resident_size);
294 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_suspend_count);
295 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_faults);
296 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_pageins);
297 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_cow_faults);
298 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_was_throttled);
299 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_did_throttle);
300 _SUBTYPE(KC_ST_UINT32, struct task_delta_snapshot_v2, tds_latency_qos);
301 setup_type_definition(retval, type_id, i, "task_delta_snapshot");
302 break;
303 }
304
305 case STACKSHOT_KCTYPE_THREAD_SNAPSHOT: {
306 i = 0;
307
308 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_thread_id);
309 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_wait_event);
310 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_continuation);
311 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_total_syscalls);
312 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_voucher_identifier);
313 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_dqserialnum);
314 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_user_time);
315 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_sys_time);
316 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_ss_flags);
317 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_last_run_time);
318 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_last_made_runnable_time);
319 _SUBTYPE(KC_ST_UINT32, struct thread_snapshot_v3, ths_state);
320 _SUBTYPE(KC_ST_UINT32, struct thread_snapshot_v3, ths_sched_flags);
321 _SUBTYPE(KC_ST_INT16, struct thread_snapshot_v3, ths_base_priority);
322 _SUBTYPE(KC_ST_INT16, struct thread_snapshot_v3, ths_sched_priority);
323 _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v3, ths_eqos);
324 _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v3, ths_rqos);
325 _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v3, ths_rqos_override);
326 _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v3, ths_io_tier);
327 _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v3, ths_thread_t);
328
329 setup_type_definition(retval, type_id, i, "thread_snapshot");
330 break;
331 }
332
333 case STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT: {
334 i = 0;
335
336 _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v2, tds_thread_id);
337 _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v2, tds_voucher_identifier);
338 _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v2, tds_ss_flags);
339 _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v2, tds_last_made_runnable_time);
340 _SUBTYPE(KC_ST_UINT32, struct thread_delta_snapshot_v2, tds_state);
341 _SUBTYPE(KC_ST_UINT32, struct thread_delta_snapshot_v2, tds_sched_flags);
342 _SUBTYPE(KC_ST_INT16, struct thread_delta_snapshot_v2, tds_base_priority);
343 _SUBTYPE(KC_ST_INT16, struct thread_delta_snapshot_v2, tds_sched_priority);
344 _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_eqos);
345 _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_rqos);
346 _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_rqos_override);
347 _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_io_tier);
348
349 setup_type_definition(retval, type_id, i, "thread_delta_snapshot");
350
351 break;
352 }
353
354 case STACKSHOT_KCTYPE_DONATING_PIDS:
355 setup_type_definition(retval, type_id, 1, "donating_pids");
356 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "donating_pids");
357 break;
358
359 case STACKSHOT_KCTYPE_THREAD_NAME: {
360 i = 0;
361 setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, 64, "pth_name");
362 setup_type_definition(retval, type_id, i, "pth_name");
363 break;
364 }
365
366 case STACKSHOT_KCTYPE_KERN_STACKFRAME:
367 setup_type_definition(retval, type_id, 2, "kernel_stack_frames");
368 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr");
369 setup_subtype_description(&subtypes[1], KC_ST_UINT32, sizeof(uint32_t), "sp");
370 break;
371
372 case STACKSHOT_KCTYPE_KERN_STACKFRAME64:
373 setup_type_definition(retval, type_id, 2, "kernel_stack_frames");
374 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr");
375 setup_subtype_description(&subtypes[1], KC_ST_UINT64, sizeof(uint64_t), "sp");
376 break;
377
378 case STACKSHOT_KCTYPE_USER_STACKFRAME:
379 setup_type_definition(retval, type_id, 2, "user_stack_frames");
380 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr");
381 setup_subtype_description(&subtypes[1], KC_ST_UINT32, sizeof(uint32_t), "sp");
382 break;
383
384 case STACKSHOT_KCTYPE_USER_STACKFRAME64:
385 setup_type_definition(retval, type_id, 2, "user_stack_frames");
386 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr");
387 setup_subtype_description(&subtypes[1], KC_ST_UINT64, sizeof(uint64_t), "sp");
388 break;
389
390 case STACKSHOT_KCTYPE_KERN_STACKLR:
391 setup_type_definition(retval, type_id, 1, "kernel_stack_frames");
392 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr");
393 subtypes[0].kcs_flags |= KCS_SUBTYPE_FLAGS_STRUCT;
394 break;
395
396 case STACKSHOT_KCTYPE_KERN_STACKLR64:
397 setup_type_definition(retval, type_id, 1, "kernel_stack_frames");
398 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr");
399 subtypes[0].kcs_flags |= KCS_SUBTYPE_FLAGS_STRUCT;
400 break;
401
402 case STACKSHOT_KCTYPE_USER_STACKLR:
403 setup_type_definition(retval, type_id, 1, "user_stack_frames");
404 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr");
405 subtypes[0].kcs_flags |= KCS_SUBTYPE_FLAGS_STRUCT;
406 break;
407
408 case STACKSHOT_KCTYPE_USER_STACKLR64:
409 setup_type_definition(retval, type_id, 1, "user_stack_frames");
410 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr");
411 subtypes[0].kcs_flags |= KCS_SUBTYPE_FLAGS_STRUCT;
412 break;
413
414 case STACKSHOT_KCTYPE_NONRUNNABLE_TIDS:
415 setup_type_definition(retval, type_id, 1, "nonrunnable_threads");
416 setup_subtype_description(&subtypes[0], KC_ST_INT64, 0, "nonrunnable_threads");
417 break;
418
419 case STACKSHOT_KCTYPE_NONRUNNABLE_TASKS:
420 setup_type_definition(retval, type_id, 1, "nonrunnable_tasks");
421 setup_subtype_description(&subtypes[0], KC_ST_INT64, 0, "nonrunnable_tasks");
422 break;
423
424 case STACKSHOT_KCTYPE_BOOTARGS: {
425 i = 0;
426 _STRINGTYPE("boot_args");
427 setup_type_definition(retval, type_id, i, "boot_args");
428 break;
429 }
430
431 case STACKSHOT_KCTYPE_OSVERSION: {
432 i = 0;
433 _STRINGTYPE("osversion");
434 setup_type_definition(retval, type_id, i, "osversion");
435 break;
436 }
437
438 case STACKSHOT_KCTYPE_KERN_PAGE_SIZE: {
439 i = 0;
440 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "kernel_page_size");
441 setup_type_definition(retval, type_id, i, "kernel_page_size");
442 break;
443 }
444
445 case STACKSHOT_KCTYPE_JETSAM_LEVEL: {
446 i = 0;
447 setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "jetsam_level");
448 setup_type_definition(retval, type_id, i, "jetsam_level");
449 break;
450 }
451
452 case STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP: {
453 i = 0;
454 setup_subtype_description(&subtypes[i++], KC_ST_UINT64, 0, "stackshot_delta_since_timestamp");
455 setup_type_definition(retval, type_id, i, "stackshot_delta_since_timestamp");
456 break;
457 }
458
459 /* crashinfo types */
460 case TASK_CRASHINFO_BSDINFOWITHUNIQID: {
461 i = 0;
462 _SUBTYPE_ARRAY(KC_ST_UINT8, struct proc_uniqidentifierinfo, p_uuid, 16);
463 _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_uniqueid);
464 _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_puniqueid);
465 /* Ignore the p_reserve fields */
466 setup_type_definition(retval, type_id, i, "proc_uniqidentifierinfo");
467 break;
468 }
469
470 case TASK_CRASHINFO_PID: {
471 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "pid");
472 setup_type_definition(retval, type_id, 1, "pid");
473 break;
474 }
475
476 case TASK_CRASHINFO_PPID: {
477 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "ppid");
478 setup_type_definition(retval, type_id, 1, "ppid");
479 break;
480 }
481
482 /* case TASK_CRASHINFO_RUSAGE: { */
483 /* /\* */
484 /* * rusage is a complex structure and is only for legacy use for crashed processes rusage info. */
485 /* * So we just consider it as opaque data. */
486 /* *\/ */
487 /* i = 0; */
488 /* setup_subtype_array_description(&subtypes[i++], KC_ST_UINT8, 0, sizeof(struct rusage), "rusage"); */
489 /* setup_type_definition(retval, type_id, i, "rusage"); */
490 /* break; */
491 /* } */
492
493 case TASK_CRASHINFO_RUSAGE_INFO: {
494 i = 0;
495 _SUBTYPE_ARRAY(KC_ST_UINT8, struct rusage_info_v3, ri_uuid, 16);
496 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_user_time);
497 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_system_time);
498 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_pkg_idle_wkups);
499 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_interrupt_wkups);
500 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_pageins);
501 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_wired_size);
502 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_resident_size);
503 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_phys_footprint);
504 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_proc_start_abstime);
505 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_proc_exit_abstime);
506 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_user_time);
507 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_system_time);
508 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_pkg_idle_wkups);
509 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_interrupt_wkups);
510 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_pageins);
511 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_elapsed_abstime);
512 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_diskio_bytesread);
513 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_diskio_byteswritten);
514 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_default);
515 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_maintenance);
516 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_background);
517 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_utility);
518 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_legacy);
519 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_user_initiated);
520 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_user_interactive);
521 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_billed_system_time);
522 _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_serviced_system_time);
523 setup_type_definition(retval, type_id, i, "rusage_info");
524 break;
525 }
526
527 case STACKSHOT_KCTYPE_CPU_TIMES: {
528 i = 0;
529 _SUBTYPE(KC_ST_UINT64, struct stackshot_cpu_times, user_usec);
530 _SUBTYPE(KC_ST_UINT64, struct stackshot_cpu_times, system_usec);
531 setup_type_definition(retval, type_id, i, "cpu_times");
532 break;
533 }
534
535 case STACKSHOT_KCTYPE_STACKSHOT_DURATION: {
536 i = 0;
537 _SUBTYPE(KC_ST_UINT64, struct stackshot_duration, stackshot_duration);
538 _SUBTYPE(KC_ST_UINT64, struct stackshot_duration, stackshot_duration_outer);
539 subtypes[0].kcs_flags |= KCS_SUBTYPE_FLAGS_MERGE;
540 subtypes[1].kcs_flags |= KCS_SUBTYPE_FLAGS_MERGE;
541 setup_type_definition(retval, type_id, i, "stackshot_duration");
542 break;
543 }
544
545 case STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS: {
546 i = 0;
547 _SUBTYPE(KC_ST_UINT32, struct stackshot_fault_stats, sfs_pages_faulted_in);
548 _SUBTYPE(KC_ST_UINT64, struct stackshot_fault_stats, sfs_time_spent_faulting);
549 _SUBTYPE(KC_ST_UINT64, struct stackshot_fault_stats, sfs_system_max_fault_time);
550 _SUBTYPE(KC_ST_UINT8, struct stackshot_fault_stats, sfs_stopped_faulting);
551
552 setup_type_definition(retval, type_id, i, "stackshot_fault_stats");
553 break;
554 }
555
556 case TASK_CRASHINFO_PROC_STARTTIME: {
557 i = 0;
558 _SUBTYPE(KC_ST_INT64, struct timeval64, tv_sec);
559 _SUBTYPE(KC_ST_INT64, struct timeval64, tv_usec);
560 setup_type_definition(retval, type_id, i, "proc_starttime");
561 break;
562 }
563
564 case TASK_CRASHINFO_EXCEPTION_CODES: {
565 i = 0;
566 char codenum[100];
567 for (i = 0; i < EXCEPTION_CODE_MAX; i++) {
568 snprintf(codenum, sizeof(codenum), "code_%d", i);
569 setup_subtype_description(&subtypes[i], KC_ST_UINT64, i * (sizeof(uint64_t)), codenum);
570 }
571 setup_type_definition(retval, type_id, i, "mach_exception_data_t");
572 break;
573 }
574
575 case TASK_CRASHINFO_PROC_NAME: {
576 i = 0;
577 _STRINGTYPE("p_comm");
578 setup_type_definition(retval, type_id, i, "p_comm");
579 break;
580 }
581
582 case TASK_CRASHINFO_USERSTACK: {
583 i = 0;
584 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "userstack_ptr");
585 setup_type_definition(retval, type_id, 1, "userstack_ptr");
586 break;
587 }
588
589 case TASK_CRASHINFO_ARGSLEN: {
590 i = 0;
591 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "p_argslen");
592 setup_type_definition(retval, type_id, 1, "p_argslen");
593 break;
594 }
595
596 case TASK_CRASHINFO_PROC_PATH: {
597 i = 0;
598 _STRINGTYPE("p_path");
599 setup_type_definition(retval, type_id, i, "p_path");
600 break;
601 }
602
603 case TASK_CRASHINFO_PROC_CSFLAGS: {
604 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "p_csflags");
605 setup_type_definition(retval, type_id, 1, "p_csflags");
606 break;
607 }
608
609 case TASK_CRASHINFO_PROC_STATUS: {
610 setup_subtype_description(&subtypes[0], KC_ST_UINT8, 0, "p_status");
611 setup_type_definition(retval, type_id, 1, "p_status");
612 break;
613 }
614
615 case TASK_CRASHINFO_UID: {
616 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "uid");
617 setup_type_definition(retval, type_id, 1, "uid");
618 break;
619 }
620
621 case TASK_CRASHINFO_GID: {
622 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "gid");
623 setup_type_definition(retval, type_id, 1, "gid");
624 break;
625 }
626
627 case TASK_CRASHINFO_PROC_ARGC: {
628 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "argc");
629 setup_type_definition(retval, type_id, 1, "argc");
630 break;
631 }
632
633 case TASK_CRASHINFO_PROC_FLAGS: {
634 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "p_flags");
635 setup_type_definition(retval, type_id, 1, "p_flags");
636 break;
637 }
638
639 case TASK_CRASHINFO_CPUTYPE: {
640 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "cputype");
641 setup_type_definition(retval, type_id, 1, "cputype");
642 break;
643 }
644
645 case TASK_CRASHINFO_RESPONSIBLE_PID: {
646 setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "responsible_pid");
647 setup_type_definition(retval, type_id, 1, "responsible_pid");
648 break;
649 }
650
651 case TASK_CRASHINFO_DIRTY_FLAGS: {
652 setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "dirty_flags");
653 setup_type_definition(retval, type_id, 1, "dirty_flags");
654 break;
655 }
656
657 case TASK_CRASHINFO_CRASHED_THREADID: {
658 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "crashed_threadid");
659 setup_type_definition(retval, type_id, 1, "crashed_threadid");
660 break;
661 }
662
663 case TASK_CRASHINFO_COALITION_ID: {
664 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "coalition_id");
665 setup_type_definition(retval, type_id, 1, "coalition_id");
666 break;
667 }
668
669 case TASK_CRASHINFO_UDATA_PTRS: {
670 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "udata_ptrs");
671 setup_type_definition(retval, type_id, 1, "udata_ptrs");
672 break;
673 }
674
675 case TASK_CRASHINFO_MEMORY_LIMIT: {
676 setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "task_phys_mem_limit");
677 setup_type_definition(retval, type_id, 1, "task_phys_mem_limit");
678 break;
679 }
680
681 case EXIT_REASON_SNAPSHOT: {
682 _SUBTYPE(KC_ST_UINT32, struct exit_reason_snapshot, ers_namespace);
683 _SUBTYPE(KC_ST_UINT64, struct exit_reason_snapshot, ers_code);
684 _SUBTYPE(KC_ST_UINT64, struct exit_reason_snapshot, ers_flags);
685 setup_type_definition(retval, type_id, i, "exit_reason_basic_info");
686
687 break;
688
689 }
690
691 case EXIT_REASON_USER_DESC: {
692 i = 0;
693
694 _STRINGTYPE("exit_reason_user_description");
695 setup_type_definition(retval, type_id, i, "exit_reason_user_description");
696 break;
697 }
698
699 case EXIT_REASON_USER_PAYLOAD: {
700 i = 0;
701
702 setup_subtype_array_description(&subtypes[i++], KC_ST_UINT8, 0, EXIT_REASON_PAYLOAD_MAX_LEN, "exit_reason_user_payload");
703 setup_type_definition(retval, type_id, i, "exit_reason_user_payload");
704 break;
705 }
706
707 case EXIT_REASON_CODESIGNING_INFO: {
708 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_virt_addr);
709 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_file_offset);
710 _SUBTYPE_ARRAY(KC_ST_CHAR, struct codesigning_exit_reason_info, ceri_pathname, EXIT_REASON_CODESIG_PATH_MAX);
711 _SUBTYPE_ARRAY(KC_ST_CHAR, struct codesigning_exit_reason_info, ceri_filename, EXIT_REASON_CODESIG_PATH_MAX);
712 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_codesig_modtime_secs);
713 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_codesig_modtime_nsecs);
714 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_page_modtime_secs);
715 _SUBTYPE(KC_ST_UINT64, struct codesigning_exit_reason_info, ceri_page_modtime_nsecs);
716 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_path_truncated);
717 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_object_codesigned);
718 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_codesig_validated);
719 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_codesig_tainted);
720 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_codesig_nx);
721 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_wpmapped);
722 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_slid);
723 _SUBTYPE(KC_ST_UINT8, struct codesigning_exit_reason_info, ceri_page_dirty);
724 _SUBTYPE(KC_ST_UINT32, struct codesigning_exit_reason_info, ceri_page_shadow_depth);
725 setup_type_definition(retval, type_id, i, "exit_reason_codesigning_info");
726
727 break;
728
729 }
730
731 default:
732 retval = NULL;
733 break;
734 }
735
736 assert(retval == NULL || (buffer_size > sizeof(struct kcdata_type_definition) +
737 (retval->kct_num_elements * sizeof(struct kcdata_subtype_descriptor))));
738 return retval;
739}
740
741static void
742setup_type_definition(struct kcdata_type_definition * d, uint32_t type, uint32_t num_elems, char * name)
743{
744 d->kct_type_identifier = type;
745 d->kct_num_elements = num_elems;
746 memcpy(d->kct_name, name, sizeof(d->kct_name));
747 d->kct_name[sizeof(d->kct_name) - 1] = '\0';
748}
749
750static uint32_t
751get_kctype_subtype_size(kctype_subtype_t type)
752{
753 switch (type) {
754 case KC_ST_CHAR:
755 case KC_ST_INT8:
756 case KC_ST_UINT8:
757 return sizeof(uint8_t);
758 break;
759 case KC_ST_INT16:
760 case KC_ST_UINT16:
761 return sizeof(uint16_t);
762 break;
763 case KC_ST_INT32:
764 case KC_ST_UINT32:
765 return sizeof(uint32_t);
766 break;
767 case KC_ST_INT64:
768 case KC_ST_UINT64:
769 return sizeof(uint64_t);
770 break;
771
772 default:
773 assert(0);
774 break;
775 }
776 return 0;
777}
778
779static void
780setup_subtype_array_description(
781 kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, uint32_t count, char * name)
782{
783 desc->kcs_flags = KCS_SUBTYPE_FLAGS_ARRAY;
784 desc->kcs_elem_type = type;
785 desc->kcs_elem_offset = offset;
786 desc->kcs_elem_size = KCS_SUBTYPE_PACK_SIZE(count, get_kctype_subtype_size(type));
787 memcpy(desc->kcs_name, name, sizeof(desc->kcs_name));
788 desc->kcs_name[sizeof(desc->kcs_name) - 1] = '\0';
789}
790
791static void
792setup_subtype_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, char * name)
793{
794 desc->kcs_flags = KCS_SUBTYPE_FLAGS_NONE;
795 desc->kcs_elem_type = type;
796 desc->kcs_elem_offset = offset;
797 desc->kcs_elem_size = get_kctype_subtype_size(type);
798 memcpy(desc->kcs_name, name, sizeof(desc->kcs_name));
799 desc->kcs_name[sizeof(desc->kcs_name) - 1] = '\0';
800}
801