changed dumper to print .debug_info in more compact form

This commit is contained in:
Nikita Smith
2025-10-03 20:10:09 -07:00
parent b1b83c4e3d
commit da0028033d
+167 -120
View File
@@ -1548,107 +1548,38 @@ dw_print_debug_str_offsets(Arena *arena, String8List *out, String8 indent, DW_In
//////////////////////////////// ////////////////////////////////
//~ rjf: Dump Entry Point //~ rjf: Dump Entry Point
internal String8List internal String8
dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubsetFlags subset_flags) dw_string_from_attrib_value(Arena *arena, DW_Input *input, Arch arch, DW_CompUnit *unit, DW_LineVMHeader *line_vm, DW_Attrib *attrib)
{ {
String8List strings = {0};
String8 indent = str8_lit(" ");
#define dump(str) str8_list_push(arena, &strings, (str))
#define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__)
#define DumpSubset(name) if(subset_flags & DW_DumpSubsetFlag_##name) DeferLoop(dumpf("// %S\n\n", dw_name_title_from_dump_subset_table[DW_DumpSubset_##name]), dump(str8_lit("\n")))
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
Rng1U64Array segment_vranges = {0};
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input);
Rng1U64List unit_ranges_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data);
Rng1U64Array unit_ranges = rng1u64_array_from_list(scratch.arena, &unit_ranges_list);
B32 relaxed = 1;
////////////////////////////// String8List attrib_fmt = {0};
//- rjf: dump .debug_info
//
DumpSubset(DebugInfo)
{
for EachIndex(unit_idx, unit_ranges.count)
{
Temp unit_temp = temp_begin(scratch.arena);
//- rjf: unpack unit
Rng1U64 unit_range = unit_ranges.v[unit_idx];
DW_CompUnit unit = dw_cu_from_info_off(unit_temp.arena, input, lu_input, unit_range.min, relaxed);
String8 unit_dir = dw_string_from_tag_attrib_kind(input, &unit, unit.tag, DW_AttribKind_CompDir );
String8 unit_name = dw_string_from_tag_attrib_kind(input, &unit, unit.tag, DW_AttribKind_Name );
String8 stmt_list = dw_line_ptr_from_tag_attrib_kind(input, &unit, unit.tag, DW_AttribKind_StmtList);
DW_LineVMHeader line_vm = {0};
dw_read_line_vm_header(unit_temp.arena, stmt_list, 0, input, unit_dir, unit_name, unit.address_size, unit.str_offsets_lu, &line_vm);
//- rjf: log top-level unit info
dumpf("unit: // compile_unit[%I64u]\n{\n", unit_idx);
dumpf(" version: %u\n", unit.version);
dumpf(" address_size: %I64u\n", unit.address_size);
dumpf(" abbrev_off: 0x%I64x\n", unit.abbrev_off);
dumpf(" info_range: [0x%I64x, 0x%I64x) // (%M)\n", unit.info_range.min, unit.info_range.max, dim_1u64(unit.info_range));
//- rjf: log tags
S64 tag_depth = 0;
U64 tag_idx = 0;
for(U64 info_off = unit.first_tag_info_off; info_off < unit.info_range.max; tag_idx += 1)
{
Temp tag_temp = temp_begin(scratch.arena);
// rjf: unpack tag
String8 tag_indent = str8_prefix(indent, (tag_depth+1)*2);
U64 tag_info_off = info_off;
DW_Tag tag = {0};
info_off += dw_read_tag_cu(tag_temp.arena, input, &unit, tag_info_off, &tag);
// rjf: log top-level tag info
dumpf("%Stag: // compile_unit[%I64u].tag[%I64u]\n%S{\n", tag_indent, unit_idx, tag_idx, tag_indent);
dumpf("%S kind: %S\n", tag_indent, dw_string_from_tag_kind(tag_temp.arena, tag.kind));
dumpf("%S info_off: 0x%I64x\n", tag_indent, tag_info_off);
dumpf("%S abbrev_id: %I64u\n", tag_indent, tag.abbrev_id);
// rjf: log attribs
for(DW_AttribNode *attrib_n = tag.attribs.first;
attrib_n != 0;
attrib_n = attrib_n->next)
{
Temp attrib_temp = temp_begin(tag_temp.arena);
DW_Attrib *attrib = &attrib_n->v;
// rjf: log attrib begin
dumpf("%S attrib: {");
// rjf: log basic info
dumpf(" off: 0x%I64x", attrib->info_off);
dumpf(", kind: %S", dw_string_from_attrib_kind(attrib_temp.arena, unit.version, unit.ext, attrib->attrib_kind));
dumpf(", form_kind: %S", dw_string_from_form_kind(attrib_temp.arena, unit.version, attrib->form_kind));
// rjf: log attrib's value based on vlass // rjf: log attrib's value based on vlass
dumpf(", "); DW_AttribClass value_class = dw_value_class_from_attrib(unit, attrib);
DW_AttribClass value_class = dw_value_class_from_attrib(&unit, attrib);
switch(value_class) switch(value_class)
{ {
default: {dumpf("`unknown value class`");}break; default: {str8_list_pushf(scratch.arena, &attrib_fmt, "`unknown value class`");}break;
case DW_AttribClass_Undefined: {dumpf("`undefined value class`");}break; case DW_AttribClass_Undefined: {str8_list_pushf(scratch.arena, &attrib_fmt, "`undefined value class`");}break;
case DW_AttribClass_Address: {dumpf("0x%I64x", dw_address_from_attrib(input, &unit, attrib));}break; case DW_AttribClass_Address: {str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", dw_address_from_attrib(input, unit, attrib));}break;
case DW_AttribClass_Const: {dumpf("0x%I64x", dw_const_u64_from_attrib(input, &unit, attrib));}break; case DW_AttribClass_Const: {str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", dw_const_u64_from_attrib(input, unit, attrib));}break;
case DW_AttribClass_Block: case DW_AttribClass_Block:
{ {
String8 block = dw_block_from_attrib(input, &unit, attrib); String8 block = dw_block_from_attrib(input, unit, attrib);
String8List block_strs = numeric_str8_list_from_data(attrib_temp.arena, 16, block, 1); String8List block_strs = numeric_str8_list_from_data(scratch.arena, 16, block, 1);
String8 block_str = str8_list_join(attrib_temp.arena, &block_strs, &(StringJoin){.sep = str8_lit(", ")}); String8 block_str = str8_list_join(scratch.arena, &block_strs, &(StringJoin){.sep = str8_lit(", ")});
dump(block_str); str8_list_pushf(scratch.arena, &attrib_fmt, "{ %S }", block_str);
}break; }break;
case DW_AttribClass_ExprLoc: case DW_AttribClass_ExprLoc:
{ {
String8 exprloc = dw_exprloc_from_attrib(input, &unit, attrib); String8 exprloc = dw_exprloc_from_attrib(input, unit, attrib);
String8 exprloc_str = dw_single_line_string_from_expression(attrib_temp.arena, exprloc, unit_range.min, unit.address_size, arch, unit.version, unit.ext, unit.format); String8 exprloc_str = dw_single_line_string_from_expression(scratch.arena, exprloc, unit->info_range.min, unit->address_size, arch, unit->version, unit->ext, unit->format);
dump(exprloc_str); str8_list_pushf(scratch.arena, &attrib_fmt, "{ %S }", exprloc_str);
}break; }break;
case DW_AttribClass_Flag: case DW_AttribClass_Flag:
{ {
B32 flag = dw_flag_from_attrib(input, &unit, attrib); B32 flag = dw_flag_from_attrib(input, unit, attrib);
dumpf("%llu: %s", flag, flag == 0 ? "false" : "true"); str8_list_pushf(scratch.arena, &attrib_fmt, "%llu (%s)", flag, flag == 0 ? "false" : "true");
}break; }break;
case DW_AttribClass_LinePtr: case DW_AttribClass_LinePtr:
case DW_AttribClass_LocListPtr: case DW_AttribClass_LocListPtr:
@@ -1660,11 +1591,11 @@ dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubs
{ {
if(attrib->form_kind == DW_Form_SecOffset) if(attrib->form_kind == DW_Form_SecOffset)
{ {
dumpf("0x%I64x", attrib->form.sec_offset); str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", attrib->form.sec_offset);
} }
else else
{ {
dumpf("`unexpected form kind %S`", dw_string_from_form_kind(attrib_temp.arena, unit.version, attrib->form_kind)); str8_list_pushf(scratch.arena, &attrib_fmt, "`unexpected form kind %S`", dw_string_from_form_kind(scratch.arena, unit->version, attrib->form_kind));
} }
}break; }break;
case DW_AttribClass_Reference: case DW_AttribClass_Reference:
@@ -1675,77 +1606,190 @@ dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubs
attrib->form_kind == DW_Form_Ref8 || attrib->form_kind == DW_Form_Ref8 ||
attrib->form_kind == DW_Form_RefUData) attrib->form_kind == DW_Form_RefUData)
{ {
U64 info_off = unit.info_range.min + attrib->form.ref; U64 info_off = unit->info_range.min + attrib->form.ref;
dumpf("0x%I64x", info_off); str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", info_off);
if(!contains_1u64(unit.info_range, attrib->form.ref)) if(!contains_1u64(unit->info_range, info_off))
{ {
dumpf(": `(out of this unit's bounds)`"); str8_list_pushf(scratch.arena, &attrib_fmt, ": `(out of this unit's bounds)`");
} }
} }
else else
{ {
dumpf("0x%I64x", attrib->form.ref); str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", attrib->form.ref);
} }
}break; }break;
case DW_AttribClass_String: case DW_AttribClass_String:
{ {
if(attrib->form_kind == DW_Form_Strp) if(attrib->form_kind == DW_Form_Strp || attrib->form_kind == DW_Form_LineStrp || attrib->form_kind == DW_Form_StrpSup)
{ {
dumpf("0x%I64x", attrib->form.sec_offset); str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x ", attrib->form.sec_offset);
} }
String8 string = dw_string_from_attrib(input, &unit, attrib); String8 string = dw_string_from_attrib(input, unit, attrib);
dumpf(": \"%S\"", string); str8_list_pushf(scratch.arena, &attrib_fmt, "\"%S\"", string);
}break; }break;
} }
// rjf: extend attrib's value with enum info // rjf: extend attrib's value with enum info
{
String8 enum_info = {0};
switch(attrib->attrib_kind) switch(attrib->attrib_kind)
{ {
case DW_AttribKind_Language: case DW_AttribKind_Language:
{ {
DW_Language lang = dw_const_u64_from_attrib(input, &unit, attrib); DW_Language lang = dw_const_u64_from_attrib(input, unit, attrib);
dumpf(": %S", dw_string_from_language(attrib_temp.arena, lang)); enum_info = dw_string_from_language(scratch.arena, lang);
}break; }break;
case DW_AttribKind_DeclFile: case DW_AttribKind_DeclFile:
{ {
U64 file_idx = dw_const_u64_from_attrib(input, &unit, attrib); U64 file_idx = dw_const_u64_from_attrib(input, unit, attrib);
DW_LineFile *file = dw_file_from_attrib(&unit, &line_vm, attrib); DW_LineFile *file = dw_file_from_attrib(unit, line_vm, attrib);
if(file != 0) if(file != 0)
{ {
dumpf(": %S", dw_path_from_file(attrib_temp.arena, &line_vm, file)); enum_info = dw_path_from_file(scratch.arena, line_vm, file);
} }
}break; }break;
case DW_AttribKind_DeclLine: case DW_AttribKind_DeclLine:
{ {
dumpf(": %I64u", dw_const_u64_from_attrib(input, &unit, attrib)); enum_info = str8f(scratch.arena, "%I64u", dw_const_u64_from_attrib(input, unit, attrib));
}break; }break;
case DW_AttribKind_Inline: case DW_AttribKind_Inline:
{ {
DW_InlKind inl = dw_const_u64_from_attrib(input, &unit, attrib); DW_InlKind inl = dw_const_u64_from_attrib(input, unit, attrib);
dumpf(": %S", dw_string_from_inl(attrib_temp.arena, inl)); enum_info = dw_string_from_inl(scratch.arena, inl);
}break; }break;
case DW_AttribKind_Accessibility: case DW_AttribKind_Accessibility:
{ {
DW_AccessKind access = dw_const_u64_from_attrib(input, &unit, attrib); DW_AccessKind access = dw_const_u64_from_attrib(input, unit, attrib);
dumpf(": %S", dw_string_from_access_kind(attrib_temp.arena, access)); enum_info = dw_string_from_access_kind(scratch.arena, access);
}break; }break;
case DW_AttribKind_CallingConvention: case DW_AttribKind_CallingConvention:
{ {
DW_CallingConventionKind calling_convetion = dw_const_u64_from_attrib(input, &unit, attrib); DW_CallingConventionKind calling_convetion = dw_const_u64_from_attrib(input, unit, attrib);
dumpf(": %S", dw_string_from_calling_convetion(attrib_temp.arena, calling_convetion)); enum_info = dw_string_from_calling_convetion(scratch.arena, calling_convetion);
}break; }break;
case DW_AttribKind_Encoding: case DW_AttribKind_Encoding:
{ {
DW_ATE encoding = dw_const_u64_from_attrib(input, &unit, attrib); DW_ATE encoding = dw_const_u64_from_attrib(input, unit, attrib);
dumpf(": %S", dw_string_from_attrib_type_encoding(attrib_temp.arena, encoding)); enum_info = dw_string_from_attrib_type_encoding(scratch.arena, encoding);
}break; }break;
} }
// rjf: log attrib end if(enum_info.size)
dumpf(" }\n"); {
str8_list_pushf(scratch.arena, &attrib_fmt, " `%S`", enum_info);
}
}
String8 result = str8_list_join(arena, &attrib_fmt, 0);
scratch_end(scratch);
return result;
}
internal String8List
dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubsetFlags subset_flags)
{
String8List strings = {0};
String8 indent = str8_lit(" ");
#define dump(str) str8_list_push(arena, &strings, (str))
#define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__)
#define DumpSubset(name) if(subset_flags & DW_DumpSubsetFlag_##name) DeferLoop(dumpf("// %S\n\n", dw_name_title_from_dump_subset_table[DW_DumpSubset_##name]), dump(str8_lit("\n")))
Temp scratch = scratch_begin(&arena, 1);
Rng1U64Array segment_vranges = {0};
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input);
B32 relaxed = 1;
DW_CompUnit *cu_arr;
{
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input);
Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data);
Rng1U64Array cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list);
cu_arr = push_array(scratch.arena, DW_CompUnit, cu_ranges.count);
for EachIndex(cu_idx, cu_ranges.count)
{
cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, input, lu_input, cu_ranges.v[cu_idx].min, relaxed);
}
}
//////////////////////////////
//- rjf: dump .debug_info
//
DumpSubset(DebugInfo)
{
Rng1U64List unit_ranges_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data);
Rng1U64Array unit_ranges = rng1u64_array_from_list(scratch.arena, &unit_ranges_list);
for EachIndex(unit_idx, unit_ranges.count)
{
Temp unit_temp = temp_begin(scratch.arena);
//- rjf: unpack unit
Rng1U64 unit_range = unit_ranges.v[unit_idx];
DW_CompUnit *unit = &cu_arr[unit_idx];
String8 unit_dir = dw_string_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_CompDir );
String8 unit_name = dw_string_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_Name );
String8 stmt_list = dw_line_ptr_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_StmtList);
DW_LineVMHeader line_vm = {0};
dw_read_line_vm_header(unit_temp.arena, stmt_list, 0, input, unit_dir, unit_name, unit->address_size, unit->str_offsets_lu, &line_vm);
//- rjf: log top-level unit info
dumpf("unit: // compile_unit[%I64u]\n{\n", unit_idx);
dumpf(" version: %u\n", unit->version);
dumpf(" address_size: %I64u\n", unit->address_size);
dumpf(" abbrev_off: 0x%I64x\n", unit->abbrev_off);
dumpf(" info_range: [0x%I64x, 0x%I64x) // (%M)\n", unit->info_range.min, unit->info_range.max, dim_1u64(unit->info_range));
//- rjf: log tags
S64 tag_depth = 0;
U64 tag_idx = 0;
for(U64 info_off = unit->first_tag_info_off; info_off < unit->info_range.max; tag_idx += 1)
{
Temp tag_temp = temp_begin(scratch.arena);
// rjf: unpack tag
String8 tag_indent = str8_prefix(indent, (tag_depth+1)*2);
U64 tag_info_off = info_off;
DW_Tag tag = {0};
info_off += dw_read_tag_cu(tag_temp.arena, input, unit, tag_info_off, &tag);
// rjf: log top-level tag info
dumpf("%Stag: // info_off: 0x%I64x, abbrev_id: %I64u, compile_unit[%I64u].tag[%I64u]\n%S{\n", tag_indent, tag_info_off, tag.abbrev_id, unit_idx, tag_idx, tag_indent);
dumpf("%S kind: %S\n", tag_indent, dw_string_from_tag_kind(tag_temp.arena, tag.kind));
// log attribs
{
// compute columns' max widths
U64 attrib_name_max_size = 0, form_kind_max_size = 0, value_max_size = 0;
for EachNode(attrib_n, DW_AttribNode, tag.attribs.first)
{
Temp attrib_temp = temp_begin(tag_temp.arena);
attrib_name_max_size = Max(attrib_name_max_size, dw_string_from_attrib_kind(attrib_temp.arena, unit->version, unit->ext, attrib_n->v.attrib_kind).size);
form_kind_max_size = Max(form_kind_max_size, dw_string_from_form_kind(attrib_temp.arena, unit->version, attrib_n->v.form_kind).size);
value_max_size = Max(value_max_size, dw_string_from_attrib_value(attrib_temp.arena, input, arch, unit, &line_vm, &attrib_n->v).size);
temp_end(attrib_temp);
}
value_max_size = Min(120, value_max_size);
// log
for EachNode(attrib_n, DW_AttribNode, tag.attribs.first)
{
DW_Attrib *attrib = &attrib_n->v;
Temp attrib_temp = temp_begin(tag_temp.arena);
String8 attrib_kind_str = dw_string_from_attrib_kind(attrib_temp.arena, unit->version, unit->ext, attrib->attrib_kind);
String8 form_kind_str = dw_string_from_form_kind(attrib_temp.arena, unit->version, attrib->form_kind);
String8 value_str = dw_string_from_attrib_value(attrib_temp.arena, input, arch, unit, &line_vm, attrib);
dumpf("%S attrib: { kind: %S, %.*sform_kind: %S, %.*svalue: %S, %.*s} // info_off: 0x%I64x\n",
tag_indent,
attrib_kind_str, attrib_name_max_size - attrib_kind_str.size, indent.str,
form_kind_str, form_kind_max_size - form_kind_str.size, indent.str,
value_str, value_str.size < value_max_size ? value_max_size - value_str.size: 0, indent.str,
attrib->info_off, unit_idx, tag_idx);
temp_end(attrib_temp); temp_end(attrib_temp);
} }
}
// rjf: log tag closes // rjf: log tag closes
if(!tag.has_children || tag.abbrev_id == 0) if(!tag.has_children || tag.abbrev_id == 0)
@@ -1758,7 +1802,7 @@ dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubs
{ {
tag_depth += 1; tag_depth += 1;
} }
if(tag.abbrev_id) if(!tag.abbrev_id)
{ {
tag_depth -= 1; tag_depth -= 1;
} }
@@ -1822,17 +1866,20 @@ dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubs
// //
DumpSubset(DebugLine) DumpSubset(DebugLine)
{ {
Rng1U64List unit_ranges_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Line].data);
Rng1U64Array unit_ranges = rng1u64_array_from_list(scratch.arena, &unit_ranges_list);
for EachIndex(unit_idx, unit_ranges.count) for EachIndex(unit_idx, unit_ranges.count)
{ {
Temp unit_temp = temp_begin(scratch.arena); Temp unit_temp = temp_begin(scratch.arena);
// rjf: unpack unit // rjf: unpack unit
String8 unit_data = str8_substr(input->sec[DW_Section_Line].data, unit_ranges.v[unit_idx]); String8 raw_lines = str8_substr(input->sec[DW_Section_Line].data, unit_ranges.v[unit_idx]);
String8 cu_dir = {0}; DW_CompUnit *cu = &cu_arr[unit_idx];
String8 cu_name = {0}; String8 cu_stmt_list = dw_line_ptr_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_StmtList);
DW_ListUnit cu_str_offsets = {0}; String8 cu_dir = dw_string_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_CompDir);
String8 cu_name = dw_string_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_Name);
DW_LineVMHeader line_vm = {0}; DW_LineVMHeader line_vm = {0};
U64 line_vm_size = dw_read_line_vm_header(unit_temp.arena, unit_data, 0, input, cu_dir, cu_name, line_vm.address_size, &cu_str_offsets, &line_vm); U64 line_vm_size = dw_read_line_vm_header(unit_temp.arena, raw_lines, 0, input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu, &line_vm);
if(line_vm_size == 0) if(line_vm_size == 0)
{ {
continue; continue;
@@ -1892,7 +1939,7 @@ dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubs
// rjf: log opcodes // rjf: log opcodes
DeferLoop(dumpf(" opcodes:\n {\n"), dumpf(" }\n\n")) DeferLoop(dumpf(" opcodes:\n {\n"), dumpf(" }\n\n"))
{ {
String8 opcodes = str8_skip(unit_data, line_vm_size); String8 opcodes = str8_skip(raw_lines, line_vm_size);
B32 end_of_seq = 0; B32 end_of_seq = 0;
DW_LineVMState vm_state = {0}; DW_LineVMState vm_state = {0};
dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); dw_line_vm_reset(&vm_state, line_vm.default_is_stmt);