rdi_from_dwarf: use sibling tags to advance in hash path too - set up for deduplicating hash work

This commit is contained in:
Ryan Fleury
2026-06-19 20:53:01 -07:00
parent 4f899ac678
commit d3d35e40d7
3 changed files with 128 additions and 75 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ commands =
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build ryan_scratch && pushd build && ryan_scratch.exe", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin no_meta telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [raddbg wsl] //- rjf: [raddbg wsl]
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
+15 -2
View File
@@ -9,6 +9,13 @@ target:
debug_subprocesses: 0 debug_subprocesses: 0
} }
target: target:
{
executable: "build/raddbg.exe"
working_directory: "../raddebugger"
arguments: "--user:test123"
debug_subprocesses: 0
}
target:
{ {
executable: "build/mule_main.exe" executable: "build/mule_main.exe"
working_directory: build working_directory: build
@@ -32,7 +39,13 @@ target:
} }
target: target:
{ {
executable: "build/ryan_scratch.exe" executable: "build/release_version/raddbg.exe"
working_directory: build working_directory: "build/release_version"
}
target:
{
executable: "build/radbin.exe"
working_directory: "build/"
arguments: "--breakpad fat.so --capture"
enabled: 1 enabled: 1
} }
+112 -72
View File
@@ -1003,17 +1003,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
off += dw2_read_tag(scratch3.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag); off += dw2_read_tag(scratch3.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag);
//- rjf: look for sibling attribute fast path //- rjf: look for sibling attribute fast path
B32 sibling_encoded = 0; DW2_Attrib *sibling_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Sibling);
U64 sibling_off = 0; B32 sibling_encoded = (sibling_attrib != &dw2_attrib_nil);
for EachNode(n, DW2_AttribNode, tag.attribs.first) U64 sibling_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &sibling_attrib->val);
{
if(n->v.attrib_kind == DW_AttribKind_Sibling)
{
sibling_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &n->v.val);
sibling_encoded = 1;
break;
}
}
//- rjf: if we have a sibling link, follow it -> depth stays the same //- rjf: if we have a sibling link, follow it -> depth stays the same
if(sibling_encoded && sibling_off >= off) if(sibling_encoded && sibling_off >= off)
@@ -1226,6 +1218,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
DW_TagKind tag_kind; DW_TagKind tag_kind;
U64 info_off; U64 info_off;
U64 hash_seed; U64 hash_seed;
B32 disable_dedup;
}; };
D2R_ParentTagNode *top_parent = 0; D2R_ParentTagNode *top_parent = 0;
D2R_ParentTagNode *free_parent = 0; D2R_ParentTagNode *free_parent = 0;
@@ -1239,35 +1232,67 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
DW2_Tag tag = {0}; DW2_Tag tag = {0};
off += dw2_read_tag(tag_scratch.arena, raw, origin_unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag); off += dw2_read_tag(tag_scratch.arena, raw, origin_unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag);
// rjf: look for sibling attribute fast path
DW2_Attrib *sibling_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Sibling);
B32 sibling_encoded = (sibling_attrib != &dw2_attrib_nil);
U64 sibling_off = dw2_reference_info_off_from_form_val(origin_unit_parse_ctx, &sibling_attrib->val);
// rjf: determine if we'll deduplicate children of this tag
//
// three possible cases:
//
// (1) namespaced by a function - we do *not* want to deduplicate.
// functions are not deduplicated, and even if types defined
// within many functions match structurally, we consider them
// unique, given that they have different definition sites &
// names (fully qualified) still.
//
// (2) namespaced by a type - we do *not* want to deduplicate. the
// root-level type will already be deduplicated, so we'll only
// produce it once, and that'll catch all sub-types etc.
//
// (3) namespaced by a namespace - we *do* want to deduplicate. the
// children of a namespace are functionally top-level, and even
// if the same namespace definition is used across units, the
// debug info for each unit will contain fragmentary parts of it,
// since presumably unused pieces of the namespace will be stripped.
// thus, we need to visit namespace children as if they're top-level.
B32 children_should_be_deduped = 0;
if(tag.kind == DW_TagKind_Namespace)
{
children_should_be_deduped = 1;
}
// rjf: is this one of the tags we'd like to dedup? -> gather // rjf: is this one of the tags we'd like to dedup? -> gather
if(tag.kind == DW_TagKind_ArrayType || if((top_parent == 0 || !top_parent->disable_dedup) &&
tag.kind == DW_TagKind_ClassType || (tag.kind == DW_TagKind_ArrayType ||
tag.kind == DW_TagKind_EnumerationType || tag.kind == DW_TagKind_ClassType ||
tag.kind == DW_TagKind_PointerType || tag.kind == DW_TagKind_EnumerationType ||
tag.kind == DW_TagKind_ReferenceType || tag.kind == DW_TagKind_PointerType ||
tag.kind == DW_TagKind_StringType || tag.kind == DW_TagKind_ReferenceType ||
tag.kind == DW_TagKind_StructureType || tag.kind == DW_TagKind_StringType ||
tag.kind == DW_TagKind_SubroutineType || tag.kind == DW_TagKind_StructureType ||
tag.kind == DW_TagKind_SubProgram || tag.kind == DW_TagKind_SubroutineType ||
tag.kind == DW_TagKind_Typedef || tag.kind == DW_TagKind_SubProgram ||
tag.kind == DW_TagKind_UnionType || tag.kind == DW_TagKind_Typedef ||
tag.kind == DW_TagKind_PtrToMemberType || tag.kind == DW_TagKind_UnionType ||
tag.kind == DW_TagKind_SetType || tag.kind == DW_TagKind_PtrToMemberType ||
tag.kind == DW_TagKind_BaseType || tag.kind == DW_TagKind_SetType ||
tag.kind == DW_TagKind_ConstType || tag.kind == DW_TagKind_BaseType ||
tag.kind == DW_TagKind_FileType || tag.kind == DW_TagKind_ConstType ||
tag.kind == DW_TagKind_PackedType || tag.kind == DW_TagKind_FileType ||
tag.kind == DW_TagKind_VolatileType || tag.kind == DW_TagKind_PackedType ||
tag.kind == DW_TagKind_RestrictType || tag.kind == DW_TagKind_VolatileType ||
tag.kind == DW_TagKind_InterfaceType || tag.kind == DW_TagKind_RestrictType ||
tag.kind == DW_TagKind_UnspecifiedType || tag.kind == DW_TagKind_InterfaceType ||
tag.kind == DW_TagKind_SharedType || tag.kind == DW_TagKind_UnspecifiedType ||
tag.kind == DW_TagKind_RValueReferenceType || tag.kind == DW_TagKind_SharedType ||
tag.kind == DW_TagKind_CoarrayType || tag.kind == DW_TagKind_RValueReferenceType ||
tag.kind == DW_TagKind_DynamicType || tag.kind == DW_TagKind_CoarrayType ||
tag.kind == DW_TagKind_AtomicType || tag.kind == DW_TagKind_DynamicType ||
tag.kind == DW_TagKind_ImmutableType || tag.kind == DW_TagKind_AtomicType ||
tag.kind == DW_TagKind_Namespace) tag.kind == DW_TagKind_ImmutableType ||
tag.kind == DW_TagKind_Namespace))
{ {
U64 container_ancestor_info_off = 0; U64 container_ancestor_info_off = 0;
for EachNode(n, D2R_ParentTagNode, top_parent) for EachNode(n, D2R_ParentTagNode, top_parent)
@@ -1307,33 +1332,44 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
} }
} }
// rjf: update depth / parent stack // rjf: if we have a sibling offset encoded, and if we do not need to dedup children,
if(tag.has_children) // then skip
if(!children_should_be_deduped && sibling_encoded && sibling_off >= off)
{ {
depth += 1; off = sibling_off;
D2R_ParentTagNode *n = free_parent;
if(n != 0)
{
SLLStackPop(free_parent);
}
else
{
n = push_array(work_scratch.arena, D2R_ParentTagNode, 1);
}
SLLStackPush(top_parent, n);
n->tag_kind = tag.kind;
n->info_off = start_off;
n->hash_seed = hash_seed;
} }
if(tag.kind == DW_TagKind_Null)
// rjf: otherwise, update depth / parent stack
else
{ {
depth -= 1; if(tag.has_children)
depth = Max(0, depth);
if(top_parent != 0)
{ {
D2R_ParentTagNode *popped = top_parent; depth += 1;
SLLStackPop(top_parent); D2R_ParentTagNode *n = free_parent;
SLLStackPush(free_parent, popped); if(n != 0)
{
SLLStackPop(free_parent);
}
else
{
n = push_array(work_scratch.arena, D2R_ParentTagNode, 1);
}
SLLStackPush(top_parent, n);
n->tag_kind = tag.kind;
n->info_off = start_off;
n->hash_seed = hash_seed;
n->disable_dedup = !children_should_be_deduped;
}
if(tag.kind == DW_TagKind_Null)
{
depth -= 1;
depth = Max(0, depth);
if(top_parent != 0)
{
D2R_ParentTagNode *popped = top_parent;
SLLStackPop(top_parent);
SLLStackPush(free_parent, popped);
}
} }
} }
@@ -1379,8 +1415,8 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
// rjf: record this task in our seen task table // rjf: record this task in our seen task table
{ {
U64 hash = u64_hash_from_str8(str8_struct(&t->off)); U64 off_hash = u64_hash_from_str8(str8_struct(&t->off));
U64 slot_idx = hash%seen_task_slots_count; U64 slot_idx = off_hash%seen_task_slots_count;
SLLStackPush(seen_task_slots[slot_idx], t); SLLStackPush(seen_task_slots[slot_idx], t);
} }
@@ -1388,8 +1424,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[t->unit_idx]; Rng1U64 unit_info_tag_range = unit_info_tag_ranges[t->unit_idx];
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[t->unit_idx]; DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[t->unit_idx];
// rjf: read/hash the full tag tree at `t_off`; kick off additional // rjf: read/hash the full tag tree at `t_off`; kick
// tasks for referenced dependency types // off additional tasks for referenced dependency types
U64 t_hash = 0;
S64 depth = 0; S64 depth = 0;
B32 hash_should_include_children = 1; B32 hash_should_include_children = 1;
for(;unit_info_tag_range.min <= t_off && t_off < unit_info_tag_range.max && (depth > 0 || t_off == t->off);) for(;unit_info_tag_range.min <= t_off && t_off < unit_info_tag_range.max && (depth > 0 || t_off == t->off);)
@@ -1416,7 +1453,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
if(!should_skip_tag) if(!should_skip_tag)
{ {
// rjf: combine tag's kind // rjf: combine tag's kind
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind)); t_hash = u64_hash_from_seed_str8(t_hash, str8_struct(&tag.kind));
// rjf: combine non-reference attributes (references could be different, // rjf: combine non-reference attributes (references could be different,
// because of deduping, but they could match ultimately). for any // because of deduping, but they could match ultimately). for any
@@ -1444,18 +1481,18 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
n->v.attrib_kind != DW_AttribKind_LowPc && n->v.attrib_kind != DW_AttribKind_LowPc &&
n->v.attrib_kind != DW_AttribKind_HighPc))) n->v.attrib_kind != DW_AttribKind_HighPc)))
{ {
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.kind)); t_hash = u64_hash_from_seed_str8(t_hash, str8_struct(&n->v.val.kind));
if(n->v.val.string.size != 0) if(n->v.val.string.size != 0)
{ {
hash = u64_hash_from_seed_str8(hash, n->v.val.string); t_hash = u64_hash_from_seed_str8(t_hash, n->v.val.string);
} }
else if(n->v.val.addr != 0) else if(n->v.val.addr != 0)
{ {
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.addr)); t_hash = u64_hash_from_seed_str8(t_hash, str8_struct(&n->v.val.addr));
} }
else else
{ {
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.u128)); t_hash = u64_hash_from_seed_str8(t_hash, str8_struct(&n->v.val.u128));
} }
} }
@@ -1485,7 +1522,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
// rjf: if we've seen -> hash the order // rjf: if we've seen -> hash the order
if(already_seen) if(already_seen)
{ {
hash = u64_hash_from_seed_str8(hash, str8_struct(&already_seen_order_idx)); t_hash = u64_hash_from_seed_str8(t_hash, str8_struct(&already_seen_order_idx));
} }
// rjf: if we've not seen -> descend // rjf: if we've not seen -> descend
@@ -1533,6 +1570,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
} }
scratch_end(tag_scratch); scratch_end(tag_scratch);
} }
// rjf: combine t_hash -> main hash
hash = u64_hash_from_seed_str8(hash, str8_struct(&t_hash));
} }
} }