xnu-3248.60.10.tar.gz
[apple/xnu.git] / osfmk / kern / kern_cdata.h
CommitLineData
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
37struct 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
46typedef struct kcdata_item * kcdata_item_t;
47
48enum 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 };
49typedef 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 */
57struct 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
67typedef 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
76static inline uint32_t
77kcs_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
86static inline uint32_t
87kcs_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
94static inline kern_return_t
95kcs_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
110struct 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
186static inline kcdata_item_t
187KCDATA_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
201static 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
207static 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 */
218struct 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
227typedef struct kcdata_descriptor * kcdata_descriptor_t;
228
229kcdata_descriptor_t kcdata_memory_alloc_init(mach_vm_address_t crash_data_p, unsigned data_type, unsigned size, unsigned flags);
230kern_return_t kcdata_memory_static_init(kcdata_descriptor_t data, mach_vm_address_t buffer_addr_p, unsigned data_type, unsigned size, unsigned flags);
231kern_return_t kcdata_memory_destroy(kcdata_descriptor_t data);
232uint64_t kcdata_memory_get_used_bytes(kcdata_descriptor_t kcd);
233kern_return_t kcdata_memcpy(kcdata_descriptor_t data, mach_vm_address_t dst_addr, void *src_addr, uint32_t size);
234
235kern_return_t kcdata_get_memory_addr(kcdata_descriptor_t data, uint32_t type, uint32_t size, mach_vm_address_t *user_addr);
236kern_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);
237kern_return_t kcdata_add_container_marker(kcdata_descriptor_t data, uint32_t header_type, uint32_t container_type, uint64_t identifier);
238kern_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
241kern_return_t kcdata_add_uint64_with_description(kcdata_descriptor_t crashinfo, uint64_t data, const char *description);
242kern_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_ */