#ifndef _KERN_CDATA_H_
#define _KERN_CDATA_H_
#include <stdint.h>
#include <mach/mach_types.h>
#define KCDATA_DESC_MAXLEN 32
struct kcdata_item {
uint32_t type;
uint32_t size;
uint64_t flags;
#ifndef KERNEL
char data[];
#endif
};
typedef struct kcdata_item * kcdata_item_t;
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 };
typedef enum KCDATA_SUBTYPE_TYPES kctype_subtype_t;
struct kcdata_subtype_descriptor {
uint8_t kcs_flags;
#define KCS_SUBTYPE_FLAGS_NONE 0x0
#define KCS_SUBTYPE_FLAGS_ARRAY 0x1
uint8_t kcs_elem_type;
uint16_t kcs_elem_offset;
uint32_t kcs_elem_size;
char kcs_name[KCDATA_DESC_MAXLEN];
};
typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t;
#define KCS_SUBTYPE_PACK_SIZE(e_count,e_size) (((e_count) & 0xffff) << 16 | ((e_size) & 0xffff))
static inline uint32_t
kcs_get_elem_size(kcdata_subtype_descriptor_t d)
{
if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) {
return (uint32_t)((d->kcs_elem_size & 0xffff) * ((d->kcs_elem_size & 0xffff0000)>>16));
}
return d->kcs_elem_size;
}
static inline uint32_t
kcs_get_elem_count(kcdata_subtype_descriptor_t d)
{
if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY)
return (d->kcs_elem_size >> 16) & 0xffff;
return 1;
}
static inline kern_return_t
kcs_set_elem_size(kcdata_subtype_descriptor_t d, uint32_t size, uint32_t count)
{
if (count > 1) {
if (size > 0xffff || count > 0xffff)
return KERN_INVALID_ARGUMENT;
d->kcs_elem_size = ((count & 0xffff) << 16 | (size & 0xffff));
}
else
{
d->kcs_elem_size = size;
}
return KERN_SUCCESS;
}
struct kcdata_type_definition {
uint32_t kct_type_identifier;
uint32_t kct_num_elements;
char kct_name[KCDATA_DESC_MAXLEN];
#ifndef KERNEL
struct kcdata_subtype_descriptor kct_elements[];
#endif
};
#define KCDATA_TYPE_INVALID 0x0
#define KCDATA_TYPE_STRING_DESC 0x1
#define KCDATA_TYPE_UINT32_DESC 0x2
#define KCDATA_TYPE_UINT64_DESC 0x3
#define KCDATA_TYPE_INT32_DESC 0x4
#define KCDATA_TYPE_INT64_DESC 0x5
#define KCDATA_TYPE_BINDATA_DESC 0x6
#define KCDATA_TYPE_ARRAY 0x11
#define KCDATA_TYPE_TYPEDEFINTION 0x12
#define KCDATA_TYPE_CONTAINER_BEGIN 0x13
#define KCDATA_TYPE_CONTAINER_END 0x14
#define KCDATA_TYPE_LIBRARY_LOADINFO 0x30
#define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31
#define KCDATA_TYPE_TIMEBASE 0x32
#define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33
#define KCDATA_TYPE_TIMEVAL 0x34
#define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35
#define KCDATA_TYPE_BUFFER_END 0xF19158ED
#define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157
#define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807
#define KCDATA_ITEM_HEADER_SIZE (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t))
#define KCDATA_ITEM_TYPE(item) (((kcdata_item_t)(item))->type)
#define KCDATA_ITEM_SIZE(item) (((kcdata_item_t)(item))->size)
#define KCDATA_ITEM_FLAGS(item) (((kcdata_item_t)(item))->flags)
#define KCDATA_ITEM_ARRAY_GET_EL_TYPE(item) ((KCDATA_ITEM_FLAGS(item) >> 32) & UINT32_MAX)
#define KCDATA_ITEM_ARRAY_GET_EL_COUNT(item) (KCDATA_ITEM_FLAGS(item) & UINT32_MAX)
#define KCDATA_ITEM_ARRAY_GET_EL_SIZE(item) (KCDATA_ITEM_SIZE(item) / KCDATA_ITEM_ARRAY_GET_EL_COUNT(item))
#define KCDATA_CONTAINER_ID(item) ((uint64_t)KCDATA_ITEM_FLAGS(item))
#define KCDATA_ITEM_NEXT_HEADER(item) ((kcdata_item_t)((uint64_t)((uintptr_t)(item)) + KCDATA_ITEM_HEADER_SIZE + KCDATA_ITEM_SIZE(item)))
#define KCDATA_ITEM_FOREACH(head) for (; KCDATA_ITEM_TYPE(head) != KCDATA_TYPE_BUFFER_END; (head) = KCDATA_ITEM_NEXT_HEADER(head))
static inline kcdata_item_t
KCDATA_ITEM_FIND_TYPE(kcdata_item_t head, uint32_t type)
{
KCDATA_ITEM_FOREACH(head)
{
if (KCDATA_ITEM_TYPE(head) == type) {
break;
}
}
return (KCDATA_ITEM_TYPE(head) == type) ? (kcdata_item_t)head : 0;
}
#ifndef KERNEL
#define KCDATA_ITEM_DATA_PTR(item) (&((kcdata_item_t)(item))->data)
static inline uint32_t kcdata_get_container_type(kcdata_item_t buffer) {
if (KCDATA_ITEM_TYPE(buffer) == KCDATA_TYPE_CONTAINER_BEGIN)
return *(uint32_t *)KCDATA_ITEM_DATA_PTR(buffer);
return 0;
}
static inline void kcdata_get_data_with_desc(kcdata_item_t buffer, char **desc_ptr, void **data_ptr) {
if (desc_ptr)
*desc_ptr = (char *)KCDATA_ITEM_DATA_PTR(buffer);
if (data_ptr)
*data_ptr = (void *)((uintptr_t)KCDATA_ITEM_DATA_PTR(buffer) + KCDATA_DESC_MAXLEN);
}
#endif
#ifdef XNU_KERNEL_PRIVATE
struct kcdata_descriptor {
uint32_t kcd_length;
uint32_t kcd_flags;
#define KCFLAG_USE_MEMCOPY 0x0
#define KCFLAG_USE_COPYOUT 0x1
mach_vm_address_t kcd_addr_begin;
mach_vm_address_t kcd_addr_end;
};
typedef struct kcdata_descriptor * kcdata_descriptor_t;
kcdata_descriptor_t kcdata_memory_alloc_init(mach_vm_address_t crash_data_p, unsigned data_type, unsigned size, unsigned flags);
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);
kern_return_t kcdata_memory_destroy(kcdata_descriptor_t data);
uint64_t kcdata_memory_get_used_bytes(kcdata_descriptor_t kcd);
kern_return_t kcdata_memcpy(kcdata_descriptor_t data, mach_vm_address_t dst_addr, void *src_addr, uint32_t size);
kern_return_t kcdata_get_memory_addr(kcdata_descriptor_t data, uint32_t type, uint32_t size, mach_vm_address_t *user_addr);
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);
kern_return_t kcdata_add_container_marker(kcdata_descriptor_t data, uint32_t header_type, uint32_t container_type, uint64_t identifier);
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);
kern_return_t kcdata_add_uint64_with_description(kcdata_descriptor_t crashinfo, uint64_t data, const char *description);
kern_return_t kcdata_add_uint32_with_description(kcdata_descriptor_t crashinfo, uint32_t data, const char *description);
#endif
#endif