Commit | Line | Data |
---|---|---|
3e170ce0 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 | #ifndef _KERN_CDATA_H_ | |
30 | #define _KERN_CDATA_H_ | |
31 | ||
32 | #include <stdint.h> | |
33 | #include <mach/mach_types.h> | |
34 | ||
35 | #define KCDATA_DESC_MAXLEN 32 /* including NULL byte at end */ | |
36 | ||
37 | struct kcdata_item { | |
38 | uint32_t type; | |
39 | uint32_t size; /* len(data) */ | |
40 | uint64_t flags; | |
41 | #ifndef KERNEL | |
42 | char data[]; /* must be at the end */ | |
43 | #endif | |
44 | }; | |
45 | ||
46 | typedef struct kcdata_item * kcdata_item_t; | |
47 | ||
48 | 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 }; | |
49 | typedef enum KCDATA_SUBTYPE_TYPES kctype_subtype_t; | |
50 | ||
51 | /* | |
52 | * A subtype description structure that defines | |
53 | * how a compound data is laid out in memory. This | |
54 | * provides on the fly definition of types and consumption | |
55 | * by the parser. | |
56 | */ | |
57 | struct kcdata_subtype_descriptor { | |
58 | uint8_t kcs_flags; | |
59 | #define KCS_SUBTYPE_FLAGS_NONE 0x0 | |
60 | #define KCS_SUBTYPE_FLAGS_ARRAY 0x1 | |
61 | uint8_t kcs_elem_type; /* restricted to kctype_subtype_t */ | |
62 | uint16_t kcs_elem_offset; /* offset in struct where data is found */ | |
63 | uint32_t kcs_elem_size; /* size of element (or) packed state for array type */ | |
64 | char kcs_name[KCDATA_DESC_MAXLEN]; /* max 31 bytes for name of field */ | |
65 | }; | |
66 | ||
67 | typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t; | |
68 | ||
69 | /* | |
70 | * In case of array of basic c types in kctype_subtype_t, | |
71 | * size is packed in lower 16 bits and | |
72 | * count is packed in upper 16 bits of kcs_elem_size field. | |
73 | */ | |
74 | #define KCS_SUBTYPE_PACK_SIZE(e_count,e_size) (((e_count) & 0xffff) << 16 | ((e_size) & 0xffff)) | |
75 | ||
76 | static inline uint32_t | |
77 | kcs_get_elem_size(kcdata_subtype_descriptor_t d) | |
78 | { | |
79 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { | |
80 | /* size is composed as ((count &0xffff)<<16 | (elem_size & 0xffff)) */ | |
81 | return (uint32_t)((d->kcs_elem_size & 0xffff) * ((d->kcs_elem_size & 0xffff0000)>>16)); | |
82 | } | |
83 | return d->kcs_elem_size; | |
84 | } | |
85 | ||
86 | static inline uint32_t | |
87 | kcs_get_elem_count(kcdata_subtype_descriptor_t d) | |
88 | { | |
89 | if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) | |
90 | return (d->kcs_elem_size >> 16) & 0xffff; | |
91 | return 1; | |
92 | } | |
93 | ||
94 | static inline kern_return_t | |
95 | kcs_set_elem_size(kcdata_subtype_descriptor_t d, uint32_t size, uint32_t count) | |
96 | { | |
97 | if (count > 1) { | |
98 | /* means we are setting up an array */ | |
99 | if (size > 0xffff || count > 0xffff) | |
100 | return KERN_INVALID_ARGUMENT; | |
101 | d->kcs_elem_size = ((count & 0xffff) << 16 | (size & 0xffff)); | |
102 | } | |
103 | else | |
104 | { | |
105 | d->kcs_elem_size = size; | |
106 | } | |
107 | return KERN_SUCCESS; | |
108 | } | |
109 | ||
110 | struct kcdata_type_definition { | |
111 | uint32_t kct_type_identifier; | |
112 | uint32_t kct_num_elements; | |
113 | char kct_name[KCDATA_DESC_MAXLEN]; | |
114 | #ifndef KERNEL | |
115 | struct kcdata_subtype_descriptor kct_elements[]; | |
116 | #endif | |
117 | }; | |
118 | ||
119 | /* chunk type definitions. 0 - 0x7ff are reserved and defined here | |
120 | * NOTE: Please update libkdd/kcdata/kcdtypes.c if you make any changes | |
121 | * in STACKSHOT_KCTYPE_* types. | |
122 | */ | |
123 | ||
124 | /* | |
125 | * Types with description value. | |
126 | * these will have KCDATA_DESC_MAXLEN-1 length string description | |
127 | * and rest of KCDATA_ITEM_SIZE() - KCDATA_DESC_MAXLEN bytes as data | |
128 | */ | |
129 | #define KCDATA_TYPE_INVALID 0x0 | |
130 | #define KCDATA_TYPE_STRING_DESC 0x1 | |
131 | #define KCDATA_TYPE_UINT32_DESC 0x2 | |
132 | #define KCDATA_TYPE_UINT64_DESC 0x3 | |
133 | #define KCDATA_TYPE_INT32_DESC 0x4 | |
134 | #define KCDATA_TYPE_INT64_DESC 0x5 | |
135 | #define KCDATA_TYPE_BINDATA_DESC 0x6 | |
136 | ||
137 | /* | |
138 | * Compound type definitions | |
139 | */ | |
140 | #define KCDATA_TYPE_ARRAY 0x11 /* Array of data */ | |
141 | #define KCDATA_TYPE_TYPEDEFINTION 0x12 /* Meta type that describes a type on the fly. */ | |
142 | #define KCDATA_TYPE_CONTAINER_BEGIN 0x13 /* Container type which has corresponding CONTAINER_END header. | |
143 | * KCDATA_TYPE_CONTAINER_BEGIN has type in the data segment. | |
144 | * Both headers have (uint64_t) ID for matching up nested data. | |
145 | */ | |
146 | #define KCDATA_TYPE_CONTAINER_END 0x14 | |
147 | ||
148 | ||
149 | /* | |
150 | * Generic data types that are most commonly used | |
151 | */ | |
152 | #define KCDATA_TYPE_LIBRARY_LOADINFO 0x30 /* struct dyld_uuid_info_32 */ | |
153 | #define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31 /* struct dyld_uuid_info_64 */ | |
154 | #define KCDATA_TYPE_TIMEBASE 0x32 /* struct mach_timebase_info */ | |
155 | #define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33 /* uint64_t */ | |
156 | #define KCDATA_TYPE_TIMEVAL 0x34 /* struct timeval64 */ | |
157 | #define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35 /* time in usecs uint64_t */ | |
158 | ||
159 | #define KCDATA_TYPE_BUFFER_END 0xF19158ED | |
160 | ||
161 | /* MAGIC numbers defined for each class of chunked data */ | |
162 | #define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157 /* owner: corpses/task_corpse.h */ | |
163 | /* type-range: 0x800 - 0x8ff */ | |
164 | #define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807 /* owner: sys/stackshot.h */ | |
165 | /* type-range: 0x900 - 0x9ff */ | |
166 | ||
167 | /* next type range number available 0x1000 */ | |
168 | ||
169 | /* Common MACROS and library functions */ | |
170 | /* make header = sizeof(type, flags, size) */ | |
171 | #define KCDATA_ITEM_HEADER_SIZE (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)) | |
172 | #define KCDATA_ITEM_TYPE(item) (((kcdata_item_t)(item))->type) | |
173 | #define KCDATA_ITEM_SIZE(item) (((kcdata_item_t)(item))->size) | |
174 | #define KCDATA_ITEM_FLAGS(item) (((kcdata_item_t)(item))->flags) | |
175 | ||
176 | #define KCDATA_ITEM_ARRAY_GET_EL_TYPE(item) ((KCDATA_ITEM_FLAGS(item) >> 32) & UINT32_MAX) | |
177 | #define KCDATA_ITEM_ARRAY_GET_EL_COUNT(item) (KCDATA_ITEM_FLAGS(item) & UINT32_MAX) | |
178 | #define KCDATA_ITEM_ARRAY_GET_EL_SIZE(item) (KCDATA_ITEM_SIZE(item) / KCDATA_ITEM_ARRAY_GET_EL_COUNT(item)) | |
179 | ||
180 | #define KCDATA_CONTAINER_ID(item) ((uint64_t)KCDATA_ITEM_FLAGS(item)) | |
181 | ||
182 | #define KCDATA_ITEM_NEXT_HEADER(item) ((kcdata_item_t)((uint64_t)((uintptr_t)(item)) + KCDATA_ITEM_HEADER_SIZE + KCDATA_ITEM_SIZE(item))) | |
183 | ||
184 | #define KCDATA_ITEM_FOREACH(head) for (; KCDATA_ITEM_TYPE(head) != KCDATA_TYPE_BUFFER_END; (head) = KCDATA_ITEM_NEXT_HEADER(head)) | |
185 | ||
186 | static inline kcdata_item_t | |
187 | KCDATA_ITEM_FIND_TYPE(kcdata_item_t head, uint32_t type) | |
188 | { | |
189 | KCDATA_ITEM_FOREACH(head) | |
190 | { | |
191 | if (KCDATA_ITEM_TYPE(head) == type) { | |
192 | break; | |
193 | } | |
194 | } | |
195 | return (KCDATA_ITEM_TYPE(head) == type) ? (kcdata_item_t)head : 0; | |
196 | } | |
197 | ||
198 | #ifndef KERNEL | |
199 | #define KCDATA_ITEM_DATA_PTR(item) (&((kcdata_item_t)(item))->data) | |
200 | ||
201 | static inline uint32_t kcdata_get_container_type(kcdata_item_t buffer) { | |
202 | if (KCDATA_ITEM_TYPE(buffer) == KCDATA_TYPE_CONTAINER_BEGIN) | |
203 | return *(uint32_t *)KCDATA_ITEM_DATA_PTR(buffer); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | static inline void kcdata_get_data_with_desc(kcdata_item_t buffer, char **desc_ptr, void **data_ptr) { | |
208 | if (desc_ptr) | |
209 | *desc_ptr = (char *)KCDATA_ITEM_DATA_PTR(buffer); | |
210 | if (data_ptr) | |
211 | *data_ptr = (void *)((uintptr_t)KCDATA_ITEM_DATA_PTR(buffer) + KCDATA_DESC_MAXLEN); | |
212 | } | |
213 | #endif /* KERNEL */ | |
214 | ||
215 | #ifdef XNU_KERNEL_PRIVATE | |
216 | ||
217 | /* Structure to save information about corpse data */ | |
218 | struct kcdata_descriptor { | |
219 | uint32_t kcd_length; | |
220 | uint32_t kcd_flags; | |
221 | #define KCFLAG_USE_MEMCOPY 0x0 | |
222 | #define KCFLAG_USE_COPYOUT 0x1 | |
223 | mach_vm_address_t kcd_addr_begin; | |
224 | mach_vm_address_t kcd_addr_end; | |
225 | }; | |
226 | ||
227 | typedef struct kcdata_descriptor * kcdata_descriptor_t; | |
228 | ||
229 | kcdata_descriptor_t kcdata_memory_alloc_init(mach_vm_address_t crash_data_p, unsigned data_type, unsigned size, unsigned flags); | |
230 | kern_return_t kcdata_memory_static_init(kcdata_descriptor_t data, mach_vm_address_t buffer_addr_p, unsigned data_type, unsigned size, unsigned flags); | |
231 | kern_return_t kcdata_memory_destroy(kcdata_descriptor_t data); | |
232 | uint64_t kcdata_memory_get_used_bytes(kcdata_descriptor_t kcd); | |
233 | kern_return_t kcdata_memcpy(kcdata_descriptor_t data, mach_vm_address_t dst_addr, void *src_addr, uint32_t size); | |
234 | ||
235 | kern_return_t kcdata_get_memory_addr(kcdata_descriptor_t data, uint32_t type, uint32_t size, mach_vm_address_t *user_addr); | |
236 | kern_return_t kcdata_get_memory_addr_for_array(kcdata_descriptor_t data, uint32_t type_of_element, uint32_t size_of_element, uint32_t count, mach_vm_address_t *user_addr); | |
237 | kern_return_t kcdata_add_container_marker(kcdata_descriptor_t data, uint32_t header_type, uint32_t container_type, uint64_t identifier); | |
238 | kern_return_t kcdata_add_type_definition(kcdata_descriptor_t data, uint32_t type_id, char *type_name, struct kcdata_subtype_descriptor *elements_array_addr, uint32_t elements_count); | |
239 | ||
240 | ||
241 | kern_return_t kcdata_add_uint64_with_description(kcdata_descriptor_t crashinfo, uint64_t data, const char *description); | |
242 | kern_return_t kcdata_add_uint32_with_description(kcdata_descriptor_t crashinfo, uint32_t data, const char *description); | |
243 | ||
244 | #endif /* XNU_KERNEL_PRIVATE */ | |
245 | ||
246 | #endif /* _KERN_CDATA_H_ */ |