X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..4ba76501152d51ccb5647018f3192c6096367d48:/osfmk/kern/kern_cdata.h diff --git a/osfmk/kern/kern_cdata.h b/osfmk/kern/kern_cdata.h index ac02b62d7..398e8a122 100644 --- a/osfmk/kern/kern_cdata.h +++ b/osfmk/kern/kern_cdata.h @@ -29,218 +29,83 @@ #ifndef _KERN_CDATA_H_ #define _KERN_CDATA_H_ -#include +#include #include -#define KCDATA_DESC_MAXLEN 32 /* including NULL byte at end */ - -struct kcdata_item { - uint32_t type; - uint32_t size; /* len(data) */ - uint64_t flags; -#ifndef KERNEL - char data[]; /* must be at the end */ -#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; - -/* - * A subtype description structure that defines - * how a compound data is laid out in memory. This - * provides on the fly definition of types and consumption - * by the parser. - */ -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; /* restricted to kctype_subtype_t */ - uint16_t kcs_elem_offset; /* offset in struct where data is found */ - uint32_t kcs_elem_size; /* size of element (or) packed state for array type */ - char kcs_name[KCDATA_DESC_MAXLEN]; /* max 31 bytes for name of field */ -}; - -typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t; - /* - * In case of array of basic c types in kctype_subtype_t, - * size is packed in lower 16 bits and - * count is packed in upper 16 bits of kcs_elem_size field. - */ -#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) { - /* size is composed as ((count &0xffff)<<16 | (elem_size & 0xffff)) */ - 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) { - /* means we are setting up an array */ - 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 -}; - -/* chunk type definitions. 0 - 0x7ff are reserved and defined here - * NOTE: Please update libkdd/kcdata/kcdtypes.c if you make any changes - * in STACKSHOT_KCTYPE_* types. - */ - -/* - * Types with description value. - * these will have KCDATA_DESC_MAXLEN-1 length string description - * and rest of KCDATA_ITEM_SIZE() - KCDATA_DESC_MAXLEN bytes as data - */ -#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 - -/* - * Compound type definitions - */ -#define KCDATA_TYPE_ARRAY 0x11 /* Array of data */ -#define KCDATA_TYPE_TYPEDEFINTION 0x12 /* Meta type that describes a type on the fly. */ -#define KCDATA_TYPE_CONTAINER_BEGIN 0x13 /* Container type which has corresponding CONTAINER_END header. - * KCDATA_TYPE_CONTAINER_BEGIN has type in the data segment. - * Both headers have (uint64_t) ID for matching up nested data. - */ -#define KCDATA_TYPE_CONTAINER_END 0x14 - - -/* - * Generic data types that are most commonly used + * Do not use these macros! + * + * Instead, you should use kcdata_iter_* functions defined in kcdata.h. These + * macoros have no idea where the kcdata buffer ends, so they are all unsafe. */ -#define KCDATA_TYPE_LIBRARY_LOADINFO 0x30 /* struct dyld_uuid_info_32 */ -#define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31 /* struct dyld_uuid_info_64 */ -#define KCDATA_TYPE_TIMEBASE 0x32 /* struct mach_timebase_info */ -#define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33 /* uint64_t */ -#define KCDATA_TYPE_TIMEVAL 0x34 /* struct timeval64 */ -#define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35 /* time in usecs uint64_t */ - -#define KCDATA_TYPE_BUFFER_END 0xF19158ED - -/* MAGIC numbers defined for each class of chunked data */ -#define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157 /* owner: corpses/task_corpse.h */ - /* type-range: 0x800 - 0x8ff */ -#define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807 /* owner: sys/stackshot.h */ - /* type-range: 0x900 - 0x9ff */ - -/* next type range number available 0x1000 */ - -/* Common MACROS and library functions */ -/* make header = sizeof(type, flags, size) */ #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 /* KERNEL */ +#define KCDATA_ITEM_ITER(item) kcdata_iter_unsafe((void*)(item)) +#define KCDATA_ITEM_TYPE(item) kcdata_iter_type(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_SIZE(item) kcdata_iter_size(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_FLAGS(item) kcdata_iter_flags(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_ARRAY_GET_EL_TYPE(item) kcdata_iter_array_elem_type(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_ARRAY_GET_EL_COUNT(item) kcdata_iter_array_elem_count(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_ARRAY_GET_EL_SIZE(item) kcdata_iter_array_elem_size(KCDATA_ITEM_ITER(item)) +#define KCDATA_CONTAINER_ID(item) kcdata_iter_container_id(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_NEXT_HEADER(itemx) (kcdata_iter_next(KCDATA_ITEM_ITER(itemx)).item) +#define KCDATA_ITEM_FOREACH(head) for (; KCDATA_ITEM_TYPE(head) != KCDATA_TYPE_BUFFER_END; (head) = KCDATA_ITEM_NEXT_HEADER(head)) +#define KCDATA_ITEM_DATA_PTR(item) kcdata_iter_payload(KCDATA_ITEM_ITER(item)) +#define KCDATA_ITEM_FIND_TYPE(itemx, type) (kcdata_iter_find_type(KCDATA_ITEM_ITER(itemx), type).item) +#define kcdata_get_container_type(buffer) kcdata_iter_container_type(KCDATA_ITEM_ITER(buffer)) +#define kcdata_get_data_with_desc(buf, desc, data) kcdata_iter_get_data_with_desc(KCDATA_ITEM_ITER(buf),desc,data,NULL) +/* Do not use these macros! */ + +#ifdef KERNEL #ifdef XNU_KERNEL_PRIVATE /* Structure to save information about corpse data */ 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; + uint16_t kcd_flags; +#define KCFLAG_USE_MEMCOPY 0x0 +#define KCFLAG_USE_COPYOUT 0x1 +#define KCFLAG_NO_AUTO_ENDBUFFER 0x2 + uint16_t kcd_user_flags; /* reserved for subsystems using kcdata */ + 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_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_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); -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_undo_add_container_begin(kcdata_descriptor_t data); +kern_return_t kcdata_write_buffer_end(kcdata_descriptor_t data); +void *kcdata_memory_get_begin_addr(kcdata_descriptor_t data); -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); +#else /* XNU_KERNEL_PRIVATE */ + +typedef void * kcdata_descriptor_t; #endif /* XNU_KERNEL_PRIVATE */ +uint32_t kcdata_estimate_required_buffer_size(uint32_t num_items, uint32_t payload_size); +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, const void * src_addr, uint32_t size); +kern_return_t kcdata_bzero(kcdata_descriptor_t data, mach_vm_address_t dst_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); + +#endif /* KERNEL */ #endif /* _KERN_CDATA_H_ */