diff --git a/src/dwarf/dwarf_parse_2.c b/src/dwarf/dwarf_parse_2.c index d2685027..7a45cbde 100644 --- a/src/dwarf/dwarf_parse_2.c +++ b/src/dwarf/dwarf_parse_2.c @@ -908,15 +908,27 @@ dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out) // rjf: version 5: read rest (this section only exists in 5+) if(version == DW_Version_5) { - // rjf: skip padding - off += sizeof(U16); + // rjf: read address / segment selector size (these need to be 0 in non-address offset tables) + U8 addr_size = 0; + U8 segment_selector_size = 0; + off += str8_deserial_read_struct(data, off, &addr_size); + off += str8_deserial_read_struct(data, off, &segment_selector_size); + + // rjf: determine entry size + U64 entry_size = dw_size_from_format(format); + if(addr_size != 0) + { + entry_size = addr_size + segment_selector_size; + } // rjf: fill table info - out->format = format; - out->version = version; - out->entry_size = dw_size_from_format(format); - out->entries_count = (unit_data_off_opl - off) / out->entry_size; - out->entries = data.str + off; + out->format = format; + out->version = version; + out->addr_size = addr_size; + out->segment_selector_size = segment_selector_size; + out->entry_size = entry_size; + out->entries_count = (unit_data_off_opl - off) / out->entry_size; + out->entries = data.str + off; // rjf: skip table off = unit_data_off_opl; @@ -934,7 +946,21 @@ dw2_try_offset_from_table_idx(DW2_OffsetTable *tbl, U64 idx, U64 *out) { U64 entry_size = tbl->entry_size; U64 entry_off = idx * entry_size; - MemoryCopy(out, (U8 *)tbl->entries + entry_off, entry_size); + if(tbl->addr_size != 0) + { + U64 segment_off = entry_off; + U64 addr_off = entry_off + tbl->segment_selector_size; + U64 segment = 0; + U64 addr = 0; + MemoryCopy(&segment, (U8 *)tbl->entries + segment_off, tbl->segment_selector_size); + MemoryCopy(&addr, (U8 *)tbl->entries + addr_off, tbl->addr_size); + // TODO(rjf): @segment_based_addressing + *out = addr; + } + else + { + MemoryCopy(out, (U8 *)tbl->entries + entry_off, entry_size); + } result = 1; } return result; diff --git a/src/dwarf/dwarf_parse_2.h b/src/dwarf/dwarf_parse_2.h index bce9f7a9..533698cc 100644 --- a/src/dwarf/dwarf_parse_2.h +++ b/src/dwarf/dwarf_parse_2.h @@ -44,6 +44,8 @@ struct DW2_OffsetTable { DW_Format format; DW_Version version; + U8 addr_size; + U8 segment_selector_size; U64 entry_size; U64 entries_count; void *entries; diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index b68e5d13..75d75299 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -281,10 +281,15 @@ e_interpret(String8 bytecode) U8 byte_size = (imm.u64&0x00FF00)>>8; U8 byte_off = (imm.u64&0xFF0000)>>16; REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(e_interpret_ctx->reg_arch, rdi_reg_code); - REGS_Rng rng = regs_reg_code_rng_table_from_arch(e_interpret_ctx->reg_arch)[base_reg_code]; - U64 off = (U64)rng.byte_off + byte_off; - U64 size = (U64)byte_size; - B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size)); + REGS_Rng *rng_table = regs_reg_code_rng_table_from_arch(e_interpret_ctx->reg_arch); + B32 good_read = 0; + if(0 <= rdi_reg_code && rdi_reg_code < regs_reg_code_count_from_arch(e_interpret_ctx->reg_arch)) + { + REGS_Rng rng = rng_table[base_reg_code]; + U64 off = (U64)rng.byte_off + byte_off; + U64 size = (U64)byte_size; + good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size)); + } if(!good_read) { result.code = E_InterpretationCode_BadRegRead; diff --git a/src/rdi_from_dwarf/rdi_from_dwarf_2.c b/src/rdi_from_dwarf/rdi_from_dwarf_2.c index e907546c..24c50683 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf_2.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf_2.c @@ -2455,7 +2455,6 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) // rjf: build type dst_type = rdim_type_chunk_list_push(arena, &lane_types, lane_types_chunk_count); dst_type->kind = RDI_TypeKind_Function; - dst_type->name = name; dst_type->direct_type = direct_type; dst_type->byte_size = arch_addr_size; @@ -2914,7 +2913,8 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) (type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_Class || - type->kind == RDI_TypeKind_Enum)) + type->kind == RDI_TypeKind_Enum || + type->kind == RDI_TypeKind_Alias)) { // rjf: produce UDT RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &lane_udts, chunk_count); @@ -3238,6 +3238,19 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) //////////////////////////// //- rjf: convert all symbols // + typedef struct D2R2_ScopeContainerNode D2R2_ScopeContainerNode; + struct D2R2_ScopeContainerNode + { + D2R2_ScopeContainerNode *next; + U64 info_off; + RDIM_Scope *scope; + }; + typedef struct D2R2_ScopeContainerMap D2R2_ScopeContainerMap; + struct D2R2_ScopeContainerMap + { + D2R2_ScopeContainerNode **slots; + U64 slots_count; + }; typedef struct D2R2_SubUnitWorkArtifacts D2R2_SubUnitWorkArtifacts; struct D2R2_SubUnitWorkArtifacts { @@ -3248,13 +3261,18 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) RDIM_ScopeChunkList scopes; RDIM_InlineSiteChunkList inline_sites; }; + D2R2_ScopeContainerMap *scope_container_map = 0; D2R2_SubUnitWorkArtifacts *sub_unit_work_artifacts = 0; ProfScope("convert all symbols") { if(lane_idx() == 0) { + scope_container_map = push_array(scratch.arena, D2R2_ScopeContainerMap, 1); + scope_container_map->slots_count = total_tag_count_estimate/8 + 1; + scope_container_map->slots = push_array(scratch.arena, D2R2_ScopeContainerNode *, scope_container_map->slots_count); sub_unit_work_artifacts = push_array(scratch.arena, D2R2_SubUnitWorkArtifacts, sub_unit_works_count); } + lane_sync_u64(&scope_container_map, 0); lane_sync_u64(&sub_unit_work_artifacts, 0); U64 work_take_idx_ = 0; U64 *work_take_idx_ptr = &work_take_idx_; @@ -4205,10 +4223,22 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) // RDIM_Symbol *new_symbol = 0; RDIM_Scope *new_scope_open = 0; + B32 parent_tag_is_container_to_deduped_tags = 0; switch(tag.kind) { default:{}break; + //- rjf: determine if parent tag is a container to deduplicated tags + case DW_TagKind_Namespace: + case DW_TagKind_StructureType: + case DW_TagKind_UnionType: + case DW_TagKind_ClassType: + case DW_TagKind_EnumerationType: + case DW_TagKind_Typedef: + { + parent_tag_is_container_to_deduped_tags = 1; + }break; + //- rjf: subprograms (procedures) case DW_TagKind_SubProgram: { @@ -4268,6 +4298,44 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) }break; } + //////////////////////// + //- rjf: if we've determined that the parent tag is a container to + // deduplicated tags (types, namespaces), then we need to record + // the .debug_info offset -> scope mapping for this scope, so it + // can be equipped as a container later. + // + if(parent_tag_is_container_to_deduped_tags) + { + U64 info_off = 0; + RDIM_Scope *scope = 0; + for(D2R2_ParentNode *n = top_parent; n != 0; n = n->next) + { + if(n->scope != 0) + { + info_off = n->info_off; + scope = n->scope; + break; + } + } + if(scope != 0) + { + D2R2_ScopeContainerNode *n = push_array(scratch.arena, D2R2_ScopeContainerNode, 1); + n->info_off = info_off; + n->scope = scope; + U64 hash = u64_hash_from_str8(str8_struct(&info_off)); + U64 slot_idx = hash%scope_container_map->slots_count; + for(B32 gathered = 0; !gathered;) + { + U64 expected_head_value = ins_atomic_u64_eval(&scope_container_map->slots[slot_idx]); + n->next = (D2R2_ScopeContainerNode *)expected_head_value; + if(expected_head_value == ins_atomic_u64_eval_cond_assign(&scope_container_map->slots[slot_idx], (U64)n, expected_head_value)) + { + gathered = 1; + } + } + } + } + //////////////////////// //- rjf: equip new symbols with container info // @@ -4464,9 +4532,26 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) continue; } + // rjf: find container scopes + RDIM_Scope *container_scope = 0; + { + U64 info_off = container_ancestor_info_off; + U64 hash = u64_hash_from_str8(str8_struct(&info_off)); + U64 slot_idx = hash%scope_container_map->slots_count; + for(D2R2_ScopeContainerNode *n = scope_container_map->slots[slot_idx]; n != 0; n = n->next) + { + if(n->info_off == info_off) + { + container_scope = n->scope; + break; + } + } + } + // rjf: find container types/namespaces RDIM_Type *container_type = 0; RDIM_Namespace *container_namespace = 0; + if(!container_scope) { U64 info_off = container_ancestor_info_off; U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off); @@ -4510,6 +4595,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) } // rjf: fill + dst_udt->container_scope = container_scope; dst_udt->container_type = container_type; dst_udt->container_namespace = container_namespace; } @@ -4532,6 +4618,22 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) continue; } + // rjf: find container scopes + RDIM_Scope *container_scope = 0; + { + U64 info_off = container_ancestor_info_off; + U64 hash = u64_hash_from_str8(str8_struct(&info_off)); + U64 slot_idx = hash%scope_container_map->slots_count; + for(D2R2_ScopeContainerNode *n = scope_container_map->slots[slot_idx]; n != 0; n = n->next) + { + if(n->info_off == info_off) + { + container_scope = n->scope; + break; + } + } + } + // rjf: find container types/namespaces RDIM_Type *container_type = 0; RDIM_Namespace *container_namespace = 0; @@ -4578,6 +4680,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) } // rjf: fill + dst_namespace->parent_scope = container_scope; dst_namespace->parent_type = container_type; dst_namespace->parent_namespace = container_namespace; } diff --git a/src/rdi_from_elf/rdi_from_elf.c b/src/rdi_from_elf/rdi_from_elf.c index 909a28a2..54ba08ab 100644 --- a/src/rdi_from_elf/rdi_from_elf.c +++ b/src/rdi_from_elf/rdi_from_elf.c @@ -20,14 +20,17 @@ e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_B if(src_section->sh_flags & ELF_Shf_Write) { flags |= RDI_BinarySectionFlag_Write; } if(src_section->sh_flags & ELF_Shf_ExecInstr) { flags |= RDI_BinarySectionFlag_Execute; } - // rjf: make rdi section - RDIM_BinarySection *dst_section = rdim_binary_section_list_push(arena, &result); - dst_section->name = name; - dst_section->flags = flags; - dst_section->voff_first = voff_first; - dst_section->voff_opl = voff_opl; - dst_section->foff_first = foff_first; - dst_section->foff_opl = foff_opl; + // rjf: make rdi section if not empty + if(name.size != 0 || voff_opl != voff_first || foff_opl != foff_first) + { + RDIM_BinarySection *dst_section = rdim_binary_section_list_push(arena, &result); + dst_section->name = name; + dst_section->flags = flags; + dst_section->voff_first = voff_first; + dst_section->voff_opl = voff_opl; + dst_section->foff_first = foff_first; + dst_section->foff_opl = foff_opl; + } } return result; } diff --git a/src/regs/regs.mdesk b/src/regs/regs.mdesk index 0408c873..765781f7 100644 --- a/src/regs/regs.mdesk +++ b/src/regs/regs.mdesk @@ -1,6 +1,15 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Architecture Tables + +@table(name, name_lower) +REGS_ArchTable: +{ + {X64 x64} +} + //////////////////////////////// //~ rjf: X64 Tables @@ -200,18 +209,6 @@ REGS_AliasTableX64: {mm7 st7 0 64 Vector} } -//////////////////////////////// -//~ rjf: Architecture Tables - -@table(name, name_lower) -REGS_ArchTable: -{ - {X64 x64} -} - -//////////////////////////////// -//~ rjf: X64 Generators - @enum REGS_RegCodeX64: { NULL,