1*d4514f0bSApple OSS Distributions/* 2*d4514f0bSApple OSS Distributions * Copyright (c) 2015 Apple Inc. All rights reserved. 3*d4514f0bSApple OSS Distributions * 4*d4514f0bSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5*d4514f0bSApple OSS Distributions * 6*d4514f0bSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7*d4514f0bSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8*d4514f0bSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9*d4514f0bSApple OSS Distributions * compliance with the License. The rights granted to you under the License 10*d4514f0bSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11*d4514f0bSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12*d4514f0bSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13*d4514f0bSApple OSS Distributions * terms of an Apple operating system software license agreement. 14*d4514f0bSApple OSS Distributions * 15*d4514f0bSApple OSS Distributions * Please obtain a copy of the License at 16*d4514f0bSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17*d4514f0bSApple OSS Distributions * 18*d4514f0bSApple OSS Distributions * The Original Code and all software distributed under the License are 19*d4514f0bSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20*d4514f0bSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21*d4514f0bSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22*d4514f0bSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23*d4514f0bSApple OSS Distributions * Please see the License for the specific language governing rights and 24*d4514f0bSApple OSS Distributions * limitations under the License. 25*d4514f0bSApple OSS Distributions * 26*d4514f0bSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27*d4514f0bSApple OSS Distributions */ 28*d4514f0bSApple OSS Distributions 29*d4514f0bSApple OSS Distributions#include <kcdata.h> 30*d4514f0bSApple OSS Distributions#import <Foundation/Foundation.h> 31*d4514f0bSApple OSS Distributions#import "kdd.h" 32*d4514f0bSApple OSS Distributions#import "KCDBasicTypeDescription.h" 33*d4514f0bSApple OSS Distributions#import "KCDStructTypeDescription.h" 34*d4514f0bSApple OSS Distributions#import "KCDEmbeddedBufferDescription.h" 35*d4514f0bSApple OSS Distributions 36*d4514f0bSApple OSS Distributions#define LIB_KCD_ERR_DOMAIN @"KCDataError" 37*d4514f0bSApple OSS Distributions 38*d4514f0bSApple OSS Distributions#define GEN_ERROR(code, msg) gen_error(__LINE__, code, @msg) 39*d4514f0bSApple OSS Distributions#define GEN_ERRORF(code, msg, ...) gen_error(__LINE__, code, [NSString stringWithFormat:@msg, __VA_ARGS__]) 40*d4514f0bSApple OSS Distributions 41*d4514f0bSApple OSS Distributions#define MAX_KCDATATYPE_BUFFER_SIZE 2048 42*d4514f0bSApple OSS Distributionsextern struct kcdata_type_definition * kcdata_get_typedescription(unsigned type_id, uint8_t * buffer, uint32_t buffer_size); 43*d4514f0bSApple OSS Distributions 44*d4514f0bSApple OSS DistributionsBOOL setKCDataTypeForID(uint32_t newTypeID, KCDataType *newTypeObj); 45*d4514f0bSApple OSS Distributions 46*d4514f0bSApple OSS Distributionsstatic NSError * 47*d4514f0bSApple OSS Distributionsgen_error(int line, NSInteger code, NSString *message) 48*d4514f0bSApple OSS Distributions{ 49*d4514f0bSApple OSS Distributions return [NSError errorWithDomain:LIB_KCD_ERR_DOMAIN 50*d4514f0bSApple OSS Distributions code:code 51*d4514f0bSApple OSS Distributions userInfo:@{ @"line": @(line), @"message": message }]; 52*d4514f0bSApple OSS Distributions} 53*d4514f0bSApple OSS Distributions 54*d4514f0bSApple OSS Distributionsstatic BOOL 55*d4514f0bSApple OSS Distributionsmergedict(NSMutableDictionary * container, NSDictionary * object, NSError ** error) 56*d4514f0bSApple OSS Distributions{ 57*d4514f0bSApple OSS Distributions for (id key in object) { 58*d4514f0bSApple OSS Distributions id existing = container[key]; 59*d4514f0bSApple OSS Distributions id new = object[key]; 60*d4514f0bSApple OSS Distributions if (existing) { 61*d4514f0bSApple OSS Distributions if ([existing isKindOfClass:[NSMutableArray class]] && [new isKindOfClass:[ NSArray class ]]) { 62*d4514f0bSApple OSS Distributions [existing addObjectsFromArray:new]; 63*d4514f0bSApple OSS Distributions } else { 64*d4514f0bSApple OSS Distributions if (error) { 65*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "repeated key: %@", key); 66*d4514f0bSApple OSS Distributions } 67*d4514f0bSApple OSS Distributions return FALSE; 68*d4514f0bSApple OSS Distributions } 69*d4514f0bSApple OSS Distributions } else { 70*d4514f0bSApple OSS Distributions [container setValue:new forKey:key]; 71*d4514f0bSApple OSS Distributions } 72*d4514f0bSApple OSS Distributions } 73*d4514f0bSApple OSS Distributions return TRUE; 74*d4514f0bSApple OSS Distributions} 75*d4514f0bSApple OSS Distributions 76*d4514f0bSApple OSS Distributions/*! 77*d4514f0bSApple OSS Distributions * @function getTypeFromTypeDef 78*d4514f0bSApple OSS Distributions * 79*d4514f0bSApple OSS Distributions * @abstract 80*d4514f0bSApple OSS Distributions * Build a KCDataType from a type definition. 81*d4514f0bSApple OSS Distributions * 82*d4514f0bSApple OSS Distributions * @param typeDef 83*d4514f0bSApple OSS Distributions * A pointer to kcdata_type_definition_t that specifies the type fields and has subtype definitions 84*d4514f0bSApple OSS Distributions * in the memory immediately following the type_definition. 85*d4514f0bSApple OSS Distributions * 86*d4514f0bSApple OSS Distributions * @return KCDataType * type object which can be used to parse data into dictionaries. 87*d4514f0bSApple OSS Distributions * This may return nil if it finds the data to be invalid. 88*d4514f0bSApple OSS Distributions * 89*d4514f0bSApple OSS Distributions * @discussion 90*d4514f0bSApple OSS Distributions * This routine tries to decode the typeDef structure and create either a basic type (KCDBasicTypeDescription) 91*d4514f0bSApple OSS Distributions * or a struct type. 92*d4514f0bSApple OSS Distributions */ 93*d4514f0bSApple OSS Distributionsstatic KCDataType * getTypeFromTypeDef(struct kcdata_type_definition * typeDef); 94*d4514f0bSApple OSS Distributions 95*d4514f0bSApple OSS Distributionsstatic KCDataType * 96*d4514f0bSApple OSS DistributionsgetTypeFromTypeDef(struct kcdata_type_definition * typeDef) 97*d4514f0bSApple OSS Distributions{ 98*d4514f0bSApple OSS Distributions if (typeDef == NULL) { 99*d4514f0bSApple OSS Distributions return nil; 100*d4514f0bSApple OSS Distributions } 101*d4514f0bSApple OSS Distributions NSString * kct_name = [NSString stringWithFormat:@"%s", typeDef->kct_name]; 102*d4514f0bSApple OSS Distributions if (typeDef->kct_num_elements == 1 && !(typeDef->kct_elements[0].kcs_flags & KCS_SUBTYPE_FLAGS_STRUCT)) { 103*d4514f0bSApple OSS Distributions KCDBasicTypeDescription * retval = [[KCDBasicTypeDescription alloc] initWithKCTypeDesc:&typeDef->kct_elements[0]]; 104*d4514f0bSApple OSS Distributions return retval; 105*d4514f0bSApple OSS Distributions } else { 106*d4514f0bSApple OSS Distributions KCDStructTypeDescription * retval = 107*d4514f0bSApple OSS Distributions [[KCDStructTypeDescription alloc] initWithType:typeDef->kct_type_identifier withName:kct_name]; 108*d4514f0bSApple OSS Distributions /* need to do work here to get the array of elements setup here */ 109*d4514f0bSApple OSS Distributions KCDBasicTypeDescription * curField = nil; 110*d4514f0bSApple OSS Distributions for (unsigned int i = 0; i < typeDef->kct_num_elements; i++) { 111*d4514f0bSApple OSS Distributions curField = [[KCDBasicTypeDescription alloc] initWithKCTypeDesc:&typeDef->kct_elements[i]]; 112*d4514f0bSApple OSS Distributions [retval addFieldBasicType:curField]; 113*d4514f0bSApple OSS Distributions if (typeDef->kct_elements[i].kcs_flags & KCS_SUBTYPE_FLAGS_MERGE) { 114*d4514f0bSApple OSS Distributions [retval setFlagsRequestedMerge]; 115*d4514f0bSApple OSS Distributions } 116*d4514f0bSApple OSS Distributions } 117*d4514f0bSApple OSS Distributions return retval; 118*d4514f0bSApple OSS Distributions } 119*d4514f0bSApple OSS Distributions return nil; 120*d4514f0bSApple OSS Distributions} 121*d4514f0bSApple OSS Distributions 122*d4514f0bSApple OSS Distributionsstatic dispatch_once_t onceToken; 123*d4514f0bSApple OSS Distributionsstatic NSMutableDictionary * knownTypes = nil; 124*d4514f0bSApple OSS Distributions 125*d4514f0bSApple OSS DistributionsKCDataType * 126*d4514f0bSApple OSS DistributionsgetKCDataTypeForID(uint32_t typeID) 127*d4514f0bSApple OSS Distributions{ 128*d4514f0bSApple OSS Distributions dispatch_once(&onceToken, ^{ 129*d4514f0bSApple OSS Distributions if (!knownTypes) { 130*d4514f0bSApple OSS Distributions knownTypes = [[NSMutableDictionary alloc] init]; 131*d4514f0bSApple OSS Distributions } 132*d4514f0bSApple OSS Distributions }); 133*d4514f0bSApple OSS Distributions 134*d4514f0bSApple OSS Distributions NSNumber * type = [NSNumber numberWithUnsignedInt:typeID]; 135*d4514f0bSApple OSS Distributions if (!knownTypes[type]) { 136*d4514f0bSApple OSS Distributions if (typeID == KCDATA_TYPE_NESTED_KCDATA) { 137*d4514f0bSApple OSS Distributions knownTypes[type] = [[KCDEmbeddedBufferDescription alloc] init]; 138*d4514f0bSApple OSS Distributions return knownTypes[type]; 139*d4514f0bSApple OSS Distributions } 140*d4514f0bSApple OSS Distributions /* code to query system for type information */ 141*d4514f0bSApple OSS Distributions uint8_t buffer[MAX_KCDATATYPE_BUFFER_SIZE]; 142*d4514f0bSApple OSS Distributions struct kcdata_type_definition * sys_def = kcdata_get_typedescription(typeID, buffer, MAX_KCDATATYPE_BUFFER_SIZE); 143*d4514f0bSApple OSS Distributions if (sys_def == NULL) { 144*d4514f0bSApple OSS Distributions knownTypes[type] = [[KCDBasicTypeDescription alloc] createDefaultForType:typeID]; 145*d4514f0bSApple OSS Distributions } else { 146*d4514f0bSApple OSS Distributions knownTypes[type] = getTypeFromTypeDef(sys_def); 147*d4514f0bSApple OSS Distributions } 148*d4514f0bSApple OSS Distributions } 149*d4514f0bSApple OSS Distributions assert(knownTypes[type] != nil); 150*d4514f0bSApple OSS Distributions return knownTypes[type]; 151*d4514f0bSApple OSS Distributions} 152*d4514f0bSApple OSS Distributions 153*d4514f0bSApple OSS DistributionsBOOL 154*d4514f0bSApple OSS DistributionssetKCDataTypeForID(uint32_t newTypeID, KCDataType *newTypeObj) { 155*d4514f0bSApple OSS Distributions if (newTypeObj == NULL || newTypeID == 0) { 156*d4514f0bSApple OSS Distributions return FALSE; 157*d4514f0bSApple OSS Distributions } 158*d4514f0bSApple OSS Distributions 159*d4514f0bSApple OSS Distributions dispatch_once(&onceToken, ^{ 160*d4514f0bSApple OSS Distributions if (!knownTypes) { 161*d4514f0bSApple OSS Distributions knownTypes = [[NSMutableDictionary alloc] init]; 162*d4514f0bSApple OSS Distributions } 163*d4514f0bSApple OSS Distributions }); 164*d4514f0bSApple OSS Distributions 165*d4514f0bSApple OSS Distributions NSNumber * type = [NSNumber numberWithUnsignedInt:newTypeID]; 166*d4514f0bSApple OSS Distributions 167*d4514f0bSApple OSS Distributions if (!knownTypes[type]) { 168*d4514f0bSApple OSS Distributions knownTypes[type] = newTypeObj; 169*d4514f0bSApple OSS Distributions return TRUE; 170*d4514f0bSApple OSS Distributions } 171*d4514f0bSApple OSS Distributions 172*d4514f0bSApple OSS Distributions return FALSE; 173*d4514f0bSApple OSS Distributions} 174*d4514f0bSApple OSS Distributions 175*d4514f0bSApple OSS Distributions 176*d4514f0bSApple OSS DistributionsNSString * 177*d4514f0bSApple OSS DistributionsKCDataTypeNameForID(uint32_t typeID) 178*d4514f0bSApple OSS Distributions{ 179*d4514f0bSApple OSS Distributions NSString * retval = [NSString stringWithFormat:@"%u", typeID]; 180*d4514f0bSApple OSS Distributions KCDataType * t = getKCDataTypeForID(typeID); 181*d4514f0bSApple OSS Distributions 182*d4514f0bSApple OSS Distributions if (![[t name] containsString:@"Type_"]) { 183*d4514f0bSApple OSS Distributions retval = [t name]; 184*d4514f0bSApple OSS Distributions } 185*d4514f0bSApple OSS Distributions return retval; 186*d4514f0bSApple OSS Distributions} 187*d4514f0bSApple OSS Distributions 188*d4514f0bSApple OSS DistributionsNSMutableDictionary * 189*d4514f0bSApple OSS DistributionsparseKCDataArray(kcdata_iter_t iter, NSError **error) 190*d4514f0bSApple OSS Distributions{ 191*d4514f0bSApple OSS Distributions if (!kcdata_iter_array_valid(iter)) { 192*d4514f0bSApple OSS Distributions if (error) 193*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_OBJECT, "invalid array"); 194*d4514f0bSApple OSS Distributions return NULL; 195*d4514f0bSApple OSS Distributions } 196*d4514f0bSApple OSS Distributions 197*d4514f0bSApple OSS Distributions uint32_t typeID = kcdata_iter_array_elem_type(iter); 198*d4514f0bSApple OSS Distributions uint32_t count = kcdata_iter_array_elem_count(iter); 199*d4514f0bSApple OSS Distributions uint32_t size = kcdata_iter_array_elem_size(iter); 200*d4514f0bSApple OSS Distributions uint8_t * buffer = (uint8_t *)kcdata_iter_payload(iter); 201*d4514f0bSApple OSS Distributions KCDataType * datatype = getKCDataTypeForID(typeID); 202*d4514f0bSApple OSS Distributions NSMutableDictionary * retval = [[NSMutableDictionary alloc] initWithCapacity:1]; 203*d4514f0bSApple OSS Distributions NSMutableArray * arr = [[NSMutableArray alloc] initWithCapacity:count]; 204*d4514f0bSApple OSS Distributions retval[[datatype name]] = arr; 205*d4514f0bSApple OSS Distributions NSDictionary * tmpdict = NULL; 206*d4514f0bSApple OSS Distributions for (uint32_t i = 0; i < count; i++) { 207*d4514f0bSApple OSS Distributions tmpdict = [datatype parseData:(void *)&buffer[i * size] ofLength:size]; 208*d4514f0bSApple OSS Distributions if (!tmpdict) { 209*d4514f0bSApple OSS Distributions if (error) 210*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "failed to parse array element. type=0x%x", (int)typeID); 211*d4514f0bSApple OSS Distributions return NULL; 212*d4514f0bSApple OSS Distributions } 213*d4514f0bSApple OSS Distributions if ([datatype shouldMergeData]) { 214*d4514f0bSApple OSS Distributions assert([tmpdict count] == 1); 215*d4514f0bSApple OSS Distributions [arr addObject: [tmpdict allValues][0]]; 216*d4514f0bSApple OSS Distributions } else { 217*d4514f0bSApple OSS Distributions [arr addObject:tmpdict]; 218*d4514f0bSApple OSS Distributions } 219*d4514f0bSApple OSS Distributions } 220*d4514f0bSApple OSS Distributions return retval; 221*d4514f0bSApple OSS Distributions} 222*d4514f0bSApple OSS Distributions 223*d4514f0bSApple OSS DistributionsNSMutableDictionary * 224*d4514f0bSApple OSS DistributionsparseKCDataContainer(kcdata_iter_t *iter_p, NSError **error) 225*d4514f0bSApple OSS Distributions{ 226*d4514f0bSApple OSS Distributions kcdata_iter_t iter = *iter_p; 227*d4514f0bSApple OSS Distributions 228*d4514f0bSApple OSS Distributions if (!kcdata_iter_container_valid(iter)) { 229*d4514f0bSApple OSS Distributions if (error) 230*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_OBJECT, "invalid container"); 231*d4514f0bSApple OSS Distributions return NULL; 232*d4514f0bSApple OSS Distributions } 233*d4514f0bSApple OSS Distributions uint64_t containerID = kcdata_iter_container_id(iter); 234*d4514f0bSApple OSS Distributions 235*d4514f0bSApple OSS Distributions /* setup collection object for sub containers */ 236*d4514f0bSApple OSS Distributions NSMutableDictionary * sub_containers = [[NSMutableDictionary alloc] init]; 237*d4514f0bSApple OSS Distributions NSMutableDictionary * retval = [[NSMutableDictionary alloc] init]; 238*d4514f0bSApple OSS Distributions NSMutableDictionary * container = [[NSMutableDictionary alloc] init]; 239*d4514f0bSApple OSS Distributions 240*d4514f0bSApple OSS Distributions KCDataType * tmptype; 241*d4514f0bSApple OSS Distributions uint32_t _t; 242*d4514f0bSApple OSS Distributions void * _d; 243*d4514f0bSApple OSS Distributions BOOL ok; 244*d4514f0bSApple OSS Distributions NSDictionary * tmpdict; 245*d4514f0bSApple OSS Distributions BOOL found_end = FALSE; 246*d4514f0bSApple OSS Distributions retval[KCDataTypeNameForID(kcdata_iter_container_type(iter))] = container; 247*d4514f0bSApple OSS Distributions 248*d4514f0bSApple OSS Distributions iter = kcdata_iter_next(iter); 249*d4514f0bSApple OSS Distributions 250*d4514f0bSApple OSS Distributions KCDATA_ITER_FOREACH(iter) 251*d4514f0bSApple OSS Distributions { 252*d4514f0bSApple OSS Distributions _t = kcdata_iter_type(iter); 253*d4514f0bSApple OSS Distributions _d = kcdata_iter_payload(iter); 254*d4514f0bSApple OSS Distributions if (_t == KCDATA_TYPE_CONTAINER_END) { 255*d4514f0bSApple OSS Distributions if (kcdata_iter_container_id(iter) != containerID) { 256*d4514f0bSApple OSS Distributions if (error) 257*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_ARGUMENT, "container marker mismatch"); 258*d4514f0bSApple OSS Distributions return NULL; 259*d4514f0bSApple OSS Distributions } 260*d4514f0bSApple OSS Distributions found_end = TRUE; 261*d4514f0bSApple OSS Distributions break; 262*d4514f0bSApple OSS Distributions } 263*d4514f0bSApple OSS Distributions 264*d4514f0bSApple OSS Distributions if (_t == KCDATA_TYPE_ARRAY) { 265*d4514f0bSApple OSS Distributions tmpdict = parseKCDataArray(iter, error); 266*d4514f0bSApple OSS Distributions if (!tmpdict) 267*d4514f0bSApple OSS Distributions return NULL; 268*d4514f0bSApple OSS Distributions 269*d4514f0bSApple OSS Distributions ok = mergedict(container, tmpdict, error); 270*d4514f0bSApple OSS Distributions if (!ok) 271*d4514f0bSApple OSS Distributions return NULL; 272*d4514f0bSApple OSS Distributions 273*d4514f0bSApple OSS Distributions continue; 274*d4514f0bSApple OSS Distributions } 275*d4514f0bSApple OSS Distributions 276*d4514f0bSApple OSS Distributions if (_t == KCDATA_TYPE_CONTAINER_BEGIN) { 277*d4514f0bSApple OSS Distributions NSString * subcontainerID = [NSString stringWithFormat:@"%llu", kcdata_iter_container_id(iter)]; 278*d4514f0bSApple OSS Distributions tmpdict = parseKCDataContainer(&iter, error); 279*d4514f0bSApple OSS Distributions if (!tmpdict) 280*d4514f0bSApple OSS Distributions return NULL; 281*d4514f0bSApple OSS Distributions assert([tmpdict count] == 1); 282*d4514f0bSApple OSS Distributions for (NSString * k in [tmpdict keyEnumerator]) { 283*d4514f0bSApple OSS Distributions if (sub_containers[k] == nil) { 284*d4514f0bSApple OSS Distributions sub_containers[k] = [[NSMutableDictionary alloc] init]; 285*d4514f0bSApple OSS Distributions } 286*d4514f0bSApple OSS Distributions if (sub_containers[k][subcontainerID] != nil) { 287*d4514f0bSApple OSS Distributions if (error) 288*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "repeated container id: %@", subcontainerID); 289*d4514f0bSApple OSS Distributions return NULL; 290*d4514f0bSApple OSS Distributions } 291*d4514f0bSApple OSS Distributions sub_containers[k][subcontainerID] = tmpdict[k]; 292*d4514f0bSApple OSS Distributions } 293*d4514f0bSApple OSS Distributions continue; 294*d4514f0bSApple OSS Distributions } 295*d4514f0bSApple OSS Distributions 296*d4514f0bSApple OSS Distributions tmptype = getKCDataTypeForID(_t); 297*d4514f0bSApple OSS Distributions tmpdict = [tmptype parseData:_d ofLength:kcdata_iter_size(iter)]; 298*d4514f0bSApple OSS Distributions if (!tmpdict) { 299*d4514f0bSApple OSS Distributions if (error) 300*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "failed to parse. type=0x%x", (int)_t); 301*d4514f0bSApple OSS Distributions return NULL; 302*d4514f0bSApple OSS Distributions } 303*d4514f0bSApple OSS Distributions if (![tmptype shouldMergeData]) { 304*d4514f0bSApple OSS Distributions tmpdict = @{[tmptype name] : tmpdict}; 305*d4514f0bSApple OSS Distributions } 306*d4514f0bSApple OSS Distributions ok = mergedict(container, tmpdict, error); 307*d4514f0bSApple OSS Distributions if (!ok) 308*d4514f0bSApple OSS Distributions return NULL; 309*d4514f0bSApple OSS Distributions } 310*d4514f0bSApple OSS Distributions 311*d4514f0bSApple OSS Distributions if (!found_end) { 312*d4514f0bSApple OSS Distributions if (error) 313*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_ARGUMENT, "missing container end"); 314*d4514f0bSApple OSS Distributions return NULL; 315*d4514f0bSApple OSS Distributions } 316*d4514f0bSApple OSS Distributions 317*d4514f0bSApple OSS Distributions ok = mergedict(container, sub_containers, error); 318*d4514f0bSApple OSS Distributions if (!ok) 319*d4514f0bSApple OSS Distributions return NULL; 320*d4514f0bSApple OSS Distributions 321*d4514f0bSApple OSS Distributions *iter_p = iter; 322*d4514f0bSApple OSS Distributions return retval; 323*d4514f0bSApple OSS Distributions} 324*d4514f0bSApple OSS Distributions 325*d4514f0bSApple OSS DistributionsNSDictionary * 326*d4514f0bSApple OSS DistributionsparseKCDataBuffer(void * dataBuffer, uint32_t size, NSError ** error) 327*d4514f0bSApple OSS Distributions{ 328*d4514f0bSApple OSS Distributions if (dataBuffer == NULL) { 329*d4514f0bSApple OSS Distributions if (error) 330*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_ARGUMENT, "buffer is null"); 331*d4514f0bSApple OSS Distributions return NULL; 332*d4514f0bSApple OSS Distributions } 333*d4514f0bSApple OSS Distributions 334*d4514f0bSApple OSS Distributions uint32_t _type = (size >= sizeof(uint32_t)) ? *(uint32_t*)dataBuffer : 0; 335*d4514f0bSApple OSS Distributions uint32_t _size = 0; 336*d4514f0bSApple OSS Distributions uint64_t _flags = 0; 337*d4514f0bSApple OSS Distributions void * _datap = NULL; 338*d4514f0bSApple OSS Distributions KCDataType * kcd_type = NULL; 339*d4514f0bSApple OSS Distributions NSString * rootKey = NULL; 340*d4514f0bSApple OSS Distributions uint32_t rootType = _type; 341*d4514f0bSApple OSS Distributions BOOL ok; 342*d4514f0bSApple OSS Distributions 343*d4514f0bSApple OSS Distributions /* validate begin tag and get root key */ 344*d4514f0bSApple OSS Distributions switch (_type) { 345*d4514f0bSApple OSS Distributions case KCDATA_BUFFER_BEGIN_CRASHINFO: 346*d4514f0bSApple OSS Distributions rootKey = @"kcdata_crashinfo"; 347*d4514f0bSApple OSS Distributions break; 348*d4514f0bSApple OSS Distributions case KCDATA_BUFFER_BEGIN_STACKSHOT: 349*d4514f0bSApple OSS Distributions rootKey = @"kcdata_stackshot"; 350*d4514f0bSApple OSS Distributions break; 351*d4514f0bSApple OSS Distributions case KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT: 352*d4514f0bSApple OSS Distributions rootKey = @"kcdata_delta_stackshot"; 353*d4514f0bSApple OSS Distributions break; 354*d4514f0bSApple OSS Distributions case KCDATA_BUFFER_BEGIN_OS_REASON: 355*d4514f0bSApple OSS Distributions rootKey = @"kcdata_reason"; 356*d4514f0bSApple OSS Distributions break; 357*d4514f0bSApple OSS Distributions case KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG: 358*d4514f0bSApple OSS Distributions rootKey = @"xnupost_testconfig"; 359*d4514f0bSApple OSS Distributions break; 360*d4514f0bSApple OSS Distributions default: { 361*d4514f0bSApple OSS Distributions if (error) 362*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_VALUE, "invalid magic number"); 363*d4514f0bSApple OSS Distributions return NULL; 364*d4514f0bSApple OSS Distributions break; 365*d4514f0bSApple OSS Distributions } 366*d4514f0bSApple OSS Distributions } 367*d4514f0bSApple OSS Distributions assert(rootKey != NULL); 368*d4514f0bSApple OSS Distributions 369*d4514f0bSApple OSS Distributions kcdata_iter_t iter = kcdata_iter(dataBuffer, size); 370*d4514f0bSApple OSS Distributions 371*d4514f0bSApple OSS Distributions if (!kcdata_iter_valid(iter)) { 372*d4514f0bSApple OSS Distributions if (error) { 373*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_OBJECT, "initial item is invalid"); 374*d4514f0bSApple OSS Distributions } 375*d4514f0bSApple OSS Distributions return NULL; 376*d4514f0bSApple OSS Distributions } 377*d4514f0bSApple OSS Distributions 378*d4514f0bSApple OSS Distributions NSMutableDictionary * rootObject = [NSMutableDictionary dictionary]; 379*d4514f0bSApple OSS Distributions NSDictionary * retval = [NSMutableDictionary dictionaryWithObject:rootObject forKey:rootKey]; 380*d4514f0bSApple OSS Distributions 381*d4514f0bSApple OSS Distributions /* iterate over each kcdata item */ 382*d4514f0bSApple OSS Distributions KCDATA_ITER_FOREACH(iter) 383*d4514f0bSApple OSS Distributions { 384*d4514f0bSApple OSS Distributions _type = kcdata_iter_type(iter); 385*d4514f0bSApple OSS Distributions _size = kcdata_iter_size(iter); 386*d4514f0bSApple OSS Distributions _flags = kcdata_iter_flags(iter); 387*d4514f0bSApple OSS Distributions _datap = kcdata_iter_payload(iter); 388*d4514f0bSApple OSS Distributions 389*d4514f0bSApple OSS Distributions if (_type == rootType) 390*d4514f0bSApple OSS Distributions continue; 391*d4514f0bSApple OSS Distributions 392*d4514f0bSApple OSS Distributions if (_type == KCDATA_TYPE_ARRAY) { 393*d4514f0bSApple OSS Distributions NSDictionary * dict = parseKCDataArray(iter, error); 394*d4514f0bSApple OSS Distributions if (!dict) 395*d4514f0bSApple OSS Distributions return nil; 396*d4514f0bSApple OSS Distributions 397*d4514f0bSApple OSS Distributions ok = mergedict(rootObject, dict, error); 398*d4514f0bSApple OSS Distributions if (!ok) 399*d4514f0bSApple OSS Distributions return NULL; 400*d4514f0bSApple OSS Distributions 401*d4514f0bSApple OSS Distributions continue; 402*d4514f0bSApple OSS Distributions } 403*d4514f0bSApple OSS Distributions 404*d4514f0bSApple OSS Distributions if (_type == KCDATA_TYPE_CONTAINER_BEGIN) { 405*d4514f0bSApple OSS Distributions NSString * containerID = [NSString stringWithFormat:@"%llu", kcdata_iter_container_id(iter)]; 406*d4514f0bSApple OSS Distributions NSMutableDictionary *container = parseKCDataContainer(&iter, error); 407*d4514f0bSApple OSS Distributions if (!container) 408*d4514f0bSApple OSS Distributions return nil; 409*d4514f0bSApple OSS Distributions assert([container count] == 1); 410*d4514f0bSApple OSS Distributions for (NSString * k in [container keyEnumerator]) { 411*d4514f0bSApple OSS Distributions if (rootObject[k] == nil) { 412*d4514f0bSApple OSS Distributions rootObject[k] = [[NSMutableDictionary alloc] init]; 413*d4514f0bSApple OSS Distributions } 414*d4514f0bSApple OSS Distributions if (rootObject[k][containerID] != nil) { 415*d4514f0bSApple OSS Distributions if (error) 416*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "repeated container id: %@", containerID); 417*d4514f0bSApple OSS Distributions return NULL; 418*d4514f0bSApple OSS Distributions } 419*d4514f0bSApple OSS Distributions rootObject[k][containerID] = container[k]; 420*d4514f0bSApple OSS Distributions } 421*d4514f0bSApple OSS Distributions continue; 422*d4514f0bSApple OSS Distributions } 423*d4514f0bSApple OSS Distributions 424*d4514f0bSApple OSS Distributions if (_type == KCDATA_TYPE_TYPEDEFINTION) { 425*d4514f0bSApple OSS Distributions KCDataType *new_type = getTypeFromTypeDef((struct kcdata_type_definition *)_datap); 426*d4514f0bSApple OSS Distributions if (new_type != NULL) { 427*d4514f0bSApple OSS Distributions setKCDataTypeForID([new_type typeID], new_type); 428*d4514f0bSApple OSS Distributions kcd_type = getKCDataTypeForID(_type); 429*d4514f0bSApple OSS Distributions NSDictionary * tmpdict = [kcd_type parseData:_datap ofLength:_size]; 430*d4514f0bSApple OSS Distributions if (!tmpdict) { 431*d4514f0bSApple OSS Distributions if (error) 432*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "failed to parse. type=0x%x", (int)_type); 433*d4514f0bSApple OSS Distributions return NULL; 434*d4514f0bSApple OSS Distributions } 435*d4514f0bSApple OSS Distributions NSString *k = [NSString stringWithFormat:@"typedef[%@]", [new_type name]]; 436*d4514f0bSApple OSS Distributions rootObject[k] = tmpdict; 437*d4514f0bSApple OSS Distributions }else { 438*d4514f0bSApple OSS Distributions if (error) 439*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "Failed to parse type definition for type %u", _type); 440*d4514f0bSApple OSS Distributions return NULL; 441*d4514f0bSApple OSS Distributions } 442*d4514f0bSApple OSS Distributions continue; 443*d4514f0bSApple OSS Distributions } 444*d4514f0bSApple OSS Distributions 445*d4514f0bSApple OSS Distributions kcd_type = getKCDataTypeForID(_type); 446*d4514f0bSApple OSS Distributions NSDictionary * tmpdict = [kcd_type parseData:_datap ofLength:_size]; 447*d4514f0bSApple OSS Distributions if (!tmpdict) { 448*d4514f0bSApple OSS Distributions if (error) 449*d4514f0bSApple OSS Distributions *error = GEN_ERRORF(KERN_INVALID_OBJECT, "failed to parse. type=0x%x", (int)_type); 450*d4514f0bSApple OSS Distributions return NULL; 451*d4514f0bSApple OSS Distributions } 452*d4514f0bSApple OSS Distributions if (![kcd_type shouldMergeData]) { 453*d4514f0bSApple OSS Distributions tmpdict = @{[kcd_type name] : tmpdict}; 454*d4514f0bSApple OSS Distributions } 455*d4514f0bSApple OSS Distributions ok = mergedict(rootObject, tmpdict, error); 456*d4514f0bSApple OSS Distributions if (!ok) 457*d4514f0bSApple OSS Distributions return NULL; 458*d4514f0bSApple OSS Distributions } 459*d4514f0bSApple OSS Distributions 460*d4514f0bSApple OSS Distributions if (KCDATA_ITER_FOREACH_FAILED(iter)) { 461*d4514f0bSApple OSS Distributions retval = nil; 462*d4514f0bSApple OSS Distributions if (error) { 463*d4514f0bSApple OSS Distributions *error = GEN_ERROR(KERN_INVALID_OBJECT, "invalid item or missing buffer end marker"); 464*d4514f0bSApple OSS Distributions } 465*d4514f0bSApple OSS Distributions } 466*d4514f0bSApple OSS Distributions 467*d4514f0bSApple OSS Distributions return retval; 468*d4514f0bSApple OSS Distributions} 469