dl_error_t dl_internal_convert_no_header( dl_ctx_t dl_ctx, unsigned char* packed_instance, unsigned char* packed_instance_base, unsigned char* out_instance, size_t out_instance_size, size_t* needed_size, dl_endian_t src_endian, dl_endian_t out_endian, dl_ptr_size_t src_ptr_size, dl_ptr_size_t out_ptr_size, const SDLType* root_type, size_t base_offset ) { dl_binary_writer writer; dl_binary_writer_init( &writer, out_instance, out_instance_size, out_instance == 0x0, src_endian, out_endian, out_ptr_size ); SConvertContext ConvCtx( src_endian, out_endian, src_ptr_size, out_ptr_size ); ConvCtx.m_lInstances.Add(SInstance(packed_instance, root_type, 0x0, dl_type_t(DL_TYPE_ATOM_POD | DL_TYPE_STORAGE_STRUCT))); dl_error_t err = dl_internal_convert_collect_instances(dl_ctx, root_type, packed_instance, packed_instance_base, ConvCtx); // TODO: we need to sort the instances here after their offset! SInstance* insts = ConvCtx.m_lInstances.GetBasePtr(); std::sort( insts, insts + ConvCtx.m_lInstances.Len(), dl_internal_sort_pred ); for(unsigned int i = 0; i < ConvCtx.m_lInstances.Len(); ++i) { err = dl_internal_convert_write_instance( dl_ctx, ConvCtx.m_lInstances[i], &ConvCtx.m_lInstances[i].m_OffsetAfterPatch, ConvCtx, &writer ); if(err != DL_ERROR_OK) return err; } if(out_instance != 0x0) // no need to patch data if we are only calculating size { for(unsigned int i = 0; i < ConvCtx.m_lPatchOffset.Len(); ++i) { SConvertContext::PatchPos& PP = ConvCtx.m_lPatchOffset[i]; // find new offset pint NewOffset = pint(-1); for(unsigned int j = 0; j < ConvCtx.m_lInstances.Len(); ++j ) { pint OldOffset = ConvCtx.m_lInstances[j].m_pAddress - packed_instance_base; if(OldOffset == PP.m_OldOffset) { NewOffset = ConvCtx.m_lInstances[j].m_OffsetAfterPatch; break; } } DL_ASSERT(NewOffset != pint(-1) && "We should have found the instance!"); dl_binary_writer_seek_set( &writer, PP.m_Pos ); dl_binary_writer_write_ptr( &writer, NewOffset + base_offset ); } } dl_binary_writer_seek_end( &writer ); *needed_size = (unsigned int)dl_binary_writer_tell( &writer ); return err; }
static dl_error_t dl_internal_convert_write_instance( dl_ctx_t dl_ctx, const SInstance& inst, pint* new_offset, SConvertContext& conv_ctx, dl_binary_writer* writer ) { union { const uint8* u8; const uint16* u16; const uint32* u32; const uint64* u64; const char* str; }; u8 = inst.m_pAddress; dl_binary_writer_seek_end( writer ); // place instance at the end! if(inst.m_pType != 0x0) dl_binary_writer_align( writer, inst.m_pType->alignment[conv_ctx.m_TargetPtrSize] ); *new_offset = dl_binary_writer_tell( writer ); dl_type_t AtomType = dl_type_t(inst.m_Type & DL_TYPE_ATOM_MASK); dl_type_t StorageType = dl_type_t(inst.m_Type & DL_TYPE_STORAGE_MASK); if(AtomType == DL_TYPE_ATOM_ARRAY) { switch(StorageType) { case DL_TYPE_STORAGE_STRUCT: { pint TypeSize = inst.m_pType->size[conv_ctx.m_SourcePtrSize]; for (pint ElemOffset = 0; ElemOffset < inst.m_ArrayCount * TypeSize; ElemOffset += TypeSize) { dl_error_t err = dl_internal_convert_write_struct( dl_ctx, u8 + ElemOffset, inst.m_pType, conv_ctx, writer ); if(err != DL_ERROR_OK) return err; } } break; case DL_TYPE_STORAGE_STR: { pint TypeSize = dl_internal_ptr_size(conv_ctx.m_SourcePtrSize); for(pint ElemOffset = 0; ElemOffset < inst.m_ArrayCount * TypeSize; ElemOffset += TypeSize) { pint OrigOffset = DLInternalReadPtrData(u8 + ElemOffset, conv_ctx.m_SourceEndian, conv_ctx.m_SourcePtrSize); conv_ctx.m_lPatchOffset.Add( SConvertContext::PatchPos( dl_binary_writer_tell( writer ), OrigOffset ) ); dl_binary_writer_write_ptr( writer, OrigOffset ); } } break; case DL_TYPE_STORAGE_INT8: case DL_TYPE_STORAGE_UINT8: dl_binary_writer_write_array( writer, u8, inst.m_ArrayCount, sizeof(uint8) ); break; case DL_TYPE_STORAGE_INT16: case DL_TYPE_STORAGE_UINT16: dl_binary_writer_write_array( writer, u16, inst.m_ArrayCount, sizeof(uint16) ); break; case DL_TYPE_STORAGE_INT32: case DL_TYPE_STORAGE_UINT32: case DL_TYPE_STORAGE_FP32: case DL_TYPE_STORAGE_ENUM: dl_binary_writer_write_array( writer, u32, inst.m_ArrayCount, sizeof(uint32) ); break; case DL_TYPE_STORAGE_INT64: case DL_TYPE_STORAGE_UINT64: case DL_TYPE_STORAGE_FP64: dl_binary_writer_write_array( writer, u64, inst.m_ArrayCount, sizeof(uint64) ); break; default: DL_ASSERT(false && "Unknown storage type!"); } return DL_ERROR_OK; } if(AtomType == DL_TYPE_ATOM_POD && StorageType == DL_TYPE_STORAGE_STR) { dl_binary_writer_write_array( writer, u8, strlen(str) + 1, sizeof(uint8) ); return DL_ERROR_OK; } DL_ASSERT(AtomType == DL_TYPE_ATOM_POD); DL_ASSERT(StorageType == DL_TYPE_STORAGE_STRUCT || StorageType == DL_TYPE_STORAGE_PTR); return dl_internal_convert_write_struct( dl_ctx, u8, inst.m_pType, conv_ctx, writer ); }
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_convert_collect_instances( dl_ctx_t dl_ctx, const SDLType* type, const uint8* data, const uint8* base_data, SConvertContext& convert_ctx ) { for(uint32 iMember = 0; iMember < type->member_count; ++iMember) { const SDLMember& Member = type->members[iMember]; const uint8* pMemberData = data + Member.offset[convert_ctx.m_SourcePtrSize]; dl_type_t AtomType = Member.AtomType(); dl_type_t StorageType = Member.StorageType(); switch(AtomType) { case DL_TYPE_ATOM_POD: { switch( StorageType ) { case DL_TYPE_STORAGE_STR: { pint Offset = DLInternalReadPtrData( pMemberData, convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize ); convert_ctx.m_lInstances.Add(SInstance(base_data + Offset, 0x0, 1337, Member.type)); } break; case DL_TYPE_STORAGE_PTR: { const SDLType* pSubType = dl_internal_find_type(dl_ctx, Member.type_id); if(pSubType == 0x0) return DL_ERROR_TYPE_NOT_FOUND; pint Offset = DLInternalReadPtrData(pMemberData, convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize); const uint8* pPtrData = base_data + Offset; if(Offset != DL_NULL_PTR_OFFSET[convert_ctx.m_SourcePtrSize] && !convert_ctx.IsSwapped(pPtrData)) { convert_ctx.m_lInstances.Add(SInstance(pPtrData, pSubType, 0, Member.type)); dl_internal_convert_collect_instances(dl_ctx, pSubType, base_data + Offset, base_data, convert_ctx); } } break; case DL_TYPE_STORAGE_STRUCT: { const SDLType* pSubType = dl_internal_find_type(dl_ctx, Member.type_id); if(pSubType == 0x0) return DL_ERROR_TYPE_NOT_FOUND; dl_internal_convert_collect_instances(dl_ctx, pSubType, pMemberData, base_data, convert_ctx); } break; default: break; } } break; case DL_TYPE_ATOM_INLINE_ARRAY: { switch(StorageType) { case DL_TYPE_STORAGE_STRUCT: { const SDLType* pSubType = dl_internal_find_type(dl_ctx, Member.type_id); if(pSubType == 0x0) return DL_ERROR_TYPE_NOT_FOUND; for (pint ElemOffset = 0; ElemOffset < Member.size[convert_ctx.m_SourcePtrSize]; ElemOffset += pSubType->size[convert_ctx.m_SourcePtrSize]) dl_internal_convert_collect_instances(dl_ctx, pSubType, pMemberData + ElemOffset, base_data, convert_ctx); } break; case DL_TYPE_STORAGE_STR: { // TODO: This might be optimized if we look at all the data in i inline-array of strings as 1 instance continious in memory. // I am not sure if that is true for all cases right now! uint32 PtrSize = (uint32)dl_internal_ptr_size(convert_ctx.m_SourcePtrSize); uint32 Count = Member.size[convert_ctx.m_SourcePtrSize] / PtrSize; for (pint iElem = 0; iElem < Count; ++iElem) { pint Offset = DLInternalReadPtrData(data + (iElem * PtrSize), convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize); convert_ctx.m_lInstances.Add(SInstance(base_data + Offset, 0x0, Count, dl_type_t(DL_TYPE_ATOM_POD | DL_TYPE_STORAGE_STR))); } } break; default: DL_ASSERT(Member.IsSimplePod() || StorageType == DL_TYPE_STORAGE_ENUM); // ignore } } break; case DL_TYPE_ATOM_ARRAY: { pint Offset = 0; uint32 Count = 0; dl_internal_read_array_data( pMemberData, &Offset, &Count, convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize ); if(Offset == DL_NULL_PTR_OFFSET[convert_ctx.m_SourcePtrSize]) { DL_ASSERT( Count == 0 ); break; } switch(StorageType) { case DL_TYPE_STORAGE_STR: { // TODO: This might be optimized if we look at all the data in i inline-array of strings as 1 instance continious in memory. // I am not sure if that is true for all cases right now! uint32 PtrSize = (uint32)dl_internal_ptr_size(convert_ctx.m_SourcePtrSize); const uint8* pArrayData = base_data + Offset; convert_ctx.m_lInstances.Add(SInstance(base_data + Offset, 0x0, Count, Member.type)); for (pint iElem = 0; iElem < Count; ++iElem) { pint ElemOffset = DLInternalReadPtrData(pArrayData + (iElem * PtrSize), convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize); convert_ctx.m_lInstances.Add(SInstance(base_data + ElemOffset, 0x0, Count, dl_type_t(DL_TYPE_ATOM_POD | DL_TYPE_STORAGE_STR))); } } break; case DL_TYPE_STORAGE_STRUCT: { dl_internal_read_array_data( pMemberData, &Offset, &Count, convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize ); const uint8* pArrayData = base_data + Offset; const SDLType* pSubType = dl_internal_find_type(dl_ctx, Member.type_id); if(pSubType == 0x0) return DL_ERROR_TYPE_NOT_FOUND; convert_ctx.m_lInstances.Add(SInstance(pArrayData, pSubType, Count, Member.type)); for (pint ElemOffset = 0; ElemOffset < pSubType->size[convert_ctx.m_SourcePtrSize] * Count; ElemOffset += pSubType->size[convert_ctx.m_SourcePtrSize]) dl_internal_convert_collect_instances(dl_ctx, pSubType, pArrayData + ElemOffset, base_data, convert_ctx); } break; default: { DL_ASSERT(Member.IsSimplePod() || StorageType == DL_TYPE_STORAGE_ENUM); dl_internal_read_array_data( pMemberData, &Offset, &Count, convert_ctx.m_SourceEndian, convert_ctx.m_SourcePtrSize ); convert_ctx.m_lInstances.Add(SInstance(base_data + Offset, 0x0, Count, Member.type)); } break; } } break; case DL_TYPE_ATOM_BITFIELD: // ignore break; default: DL_ASSERT(false && "Invalid ATOM-type!"); } } 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; }