]>
Commit | Line | Data |
---|---|---|
3e170ce0 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 | ||
25 | #include <Kernel/kern/kern_cdata.h> | |
26 | #include <Kernel/kern/debug.h> | |
27 | #include <sys/time.h> | |
28 | #include <stdlib.h> | |
29 | #include <stddef.h> | |
30 | #include <string.h> | |
31 | #include <assert.h> | |
32 | #include <mach/mach_time.h> | |
33 | #include <sys/proc_info.h> | |
34 | #include <corpses/task_corpse.h> | |
35 | ||
36 | /*! | |
37 | * @function kcdata_get_typedescription | |
38 | * | |
39 | * @abstract | |
40 | * Search the known type definitions for type with id type_id. | |
41 | * | |
42 | * @param type_id | |
43 | * A unsinged int type specified by the KCDATA. | |
44 | * | |
45 | * @param buffer | |
46 | * pointer to data area where type definition will be saved. | |
47 | * | |
48 | * @param buffer_size | |
49 | * size of the buffer provided. | |
50 | * | |
51 | * @return struct kcdata_type_definition * | |
52 | * pointer to a malloc'ed buffer holding the type definition and each subtype defintion for its fields. | |
53 | * It may return NULL if no type with id == type_id is found. | |
54 | * Note: The caller is responsible to free() the memory when its no longer used. | |
55 | * | |
56 | * @discussion | |
57 | * This function queries the known type definitions table. If found the defintion data is returned | |
58 | * else NULL is returned. It is advised to cache the return value from this function since the data | |
59 | * is always going to be the same for same type_id. The definition setup requires memory on heap. | |
60 | * The caller should make sure to free() the data once its done with using it. | |
61 | * | |
62 | */ | |
63 | struct kcdata_type_definition *kcdata_get_typedescription(unsigned type_id, uint8_t *buffer, uint32_t buffer_size); | |
64 | ||
65 | ||
66 | ||
67 | /* forward declarations for helper routines */ | |
68 | static uint32_t get_kctype_subtype_size(kctype_subtype_t type); | |
69 | static void setup_subtype_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, char *name); | |
70 | static void setup_subtype_array_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, uint32_t count, char *name); | |
71 | static void setup_type_definition(struct kcdata_type_definition *d, uint32_t type, uint32_t num_elems, char *name); | |
72 | ||
73 | struct kcdata_type_definition *kcdata_get_typedescription(unsigned type_id, uint8_t *buffer, uint32_t buffer_size) | |
74 | { | |
75 | int i = 0; | |
76 | #define _STR_VALUE(x) #x | |
77 | #define _SUBTYPE(t, s, f) setup_subtype_description(&subtypes[i++], (t), offsetof(s,f), _STR_VALUE(f)) | |
78 | #define _SUBTYPE_ARRAY(t, s, f, c) setup_subtype_array_description(&subtypes[i++], (t), offsetof(s,f), (c), _STR_VALUE(f)) | |
79 | #define _STRINGTYPE(f) setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, UINT16_MAX, f) | |
80 | ||
81 | ||
82 | ||
83 | if (buffer_size < sizeof(struct kcdata_type_definition) || buffer == NULL) | |
84 | return NULL; | |
85 | ||
86 | struct kcdata_type_definition *retval = (struct kcdata_type_definition *)&buffer[0]; | |
87 | kcdata_subtype_descriptor_t subtypes = (kcdata_subtype_descriptor_t)&buffer[sizeof(struct kcdata_type_definition)]; | |
88 | switch (type_id) { | |
89 | ||
90 | case KCDATA_TYPE_STRING_DESC: { | |
91 | i = 0; | |
92 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc"); | |
93 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, KCDATA_DESC_MAXLEN, UINT16_MAX, "data"); | |
94 | setup_type_definition(retval, type_id, i, "string_desc"); | |
95 | break; | |
96 | } | |
97 | ||
98 | case KCDATA_TYPE_UINT32_DESC: { | |
99 | i = 0; | |
100 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc"); | |
101 | setup_subtype_description(&subtypes[i++], KC_ST_UINT32, KCDATA_DESC_MAXLEN, "data"); | |
102 | setup_type_definition(retval, type_id, i, "uint32_desc"); | |
103 | break; | |
104 | } | |
105 | ||
106 | case KCDATA_TYPE_UINT64_DESC: { | |
107 | i = 0; | |
108 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc"); | |
109 | setup_subtype_description(&subtypes[i++], KC_ST_UINT64, KCDATA_DESC_MAXLEN, "data"); | |
110 | setup_type_definition(retval, type_id, i, "uint64_desc"); | |
111 | break; | |
112 | } | |
113 | ||
114 | case KCDATA_TYPE_INT32_DESC: { | |
115 | i = 0; | |
116 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc"); | |
117 | setup_subtype_description(&subtypes[i++], KC_ST_INT32, KCDATA_DESC_MAXLEN, "data"); | |
118 | setup_type_definition(retval, type_id, i, "int32_desc"); | |
119 | break; | |
120 | } | |
121 | ||
122 | case KCDATA_TYPE_INT64_DESC: { | |
123 | i = 0; | |
124 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, KCDATA_DESC_MAXLEN, "desc"); | |
125 | setup_subtype_description(&subtypes[i++], KC_ST_INT64, KCDATA_DESC_MAXLEN, "data"); | |
126 | setup_type_definition(retval, type_id, i, "int64_desc"); | |
127 | break; | |
128 | } | |
129 | ||
130 | case KCDATA_TYPE_CONTAINER_BEGIN :{ | |
131 | i = 0; | |
132 | setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "kcContainerType"); | |
133 | setup_type_definition(retval, type_id, i, "container_begin"); | |
134 | break; | |
135 | } | |
136 | ||
137 | case KCDATA_TYPE_LIBRARY_LOADINFO: { | |
138 | i = 0; | |
139 | _SUBTYPE(KC_ST_UINT32, struct dyld_uuid_info_32, imageLoadAddress); | |
140 | _SUBTYPE_ARRAY(KC_ST_UINT8, struct dyld_uuid_info_32, imageUUID, 16); | |
141 | setup_type_definition(retval, type_id, i, "dyld_load_info"); | |
142 | break; | |
143 | ||
144 | } | |
145 | ||
146 | case KCDATA_TYPE_LIBRARY_LOADINFO64: /* fall through */ | |
147 | case STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO: { | |
148 | i = 0; | |
149 | _SUBTYPE(KC_ST_UINT64, struct dyld_uuid_info_64, imageLoadAddress); | |
150 | _SUBTYPE_ARRAY(KC_ST_UINT8, struct dyld_uuid_info_64, imageUUID, 16); | |
151 | setup_type_definition(retval, type_id, i, "dyld_load_info"); | |
152 | break; | |
153 | } | |
154 | ||
155 | case KCDATA_TYPE_TIMEBASE: { | |
156 | i = 0; | |
157 | _SUBTYPE(KC_ST_UINT32, struct mach_timebase_info, numer); | |
158 | _SUBTYPE(KC_ST_UINT32, struct mach_timebase_info, denom); | |
159 | setup_type_definition(retval, type_id, i, "mach_timebase_info"); | |
160 | } | |
161 | ||
162 | case KCDATA_TYPE_MACH_ABSOLUTE_TIME: | |
163 | setup_type_definition(retval, type_id, 1, "mach_absolute_time"); | |
164 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "mach_absolute_time"); | |
165 | break; | |
166 | ||
167 | case KCDATA_TYPE_TIMEVAL: { | |
168 | i = 0; | |
169 | _SUBTYPE(KC_ST_INT64, struct timeval64, tv_sec); | |
170 | _SUBTYPE(KC_ST_INT64, struct timeval64, tv_usec); | |
171 | setup_type_definition(retval, type_id, i, "timeval"); | |
172 | } | |
173 | ||
174 | case KCDATA_TYPE_USECS_SINCE_EPOCH: | |
175 | setup_type_definition(retval, type_id, 1, "usecs_since_epoch"); | |
176 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "usecs_since_epoch"); | |
177 | break; | |
178 | ||
179 | ||
180 | /* stackshot specific types */ | |
181 | case STACKSHOT_KCTYPE_IOSTATS: { | |
182 | i = 0; | |
183 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_reads_count); | |
184 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_reads_size); | |
185 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_writes_count); | |
186 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_disk_writes_size); | |
187 | _SUBTYPE_ARRAY(KC_ST_UINT64, struct io_stats_snapshot, ss_io_priority_count, STACKSHOT_IO_NUM_PRIORITIES); | |
188 | _SUBTYPE_ARRAY(KC_ST_UINT64, struct io_stats_snapshot, ss_io_priority_size, STACKSHOT_IO_NUM_PRIORITIES); | |
189 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_paging_count); | |
190 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_paging_size); | |
191 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_non_paging_count); | |
192 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_non_paging_size); | |
193 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_data_count); | |
194 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_data_size); | |
195 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_metadata_count); | |
196 | _SUBTYPE(KC_ST_UINT64, struct io_stats_snapshot, ss_metadata_size); | |
197 | ||
198 | setup_type_definition(retval, type_id, i, "io_statistics"); | |
199 | break; | |
200 | } | |
201 | ||
202 | case STACKSHOT_KCTYPE_GLOBAL_MEM_STATS : | |
203 | { i = 0; | |
204 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, snapshot_magic); | |
205 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, free_pages); | |
206 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, active_pages); | |
207 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, inactive_pages); | |
208 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, purgeable_pages); | |
209 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, wired_pages); | |
210 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, speculative_pages); | |
211 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, throttled_pages); | |
212 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, filebacked_pages); | |
213 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, compressions); | |
214 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, decompressions); | |
215 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, compressor_size); | |
216 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, busy_buffer_count); | |
217 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, pages_wanted); | |
218 | _SUBTYPE(KC_ST_UINT32, struct mem_and_io_snapshot, pages_reclaimed); | |
219 | _SUBTYPE(KC_ST_UINT8, struct mem_and_io_snapshot, pages_wanted_reclaimed_valid); | |
220 | setup_type_definition(retval, type_id, i, "mem_and_io_snapshot"); | |
221 | break; | |
222 | } | |
223 | ||
224 | case STACKSHOT_KCCONTAINER_TASK: | |
225 | setup_type_definition(retval, type_id, 0, "task_snapshots"); | |
226 | break; | |
227 | ||
228 | case STACKSHOT_KCCONTAINER_THREAD: | |
229 | setup_type_definition(retval, type_id, 0, "thread_snapshots"); | |
230 | break; | |
231 | ||
232 | ||
233 | case STACKSHOT_KCTYPE_TASK_SNAPSHOT: { | |
234 | i = 0; | |
235 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_unique_pid); | |
236 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_ss_flags); | |
237 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_user_time_in_terminated_threads); | |
238 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_system_time_in_terminated_threads); | |
239 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_p_start_sec); | |
240 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_task_size); | |
241 | _SUBTYPE(KC_ST_UINT64, struct task_snapshot_v2, ts_max_resident_size); | |
242 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_suspend_count); | |
243 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_faults); | |
244 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_pageins); | |
245 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_cow_faults); | |
246 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_was_throttled); | |
247 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_did_throttle); | |
248 | _SUBTYPE(KC_ST_UINT32, struct task_snapshot_v2, ts_latency_qos); | |
249 | _SUBTYPE(KC_ST_INT32, struct task_snapshot_v2, ts_pid); | |
250 | _SUBTYPE_ARRAY(KC_ST_CHAR, struct task_snapshot_v2, ts_p_comm, 32); | |
251 | setup_type_definition(retval, type_id, i, "task_snapshot"); | |
252 | break; | |
253 | } | |
254 | ||
255 | case STACKSHOT_KCTYPE_THREAD_SNAPSHOT: { | |
256 | i = 0; | |
257 | ||
258 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_thread_id); | |
259 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_wait_event); | |
260 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_continuation); | |
261 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_total_syscalls); | |
262 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_voucher_identifier); | |
263 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_dqserialnum); | |
264 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_user_time); | |
265 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_sys_time); | |
266 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_ss_flags); | |
267 | _SUBTYPE(KC_ST_UINT64, struct thread_snapshot_v2, ths_last_run_time); | |
268 | _SUBTYPE(KC_ST_UINT32, struct thread_snapshot_v2, ths_state); | |
269 | _SUBTYPE(KC_ST_UINT32, struct thread_snapshot_v2, ths_sched_flags); | |
270 | _SUBTYPE(KC_ST_INT16, struct thread_snapshot_v2, ths_base_priority); | |
271 | _SUBTYPE(KC_ST_INT16, struct thread_snapshot_v2, ths_sched_priority); | |
272 | _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v2, ths_eqos); | |
273 | _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v2, ths_rqos); | |
274 | _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v2, ths_rqos_override); | |
275 | _SUBTYPE(KC_ST_UINT8, struct thread_snapshot_v2, ths_io_tier); | |
276 | ||
277 | setup_type_definition(retval, type_id, i, "thread_snapshot"); | |
278 | break; | |
279 | } | |
280 | ||
281 | ||
282 | case STASKSHOT_KCTYPE_DONATING_PIDS: | |
283 | setup_type_definition(retval, type_id, 1, "donating_pids"); | |
284 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "pid"); | |
285 | break; | |
286 | ||
287 | case STACKSHOT_KCTYPE_THREAD_NAME:{ | |
288 | i = 0; | |
289 | setup_subtype_array_description(&subtypes[i++], KC_ST_CHAR, 0, 64, "pth_name"); | |
290 | setup_type_definition(retval, type_id, i, "pth_name"); | |
291 | break; | |
292 | } | |
293 | ||
294 | case STACKSHOT_KCTYPE_KERN_STACKFRAME : | |
295 | setup_type_definition(retval, type_id, 2, "kernel_stack_frames"); | |
296 | setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr"); | |
297 | setup_subtype_description(&subtypes[1], KC_ST_UINT32, sizeof(uint32_t), "sp"); | |
298 | break; | |
299 | ||
300 | case STACKSHOT_KCTYPE_KERN_STACKFRAME64 : | |
301 | setup_type_definition(retval, type_id, 2, "kernel_stack_frames"); | |
302 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr"); | |
303 | setup_subtype_description(&subtypes[1], KC_ST_UINT64, sizeof(uint64_t), "sp"); | |
304 | break; | |
305 | ||
306 | case STACKSHOT_KCTYPE_USER_STACKFRAME : | |
307 | setup_type_definition(retval, type_id, 2, "user_stack_frames"); | |
308 | setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "lr"); | |
309 | setup_subtype_description(&subtypes[1], KC_ST_UINT32, sizeof(uint32_t), "sp"); | |
310 | break; | |
311 | ||
312 | case STACKSHOT_KCTYPE_USER_STACKFRAME64 : | |
313 | setup_type_definition(retval, type_id, 2, "user_stack_frames"); | |
314 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "lr"); | |
315 | setup_subtype_description(&subtypes[1], KC_ST_UINT64, sizeof(uint64_t), "sp"); | |
316 | break; | |
317 | ||
318 | case STACKSHOT_KCTYPE_BOOTARGS: { | |
319 | i = 0; | |
320 | _STRINGTYPE("boot_args"); | |
321 | setup_type_definition(retval, type_id, i, "boot_args"); | |
322 | break; | |
323 | } | |
324 | ||
325 | case STACKSHOT_KCTYPE_OSVERSION: { | |
326 | i = 0; | |
327 | _STRINGTYPE("osversion"); | |
328 | setup_type_definition(retval, type_id, i, "osversion"); | |
329 | break; | |
330 | } | |
331 | ||
332 | case STACKSHOT_KCTYPE_KERN_PAGE_SIZE: { | |
333 | i = 0; | |
334 | setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "kernel_page_size"); | |
335 | setup_type_definition(retval, type_id, i, "kernel_page_size"); | |
336 | break; | |
337 | } | |
338 | ||
339 | case STACKSHOT_KCTYPE_JETSAM_LEVEL: { | |
340 | i = 0; | |
341 | setup_subtype_description(&subtypes[i++], KC_ST_UINT32, 0, "jetsam_level"); | |
342 | setup_type_definition(retval, type_id, i, "jetsam_level"); | |
343 | break; | |
344 | } | |
345 | ||
346 | /* crashinfo types */ | |
347 | case TASK_CRASHINFO_BSDINFOWITHUNIQID: | |
348 | { i = 0; | |
349 | _SUBTYPE_ARRAY(KC_ST_UINT8, struct proc_uniqidentifierinfo, p_uuid, 16); | |
350 | _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_uniqueid); | |
351 | _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_puniqueid); | |
352 | /* Ignore the p_reserve fields */ | |
353 | setup_type_definition(retval, type_id, i, "proc_uniqidentifierinfo"); | |
354 | break; | |
355 | } | |
356 | ||
357 | case TASK_CRASHINFO_PID:{ | |
358 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "pid"); | |
359 | setup_type_definition(retval, type_id, 1, "pid"); | |
360 | break; | |
361 | } | |
362 | ||
363 | case TASK_CRASHINFO_PPID:{ | |
364 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "ppid"); | |
365 | setup_type_definition(retval, type_id, 1, "ppid"); | |
366 | break; | |
367 | } | |
368 | ||
369 | case TASK_CRASHINFO_RUSAGE_INFO: { | |
370 | i = 0; | |
371 | _SUBTYPE_ARRAY(KC_ST_UINT8, struct rusage_info_v3, ri_uuid, 16); | |
372 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_user_time); | |
373 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_system_time); | |
374 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_pkg_idle_wkups); | |
375 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_interrupt_wkups); | |
376 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_pageins); | |
377 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_wired_size); | |
378 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_resident_size); | |
379 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_phys_footprint); | |
380 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_proc_start_abstime); | |
381 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_proc_exit_abstime); | |
382 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_user_time); | |
383 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_system_time); | |
384 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_pkg_idle_wkups); | |
385 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_interrupt_wkups); | |
386 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_pageins); | |
387 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_child_elapsed_abstime); | |
388 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_diskio_bytesread); | |
389 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_diskio_byteswritten); | |
390 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_default); | |
391 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_maintenance); | |
392 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_background); | |
393 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_utility); | |
394 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_legacy); | |
395 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_user_initiated); | |
396 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_cpu_time_qos_user_interactive); | |
397 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_billed_system_time); | |
398 | _SUBTYPE(KC_ST_UINT64, struct rusage_info_v3, ri_serviced_system_time); | |
399 | setup_type_definition(retval, type_id, i, "rusage_info"); | |
400 | } | |
401 | ||
402 | case TASK_CRASHINFO_PROC_NAME: { | |
403 | i = 0; | |
404 | _STRINGTYPE("p_comm"); | |
405 | setup_type_definition(retval, type_id, i, "p_comm"); | |
406 | } | |
407 | ||
408 | case TASK_CRASHINFO_USERSTACK: { | |
409 | i = 0; | |
410 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "userstack_ptr"); | |
411 | setup_type_definition(retval, type_id, 1, "userstack_ptr"); | |
412 | break; | |
413 | } | |
414 | ||
415 | case TASK_CRASHINFO_ARGSLEN: { | |
416 | i = 0; | |
417 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "p_argslen"); | |
418 | setup_type_definition(retval, type_id, 1, "p_argslen"); | |
419 | break; | |
420 | } | |
421 | ||
422 | case TASK_CRASHINFO_PROC_PATH: { | |
423 | i = 0; | |
424 | _STRINGTYPE("p_path"); | |
425 | setup_type_definition(retval, type_id, i, "p_path"); | |
426 | } | |
427 | ||
428 | case TASK_CRASHINFO_PROC_CSFLAGS:{ | |
429 | setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "p_csflags"); | |
430 | setup_type_definition(retval, type_id, 1, "p_csflags"); | |
431 | break; | |
432 | } | |
433 | ||
434 | case TASK_CRASHINFO_PROC_STATUS: { | |
435 | setup_subtype_description(&subtypes[0], KC_ST_UINT8, 0, "p_status"); | |
436 | setup_type_definition(retval, type_id, 1, "p_status"); | |
437 | break; | |
438 | } | |
439 | ||
440 | case TASK_CRASHINFO_UID:{ | |
441 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "uid"); | |
442 | setup_type_definition(retval, type_id, 1, "uid"); | |
443 | break; | |
444 | } | |
445 | ||
446 | case TASK_CRASHINFO_GID:{ | |
447 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "gid"); | |
448 | setup_type_definition(retval, type_id, 1, "gid"); | |
449 | break; | |
450 | } | |
451 | ||
452 | case TASK_CRASHINFO_PROC_ARGC:{ | |
453 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "argc"); | |
454 | setup_type_definition(retval, type_id, 1, "argc"); | |
455 | break; | |
456 | } | |
457 | ||
458 | case TASK_CRASHINFO_PROC_FLAGS:{ | |
459 | setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "p_flags"); | |
460 | setup_type_definition(retval, type_id, 1, "p_flags"); | |
461 | break; | |
462 | } | |
463 | ||
464 | case TASK_CRASHINFO_CPUTYPE:{ | |
465 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "cputype"); | |
466 | setup_type_definition(retval, type_id, 1, "cputype"); | |
467 | break; | |
468 | } | |
469 | ||
470 | case TASK_CRASHINFO_RESPONSIBLE_PID:{ | |
471 | setup_subtype_description(&subtypes[0], KC_ST_INT32, 0, "responsible_pid"); | |
472 | setup_type_definition(retval, type_id, 1, "responsible_pid"); | |
473 | break; | |
474 | } | |
475 | ||
476 | case TASK_CRASHINFO_DIRTY_FLAGS:{ | |
477 | setup_subtype_description(&subtypes[0], KC_ST_UINT32, 0, "dirty_flags"); | |
478 | setup_type_definition(retval, type_id, 1, "dirty_flags"); | |
479 | break; | |
480 | } | |
481 | ||
482 | case TASK_CRASHINFO_CRASHED_THREADID: { | |
483 | setup_subtype_description(&subtypes[0], KC_ST_UINT64, 0, "crashed_threadid"); | |
484 | setup_type_definition(retval, type_id, 1, "crashed_threadid"); | |
485 | break; | |
486 | } | |
487 | ||
488 | default: | |
489 | retval = NULL; | |
490 | break; | |
491 | } | |
492 | ||
493 | assert(retval == NULL || (buffer_size > sizeof(struct kcdata_type_definition) + (retval->kct_num_elements * sizeof(struct kcdata_subtype_descriptor)))); | |
494 | return retval; | |
495 | } | |
496 | ||
497 | ||
498 | static void setup_type_definition(struct kcdata_type_definition *d, uint32_t type, uint32_t num_elems, char *name) | |
499 | { | |
500 | d->kct_type_identifier = type; | |
501 | d->kct_num_elements = num_elems; | |
502 | memcpy(d->kct_name, name, sizeof(d->kct_name)); | |
503 | d->kct_name[sizeof(d->kct_name) - 1] = '\0'; | |
504 | } | |
505 | ||
506 | static uint32_t get_kctype_subtype_size(kctype_subtype_t type){ | |
507 | switch (type) { | |
508 | case KC_ST_CHAR: | |
509 | case KC_ST_INT8: | |
510 | case KC_ST_UINT8: | |
511 | return sizeof(uint8_t); | |
512 | break; | |
513 | case KC_ST_INT16: | |
514 | case KC_ST_UINT16: | |
515 | return sizeof(uint16_t); | |
516 | break; | |
517 | case KC_ST_INT32: | |
518 | case KC_ST_UINT32: | |
519 | return sizeof(uint32_t); | |
520 | break; | |
521 | case KC_ST_INT64: | |
522 | case KC_ST_UINT64: | |
523 | return sizeof(uint64_t); | |
524 | break; | |
525 | ||
526 | default: | |
527 | assert(0); | |
528 | break; | |
529 | } | |
530 | return 0; | |
531 | } | |
532 | ||
533 | static void setup_subtype_array_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, uint32_t count, char *name) | |
534 | { | |
535 | desc->kcs_flags = KCS_SUBTYPE_FLAGS_ARRAY; | |
536 | desc->kcs_elem_type = type; | |
537 | desc->kcs_elem_offset = offset; | |
538 | desc->kcs_elem_size = KCS_SUBTYPE_PACK_SIZE(count, get_kctype_subtype_size(type)); | |
539 | memcpy(desc->kcs_name, name, sizeof(desc->kcs_name)); | |
540 | desc->kcs_name[sizeof(desc->kcs_name) - 1] = '\0'; | |
541 | } | |
542 | ||
543 | static void setup_subtype_description(kcdata_subtype_descriptor_t desc, kctype_subtype_t type, uint32_t offset, char *name) | |
544 | { | |
545 | desc->kcs_flags = KCS_SUBTYPE_FLAGS_NONE; | |
546 | desc->kcs_elem_type = type; | |
547 | desc->kcs_elem_offset = offset; | |
548 | desc->kcs_elem_size = get_kctype_subtype_size(type); | |
549 | memcpy(desc->kcs_name, name, sizeof(desc->kcs_name)); | |
550 | desc->kcs_name[sizeof(desc->kcs_name) - 1] = '\0'; | |
551 | } | |
552 |