1*bbb1b6f9SApple OSS Distributions# Extensible Paniclog 2*bbb1b6f9SApple OSS Distributions 3*bbb1b6f9SApple OSS DistributionsThis documentation discusses the API and features of the extensible paniclog in XNU's panic flow. 4*bbb1b6f9SApple OSS Distributions 5*bbb1b6f9SApple OSS Distributions## Overview 6*bbb1b6f9SApple OSS Distributions 7*bbb1b6f9SApple OSS DistributionsWith this feature we want to provide an infrastructure for kexts / dexts to insert their system state into the paniclog. Currently there is no way of knowing the kext or dext state unless we take a full coredump. With this feature, they can drop relevant state information that will end up in the paniclog and can be used to triage panics. 8*bbb1b6f9SApple OSS Distributions 9*bbb1b6f9SApple OSS Distributions## UUID ↔ buffer data mapping 10*bbb1b6f9SApple OSS Distributions 11*bbb1b6f9SApple OSS DistributionsAll clients who adopt this infrastructure will have to use a UUID that maps to a format of the buffer data. Clients will have to provide a mapping that specifies how to decode the data. This mapping will be used to decode the data in DumpPanic or a tool integrated into MPT. 12*bbb1b6f9SApple OSS Distributions 13*bbb1b6f9SApple OSS Distributions## IOKit APIs 14*bbb1b6f9SApple OSS Distributions 15*bbb1b6f9SApple OSS DistributionsSource Code: `iokit/IOKit/IOExtensiblePaniclog.h` 16*bbb1b6f9SApple OSS Distributions 17*bbb1b6f9SApple OSS Distributions```c 18*bbb1b6f9SApple OSS Distributionsstatic bool createWithUUID(uuid_t uuid, const char *data_id, uint32_t max_len, ext_paniclog_create_options_t options, IOExtensiblePaniclog **out); 19*bbb1b6f9SApple OSS Distributions``` 20*bbb1b6f9SApple OSS Distributions 21*bbb1b6f9SApple OSS DistributionsThis is the first API that is called by a kext to initialize an IOExtensiblePaniclog instance. It takes a UUID, data_id, max len, and options as input and emits an instance in the out pointer. The data id takes a short description of the buffer and the maximum length is 32 bytes. 22*bbb1b6f9SApple OSS Distributions 23*bbb1b6f9SApple OSS Distributions```c 24*bbb1b6f9SApple OSS Distributionsint setActive(); 25*bbb1b6f9SApple OSS Distributionsint setInactive(); 26*bbb1b6f9SApple OSS Distributions``` 27*bbb1b6f9SApple OSS Distributions 28*bbb1b6f9SApple OSS DistributionsThese functions are called to make an IOExtensiblePaniclog instance active or inactive. An instance is collected and put into the panic file only if it's active. It's ignored in the panic path if it's inactive. 29*bbb1b6f9SApple OSS Distributions 30*bbb1b6f9SApple OSS Distributions```c 31*bbb1b6f9SApple OSS Distributionsint insertData(void *addr, uint32_t len); 32*bbb1b6f9SApple OSS Distributions``` 33*bbb1b6f9SApple OSS Distributions 34*bbb1b6f9SApple OSS DistributionsThis function inserts the data pointed to by addr into the IOExtensiblePaniclog instance. It will copy the data into the buffer from offset 0. 35*bbb1b6f9SApple OSS Distributions 36*bbb1b6f9SApple OSS Distributions```c 37*bbb1b6f9SApple OSS Distributionsint appendData(void *addr, uint32_t len); 38*bbb1b6f9SApple OSS Distributions``` 39*bbb1b6f9SApple OSS Distributions 40*bbb1b6f9SApple OSS DistributionsThis function appends the data pointed to by addr into the IOExtensiblePaniclog instance. It will position the data after the previous insert or append. 41*bbb1b6f9SApple OSS Distributions 42*bbb1b6f9SApple OSS Distributions```c 43*bbb1b6f9SApple OSS Distributionsvoid *claimBuffer(); 44*bbb1b6f9SApple OSS Distributions``` 45*bbb1b6f9SApple OSS Distributions 46*bbb1b6f9SApple OSS DistributionsThis function returns the buffer of the IOExtensiblePaniclog instance. This function also sets the used length of the handle to the max length. The entire buffer is copied out when the system panic after this function call. yieldBuffer() has to be called before using insertData() or appendData(). 47*bbb1b6f9SApple OSS Distributions 48*bbb1b6f9SApple OSS Distributions```c 49*bbb1b6f9SApple OSS Distributionsint yieldBuffer(uint32_t used_len); 50*bbb1b6f9SApple OSS Distributions``` 51*bbb1b6f9SApple OSS Distributions 52*bbb1b6f9SApple OSS DistributionsThis function is called to yield the buffer and set the used_len for the buffer. 53*bbb1b6f9SApple OSS Distributions 54*bbb1b6f9SApple OSS Distributions```c 55*bbb1b6f9SApple OSS Distributionsint setUsedLen(uint32_t used_len) 56*bbb1b6f9SApple OSS Distributions``` 57*bbb1b6f9SApple OSS Distributions 58*bbb1b6f9SApple OSS DistributionsThis function is called to set the used len of the buffer. 59*bbb1b6f9SApple OSS Distributions 60*bbb1b6f9SApple OSS Distributions## DriverKit APIs 61*bbb1b6f9SApple OSS Distributions 62*bbb1b6f9SApple OSS DistributionsSource Code: `iokit/DriverKit/IOExtensiblePaniclog.iig` 63*bbb1b6f9SApple OSS Distributions 64*bbb1b6f9SApple OSS Distributions```cpp 65*bbb1b6f9SApple OSS Distributionsstatic kern_return_t Create(OSData *uuid, OSString *data_id, uint32_t max_len, IOExtensiblePaniclog **out); 66*bbb1b6f9SApple OSS Distributions``` 67*bbb1b6f9SApple OSS Distributions 68*bbb1b6f9SApple OSS DistributionsThis is first API that is called by a dext to initialize an IOExtensiblePaniclog instance. It takes a UUID, data_id and the max len as input and emits an instance in the out pointer. The data id takes a short description of the buffer and the maximum length is 32 bytes. 69*bbb1b6f9SApple OSS Distributions 70*bbb1b6f9SApple OSS Distributions```cpp 71*bbb1b6f9SApple OSS Distributionskern_return_t SetActive(); 72*bbb1b6f9SApple OSS Distributionskern_return_t SetInactive(); 73*bbb1b6f9SApple OSS Distributions``` 74*bbb1b6f9SApple OSS Distributions 75*bbb1b6f9SApple OSS DistributionsThese functions are called to make an IOExtensiblePaniclog instance active or inactive. An instance is collected and put into the panic file only if it's active. It's ignored in the panic path if it's inactive. 76*bbb1b6f9SApple OSS Distributions 77*bbb1b6f9SApple OSS Distributions```cpp 78*bbb1b6f9SApple OSS Distributionskern_return_t InsertData(OSData *data); 79*bbb1b6f9SApple OSS Distributions``` 80*bbb1b6f9SApple OSS Distributions 81*bbb1b6f9SApple OSS DistributionsThis function inserts the data pointed to by addr into the IOExtensiblePaniclog instance. It will copy the data into the buffer from offset 0. 82*bbb1b6f9SApple OSS Distributions 83*bbb1b6f9SApple OSS Distributions```cpp 84*bbb1b6f9SApple OSS Distributionskern_return_t AppendData(OSData *data); 85*bbb1b6f9SApple OSS Distributions``` 86*bbb1b6f9SApple OSS Distributions 87*bbb1b6f9SApple OSS DistributionsThis function appends the data pointed to by addr into the IOExtensiblePaniclog instance. It will position the data after the previous insert or append. 88*bbb1b6f9SApple OSS Distributions 89*bbb1b6f9SApple OSS Distributions```cpp 90*bbb1b6f9SApple OSS Distributionskern_return_t ClaimBuffer(uint64_t *addr, uint64_t *len); 91*bbb1b6f9SApple OSS Distributions``` 92*bbb1b6f9SApple OSS Distributions 93*bbb1b6f9SApple OSS DistributionsThis function is called to get a pointer to the ext paniclog buffer. After this function is called, the user is responsible for copying data into the buffer. The entire buffer is copied when a system panics. After claiming the buffer, YieldBuffer() has to be called to set the used_len of the buffer before calling InsertData() or AppendData(). 94*bbb1b6f9SApple OSS Distributions 95*bbb1b6f9SApple OSS Distributions```cpp 96*bbb1b6f9SApple OSS Distributionskern_return_t YieldBuffer(uint32_t used_len); 97*bbb1b6f9SApple OSS Distributions``` 98*bbb1b6f9SApple OSS Distributions 99*bbb1b6f9SApple OSS DistributionsThis function is called to yield the buffer and set the used_len for the buffer. 100*bbb1b6f9SApple OSS Distributions 101*bbb1b6f9SApple OSS Distributions```cpp 102*bbb1b6f9SApple OSS Distributionskern_return_t SetUsedLen(uint32_t used_len); 103*bbb1b6f9SApple OSS Distributions``` 104*bbb1b6f9SApple OSS Distributions 105*bbb1b6f9SApple OSS DistributionsThis function is called to set the used len of the buffer. 106*bbb1b6f9SApple OSS Distributions 107*bbb1b6f9SApple OSS Distributions## Low-Level Kernel APIs 108*bbb1b6f9SApple OSS Distributions 109*bbb1b6f9SApple OSS DistributionsSource Code: `osfmk/kern/ext_paniclog.h` 110*bbb1b6f9SApple OSS Distributions 111*bbb1b6f9SApple OSS Distributions### ExtensiblePaniclog Handle Struct 112*bbb1b6f9SApple OSS Distributions 113*bbb1b6f9SApple OSS Distributions```c 114*bbb1b6f9SApple OSS Distributionstypedef struct ext_paniclog_handle { 115*bbb1b6f9SApple OSS Distributions LIST_ENTRY(ext_paniclog_handle) handles; 116*bbb1b6f9SApple OSS Distributions uuid_t uuid; 117*bbb1b6f9SApple OSS Distributions char data_id[MAX_DATA_ID_SIZE]; 118*bbb1b6f9SApple OSS Distributions void *buf_addr; 119*bbb1b6f9SApple OSS Distributions uint32_t max_len; 120*bbb1b6f9SApple OSS Distributions uint32_t used_len; 121*bbb1b6f9SApple OSS Distributions ext_paniclog_create_options_t options; 122*bbb1b6f9SApple OSS Distributions ext_paniclog_flags_t flags; 123*bbb1b6f9SApple OSS Distributions uint8_t active; 124*bbb1b6f9SApple OSS Distributions} ext_paniclog_handle_t; 125*bbb1b6f9SApple OSS Distributions``` 126*bbb1b6f9SApple OSS Distributions 127*bbb1b6f9SApple OSS DistributionsWe employ handles in XNU to guarantee the effective management of buffer lifecycles, prevent nested panics from occurring during access from the panic path, and build a durable and expandable API. The primary reason for using handles is to allow XNU to oversee the entire buffer lifecycle. By keeping track of the buffer's state and managing its deallocation, we can avoid potential issues that may arise during panic scenarios. 128*bbb1b6f9SApple OSS Distributions 129*bbb1b6f9SApple OSS Distributions```c 130*bbb1b6f9SApple OSS Distributionsext_paniclog_handle_t *ext_paniclog_handle_alloc_with_uuid(uuid_t uuid, const char *data_id, uint32_t max_len, ext_paniclog_create_options_t); 131*bbb1b6f9SApple OSS Distributions``` 132*bbb1b6f9SApple OSS Distributions 133*bbb1b6f9SApple OSS DistributionsThis function will be called to initialize a buffer of the specified length. For all subsequent operations we use this handle as input. It takes a UUID, data_id, max len, and options as input and emits an instance in the out pointer. The data id takes a short description of the buffer and the maximum length is 32 bytes. This function will return a handle on success and NULL on failure. 134*bbb1b6f9SApple OSS Distributions 135*bbb1b6f9SApple OSS Distributions```c 136*bbb1b6f9SApple OSS Distributionsint ext_paniclog_handle_set_active(ext_paniclog_handle_t *handle); 137*bbb1b6f9SApple OSS Distributions``` 138*bbb1b6f9SApple OSS Distributions 139*bbb1b6f9SApple OSS DistributionsThis function sets the handle as active. In active state, this buffer will get picked up by the panic path and put into the panic file. 140*bbb1b6f9SApple OSS Distributions 141*bbb1b6f9SApple OSS Distributions```c 142*bbb1b6f9SApple OSS Distributionsint ext_paniclog_handle_set_inactive(ext_paniclog_handle_t *handle); 143*bbb1b6f9SApple OSS Distributions``` 144*bbb1b6f9SApple OSS Distributions 145*bbb1b6f9SApple OSS DistributionsThis function sets the handle as inactive. 146*bbb1b6f9SApple OSS Distributions 147*bbb1b6f9SApple OSS Distributions```c 148*bbb1b6f9SApple OSS Distributionsvoid ext_paniclog_handle_free(ext_paniclog_handle_t *handle) 149*bbb1b6f9SApple OSS Distributions``` 150*bbb1b6f9SApple OSS Distributions 151*bbb1b6f9SApple OSS DistributionsThis functions deallocates all the memory that is allocated in the alloc function. The handle has to a be a valid and this function should only be called after handle_alloc is called. 152*bbb1b6f9SApple OSS Distributions 153*bbb1b6f9SApple OSS Distributions```c 154*bbb1b6f9SApple OSS Distributionsint ext_paniclog_insert_data(ext_paniclog_handle_t *handle, void *addr, size_t len) 155*bbb1b6f9SApple OSS Distributions``` 156*bbb1b6f9SApple OSS Distributions 157*bbb1b6f9SApple OSS DistributionsThis function is called to insert the data from a buffer to the handle buffer. This function will take a handle that has been previously allocated, an address to the buffer and length of the buffer. This function will return 0 on success and a negative value on failure. 158*bbb1b6f9SApple OSS Distributions 159*bbb1b6f9SApple OSS Distributions```c 160*bbb1b6f9SApple OSS Distributionsint ext_paniclog_append_data(ext_paniclog_handle_t *handle, void *addr, uint32_t len); 161*bbb1b6f9SApple OSS Distributions``` 162*bbb1b6f9SApple OSS Distributions 163*bbb1b6f9SApple OSS DistributionsThis function is called to append to the data that is already present in the buffer. 164*bbb1b6f9SApple OSS Distributions 165*bbb1b6f9SApple OSS Distributions```c 166*bbb1b6f9SApple OSS Distributionsvoid *ext_paniclog_get_buffer(ext_paniclog_handle_t *handle) 167*bbb1b6f9SApple OSS Distributions``` 168*bbb1b6f9SApple OSS Distributions 169*bbb1b6f9SApple OSS DistributionsThis function is called to get a pointer to the ext paniclog buffer. To modify the buffer after getting the pointer use the `ext_paniclog_claim_buffer()`. 170*bbb1b6f9SApple OSS Distributions 171*bbb1b6f9SApple OSS Distributions```c 172*bbb1b6f9SApple OSS Distributionsvoid *ext_paniclog_claim_buffer(ext_paniclog_handle_t *handle); 173*bbb1b6f9SApple OSS Distributions``` 174*bbb1b6f9SApple OSS Distributions 175*bbb1b6f9SApple OSS DistributionsThis function is called to get a pointer to the ext paniclog buffer. After this function is called, the user is responsible for copying data into the buffer. The entire buffer is copied when a system panics. After claiming the buffer, `ext_paniclog_yield_buffer()` has to be called to set the `used_len` of the buffer before calling `ext_paniclog_insert_data()` or `ext_paniclog_append_data()`. 176*bbb1b6f9SApple OSS Distributions 177*bbb1b6f9SApple OSS Distributions```c 178*bbb1b6f9SApple OSS Distributionsint ext_paniclog_yield_buffer(ext_paniclog_handle_t *handle, uint32_t used_len); 179*bbb1b6f9SApple OSS Distributions``` 180*bbb1b6f9SApple OSS Distributions 181*bbb1b6f9SApple OSS DistributionsThis function is called to yield the buffer and set the used_len for the buffer. 182*bbb1b6f9SApple OSS Distributions 183*bbb1b6f9SApple OSS Distributions```c 184*bbb1b6f9SApple OSS Distributionsint ext_paniclog_set_used_len(ext_paniclog_handle_t *handle, uint32_t used_len); 185*bbb1b6f9SApple OSS Distributions``` 186*bbb1b6f9SApple OSS Distributions 187*bbb1b6f9SApple OSS DistributionsThis function is called to set the used len of the buffer. 188*bbb1b6f9SApple OSS Distributions 189*bbb1b6f9SApple OSS Distributions## panic_with_data APIs 190*bbb1b6f9SApple OSS Distributions 191*bbb1b6f9SApple OSS Distributions```c 192*bbb1b6f9SApple OSS Distributionsvoid panic_with_data(uuid_t uuid, void *addr, uint32_t len, uint64_t debugger_options_mask, const char *format, ...); 193*bbb1b6f9SApple OSS Distributions``` 194*bbb1b6f9SApple OSS Distributions 195*bbb1b6f9SApple OSS DistributionsThis function is called when a kernel client is panicking and wants to insert the data into the extensible panic log. We treat this as a special case and put this data at the start of the extensible panic log region. The client has to supply the UUID to decode the buffer that is pushed to the paniclog. 196*bbb1b6f9SApple OSS Distributions 197*bbb1b6f9SApple OSS Distributions```c 198*bbb1b6f9SApple OSS Distributionsint panic_with_data(char *uuid, void *addr, uint32_t len, uint32_t flags, const char *msg); 199*bbb1b6f9SApple OSS Distributions``` 200*bbb1b6f9SApple OSS Distributions 201*bbb1b6f9SApple OSS DistributionsThis provides the same functionality as panic_with_data() for userspace clients. 202*bbb1b6f9SApple OSS Distributions 203*bbb1b6f9SApple OSS Distributions## Special Options 204*bbb1b6f9SApple OSS Distributions 205*bbb1b6f9SApple OSS Distributions### `EXT_PANICLOG_OPTIONS_ADD_SEPARATE_KEY` 206*bbb1b6f9SApple OSS Distributions 207*bbb1b6f9SApple OSS DistributionsIf the `EXT_PANICLOG_OPTIONS_ADD_SEPARATE_KEY` option is set when creating an ExtensiblePaniclog handle, the Data ID / buffer data (key / value) pair will be added directly to the paniclog instead of under the "ExtensiblePaniclog" key. 208*bbb1b6f9SApple OSS Distributions 209*bbb1b6f9SApple OSS Distributions## Implementation 210*bbb1b6f9SApple OSS Distributions 211*bbb1b6f9SApple OSS Distributions### Estimating the panic log size 212*bbb1b6f9SApple OSS Distributions 213*bbb1b6f9SApple OSS DistributionsWe want to add the utilization metrics of the panic log to the panic.ips file. This will give us an idea of the percentage of the panic log we currently use and how big each section in the panic log is. We will use this data to estimate how big the other log section usually is and ensure that we leave enough space for this section when inserting the extensible panic log. We will cut off the extensible panic log if we cannot fit all the buffers into the free region. 214*bbb1b6f9SApple OSS Distributions 215*bbb1b6f9SApple OSS Distributions### Registering a buffer + Writing data to the buffer 216*bbb1b6f9SApple OSS Distributions 217*bbb1b6f9SApple OSS DistributionsWe have APIs exposed at different layers so that a client can use whatever suits it best. In DriverKit and IOKit cases, they call the `createWithUUID` or `Create` methods to create an IOExtensiblePaniclog instance and use that instance to insert or append data to a buffer. 218*bbb1b6f9SApple OSS Distributions 219*bbb1b6f9SApple OSS DistributionsLower level clients use `ext_paniclog_handle_alloc_with_uuid` to allocate a handle and use that handle to insert data using `ext_paniclog_insert_data` and `ext_paniclog_append_data` functions. 220*bbb1b6f9SApple OSS Distributions 221*bbb1b6f9SApple OSS DistributionsWhen a kernel client is panicking, it has the option to call `panic_with_data()`, which just takes a UUID, buffer address and length. This API makes sure that we copy this data in to the extensible panic log. 222*bbb1b6f9SApple OSS Distributions 223*bbb1b6f9SApple OSS Distributions### Insert data into the extended panic log 224*bbb1b6f9SApple OSS Distributions 225*bbb1b6f9SApple OSS DistributionsCurrent structure of the panic log is as follows: 226*bbb1b6f9SApple OSS Distributions 227*bbb1b6f9SApple OSS Distributions``` 228*bbb1b6f9SApple OSS Distributions------------------------- 229*bbb1b6f9SApple OSS Distributions- Panic Header - 230*bbb1b6f9SApple OSS Distributions------------------------- 231*bbb1b6f9SApple OSS Distributions- - 232*bbb1b6f9SApple OSS Distributions- Panic Log - 233*bbb1b6f9SApple OSS Distributions- - 234*bbb1b6f9SApple OSS Distributions------------------------- 235*bbb1b6f9SApple OSS Distributions- - 236*bbb1b6f9SApple OSS Distributions- Stack shots - 237*bbb1b6f9SApple OSS Distributions- - 238*bbb1b6f9SApple OSS Distributions------------------------- 239*bbb1b6f9SApple OSS Distributions- - 240*bbb1b6f9SApple OSS Distributions- Other Log - 241*bbb1b6f9SApple OSS Distributions- - 242*bbb1b6f9SApple OSS Distributions------------------------- 243*bbb1b6f9SApple OSS Distributions- Misc Data - 244*bbb1b6f9SApple OSS Distributions------------------------- 245*bbb1b6f9SApple OSS Distributions- - 246*bbb1b6f9SApple OSS Distributions- - 247*bbb1b6f9SApple OSS Distributions- Free - 248*bbb1b6f9SApple OSS Distributions- - 249*bbb1b6f9SApple OSS Distributions- - 250*bbb1b6f9SApple OSS Distributions------------------------- 251*bbb1b6f9SApple OSS Distributions``` 252*bbb1b6f9SApple OSS Distributions 253*bbb1b6f9SApple OSS DistributionsWe want to use the free part of the panic log to insert the extensible panic log. After we insert the stackshots, we calculate and see how much space we have in the panic log to insert the extensible panic log. These calculations will use the data that we collect from our utilization metrics and leave out space for the other log section. We then go through the ext_paniclog linked list and start inserting the buffers into the panic log region until we fill out size we calculated. After this, we move onto inserting data into the other log section. 254*bbb1b6f9SApple OSS Distributions 255*bbb1b6f9SApple OSS Distributions## Format / structure of the extensible panic log: 256*bbb1b6f9SApple OSS Distributions 257*bbb1b6f9SApple OSS Distributions``` 258*bbb1b6f9SApple OSS Distributions+---------+------------+---------+---------+------------+------------+---------+---------+---------+-----------+------------+----------+ 259*bbb1b6f9SApple OSS Distributions| | | | | | | | | | | | | 260*bbb1b6f9SApple OSS Distributions|Version | No of logs | UUID 1 | Flags 1 | Data ID 1 | Data len 1 | Data 1 | UUID 2 | Flags 2 | Data ID 2 | Data len 2 | Data 2 | 261*bbb1b6f9SApple OSS Distributions| | | | | | | | | | | | | 262*bbb1b6f9SApple OSS Distributions+---------+------------+---------+---------+------------+------------+---------+---------+---------+-----------+------------+----------+ 263*bbb1b6f9SApple OSS Distributions``` 264*bbb1b6f9SApple OSS Distributions 265*bbb1b6f9SApple OSS Distributions## Extract and format the extensible panic log into the panic.ips file 266*bbb1b6f9SApple OSS Distributions 267*bbb1b6f9SApple OSS DistributionsIn DumpPanic, we will extract this data from the panic log region and format it to be readable. We can group the data according to uuid and sort it with the data_id of the data. An example of the extensible panic log data in the panic.ips file shown below. 268*bbb1b6f9SApple OSS Distributions 269*bbb1b6f9SApple OSS Distributions``` 270*bbb1b6f9SApple OSS Distributions{ 271*bbb1b6f9SApple OSS Distributions "ExtensiblePanicLog": { 272*bbb1b6f9SApple OSS Distributions "<UUID_1>": [ 273*bbb1b6f9SApple OSS Distributions { 274*bbb1b6f9SApple OSS Distributions "DataID": "0x1" 275*bbb1b6f9SApple OSS Distributions "data" : <buffer1> 276*bbb1b6f9SApple OSS Distributions }, 277*bbb1b6f9SApple OSS Distributions { 278*bbb1b6f9SApple OSS Distributions "DataID": "0x2" 279*bbb1b6f9SApple OSS Distributions "data" : <buffer2> 280*bbb1b6f9SApple OSS Distributions } 281*bbb1b6f9SApple OSS Distributions ], 282*bbb1b6f9SApple OSS Distributions "<UUID_2>": [ 283*bbb1b6f9SApple OSS Distributions { 284*bbb1b6f9SApple OSS Distributions "DataID": "0x1" 285*bbb1b6f9SApple OSS Distributions "data" : <buffer1> 286*bbb1b6f9SApple OSS Distributions }, 287*bbb1b6f9SApple OSS Distributions { 288*bbb1b6f9SApple OSS Distributions "DataID": "0x2" 289*bbb1b6f9SApple OSS Distributions "data" : <buffer2> 290*bbb1b6f9SApple OSS Distributions } 291*bbb1b6f9SApple OSS Distributions ], 292*bbb1b6f9SApple OSS Distributions }, 293*bbb1b6f9SApple OSS Distributions "SeparateFieldDataID1": "Separate buffer value here 1", 294*bbb1b6f9SApple OSS Distributions "SeparateFieldDataID2": "Separate buffer value here 2", 295*bbb1b6f9SApple OSS Distributions} 296*bbb1b6f9SApple OSS Distributions``` 297*bbb1b6f9SApple OSS Distributions 298*bbb1b6f9SApple OSS DistributionsNotice that there are two fields below ExtensiblePanicLog in the panic.ips example above. If you were to pass the option `EXT_PANICLOG_CREATE_OPTIONS_ADD_SEPARATE_KEY` to the handle create function, DumpPanic would process that handle as seen above, by adding it as a field directly to the panic file instead of including it in the ExtensiblePanicLog field. 299*bbb1b6f9SApple OSS Distributions 300*bbb1b6f9SApple OSS Distributions## Example code 301*bbb1b6f9SApple OSS Distributions 302*bbb1b6f9SApple OSS Distributions### IOKit Example 303*bbb1b6f9SApple OSS Distributions 304*bbb1b6f9SApple OSS Distributions#### Creating the handle 305*bbb1b6f9SApple OSS Distributions 306*bbb1b6f9SApple OSS Distributions```c 307*bbb1b6f9SApple OSS Distributionschar uuid_string_1[] = "E2070C7E-A1C3-41DF-ABA4-B9921DACCD87"; 308*bbb1b6f9SApple OSS Distributionsbool res; 309*bbb1b6f9SApple OSS Distributionskern_return_t ret; 310*bbb1b6f9SApple OSS Distributions 311*bbb1b6f9SApple OSS Distributionsuuid_t uuid_1; 312*bbb1b6f9SApple OSS Distributionsuuid_parse(uuid_string_1, uuid_1); 313*bbb1b6f9SApple OSS Distributions 314*bbb1b6f9SApple OSS Distributionsres = IOExtensiblePaniclog::createWithUUID(uuid_1, "Lha ops 1", 1024, EXT_PANICLOG_OPTIONS_NONE, &paniclog_handle_1); 315*bbb1b6f9SApple OSS Distributionsif (res == false) { 316*bbb1b6f9SApple OSS Distributions DEBUG_LOG ("Failed to create ext paniclog handle: %d\n", res); 317*bbb1b6f9SApple OSS Distributions} 318*bbb1b6f9SApple OSS Distributions 319*bbb1b6f9SApple OSS DistributionsDEBUG_LOG("Created panic log handle 1 with UUID: %s\n", uuid_string_1); 320*bbb1b6f9SApple OSS Distributions 321*bbb1b6f9SApple OSS Distributionschar uuid_string_2[] = "28245A8F-04CA-4932-8A38-E6C159FD9C92"; 322*bbb1b6f9SApple OSS Distributionsuuid_t uuid_2; 323*bbb1b6f9SApple OSS Distributionsuuid_parse(uuid_string_2, uuid_2); 324*bbb1b6f9SApple OSS Distributionsres = IOExtensiblePaniclog::createWithUUID(uuid_2, "Lha ops 2", 1024, EXT_PANICLOG_OPTIONS_NONE, &paniclog_handle_2); 325*bbb1b6f9SApple OSS Distributionsif (res == false) { 326*bbb1b6f9SApple OSS Distributions DEBUG_LOG ("Failed to create ext paniclog handle: %d\n", res); 327*bbb1b6f9SApple OSS Distributions} 328*bbb1b6f9SApple OSS Distributions 329*bbb1b6f9SApple OSS DistributionsDEBUG_LOG("Created panic log handle 2 with UUID: %s\n", uuid_string_2); 330*bbb1b6f9SApple OSS Distributions``` 331*bbb1b6f9SApple OSS Distributions 332*bbb1b6f9SApple OSS Distributions#### Inserting the data 333*bbb1b6f9SApple OSS Distributions 334*bbb1b6f9SApple OSS Distributions```c 335*bbb1b6f9SApple OSS DistributionsDEBUG_LOG ("%s\n", __FUNCTION__); 336*bbb1b6f9SApple OSS Distributionschar buff[1024] = {0}; 337*bbb1b6f9SApple OSS Distributionssnprintf(buff, 1024, "HW access Dir: %u Type: %u Address: %llu\n", input->direction, input->type, input->address); 338*bbb1b6f9SApple OSS Distributions 339*bbb1b6f9SApple OSS Distributionschar buff1[1024] = {0}; 340*bbb1b6f9SApple OSS Distributions 341*bbb1b6f9SApple OSS Distributionspaniclog_handle_1->insertData(buff, (uint32_t)strlen(buff)); 342*bbb1b6f9SApple OSS Distributionspaniclog_handle_1->setActive(); 343*bbb1b6f9SApple OSS Distributions 344*bbb1b6f9SApple OSS Distributionspaniclog_handle_2->insertData(input, sizeof(HardwareAccessParameters)); 345*bbb1b6f9SApple OSS Distributionspaniclog_handle_2->setActive(); 346*bbb1b6f9SApple OSS Distributions``` 347*bbb1b6f9SApple OSS Distributions 348*bbb1b6f9SApple OSS Distributions### DriverKit Example 349*bbb1b6f9SApple OSS Distributions 350*bbb1b6f9SApple OSS Distributions#### Creating the handle 351*bbb1b6f9SApple OSS Distributions 352*bbb1b6f9SApple OSS Distributions```cpp 353*bbb1b6f9SApple OSS DistributionsOSData *uuid_data = OSData::withBytes(&uuid_3[0], sizeof(uuid_t)); 354*bbb1b6f9SApple OSS Distributionsif (!uuid_data) { 355*bbb1b6f9SApple OSS Distributions IOLog("Data was not created\n"); 356*bbb1b6f9SApple OSS Distributions return NULL; 357*bbb1b6f9SApple OSS Distributions} 358*bbb1b6f9SApple OSS Distributions 359*bbb1b6f9SApple OSS DistributionsOSString *data_id = OSString::withCString("DriverKit OP 1"); 360*bbb1b6f9SApple OSS Distributions 361*bbb1b6f9SApple OSS Distributionsret = IOExtensiblePaniclog::Create(uuid_data, data_id, 64, kIOExtensiblePaniclogOptionsNone, &paniclog_handle_3); 362*bbb1b6f9SApple OSS Distributionsif (ret != kIOReturnSuccess) { 363*bbb1b6f9SApple OSS Distributions IOLog("Failed to create paniclog handle 3\n"); 364*bbb1b6f9SApple OSS Distributions return NULL; 365*bbb1b6f9SApple OSS Distributions} 366*bbb1b6f9SApple OSS DistributionsIOLog("EXT_PANICLOG: Created panic log handle 3 with UUID: %s\n", uuid_string_3); 367*bbb1b6f9SApple OSS Distributions``` 368*bbb1b6f9SApple OSS Distributions 369*bbb1b6f9SApple OSS Distributions#### Inserting the data 370*bbb1b6f9SApple OSS Distributions 371*bbb1b6f9SApple OSS Distributions```cpp 372*bbb1b6f9SApple OSS Distributionsret = paniclog_handle_3->ClaimBuffer(&addr, &len); 373*bbb1b6f9SApple OSS Distributionsif (ret != kIOReturnSuccess) { 374*bbb1b6f9SApple OSS Distributions IOLog("EXT_PANICLOG: Failed to claim buffer. Ret: %x\n", ret); 375*bbb1b6f9SApple OSS Distributions return NULL; 376*bbb1b6f9SApple OSS Distributions} 377*bbb1b6f9SApple OSS Distributions 378*bbb1b6f9SApple OSS DistributionsIOLog("EXT_PANICLOG: Got buffer address %llu, %llu", addr, len); 379*bbb1b6f9SApple OSS Distributions 380*bbb1b6f9SApple OSS Distributionsbuff1 = (char *)addr; 381*bbb1b6f9SApple OSS Distributions 382*bbb1b6f9SApple OSS DistributionsIOLog("EXT_PANICLOG: Ignoring write for now"); 383*bbb1b6f9SApple OSS Distributionsmemcpy(buff1, buff, strlen(buff)); 384*bbb1b6f9SApple OSS Distributions 385*bbb1b6f9SApple OSS Distributionspaniclog_handle_3->YieldBuffer((uint32_t)strlen(buff)); 386*bbb1b6f9SApple OSS Distributions 387*bbb1b6f9SApple OSS Distributionspaniclog_handle_3->SetActive(); 388*bbb1b6f9SApple OSS Distributions``` 389*bbb1b6f9SApple OSS Distributions 390