d2r2: hook up scope containers to contained types / namespaces; fix address table parsing

This commit is contained in:
Ryan Fleury
2026-05-05 09:42:55 -07:00
parent aee299efe7
commit fb04768002
6 changed files with 170 additions and 34 deletions
+29 -3
View File
@@ -908,13 +908,25 @@ 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->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;
@@ -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;
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;
+2
View File
@@ -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;
+7 -2
View File
@@ -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];
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;
B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
}
if(!good_read)
{
result.code = E_InterpretationCode_BadRegRead;
+105 -2
View File
@@ -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;
}
+4 -1
View File
@@ -20,7 +20,9 @@ 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
// 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;
@@ -29,5 +31,6 @@ e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_B
dst_section->foff_first = foff_first;
dst_section->foff_opl = foff_opl;
}
}
return result;
}
+9 -12
View File
@@ -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,