From 15601d48d4c947f6fd204f0c19632fadf2a7708b Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 19 Jun 2026 20:11:50 -0700 Subject: [PATCH] rdi_from_dwarf: use sibling tag attributes to gather root-level tag offsets when present - 15x speedup in the gather on webkit DWARFs... --- src/elf/elf_dump.c | 190 ++++++++++++++-------------- src/rdi_from_dwarf/rdi_from_dwarf.c | 47 +++++-- 2 files changed, 133 insertions(+), 104 deletions(-) diff --git a/src/elf/elf_dump.c b/src/elf/elf_dump.c index c948ed3c..b7e530ca 100644 --- a/src/elf/elf_dump.c +++ b/src/elf/elf_dump.c @@ -5,162 +5,162 @@ internal String8List elf_dump_note(Arena *arena, String8 raw_notes, ELF_Class elf_class, ELF_MachineKind e_machine) { Temp scratch = scratch_begin(&arena, 1); - + B32 is_bad_parse = 1; String8List strings = {0}; U64 cursor = 0; - + for (;cursor < raw_notes.size;) { U32 owner_size; U64 owner_size_size = str8_deserial_read_struct(raw_notes, cursor, &owner_size); if (owner_size_size == 0) { goto exit; } cursor += owner_size_size; - + U32 desc_size; U64 desc_size_size = str8_deserial_read_struct(raw_notes, cursor, &desc_size); if (desc_size_size == 0) { goto exit; } cursor += desc_size_size; - + ELF_NoteType note_type; U64 type_size = str8_deserial_read_struct(raw_notes, cursor, ¬e_type); if (type_size == 0) { goto exit; } cursor += type_size; - + if (cursor + owner_size > raw_notes.size) { goto exit; } String8 owner = str8_cstring_capped(raw_notes.str + cursor, raw_notes.str + cursor + owner_size); cursor += owner_size; - + if (cursor + desc_size > raw_notes.size) { goto exit; } String8 raw_desc = str8_substr(raw_notes, r1u64(cursor, cursor + desc_size)); cursor += desc_size; cursor = AlignPow2(cursor, 4); - + String8List desc_fmt = {0}; String8 note_type_str = {0}; if (str8_match(owner, str8_lit("GNU"), StringMatchFlag_CaseInsensitive)) { // format description switch (note_type) { - case GNU_NoteType_Abi: { - U64 desc_cursor = 0; - - GNU_AbiTag os = 0; - U64 os_size = str8_deserial_read_struct(raw_desc, desc_cursor, &os); - if (os_size == 0) { goto exit; } - cursor += os_size; - - U32 major = 0; - U64 major_size = str8_deserial_read_struct(raw_desc, desc_cursor, &major); - if (major_size == 0) { goto exit; } - cursor += major_size; - - U32 minor = 0; - U64 minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &minor); - if (minor_size == 0) { goto exit; } - cursor += minor_size; - - U32 sub_minor = 0; - U64 sub_minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &sub_minor); - if (sub_minor_size == 0) { goto exit; } - cursor += sub_minor_size; - - String8 os_str = gnu_string_from_abi_tag(os); - if (os_str.size == 0) os_str = str8f(scratch.arena, "0x%x", os); - - str8_list_pushf(scratch.arena, &desc_fmt, "OS: %S, ABI: %u.%u.%u", os_str, major, minor, sub_minor); - } break; - case GNU_NoteType_BuildId: { - String8List build_id = {0}; - for EachIndex(desc_cursor, desc_size) { - U8 v = 0; - U64 v_size = str8_deserial_read_struct(raw_desc, desc_cursor, &v); - if (v_size == 0) { goto exit; } - desc_cursor += v_size; - str8_list_pushf(scratch.arena, &build_id, "%02x", v); - } - String8 build_id_str = str8_list_join(scratch.arena, &build_id, 0); - str8_list_pushf(scratch.arena, &desc_fmt, "Build ID: %S", build_id_str); - } break; - case GNU_NoteType_PropertyType0: { - U64 align = elf_class == ELF_Class_64 ? 8 : 4; - for (U64 desc_cursor = 0; desc_cursor < raw_desc.size; ) { - GNU_Property type = 0; - U64 type_size = str8_deserial_read_struct(raw_desc, desc_cursor, &type); - if (type_size == 0) { goto exit; } - desc_cursor += type_size; - - U32 size = 0; - U64 size_size = str8_deserial_read_struct(raw_desc, desc_cursor, &size); - if (size_size == 0) { goto exit; } - desc_cursor += size_size; - - U32 flags = 0; - if (size == 4) { - U64 flags_size = str8_deserial_read_struct(raw_desc, desc_cursor, &flags); - if (flags_size == 0) { goto exit; } - desc_cursor += flags_size; + case GNU_NoteType_Abi: { + U64 desc_cursor = 0; + + GNU_AbiTag os = 0; + U64 os_size = str8_deserial_read_struct(raw_desc, desc_cursor, &os); + if (os_size == 0) { goto exit; } + cursor += os_size; + + U32 major = 0; + U64 major_size = str8_deserial_read_struct(raw_desc, desc_cursor, &major); + if (major_size == 0) { goto exit; } + cursor += major_size; + + U32 minor = 0; + U64 minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &minor); + if (minor_size == 0) { goto exit; } + cursor += minor_size; + + U32 sub_minor = 0; + U64 sub_minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &sub_minor); + if (sub_minor_size == 0) { goto exit; } + cursor += sub_minor_size; + + String8 os_str = gnu_string_from_abi_tag(os); + if (os_str.size == 0) os_str = str8f(scratch.arena, "0x%x", os); + + str8_list_pushf(scratch.arena, &desc_fmt, "OS: %S, ABI: %u.%u.%u", os_str, major, minor, sub_minor); + } break; + case GNU_NoteType_BuildId: { + String8List build_id = {0}; + for EachIndex(desc_cursor, desc_size) { + U8 v = 0; + U64 v_size = str8_deserial_read_struct(raw_desc, desc_cursor, &v); + if (v_size == 0) { goto exit; } + desc_cursor += v_size; + str8_list_pushf(scratch.arena, &build_id, "%02x", v); } - - switch (e_machine) { - case ELF_MachineKind_None: break; - case ELF_MachineKind_X86_64: { - String8 features = gnu_string_from_property_flags_x86(scratch.arena, type, flags); - str8_list_pushf(scratch.arena, &desc_fmt, "x86 features: %S", features); - } break; - default: NotImplemented; break; + String8 build_id_str = str8_list_join(scratch.arena, &build_id, 0); + str8_list_pushf(scratch.arena, &desc_fmt, "Build ID: %S", build_id_str); + } break; + case GNU_NoteType_PropertyType0: { + U64 align = elf_class == ELF_Class_64 ? 8 : 4; + for (U64 desc_cursor = 0; desc_cursor < raw_desc.size; ) { + GNU_Property type = 0; + U64 type_size = str8_deserial_read_struct(raw_desc, desc_cursor, &type); + if (type_size == 0) { goto exit; } + desc_cursor += type_size; + + U32 size = 0; + U64 size_size = str8_deserial_read_struct(raw_desc, desc_cursor, &size); + if (size_size == 0) { goto exit; } + desc_cursor += size_size; + + U32 flags = 0; + if (size == 4) { + U64 flags_size = str8_deserial_read_struct(raw_desc, desc_cursor, &flags); + if (flags_size == 0) { goto exit; } + desc_cursor += flags_size; + } + + switch (e_machine) { + case ELF_MachineKind_None: break; + case ELF_MachineKind_X86_64: { + String8 features = gnu_string_from_property_flags_x86(scratch.arena, type, flags); + str8_list_pushf(scratch.arena, &desc_fmt, "x86 features: %S", features); + } break; + default:{}break; + } + + desc_cursor = AlignPow2(desc_cursor, align); } - - desc_cursor = AlignPow2(desc_cursor, align); - } - } break; - default: NotImplemented; break; + } break; + default:{}break; } - + note_type_str = gnu_string_from_note_type(note_type); } else if (str8_match(owner, str8_lit("stapsdt"), StringMatchFlag_CaseInsensitive)) { if (note_type == ELF_NoteType_STapSdt) { U64 desc_cursor = 0; U64 addr_size = elf_class == ELF_Class_64 ? 8 : 4; - + U64 pc = 0; U64 pc_size = str8_deserial_read(raw_desc, desc_cursor, &pc, addr_size, addr_size); if (pc_size == 0) { goto exit; } desc_cursor += pc_size; - + U64 base_addr = 0; U64 base_addr_size = str8_deserial_read(raw_desc, desc_cursor, &base_addr, addr_size, addr_size); if (base_addr_size == 0) { goto exit; } desc_cursor += base_addr_size; - + U64 semaphore = 0; U64 semaphore_size = str8_deserial_read(raw_desc, desc_cursor, &semaphore, addr_size, addr_size); if (semaphore_size == 0) { goto exit; } desc_cursor += semaphore_size; - + String8 provider = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += provider.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } - + String8 probe = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += probe.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } - + String8 args = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += args.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } - + str8_list_pushf(scratch.arena, &desc_fmt, "Provider: %S", provider); str8_list_pushf(scratch.arena, &desc_fmt, "Probe: %S", probe); str8_list_pushf(scratch.arena, &desc_fmt, "PC: 0x%I64x", pc); str8_list_pushf(scratch.arena, &desc_fmt, "Base: 0x%I64x", base_addr); str8_list_pushf(scratch.arena, &desc_fmt, "Semaphore: 0x%I64x", semaphore); str8_list_pushf(scratch.arena, &desc_fmt, "Arguments: %S", args); - + note_type_str = str8_lit("NT_STAPSDT"); } } - + if (note_type_str.size == 0) note_type_str = str8f(scratch.arena, "0x%x", note_type); - + str8_list_pushf(arena, &strings, "{"); str8_list_pushf(arena, &strings, " Owner: %S", owner); str8_list_pushf(arena, &strings, " Data Size: 0x%x", desc_size); @@ -173,9 +173,9 @@ elf_dump_note(Arena *arena, String8 raw_notes, ELF_Class elf_class, ELF_MachineK } str8_list_pushf(arena, &strings, "}"); } - + is_bad_parse = 0; -exit:; + exit:; if (is_bad_parse) { str8_list_pushf(arena, &strings, "ERROR: unable to parse data @ 0x%Ix64", cursor); } @@ -187,10 +187,10 @@ internal String8List elf_dump(Arena *arena, String8 raw_elf, ELF_DumpSubsetFlags flags) { Temp scratch = scratch_begin(&arena, 1); - + String8List strings = {0}; ELF_Bin elf = elf_bin_from_data(scratch.arena, raw_elf); - + if (flags & ELF_DumpSubsetFlag_Note) { for EachIndex(sect_idx, elf.shdrs.count) { ELF_Shdr64 *shdr = &elf.shdrs.v[sect_idx]; @@ -205,11 +205,11 @@ elf_dump(Arena *arena, String8 raw_elf, ELF_DumpSubsetFlags flags) } } } - + String8 out = str8_list_join(arena, &strings, &(StringJoin){.sep=str8_lit("\n"), .post=str8_lit("\n")}); String8List result = {0}; str8_list_push(arena, &result, out); - + scratch_end(scratch); return result; } diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index b7412885..5520f3b7 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -1002,14 +1002,36 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) DW2_Tag tag = {0}; off += dw2_read_tag(scratch3.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag); - //- rjf: do tree navigations - if(tag.has_children) + //- rjf: look for sibling attribute fast path + B32 sibling_encoded = 0; + U64 sibling_off = 0; + for EachNode(n, DW2_AttribNode, tag.attribs.first) { - depth += 1; + 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; + } } - if(tag.kind == DW_TagKind_Null) + + //- rjf: if we have a sibling link, follow it -> depth stays the same + if(sibling_encoded && sibling_off >= off) { - depth -= 1; + off = sibling_off; + } + + //- rjf: otherwise, do tree navigations... + else + { + if(tag.has_children) + { + depth += 1; + } + if(tag.kind == DW_TagKind_Null) + { + depth -= 1; + } } scratch_end(scratch3); @@ -1149,7 +1171,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) for EachInRange(unit_idx, range) { Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx]; - unit_deduped_tag_maps[unit_idx].slots_count = dim_1u64(unit_info_tag_range) / 256 + 1; + unit_deduped_tag_maps[unit_idx].slots_count = dim_1u64(unit_info_tag_range) / 32 + 1; unit_deduped_tag_maps[unit_idx].slots = push_array(scratch.arena, D2R_UnitDedupedTagNode *, unit_deduped_tag_maps[unit_idx].slots_count); } lane_sync(); @@ -1168,6 +1190,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) { break; } + ProfBegin("gather unique tags work"); Temp work_scratch = scratch_begin(&scratch.arena, 1); //- rjf: unpack work @@ -1188,6 +1211,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) U64 container_ancestor_info_off; U64 hash_seed; }; + U64 tags_to_dedup_count = 0; D2R_TagNode *first_tag_to_dedup = 0; D2R_TagNode *last_tag_to_dedup = 0; for(U64 root_tag_idx = origin_unit_root_tag_idx_range.min; @@ -1265,6 +1289,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) n->container_ancestor_info_off = container_ancestor_info_off; n->hash_seed = top_parent ? top_parent->hash_seed : 0; SLLQueuePush(first_tag_to_dedup, last_tag_to_dedup, n); + tags_to_dedup_count += 1; } // rjf: compute hash seed for this tag @@ -1321,6 +1346,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) } //- rjf: hash all tags we need to deduplicate & gather + U64 total_tag_count_this_work = 0; for(D2R_TagNode *tag_n = first_tag_to_dedup; tag_n != 0; tag_n = tag_n->next) { Temp dedup_root_scratch = scratch_begin(&scratch.arena, 1); @@ -1331,6 +1357,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) //- rjf: hash all tags & dependency tag trees U64 hash = hash_seed; + ProfScope("hash tag trees & dependencies") { typedef struct TagTask TagTask; struct TagTask @@ -1373,6 +1400,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) // rjf: read tag DW2_Tag tag = {0}; t_off += dw2_read_tag(tag_scratch.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, t_off, &tag); + total_tag_count_this_work += 1; // rjf: determine if tag should be skipped from hashing B32 should_skip_tag = (tag.kind == DW_TagKind_LexicalBlock || @@ -1624,7 +1652,8 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) } scratch_end(dedup_root_scratch); } - + // ProfMsg("work_idx %I64u: %I64u tags encountered", work_idx, total_tag_count_this_work); + ProfEnd(); scratch_end(work_scratch); } lane_sync(); @@ -2896,7 +2925,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) { U64 voff_base = lopc_attrib->val.addr - base_vaddr; U64 voff_opl = 0; - if(dw_attrib_class_from_form_kind(unit_parse_ctx->version, unit_parse_ctx->exts, hipc_attrib->val.kind) & (1<version, unit_parse_ctx->exts, hipc_attrib->val.kind) & DW_AttribClass_Address) { voff_opl = voff_base + hipc_attrib->val.u128.u64[0]; } @@ -3078,7 +3107,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) { U64 voff_base = lopc_attrib->val.addr - base_vaddr; U64 voff_opl = 0; - if(dw_attrib_class_from_form_kind(unit_parse_ctx->version, unit_parse_ctx->exts, hipc_attrib->val.kind) & (1<version, unit_parse_ctx->exts, hipc_attrib->val.kind) & DW_AttribClass_Address) { voff_opl = hipc_attrib->val.addr; }