static dl_error_t dl_internal_load_type_library_defaults(dl_ctx_t dl_ctx, unsigned int first_new_type, const uint8* default_data, unsigned int default_data_size) { if( default_data_size == 0 ) return DL_ERROR_OK; if( dl_ctx->default_data != 0x0 ) return DL_ERROR_OUT_OF_DEFAULT_VALUE_SLOTS; dl_ctx->default_data = (uint8*)dl_ctx->alloc_func( default_data_size * 2, sizeof(void*), dl_ctx->alloc_ctx ); // TODO: times 2 here need to be fixed! uint8* dst = dl_ctx->default_data; // ptr-patch and convert to native for( unsigned int type_index = first_new_type; type_index < dl_ctx->type_count; ++type_index ) { union { const uint8* data_ptr; const SDLType* type_ptr; } ptr_conv; ptr_conv.data_ptr = dl_ctx->type_info_data + dl_ctx->type_lookup[type_index].offset; for( unsigned int member_index = 0; member_index < ptr_conv.type_ptr->member_count; ++member_index ) { SDLMember* member = (SDLMember*)ptr_conv.type_ptr->members + member_index; if( member->default_value_offset == DL_UINT32_MAX ) continue; dst = dl_internal_align_up( dst, member->alignment[DL_PTR_SIZE_HOST] ); uint8* src = (uint8*)default_data + member->default_value_offset; pint base_offset = pint( dst ) - pint( dl_ctx->default_data ); member->default_value_offset = uint32( base_offset ); dl_one_member_type dummy( member ); size_t needed_size; union { dl_one_member_type* one_mem_ptr; SDLType* type_ptr; } conv; conv.one_mem_ptr = &dummy; dl_internal_convert_no_header( dl_ctx, src, (unsigned char*)default_data, dst, 1337, // need to check this size ;) Should be the remainder of space in m_pDefaultInstances. &needed_size, DL_ENDIAN_LITTLE, DL_ENDIAN_HOST, DL_PTR_SIZE_32BIT, DL_PTR_SIZE_HOST, conv.type_ptr, base_offset ); SPatchedInstances patch_instances; dl_internal_patch_loaded_ptrs( dl_ctx, &patch_instances, dst, conv.type_ptr, dl_ctx->default_data, false ); dst += needed_size; } } return DL_ERROR_OK; }
void dl_internal_patch_struct_array( dl_ctx_t ctx, const dl_type_desc* type, uint8_t* array_data, uint32_t count, uintptr_t patch_distance, uintptr_t base_address, dl_patched_ptrs* patched_ptrs ) { uint32_t size = dl_internal_align_up( type->size[DL_PTR_SIZE_HOST], type->alignment[DL_PTR_SIZE_HOST] ); for( uint32_t index = 0; index < count; ++index ) { uint8_t* struct_data = array_data + index * size; dl_internal_patch_struct( ctx, type, struct_data, base_address, patch_distance, patched_ptrs ); } }
static void dl_load_txt_calc_type_size_and_align( dl_ctx_t ctx, dl_txt_read_ctx* read_state, dl_type_desc* type ) { // ... is the type already processed ... if( type->size[0] > 0 ) return; dl_load_txt_fixup_bitfield_members( ctx, type ); uint32_t size[2] = { 0, 0 }; uint32_t align[2] = { type->alignment[DL_PTR_SIZE_32BIT], type->alignment[DL_PTR_SIZE_64BIT] }; unsigned int mem_start = type->member_start; unsigned int mem_end = type->member_start + type->member_count; dl_member_desc* bitfield_group_start = 0x0; for( unsigned int member_index = mem_start; member_index < mem_end; ++member_index ) { dl_member_desc* member = ctx->member_descs + member_index; // If a member is marked as a struct it could also have been an enum that we didn't know about parse-time, patch it in that case. if( member->StorageType() == DL_TYPE_STORAGE_STRUCT ) { if( const dl_enum_desc* edesc = dl_internal_find_enum( ctx, member->type_id ) ) member->set_storage( edesc->storage ); } dl_type_atom_t atom = member->AtomType(); dl_type_storage_t storage = member->StorageType(); switch( atom ) { case DL_TYPE_ATOM_POD: case DL_TYPE_ATOM_INLINE_ARRAY: { if( atom == DL_TYPE_ATOM_INLINE_ARRAY ) { if( member->inline_array_cnt() == 0 ) { const char* enum_value_name = 0x0; uint32_t enum_value_name_len = 0; if( sizeof(void*) == 8 ) { enum_value_name = (const char*)( ( (uint64_t)member->size[0] ) | (uint64_t)member->size[1] << 32 ); enum_value_name_len = member->alignment[0]; } else { enum_value_name = (const char*)(uint64_t)member->size[0]; enum_value_name_len = member->alignment[0]; } uint64_t val; if( !dl_internal_find_enum_value_from_name( ctx, enum_value_name, (size_t)enum_value_name_len, &val ) ) dl_txt_read_failed( ctx, read_state, DL_ERROR_TXT_INVALID_ENUM_VALUE, "%s.%s is an inline array with size %.*s, but that enum value does not exist.", dl_internal_type_name( ctx, type ), dl_internal_member_name( ctx, member ), (int)enum_value_name_len, enum_value_name ); member->set_inline_array_cnt( (uint32_t)val ); } } if( storage == DL_TYPE_STORAGE_STRUCT ) { const dl_type_desc* sub_type = dl_internal_find_type( ctx, member->type_id ); if( sub_type == 0x0 ) continue; dl_load_txt_calc_type_size_and_align( ctx, read_state, (dl_type_desc*)sub_type ); member->copy_size( sub_type->size ); member->copy_align( sub_type->alignment ); } else dl_set_member_size_and_align_from_builtin( storage, member ); if( atom == DL_TYPE_ATOM_INLINE_ARRAY ) { member->size[DL_PTR_SIZE_32BIT] *= member->inline_array_cnt(); member->size[DL_PTR_SIZE_64BIT] *= member->inline_array_cnt(); } bitfield_group_start = 0x0; } break; case DL_TYPE_ATOM_ARRAY: { member->set_size( 8, 16 ); member->set_align( 4, 8 ); } break; case DL_TYPE_ATOM_BITFIELD: { if( bitfield_group_start ) { member->offset[DL_PTR_SIZE_32BIT] = bitfield_group_start->offset[DL_PTR_SIZE_32BIT]; member->offset[DL_PTR_SIZE_64BIT] = bitfield_group_start->offset[DL_PTR_SIZE_64BIT]; continue; } bitfield_group_start = member; } break; default: bitfield_group_start = 0x0; } if( type->flags & DL_TYPE_FLAG_IS_UNION ) { member->set_offset( 0, 0 ); size[DL_PTR_SIZE_32BIT] = member->size[DL_PTR_SIZE_32BIT] > size[DL_PTR_SIZE_32BIT] ? member->size[DL_PTR_SIZE_32BIT] : size[DL_PTR_SIZE_32BIT]; size[DL_PTR_SIZE_64BIT] = member->size[DL_PTR_SIZE_64BIT] > size[DL_PTR_SIZE_64BIT] ? member->size[DL_PTR_SIZE_64BIT] : size[DL_PTR_SIZE_64BIT]; } else { member->offset[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], member->alignment[DL_PTR_SIZE_32BIT] ); member->offset[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], member->alignment[DL_PTR_SIZE_64BIT] ); size[DL_PTR_SIZE_32BIT] = member->offset[DL_PTR_SIZE_32BIT] + member->size[DL_PTR_SIZE_32BIT]; size[DL_PTR_SIZE_64BIT] = member->offset[DL_PTR_SIZE_64BIT] + member->size[DL_PTR_SIZE_64BIT]; } align[DL_PTR_SIZE_32BIT] = member->alignment[DL_PTR_SIZE_32BIT] > align[DL_PTR_SIZE_32BIT] ? member->alignment[DL_PTR_SIZE_32BIT] : align[DL_PTR_SIZE_32BIT]; align[DL_PTR_SIZE_64BIT] = member->alignment[DL_PTR_SIZE_64BIT] > align[DL_PTR_SIZE_64BIT] ? member->alignment[DL_PTR_SIZE_64BIT] : align[DL_PTR_SIZE_64BIT]; } if( type->flags & DL_TYPE_FLAG_IS_UNION ) { // ... add size for the union type flag ... size[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], align[DL_PTR_SIZE_32BIT] ) + (uint32_t)sizeof(uint32_t); size[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], align[DL_PTR_SIZE_64BIT] ) + (uint32_t)sizeof(uint32_t); } type->size[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], align[DL_PTR_SIZE_32BIT] ); type->size[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], align[DL_PTR_SIZE_64BIT] ); type->alignment[DL_PTR_SIZE_32BIT] = align[DL_PTR_SIZE_32BIT]; type->alignment[DL_PTR_SIZE_64BIT] = align[DL_PTR_SIZE_64BIT]; }
static dl_error_t dl_internal_store_member( dl_ctx_t dl_ctx, const SDLMember* member, uint8* instance, CDLBinStoreContext* store_ctx ) { dl_type_t atom_type = dl_type_t(member->type & DL_TYPE_ATOM_MASK); dl_type_t storage_type = dl_type_t(member->type & DL_TYPE_STORAGE_MASK); switch ( atom_type ) { case DL_TYPE_ATOM_POD: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: { const SDLType* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); if( sub_type == 0x0 ) { dl_log_error( dl_ctx, "Could not find subtype for member %s", member->name ); return DL_ERROR_TYPE_NOT_FOUND; } dl_internal_instance_store( dl_ctx, sub_type, instance, store_ctx ); } break; case DL_TYPE_STORAGE_STR: dl_internal_store_string( instance, store_ctx ); break; case DL_TYPE_STORAGE_PTR: { uint8* data = *(uint8**)instance; pint offset = store_ctx->FindWrittenPtr( data ); if( data == 0x0 ) // Null-pointer, store pint(-1) to signal to patching! { DL_ASSERT(offset == pint(-1) && "This pointer should not have been found among the written ptrs!"); // keep the -1 in Offset and store it to ptr. } else if( offset == pint(-1) ) // has not been written yet! { pint pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); const SDLType* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); pint size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, size ); // reserve space for ptr so subdata is placed correctly store_ctx->AddWrittenPtr(data, offset); dl_internal_instance_store(dl_ctx, sub_type, data, store_ctx); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(pint) ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_INLINE_ARRAY: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); // TODO: I Guess that this is a bug! Will it fix ptrs well? break; case DL_TYPE_STORAGE_STR: { uint32 count = member->size[DL_PTR_SIZE_HOST] / sizeof(char*); for( uint32 elem = 0; elem < count; ++elem ) dl_internal_store_string( instance + (elem * sizeof(char*)), store_ctx ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_ARRAY: { pint size = 0; const SDLType* sub_type = 0x0; uint8* data_ptr = instance; uint32 count = *(uint32*)( data_ptr + sizeof(void*) ); pint offset = 0; if( count == 0 ) offset = DL_NULL_PTR_OFFSET[ DL_PTR_SIZE_HOST ]; else { pint pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: sub_type = dl_internal_find_type( dl_ctx, member->type_id ); size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); break; case DL_TYPE_STORAGE_STR: size = sizeof(void*); dl_binary_writer_align( &store_ctx->writer, size ); break; default: size = DLPodSize( member->type ); dl_binary_writer_align( &store_ctx->writer, size ); } offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, count * size ); // reserve space for array so subdata is placed correctly uint8* data = *(uint8**)data_ptr; switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: for ( unsigned int elem = 0; elem < count; ++elem ) dl_internal_instance_store( dl_ctx, sub_type, data + (elem * size), store_ctx ); break; case DL_TYPE_STORAGE_STR: for ( unsigned int elem = 0; elem < count; ++elem ) dl_internal_store_string( data + (elem * size), store_ctx ); break; default: for ( unsigned int elem = 0; elem < count; ++elem ) dl_binary_writer_write( &store_ctx->writer, data + (elem * size), size ); break; } dl_binary_writer_seek_set( &store_ctx->writer, pos ); } // make room for ptr dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(pint) ); // write count dl_binary_writer_write( &store_ctx->writer, &count, sizeof(uint32) ); } return DL_ERROR_OK; case DL_TYPE_ATOM_BITFIELD: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; default: DL_ASSERT(false && "Invalid ATOM-type!"); break; } return DL_ERROR_OK; }
static dl_error_t dl_internal_patch_loaded_ptrs( dl_ctx_t dl_ctx, SPatchedInstances* patched_instances, const uint8* instance, const SDLType* type, const uint8* base_data, bool is_member_struct ) { // TODO: Optimize this please, linear search might not be the best if many subinstances is in file! if( !is_member_struct ) { if(patched_instances->IsPatched(instance)) return DL_ERROR_OK; patched_instances->m_lpPatched.Add(instance); } for( uint32 member_index = 0; member_index < type->member_count; ++member_index ) { const SDLMember* member = type->members + member_index; const uint8* member_data = instance + member->offset[DL_PTR_SIZE_HOST]; dl_type_t atom_type = member->AtomType(); dl_type_t storage_type = member->StorageType(); switch( atom_type ) { case DL_TYPE_ATOM_POD: { switch( storage_type ) { case DL_TYPE_STORAGE_STR: dl_internal_patch_ptr( member_data, base_data ); break; case DL_TYPE_STORAGE_STRUCT: dl_internal_patch_loaded_ptrs( dl_ctx, patched_instances, member_data, dl_internal_find_type( dl_ctx, member->type_id ), base_data, true ); break; case DL_TYPE_STORAGE_PTR: { uint8** ptr = (uint8**)member_data; dl_internal_patch_ptr(member_data, base_data); if(*ptr != 0x0) dl_internal_patch_loaded_ptrs( dl_ctx, patched_instances, *ptr, dl_internal_find_type( dl_ctx, member->type_id ), base_data, false ); } break; default: // ignore break; } } break; case DL_TYPE_ATOM_ARRAY: { if( storage_type == DL_TYPE_STORAGE_STR || storage_type == DL_TYPE_STORAGE_STRUCT ) { dl_internal_patch_ptr( member_data, base_data ); const uint8* array_data = *(const uint8**)member_data; pint count = *(uint32*)( member_data + sizeof(void*) ); if( count > 0 ) { if(storage_type == DL_TYPE_STORAGE_STRUCT) { // patch sub-ptrs! const SDLType* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); pint size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); for( pint elem_offset = 0; elem_offset < count * size; elem_offset += size ) dl_internal_patch_loaded_ptrs( dl_ctx, patched_instances, array_data + elem_offset, sub_type, base_data, true ); } else { for( pint elem_offset = 0; elem_offset < count * sizeof(char*); elem_offset += sizeof(char*) ) dl_internal_patch_ptr( array_data + elem_offset, base_data ); } } } else // pod dl_internal_patch_ptr( member_data, base_data ); } break; case DL_TYPE_ATOM_INLINE_ARRAY: { if( storage_type == DL_TYPE_STORAGE_STR ) { for( pint elem_offset = 0; elem_offset < member->size[DL_PTR_SIZE_HOST]; elem_offset += sizeof(char*) ) dl_internal_patch_ptr( member_data + elem_offset, base_data ); } } break; case DL_TYPE_ATOM_BITFIELD: // ignore break; default: DL_ASSERT(false && "Unknown atom type"); break; } } return DL_ERROR_OK; }
static dl_error_t dl_internal_store_member( dl_ctx_t dl_ctx, const dl_member_desc* member, uint8_t* instance, CDLBinStoreContext* store_ctx ) { dl_type_t atom_type = dl_type_t(member->type & DL_TYPE_ATOM_MASK); dl_type_t storage_type = dl_type_t(member->type & DL_TYPE_STORAGE_MASK); switch ( atom_type ) { case DL_TYPE_ATOM_POD: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: { const dl_type_desc* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); if( sub_type == 0x0 ) { dl_log_error( dl_ctx, "Could not find subtype for member %s", dl_internal_member_name( dl_ctx, member ) ); return DL_ERROR_TYPE_NOT_FOUND; } dl_internal_instance_store( dl_ctx, sub_type, instance, store_ctx ); } break; case DL_TYPE_STORAGE_STR: dl_internal_store_string( instance, store_ctx ); break; case DL_TYPE_STORAGE_PTR: { uint8_t* data = *(uint8_t**)instance; uintptr_t offset = store_ctx->FindWrittenPtr( data ); if( data == 0x0 ) // Null-pointer, store pint(-1) to signal to patching! { DL_ASSERT(offset == (uintptr_t)-1 && "This pointer should not have been found among the written ptrs!"); // keep the -1 in Offset and store it to ptr. } else if( offset == (uintptr_t)-1 ) // has not been written yet! { uintptr_t pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); const dl_type_desc* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); uintptr_t size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, size ); // reserve space for ptr so subdata is placed correctly store_ctx->AddWrittenPtr(data, offset); dl_internal_instance_store(dl_ctx, sub_type, data, store_ctx); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(uintptr_t) ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_INLINE_ARRAY: { const dl_type_desc* sub_type = 0x0; uint32_t count = member->inline_array_cnt(); if( storage_type == DL_TYPE_STORAGE_STRUCT ) { sub_type = dl_internal_find_type(dl_ctx, member->type_id); if (sub_type == 0x0) { dl_log_error(dl_ctx, "Could not find subtype for member %s", dl_internal_member_name(dl_ctx, member)); return DL_ERROR_TYPE_NOT_FOUND; } } else if( storage_type != DL_TYPE_STORAGE_STR ) count = member->size[DL_PTR_SIZE_HOST]; dl_internal_store_array( dl_ctx, storage_type, sub_type, instance, count, 1, store_ctx ); } return DL_ERROR_OK; case DL_TYPE_ATOM_ARRAY: { uintptr_t size = 0; const dl_type_desc* sub_type = 0x0; uint8_t* data_ptr = instance; uint32_t count = *(uint32_t*)( data_ptr + sizeof(void*) ); uintptr_t offset = 0; if( count == 0 ) offset = DL_NULL_PTR_OFFSET[ DL_PTR_SIZE_HOST ]; else { uintptr_t pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: sub_type = dl_internal_find_type( dl_ctx, member->type_id ); size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); break; case DL_TYPE_STORAGE_STR: size = sizeof(void*); dl_binary_writer_align( &store_ctx->writer, size ); break; default: size = dl_pod_size( member->type ); dl_binary_writer_align( &store_ctx->writer, size ); } offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, count * size ); // reserve space for array so subdata is placed correctly uint8_t* data = *(uint8_t**)data_ptr; dl_internal_store_array( dl_ctx, storage_type, sub_type, data, count, size, store_ctx ); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } // make room for ptr dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(uintptr_t) ); // write count dl_binary_writer_write( &store_ctx->writer, &count, sizeof(uint32_t) ); } return DL_ERROR_OK; case DL_TYPE_ATOM_BITFIELD: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; default: DL_ASSERT(false && "Invalid ATOM-type!"); break; } return DL_ERROR_OK; }