From f396b2eaa32850742700487fd7771b95ab80df7d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Nov 2025 15:06:52 -0800 Subject: [PATCH] start dwarf -> rdi cleanup; eliminate some assertions-as-validation, remove incorrect assumption that line info addresses are vaddrs (they seem to be voffs) --- project.4coder | 4 +- src/dwarf/dwarf.h | 6 +- src/dwarf/dwarf_dump.c | 444 +++++------ src/dwarf/dwarf_parse.c | 1141 ++++++++++++++------------- src/elf/elf.h | 6 +- src/rdi_from_coff/rdi_from_coff.c | 13 +- src/rdi_from_dwarf/rdi_from_dwarf.c | 1008 +++++++++++++---------- src/rdi_from_dwarf/rdi_from_dwarf.h | 23 +- src/rdi_from_elf/rdi_from_elf.c | 31 +- src/rdi_from_elf/rdi_from_elf.h | 3 +- src/rdi_from_pdb/rdi_from_pdb.h | 4 +- 11 files changed, 1433 insertions(+), 1250 deletions(-) diff --git a/project.4coder b/project.4coder index 69b7529f..137f091b 100644 --- a/project.4coder +++ b/project.4coder @@ -46,8 +46,8 @@ load_paths = commands = { //- rjf: [raddbg] - .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg meta telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - // .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin 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 meta telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [raddbg wsl] // .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/dwarf/dwarf.h b/src/dwarf/dwarf.h index 89e9b099..2fc8668f 100644 --- a/src/dwarf/dwarf.h +++ b/src/dwarf/dwarf.h @@ -1582,9 +1582,9 @@ typedef enum DW_ExprOpEnum { #define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) DW_ExprOp_##_N = _ID, DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) + DW_Expr_V4_XList(X) + DW_Expr_V5_XList(X) + DW_Expr_GNU_XList(X) #undef X } DW_ExprOpEnum; diff --git a/src/dwarf/dwarf_dump.c b/src/dwarf/dwarf_dump.c index 27ad6dd0..e551e4ea 100644 --- a/src/dwarf/dwarf_dump.c +++ b/src/dwarf/dwarf_dump.c @@ -350,7 +350,7 @@ dw_string_list_from_cfi_program(Arena *arena, { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; - + U64 reg_max = dw_reg_count_from_arch(arch); U64 pc = pc_begin; for (U64 cursor = 0, inst_size; cursor < program.size; cursor += inst_size) { @@ -362,134 +362,134 @@ dw_string_list_from_cfi_program(Arena *arena, str8_list_pushf(arena, &list, "ERROR: failed to unpack CFA instruction @ 0x%I64", cursor); break; } - + // error check operands DW_CFA_OperandType *operand_types = dw_operand_types_from_cfa_op(inst.opcode); U64 operand_count = dw_operand_count_from_cfa_opcode(inst.opcode); for EachIndex(operand_idx, operand_count) { switch (operand_types[operand_idx]) { - case DW_CFA_OperandType_Null: break; - case DW_CFA_OperandType_Value: break; - case DW_CFA_OperandType_Register: { - if (inst.operands[operand_idx].u64 >= reg_max) { - str8_list_pushf(arena, &list, "ERROR: DW_CFA_%S @ 0x%I64x has an invalid register", - dw_string_from_cfa_opcode(inst.opcode), - cursor); - } - } break; - case DW_CFA_OperandType_Expression: { - DW_Expr expr = dw_expr_from_data(scratch.arena, format, cie->address_size, inst.operands[operand_idx].block); - for EachNode(inst, DW_ExprInst, expr.first) { - if (dw_is_cfa_expr_opcode_invalid(inst->opcode)) { - String8 expr_opcode_str = dw_string_from_expr_op(scratch.arena, ver, ext, inst->opcode); - str8_list_pushf(arena, &list, "ERROR: Exrepssion in DW_CFA_%S @ 0x%I64x has an invalid opcode DW_ExprOp_%S", expr_opcode_str); + case DW_CFA_OperandType_Null: break; + case DW_CFA_OperandType_Value: break; + case DW_CFA_OperandType_Register: { + if (inst.operands[operand_idx].u64 >= reg_max) { + str8_list_pushf(arena, &list, "ERROR: DW_CFA_%S @ 0x%I64x has an invalid register", + dw_string_from_cfa_opcode(inst.opcode), + cursor); } - } - } break; - default: { InvalidPath; } break; + } break; + case DW_CFA_OperandType_Expression: { + DW_Expr expr = dw_expr_from_data(scratch.arena, format, cie->address_size, inst.operands[operand_idx].block); + for EachNode(inst, DW_ExprInst, expr.first) { + if (dw_is_cfa_expr_opcode_invalid(inst->opcode)) { + String8 expr_opcode_str = dw_string_from_expr_op(scratch.arena, ver, ext, inst->opcode); + str8_list_pushf(arena, &list, "ERROR: Exrepssion in DW_CFA_%S @ 0x%I64x has an invalid opcode DW_ExprOp_%S", expr_opcode_str); + } + } + } break; + default: { InvalidPath; } break; } } - + // format operands String8 operand_str = str8_lit("???"); switch (inst.opcode) { - case DW_CFA_Nop: { operand_str = str8_zero(); } break; - case DW_CFA_SetLoc: { - operand_str = str8f(arena, "0x%X", inst.operands[0].u64); - pc = inst.operands[0].u64; - } break; - case DW_CFA_AdvanceLoc1: { - U64 delta = inst.operands[0].u64; - pc += delta; - operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); - } break; - case DW_CFA_AdvanceLoc2: { - U64 delta = inst.operands[0].u64; - pc += delta; - operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); - } break; - case DW_CFA_AdvanceLoc4: { - U64 delta = inst.operands[0].u64; - pc += delta; - operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); - } break; - case DW_CFA_OffsetExt: { - U64 reg = inst.operands[0].u64; - S64 offset = (S64)inst.operands[1].u64; - operand_str = dw_string_from_reg_off(arena, arch, reg, offset); - } break; - case DW_CFA_RestoreExt: { operand_str = str8_zero(); } break; - case DW_CFA_Undefined: { - operand_str = str8f(arena, "%I64u", inst.operands[0].u64); - } break; - case DW_CFA_SameValue: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); - } break; - case DW_CFA_Register: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); - } break; - case DW_CFA_RememberState: { operand_str = str8_zero(); } break; - case DW_CFA_RestoreState: { operand_str = str8_zero(); } break; - case DW_CFA_DefCfa: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); - } break; - case DW_CFA_DefCfaRegister: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); - } break; - case DW_CFA_DefCfaOffset: { - operand_str = str8f(arena, "+%I64u", inst.operands[0].u64); - } break; - case DW_CFA_DefCfaExpr: { - operand_str = dw_string_from_expression(arena, inst.operands[0].block, cu_base, cie->address_size, arch, ver, ext, format); - } break; - case DW_CFA_Expr: { - String8 reg_str = dw_string_from_reg_off(scratch.arena, arch, inst.operands[0].u64, 0); - String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); - operand_str = str8f(arena, "%S expression %S", reg_str, expr_str); - } break; - case DW_CFA_OffsetExtSf: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); - } break; - case DW_CFA_DefCfaSf: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); - } break; - case DW_CFA_DefCfaOffsetSf: { operand_str = str8_zero(); } break; - case DW_CFA_ValOffset: { - operand_str = str8f(arena, "value 0x%llx, offset %+I64d", inst.operands[0].u64, inst.operands[1].u64); - } break; - case DW_CFA_ValOffsetSf: { - operand_str = str8f(arena, "value %llu, offset %+I64d", inst.operands[0].u64, inst.operands[1].s64); - } break; - case DW_CFA_ValExpr: { - String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); - operand_str = str8f(arena, "value +%I64u, expression %S", inst.operands[0].u64, expr_str); - } break; - case DW_CFA_AdvanceLoc: { - U64 delta = inst.operands[0].u64; - pc += delta; - operand_str = str8f(arena, "+%I64u `PC 0x%I64x`", delta, pc); - } break; - case DW_CFA_Offset: { - U64 reg = inst.operands[0].u64; - S64 offset = (S64)inst.operands[1].u64; - operand_str = dw_string_from_reg_off(arena, arch, reg, offset); - } break; - case DW_CFA_Restore: { - operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); - } break; - default: { - str8_list_pushf(arena, &list, "ERROR: unknown CFA opcode 0x%I64u", inst.opcode); - } goto exit; + case DW_CFA_Nop: { operand_str = str8_zero(); } break; + case DW_CFA_SetLoc: { + operand_str = str8f(arena, "0x%X", inst.operands[0].u64); + pc = inst.operands[0].u64; + } break; + case DW_CFA_AdvanceLoc1: { + U64 delta = inst.operands[0].u64; + pc += delta; + operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); + } break; + case DW_CFA_AdvanceLoc2: { + U64 delta = inst.operands[0].u64; + pc += delta; + operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); + } break; + case DW_CFA_AdvanceLoc4: { + U64 delta = inst.operands[0].u64; + pc += delta; + operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); + } break; + case DW_CFA_OffsetExt: { + U64 reg = inst.operands[0].u64; + S64 offset = (S64)inst.operands[1].u64; + operand_str = dw_string_from_reg_off(arena, arch, reg, offset); + } break; + case DW_CFA_RestoreExt: { operand_str = str8_zero(); } break; + case DW_CFA_Undefined: { + operand_str = str8f(arena, "%I64u", inst.operands[0].u64); + } break; + case DW_CFA_SameValue: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); + } break; + case DW_CFA_Register: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); + } break; + case DW_CFA_RememberState: { operand_str = str8_zero(); } break; + case DW_CFA_RestoreState: { operand_str = str8_zero(); } break; + case DW_CFA_DefCfa: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); + } break; + case DW_CFA_DefCfaRegister: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); + } break; + case DW_CFA_DefCfaOffset: { + operand_str = str8f(arena, "+%I64u", inst.operands[0].u64); + } break; + case DW_CFA_DefCfaExpr: { + operand_str = dw_string_from_expression(arena, inst.operands[0].block, cu_base, cie->address_size, arch, ver, ext, format); + } break; + case DW_CFA_Expr: { + String8 reg_str = dw_string_from_reg_off(scratch.arena, arch, inst.operands[0].u64, 0); + String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); + operand_str = str8f(arena, "%S expression %S", reg_str, expr_str); + } break; + case DW_CFA_OffsetExtSf: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); + } break; + case DW_CFA_DefCfaSf: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); + } break; + case DW_CFA_DefCfaOffsetSf: { operand_str = str8_zero(); } break; + case DW_CFA_ValOffset: { + operand_str = str8f(arena, "value 0x%llx, offset %+I64d", inst.operands[0].u64, inst.operands[1].u64); + } break; + case DW_CFA_ValOffsetSf: { + operand_str = str8f(arena, "value %llu, offset %+I64d", inst.operands[0].u64, inst.operands[1].s64); + } break; + case DW_CFA_ValExpr: { + String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); + operand_str = str8f(arena, "value +%I64u, expression %S", inst.operands[0].u64, expr_str); + } break; + case DW_CFA_AdvanceLoc: { + U64 delta = inst.operands[0].u64; + pc += delta; + operand_str = str8f(arena, "+%I64u `PC 0x%I64x`", delta, pc); + } break; + case DW_CFA_Offset: { + U64 reg = inst.operands[0].u64; + S64 offset = (S64)inst.operands[1].u64; + operand_str = dw_string_from_reg_off(arena, arch, reg, offset); + } break; + case DW_CFA_Restore: { + operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); + } break; + default: { + str8_list_pushf(arena, &list, "ERROR: unknown CFA opcode 0x%I64u", inst.opcode); + } goto exit; } - + if (operand_str.size) { str8_list_pushf(arena, &list, "DW_CFA_%S: %S", dw_string_from_cfa_opcode(inst.opcode), operand_str); } else { str8_list_pushf(arena, &list, "DW_CFA_%S", dw_string_from_cfa_opcode(inst.opcode)); } } - -exit:; + + exit:; scratch_end(scratch); return list; } @@ -499,10 +499,10 @@ dw_string_from_cfa(Arena *arena, Arch arch, U64 address_size, DW_Version version { String8 cfa_str = str8_lit("???"); switch (cfa.rule) { - case DW_CFA_Rule_Null: {} break; - case DW_CFA_Rule_RegOff: { cfa_str = dw_string_from_reg_off(arena, arch, cfa.reg, cfa.off); } break; - case DW_CFA_Rule_Expression: { cfa_str = dw_string_from_expression(arena, cfa.expr, max_U64, address_size, arch, version, ext, format); } break; - default: { InvalidPath; } break; + case DW_CFA_Rule_Null: {} break; + case DW_CFA_Rule_RegOff: { cfa_str = dw_string_from_reg_off(arena, arch, cfa.reg, cfa.off); } break; + case DW_CFA_Rule_Expression: { cfa_str = dw_string_from_expression(arena, cfa.expr, max_U64, address_size, arch, version, ext, format); } break; + default: { InvalidPath; } break; } return cfa_str; } @@ -517,40 +517,40 @@ dw_string_from_cfi_row(Arena *arena, Arch arch, U64 address_size, DW_Version ver DW_CFI_Register *cfi_reg = &row->regs[reg_idx]; String8 rule_str = str8_lit("???"); switch (cfi_reg->rule) { - case DW_CFI_RegisterRule_Undefined: { - rule_str = str8f(scratch.arena, "Undefined(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); - } break; - case DW_CFI_RegisterRule_SameValue: { - rule_str = str8_zero(); - } break; - case DW_CFI_RegisterRule_Offset: { - rule_str = str8f(scratch.arena, "[CFA%+I64d]", cfi_reg->n); - } break; - case DW_CFI_RegisterRule_ValOffset: { - rule_str = str8f(scratch.arena, "Val(CFA%+I64d)", cfi_reg->n); - } break; - case DW_CFI_RegisterRule_Register: { - rule_str = str8f(scratch.arena, "Register(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); - } break; - case DW_CFI_RegisterRule_Expression: { - rule_str = str8f(scratch.arena, "Expression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); - } break; - case DW_CFI_RegisterRule_ValExpression: { - rule_str = str8f(scratch.arena, "ValExpression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); - } break; - case DW_CFI_RegisterRule_Architectural: { - rule_str = str8_lit("???"); - } break; - default: { InvalidPath; } break; + case DW_CFI_RegisterRule_Undefined: { + rule_str = str8f(scratch.arena, "Undefined(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); + } break; + case DW_CFI_RegisterRule_SameValue: { + rule_str = str8_zero(); + } break; + case DW_CFI_RegisterRule_Offset: { + rule_str = str8f(scratch.arena, "[CFA%+I64d]", cfi_reg->n); + } break; + case DW_CFI_RegisterRule_ValOffset: { + rule_str = str8f(scratch.arena, "Val(CFA%+I64d)", cfi_reg->n); + } break; + case DW_CFI_RegisterRule_Register: { + rule_str = str8f(scratch.arena, "Register(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); + } break; + case DW_CFI_RegisterRule_Expression: { + rule_str = str8f(scratch.arena, "Expression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); + } break; + case DW_CFI_RegisterRule_ValExpression: { + rule_str = str8f(scratch.arena, "ValExpression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); + } break; + case DW_CFI_RegisterRule_Architectural: { + rule_str = str8_lit("???"); + } break; + default: { InvalidPath; } break; } - + if (rule_str.size) { str8_list_pushf(scratch.arena, &cfi_regs_list, "%S: %S", dw_string_from_reg(scratch.arena, arch, reg_idx), rule_str); } } - + String8 string = str8_list_join(arena, &cfi_regs_list, &(StringJoin){.sep=str8_lit(", ")}); - + scratch_end(scratch); return string; } @@ -1601,7 +1601,7 @@ internal String8 dw_string_from_attrib_value(Arena *arena, DW_Input *input, Arch arch, DW_CompUnit *unit, DW_LineVMHeader *line_vm, DW_Attrib *attrib) { Temp scratch = scratch_begin(&arena, 1); - + String8List attrib_fmt = {0}; // rjf: log attrib's value based on vlass @@ -1722,7 +1722,7 @@ dw_string_from_attrib_value(Arena *arena, DW_Input *input, Arch arch, DW_CompUni enum_info = dw_string_from_attrib_type_encoding(scratch.arena, encoding); }break; } - + if(enum_info.size) { str8_list_pushf(scratch.arena, &attrib_fmt, " `%S`", enum_info); @@ -1730,7 +1730,7 @@ dw_string_from_attrib_value(Arena *arena, DW_Input *input, Arch arch, DW_CompUni } String8 result = str8_list_join(arena, &attrib_fmt, 0); - + scratch_end(scratch); return result; } @@ -1750,7 +1750,7 @@ dw_dump_list_from_sections(Arena *arena, 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); @@ -1780,7 +1780,7 @@ dw_dump_list_from_sections(Arena *arena, 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_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 @@ -1820,25 +1820,25 @@ dw_dump_list_from_sections(Arena *arena, 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); - + 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); } } @@ -2199,7 +2199,7 @@ dw_dump_list_from_sections(Arena *arena, dumpf(" { 0x%08I64x %llu \"%S\" }\n", cursor, string.size, string); } } - + ////////////////////////////// //~ dump .debug_frame DumpSubset(DebugFrame) @@ -2207,7 +2207,7 @@ dw_dump_list_from_sections(Arena *arena, HashTable *cie_ht = hash_table_init(scratch.arena, 0x2000); String8 debug_frame = input->sec[DW_Section_Frame].data; U64 addr_size = byte_size_from_arch(arch); - + // make offset -> CIE hash table for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; @@ -2229,71 +2229,71 @@ dw_dump_list_from_sections(Arena *arena, desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); String8 raw_desc = str8_substr(debug_frame, desc.entry_range); switch (desc.type) { - case DW_DescriptorEntryType_Null: {} break; - case DW_DescriptorEntryType_CIE: { - DW_CIE cie = {0}; - if (dw_parse_cie(raw_desc, desc.format, arch, &cie)) { - String8List init_insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, DW_Version_5, DW_Ext_All, cie.format, 0, &cie, dw_decode_ptr_debug_frame, &cie, cie.insts); - - dumpf("CIE: // entry range: %r\n", desc.entry_range); - dumpf("{\n"); - dumpf(" Format: %S\n", dw_string_from_format(desc.format)); - dumpf(" Version: %u\n", cie.version); - dumpf(" Aug string: \"%S\"\n", cie.aug_string); - dumpf(" Code align: %I64u\n", cie.code_align_factor); - dumpf(" Data align: %I64d\n", cie.data_align_factor); - dumpf(" Return addr reg: %u\n", cie.ret_addr_reg); - if (cie.version > DW_Version_3) { - dumpf(" Address size: %u\n", cie.address_size); - dumpf(" Segment selector size: %u\n", cie.segment_selector_size); - } - dumpf(" Initial Insturction:\n"); - dumpf(" {\n"); - for EachNode(n, String8Node, init_insts_str_list.first) { dumpf(" %S\n", n->string); } - dumpf(" }\n"); - dumpf("}\n"); - } else { - dumpf("ERROR: unable to parse CIE @ %I64x\n", desc.entry_range.min); - } - } break; - case DW_DescriptorEntryType_FDE: { - DW_DescriptorEntry cie_desc = {0}; - U64 cie_desc_size = dw_parse_descriptor_entry_header(debug_frame, desc.cie_pointer, &cie_desc); - String8 cie_data = str8_substr(debug_frame, cie_desc.entry_range); - DW_CIE cie = {0}; - dw_parse_cie(cie_data, cie_desc.format, arch, &cie); - - DW_FDE fde = {0}; - if (dw_parse_fde(raw_desc, desc.format, &cie, &fde)) { - DW_Version version = DW_Version_5; - DW_Ext ext = DW_Ext_All; - String8List insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, version, ext, fde.format, fde.pc_range.min, &cie, dw_decode_ptr_debug_frame, &cie, fde.insts); - dumpf("FDE: // entry range: %r\n", desc.entry_range); - dumpf("{\n"); - { - dumpf(" Format: %S\n", dw_string_from_format(fde.format)); - dumpf(" CIE pointer: 0x%I64x\n", fde.cie_pointer); - dumpf(" PC range: %r\n", fde.pc_range); - dumpf(" Instructions:\n"); + case DW_DescriptorEntryType_Null: {} break; + case DW_DescriptorEntryType_CIE: { + DW_CIE cie = {0}; + if (dw_parse_cie(raw_desc, desc.format, arch, &cie)) { + String8List init_insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, DW_Version_5, DW_Ext_All, cie.format, 0, &cie, dw_decode_ptr_debug_frame, &cie, cie.insts); + + dumpf("CIE: // entry range: %r\n", desc.entry_range); + dumpf("{\n"); + dumpf(" Format: %S\n", dw_string_from_format(desc.format)); + dumpf(" Version: %u\n", cie.version); + dumpf(" Aug string: \"%S\"\n", cie.aug_string); + dumpf(" Code align: %I64u\n", cie.code_align_factor); + dumpf(" Data align: %I64d\n", cie.data_align_factor); + dumpf(" Return addr reg: %u\n", cie.ret_addr_reg); + if (cie.version > DW_Version_3) { + dumpf(" Address size: %u\n", cie.address_size); + dumpf(" Segment selector size: %u\n", cie.segment_selector_size); + } + dumpf(" Initial Insturction:\n"); dumpf(" {\n"); - for EachNode(n, String8Node, insts_str_list.first) { dumpf(" %S\n", n->string); } + for EachNode(n, String8Node, init_insts_str_list.first) { dumpf(" %S\n", n->string); } dumpf(" }\n"); + dumpf("}\n"); + } else { + dumpf("ERROR: unable to parse CIE @ %I64x\n", desc.entry_range.min); } - dumpf(" Unwind:\n"); - dumpf(" {\n"); - DW_CFI_Unwind *cfi_unwind = dw_cfi_unwind_init(scratch.arena, arch, &cie, &fde, dw_decode_ptr_debug_frame, &cie); - do { - String8 cfa_str = dw_string_from_cfa(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row->cfa); - String8 cfi_regs_str = dw_string_from_cfi_row(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row); - dumpf(" { PC: 0x%I64x, CFA: %-7S, Rules: { %S }\n", cfi_unwind->pc, cfa_str, cfi_regs_str); - } while (dw_cfi_next_row(scratch.arena, cfi_unwind)); - dumpf(" }\n"); - - dumpf("}\n"); - } else { - dumpf("ERROR: unable to parse FDE @ %I64x\n", desc.entry_range.min); - } - } break; + } break; + case DW_DescriptorEntryType_FDE: { + DW_DescriptorEntry cie_desc = {0}; + U64 cie_desc_size = dw_parse_descriptor_entry_header(debug_frame, desc.cie_pointer, &cie_desc); + String8 cie_data = str8_substr(debug_frame, cie_desc.entry_range); + DW_CIE cie = {0}; + dw_parse_cie(cie_data, cie_desc.format, arch, &cie); + + DW_FDE fde = {0}; + if (dw_parse_fde(raw_desc, desc.format, &cie, &fde)) { + DW_Version version = DW_Version_5; + DW_Ext ext = DW_Ext_All; + String8List insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, version, ext, fde.format, fde.pc_range.min, &cie, dw_decode_ptr_debug_frame, &cie, fde.insts); + dumpf("FDE: // entry range: %r\n", desc.entry_range); + dumpf("{\n"); + { + dumpf(" Format: %S\n", dw_string_from_format(fde.format)); + dumpf(" CIE pointer: 0x%I64x\n", fde.cie_pointer); + dumpf(" PC range: %r\n", fde.pc_range); + dumpf(" Instructions:\n"); + dumpf(" {\n"); + for EachNode(n, String8Node, insts_str_list.first) { dumpf(" %S\n", n->string); } + dumpf(" }\n"); + } + dumpf(" Unwind:\n"); + dumpf(" {\n"); + DW_CFI_Unwind *cfi_unwind = dw_cfi_unwind_init(scratch.arena, arch, &cie, &fde, dw_decode_ptr_debug_frame, &cie); + do { + String8 cfa_str = dw_string_from_cfa(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row->cfa); + String8 cfi_regs_str = dw_string_from_cfi_row(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row); + dumpf(" { PC: 0x%I64x, CFA: %-7S, Rules: { %S }\n", cfi_unwind->pc, cfa_str, cfi_regs_str); + } while (dw_cfi_next_row(scratch.arena, cfi_unwind)); + dumpf(" }\n"); + + dumpf("}\n"); + } else { + dumpf("ERROR: unable to parse FDE @ %I64x\n", desc.entry_range.min); + } + } break; } } } diff --git a/src/dwarf/dwarf_parse.c b/src/dwarf/dwarf_parse.c index 8559b08d..481b5eee 100644 --- a/src/dwarf/dwarf_parse.c +++ b/src/dwarf/dwarf_parse.c @@ -12,12 +12,17 @@ internal U64 str8_deserial_read_dwarf_packed_size(String8 string, U64 off, U64 *size_out) { U64 bytes_read = 0; - if (str8_deserial_read(string, off, size_out, sizeof(U32), sizeof(U32))) { - if (*size_out == max_U32) { - if (str8_deserial_read_struct(string, off+sizeof(U32), size_out)) { + if(str8_deserial_read(string, off, size_out, sizeof(U32), sizeof(U32))) + { + if(*size_out == max_U32) + { + if(str8_deserial_read_struct(string, off+sizeof(U32), size_out)) + { bytes_read = sizeof(U32) + sizeof(U64); } - } else { + } + else + { *size_out &= (U64)max_U32; bytes_read = sizeof(U32); } @@ -29,15 +34,18 @@ internal U64 str8_deserial_read_dwarf_uint(String8 string, U64 off, DW_Format format, U64 *uint_out) { U64 bytes_read = 0; - switch (format) { + switch(format) + { case DW_Format_Null: break; - case DW_Format_32Bit: { + case DW_Format_32Bit: + { *uint_out &= (U64)max_U32; bytes_read = str8_deserial_read(string, off, uint_out, sizeof(U32), sizeof(U32)); - } break; - case DW_Format_64Bit: { + }break; + case DW_Format_64Bit: + { bytes_read = str8_deserial_read_struct(string, off, uint_out); - } break; + }break; } return bytes_read; } @@ -196,27 +204,26 @@ internal Rng1U64List dw_unit_ranges_from_data(Arena *arena, String8 data) { Rng1U64List result = {0}; - - for (U64 cursor = 0; cursor < data.size; ) { - // read CU size - U64 cu_size = 0; + for(U64 cursor = 0; cursor < data.size;) + { + // rjf: read CU size; bad read -> terminate + U64 cu_size = 0; U64 cu_size_size = str8_deserial_read_dwarf_packed_size(data, cursor, &cu_size); - - // was read ok? - if (cu_size_size == 0) { + if(cu_size_size == 0) + { break; } - if (cu_size > 0) { - // push unit range + // rjf: push + if(cu_size > 0) + { rng1u64_list_push(arena, &result, rng_1u64(cursor, cursor+cu_size+cu_size_size)); } - // advance + // rjf: advance cursor += cu_size_size; cursor += cu_size; } - return result; } @@ -2420,15 +2427,7 @@ dw_read_line_file_array(Arena *arena, } internal U64 -dw_read_line_vm_header(Arena *arena, - String8 line_data, - U64 line_off, - DW_Input *input, - String8 cu_dir, - String8 cu_name, - U8 cu_address_size, - DW_ListUnit *cu_str_offsets, - DW_LineVMHeader *header_out) +dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out) { Temp scratch = scratch_begin(&arena, 1); @@ -2824,37 +2823,35 @@ dw_path_from_file_idx(Arena *arena, DW_LineVMHeader *vm, U64 file_idx) } internal DW_LineTableParseResult -dw_parsed_line_table_from_data(Arena *arena, - String8 unit_data, - DW_Input *input, - String8 cu_dir, - String8 cu_name, - U8 cu_address_size, - DW_ListUnit *cu_str_offsets) +dw_parsed_line_table_from_data(Arena *arena, String8 unit_data, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets) { DW_LineVMHeader vm_header = {0}; U64 vm_header_size = dw_read_line_vm_header(arena, unit_data, 0, input, cu_dir, cu_name, cu_address_size, cu_str_offsets, &vm_header); - U64 unit_cursor = vm_header_size; + U64 unit_cursor_opl = Min(unit_data.size, vm_header.unit_range.max); //- rjf: prep state for VM DW_LineVMState vm_state = {0}; dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); //- rjf: VM loop; build output list - DW_LineTableParseResult result = { .vm_header = vm_header }; - B32 end_of_seq = 0; - B32 error = 0; - for (; !error && unit_cursor < unit_data.size; ) { + DW_LineTableParseResult result = {.vm_header = vm_header}; + B32 end_of_seq = 0; + B32 error = 0; + for(;!error && unit_cursor < unit_cursor_opl;) + { //- rjf: parse opcode U8 opcode = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &opcode); //- rjf: do opcode action - switch (opcode) { - default: { - //- rjf: special opcode case - if (opcode >= vm_header.opcode_base) { + switch(opcode) + { + //- rjf: special opcode cases + default: + { + if(opcode >= vm_header.opcode_base) + { U32 adjusted_opcode = (U32)(opcode - vm_header.opcode_base); U32 op_advance = adjusted_opcode / vm_header.line_range; S32 line_inc = (S32)vm_header.line_base + ((S32)adjusted_opcode) % (S32)vm_header.line_range; @@ -2884,25 +2881,31 @@ dw_parsed_line_table_from_data(Arena *arena, } #endif } + // Skipping unknown opcode. This is a valid case and // it works because compiler stores operand lengths. - else { - if (0 < opcode && opcode <= vm_header.num_opcode_lens) { + else + { + if(0 < opcode && opcode <= vm_header.num_opcode_lens) + { U8 num_operands = vm_header.opcode_lens[opcode - 1]; - for (U8 i = 0; i < num_operands; ++i) { + for(U8 i = 0; i < num_operands; i += 1) + { U64 operand = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &operand); } - } else { + } + else + { error = 1; goto exit; } } - } break; + }break; - //- Standard opcodes - - case DW_StdOpcode_Copy: { + //- standard opcodes + case DW_StdOpcode_Copy: + { if(vm_state.is_stmt) { dw_push_line(arena, &result, &vm_state, end_of_seq); @@ -2912,68 +2915,69 @@ dw_parsed_line_table_from_data(Arena *arena, vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; - } break; - - case DW_StdOpcode_AdvancePc: { + }break; + case DW_StdOpcode_AdvancePc: + { U64 advance = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &advance); dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); - } break; - - case DW_StdOpcode_AdvanceLine: { + }break; + case DW_StdOpcode_AdvanceLine: + { S64 s = 0; unit_cursor += str8_deserial_read_sleb128(unit_data, unit_cursor, &s); vm_state.line += s; - } break; - - case DW_StdOpcode_SetFile: { + }break; + case DW_StdOpcode_SetFile: + { U64 file_index = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_index); vm_state.file_index = file_index; - } break; - - case DW_StdOpcode_SetColumn: { + }break; + case DW_StdOpcode_SetColumn: + { U64 column = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &column); vm_state.column = column; - } break; - - case DW_StdOpcode_NegateStmt: { + }break; + case DW_StdOpcode_NegateStmt: + { vm_state.is_stmt = !vm_state.is_stmt; - } break; - - case DW_StdOpcode_SetBasicBlock: { + }break; + case DW_StdOpcode_SetBasicBlock: + { vm_state.basic_block = 1; - } break; - - case DW_StdOpcode_ConstAddPc: { + }break; + case DW_StdOpcode_ConstAddPc: + { U64 advance = (0xffu - vm_header.opcode_base) / vm_header.line_range; dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); - } break; - - case DW_StdOpcode_FixedAdvancePc: { + }break; + case DW_StdOpcode_FixedAdvancePc: + { U16 operand = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &operand); vm_state.address += operand; vm_state.op_index = 0; - } break; - - case DW_StdOpcode_SetPrologueEnd: { + }break; + case DW_StdOpcode_SetPrologueEnd: + { vm_state.prologue_end = 1; - } break; - - case DW_StdOpcode_SetEpilogueBegin: { + }break; + case DW_StdOpcode_SetEpilogueBegin: + { vm_state.epilogue_begin = 1; - } break; - - case DW_StdOpcode_SetIsa: { + }break; + case DW_StdOpcode_SetIsa: + { U64 v = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); vm_state.isa = v; - } break; + }break; - //- Extended opcodes - case DW_StdOpcode_ExtendedOpcode: { + //- extended opcodes + case DW_StdOpcode_ExtendedOpcode: + { U64 length = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &length); @@ -2981,8 +2985,12 @@ dw_parsed_line_table_from_data(Arena *arena, U8 extended_opcode = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &extended_opcode); - switch (extended_opcode) { - case DW_ExtOpcode_EndSequence: { + switch(extended_opcode) + { + default:{}break; + + case DW_ExtOpcode_EndSequence: + { vm_state.end_sequence = 1; if(vm_state.is_stmt) { @@ -2990,16 +2998,18 @@ dw_parsed_line_table_from_data(Arena *arena, } dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); end_of_seq = 1; - } break; + }break; - case DW_ExtOpcode_SetAddress: { + case DW_ExtOpcode_SetAddress: + { U64 address = 0; unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, vm_header.address_size, vm_header.address_size); vm_state.address = address; vm_state.op_index = 0; - } break; + }break; - case DW_ExtOpcode_DefineFile: { + case DW_ExtOpcode_DefineFile: + { String8 file_name = {0}; U64 dir_index = 0; U64 modify_time = 0; @@ -3017,25 +3027,22 @@ dw_parsed_line_table_from_data(Arena *arena, // // See the DWARF V4 spec (June 10, 2010), page 122. error = 1; - AssertAlways(!"UNHANDLED DEFINE FILE!!!"); - } break; + // AssertAlways(!"UNHANDLED DEFINE FILE!!!"); + }break; - case DW_ExtOpcode_SetDiscriminator: { + case DW_ExtOpcode_SetDiscriminator: + { U64 v = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); vm_state.discriminator = v; - } break; - - default: break; + }break; } unit_cursor = extended_opl; - } break; + }break; } } - exit:; - return result; } @@ -3118,205 +3125,205 @@ dw_expr_from_data(Arena *arena, DW_Format format, U64 addr_size, String8 data) DW_Expr expr = {0}; for (U64 cursor = 0; cursor < data.size; ) { U64 inst_start = cursor; - + DW_ExprOp opcode = 0; cursor += str8_deserial_read_struct(data, cursor, &opcode); DW_ExprOperand operands[4] = {0}; switch (opcode) { - case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: - case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: - case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: - case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: - case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: - case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: - case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: - case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: - case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: - case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: - case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { - // implicit operands - } break; - case DW_ExprOp_Const1U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; - case DW_ExprOp_Const2U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); } break; - case DW_ExprOp_Const4U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; - case DW_ExprOp_Const8U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_Const1S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s8); } break; - case DW_ExprOp_Const2S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; - case DW_ExprOp_Const4S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s32); } break; - case DW_ExprOp_Const8S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s64); } break; - case DW_ExprOp_ConstU: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_ConstS: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; - case DW_ExprOp_Addr: { cursor += str8_deserial_read(data, cursor, &operands[0].u64, addr_size, addr_size); } break; - case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: - case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: - case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: - case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: - case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: - case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: - case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: - case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: - case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: - case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: - case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { - // implicit operands - } break; - case DW_ExprOp_RegX: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_ImplicitValue: { - U64 value_size = 0; String8 value = {0}; - cursor += str8_deserial_read_uleb128(data, cursor, &value_size); - cursor += str8_deserial_read_block(data, cursor, value_size, &operands[0].block); - } break; - case DW_ExprOp_Piece: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_BitPiece: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_Pick: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_PlusUConst: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_Skip: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); - } break; - case DW_ExprOp_Bra: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); - } break; - case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: - case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: - case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: - case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: - case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: - case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: - case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: - case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: - case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: - case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: - case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { - cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); - } break; - case DW_ExprOp_BRegX: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); - } break; - case DW_ExprOp_FBReg: { - cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); - } break; - case DW_ExprOp_Deref: { - // no operands - } break; - case DW_ExprOp_DerefSize: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_XDerefSize: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_Call2: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); - } break; - case DW_ExprOp_Call4: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); - } break; - case DW_ExprOp_CallRef: { - cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); - } break; - case DW_ExprOp_ImplicitPointer: - case DW_ExprOp_GNU_ImplicitPointer: { - cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); - cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); - } break; - case DW_ExprOp_Convert: - case DW_ExprOp_GNU_Convert: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_GNU_ParameterRef: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); - } break; - case DW_ExprOp_DerefType: - case DW_ExprOp_GNU_DerefType: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_XDerefType: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_ConstType: - case DW_ExprOp_GNU_ConstType: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_struct(data, cursor, &operands[1].u8); - cursor += str8_deserial_read_block(data, cursor, operands[1].u8, &operands[2].block); - } break; - case DW_ExprOp_RegvalType: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_EntryValue: - case DW_ExprOp_GNU_EntryValue: { - U64 entry_value_expr_size = 0; - cursor += str8_deserial_read_uleb128(data, cursor, &entry_value_expr_size); - cursor += str8_deserial_read_block(data, cursor, entry_value_expr_size, &operands[0].block); - } break; - case DW_ExprOp_Addrx: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_Constx: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_CallFrameCfa: - case DW_ExprOp_FormTlsAddress: - case DW_ExprOp_PushObjectAddress: - case DW_ExprOp_Nop: - case DW_ExprOp_Eq: - case DW_ExprOp_Ge: - case DW_ExprOp_Gt: - case DW_ExprOp_Le: - case DW_ExprOp_Lt: - case DW_ExprOp_Ne: - case DW_ExprOp_Shl: - case DW_ExprOp_Shr: - case DW_ExprOp_Shra: - case DW_ExprOp_Xor: - case DW_ExprOp_XDeref: - case DW_ExprOp_Abs: - case DW_ExprOp_And: - case DW_ExprOp_Div: - case DW_ExprOp_Minus: - case DW_ExprOp_Mod: - case DW_ExprOp_Mul: - case DW_ExprOp_Neg: - case DW_ExprOp_Not: - case DW_ExprOp_Or: - case DW_ExprOp_Plus: - case DW_ExprOp_Rot: - case DW_ExprOp_Swap: - case DW_ExprOp_Dup: - case DW_ExprOp_Drop: - case DW_ExprOp_Over: - case DW_ExprOp_StackValue: - case DW_ExprOp_GNU_PushTlsAddress: { - // no operands - } break; - case DW_ExprOp_GNU_AddrIndex: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_GNU_ConstIndex: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - default: { InvalidPath; } break; + case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: + case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: + case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: + case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: + case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: + case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: + case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: + case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: + case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: + case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: + case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { + // implicit operands + } break; + case DW_ExprOp_Const1U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; + case DW_ExprOp_Const2U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); } break; + case DW_ExprOp_Const4U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; + case DW_ExprOp_Const8U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u64); } break; + case DW_ExprOp_Const1S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s8); } break; + case DW_ExprOp_Const2S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; + case DW_ExprOp_Const4S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s32); } break; + case DW_ExprOp_Const8S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s64); } break; + case DW_ExprOp_ConstU: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; + case DW_ExprOp_ConstS: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; + case DW_ExprOp_Addr: { cursor += str8_deserial_read(data, cursor, &operands[0].u64, addr_size, addr_size); } break; + case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: + case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: + case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: + case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: + case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: + case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: + case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: + case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: + case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: + case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: + case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { + // implicit operands + } break; + case DW_ExprOp_RegX: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; + case DW_ExprOp_ImplicitValue: { + U64 value_size = 0; String8 value = {0}; + cursor += str8_deserial_read_uleb128(data, cursor, &value_size); + cursor += str8_deserial_read_block(data, cursor, value_size, &operands[0].block); + } break; + case DW_ExprOp_Piece: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_BitPiece: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); + } break; + case DW_ExprOp_Pick: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); + } break; + case DW_ExprOp_PlusUConst: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_Skip: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); + } break; + case DW_ExprOp_Bra: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); + } break; + case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: + case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: + case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: + case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: + case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: + case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: + case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: + case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: + case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: + case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: + case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { + cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); + } break; + case DW_ExprOp_BRegX: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); + } break; + case DW_ExprOp_FBReg: { + cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); + } break; + case DW_ExprOp_Deref: { + // no operands + } break; + case DW_ExprOp_DerefSize: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); + } break; + case DW_ExprOp_XDerefSize: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); + } break; + case DW_ExprOp_Call2: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); + } break; + case DW_ExprOp_Call4: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); + } break; + case DW_ExprOp_CallRef: { + cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); + } break; + case DW_ExprOp_ImplicitPointer: + case DW_ExprOp_GNU_ImplicitPointer: { + cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); + cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); + } break; + case DW_ExprOp_Convert: + case DW_ExprOp_GNU_Convert: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_GNU_ParameterRef: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); + } break; + case DW_ExprOp_DerefType: + case DW_ExprOp_GNU_DerefType: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); + cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); + } break; + case DW_ExprOp_XDerefType: { + cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); + cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); + } break; + case DW_ExprOp_ConstType: + case DW_ExprOp_GNU_ConstType: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + cursor += str8_deserial_read_struct(data, cursor, &operands[1].u8); + cursor += str8_deserial_read_block(data, cursor, operands[1].u8, &operands[2].block); + } break; + case DW_ExprOp_RegvalType: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); + } break; + case DW_ExprOp_EntryValue: + case DW_ExprOp_GNU_EntryValue: { + U64 entry_value_expr_size = 0; + cursor += str8_deserial_read_uleb128(data, cursor, &entry_value_expr_size); + cursor += str8_deserial_read_block(data, cursor, entry_value_expr_size, &operands[0].block); + } break; + case DW_ExprOp_Addrx: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_Constx: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_CallFrameCfa: + case DW_ExprOp_FormTlsAddress: + case DW_ExprOp_PushObjectAddress: + case DW_ExprOp_Nop: + case DW_ExprOp_Eq: + case DW_ExprOp_Ge: + case DW_ExprOp_Gt: + case DW_ExprOp_Le: + case DW_ExprOp_Lt: + case DW_ExprOp_Ne: + case DW_ExprOp_Shl: + case DW_ExprOp_Shr: + case DW_ExprOp_Shra: + case DW_ExprOp_Xor: + case DW_ExprOp_XDeref: + case DW_ExprOp_Abs: + case DW_ExprOp_And: + case DW_ExprOp_Div: + case DW_ExprOp_Minus: + case DW_ExprOp_Mod: + case DW_ExprOp_Mul: + case DW_ExprOp_Neg: + case DW_ExprOp_Not: + case DW_ExprOp_Or: + case DW_ExprOp_Plus: + case DW_ExprOp_Rot: + case DW_ExprOp_Swap: + case DW_ExprOp_Dup: + case DW_ExprOp_Drop: + case DW_ExprOp_Over: + case DW_ExprOp_StackValue: + case DW_ExprOp_GNU_PushTlsAddress: { + // no operands + } break; + case DW_ExprOp_GNU_AddrIndex: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + case DW_ExprOp_GNU_ConstIndex: { + cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); + } break; + default: { InvalidPath; } break; } - + U64 operand_count = dw_operand_count_from_expr_op(opcode); DW_ExprInst *inst = push_array(arena, DW_ExprInst, 1); inst->opcode = opcode; inst->size = cursor - inst_start; inst->operands = push_array(arena, DW_ExprOperand, operand_count); MemoryCopy(inst->operands, operands, operand_count * sizeof(DW_ExprOperand)); - + DLLPushBack(expr.first, expr.last, inst); expr.count += 1; } @@ -3357,25 +3364,25 @@ dw_parse_descriptor_entry_header(String8 data, U64 off, DW_DescriptorEntry *desc U32 first_four_bytes = 0; str8_deserial_read_struct(data, off, &first_four_bytes); DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit; - + U64 length = 0; U64 length_size = str8_deserial_read_dwarf_packed_size(data, off, &length); if (length_size == 0) { goto exit; } - + Rng1U64 entry_range = rng_1u64(off, off + length_size + length); String8 entry_data = str8_substr(data, entry_range); U64 id = 0; U64 id_size = str8_deserial_read_dwarf_uint(entry_data, length_size, format, &id); if (id_size == 0) { goto exit; } - + U64 id_type = format == DW_Format_32Bit ? max_U32 : max_U64; desc_out->format = format; desc_out->type = (id == id_type) ? DW_DescriptorEntryType_CIE : DW_DescriptorEntryType_FDE; desc_out->entry_range = entry_range; desc_out->cie_pointer = id; desc_out->cie_pointer_off = length_size; - -exit:; + + exit:; return length + length_size; } @@ -3384,55 +3391,55 @@ dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 4 : 12; - + U64 cie_id = 0; U64 cie_id_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_id); if (cie_id_size == 0) { goto exit; } cursor += cie_id_size; - + U8 version = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &version); if (version_size == 0) { goto exit; } cursor += version_size; - + String8 aug_string = {0}; U64 aug_string_size = str8_deserial_read_cstr(data, cursor, &aug_string); if (aug_string_size == 0) { goto exit; } cursor += aug_string_size; - + U8 address_size = 0; U8 segment_selector_size = 0; if (version >= DW_Version_4) { U64 address_size_size = str8_deserial_read_struct(data, cursor, &address_size); if (address_size_size == 0) { goto exit; } cursor += address_size_size; - + U64 segment_selector_size_size = str8_deserial_read_struct(data, cursor, &segment_selector_size); if (segment_selector_size_size == 0) { goto exit; } cursor += segment_selector_size; } else { address_size = byte_size_from_arch(arch); } - + U64 code_align_factor = 0; U64 code_align_factor_size = str8_deserial_read_uleb128(data, cursor, &code_align_factor); if (code_align_factor_size == 0) { goto exit; } cursor += code_align_factor_size; - + S64 data_align_factor = 0; U64 data_align_factor_size = str8_deserial_read_sleb128(data, cursor, &data_align_factor); if (data_align_factor_size == 0) { goto exit; } cursor += data_align_factor_size; - + U64 ret_addr_reg = 0; U64 ret_addr_reg_size = 0; if (version == DW_Version_1) { ret_addr_reg_size = str8_deserial_read(data, cursor, &ret_addr_reg, sizeof(U8), sizeof(U8)); } else { ret_addr_reg_size = str8_deserial_read_uleb128(data, cursor, &ret_addr_reg); } if (ret_addr_reg_size == 0) { goto exit; } cursor += ret_addr_reg_size; - + if (aug_string.size > 0) { goto exit; } - + cie_out->insts = str8_skip(data, cursor); cie_out->aug_string = aug_string; cie_out->code_align_factor = code_align_factor; @@ -3442,9 +3449,9 @@ dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out) cie_out->version = version; cie_out->address_size = address_size; cie_out->segment_selector_size = segment_selector_size; - + is_parsed = 1; -exit:; + exit:; return is_parsed; } @@ -3453,37 +3460,37 @@ dw_parse_fde(String8 data, DW_Format format, DW_CIE *cie, DW_FDE *fde_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 4 : 12; - + // extract CIE pointer U64 cie_pointer = 0; U64 cie_pointer_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_pointer); if (cie_pointer_size == 0) { goto exit; } cursor += cie_pointer_size; - + // extract address of first instruction U64 pc_begin = 0; U64 pc_begin_size = dw_read_debug_frame_ptr(str8_skip(data, cursor), cie, &pc_begin); if (pc_begin_size == 0) { goto exit; } cursor += pc_begin_size; - + // extract instruction range size U64 pc_range = 0; U64 pc_range_size = dw_read_debug_frame_ptr(str8_skip(data, cursor), cie, &pc_range); if (pc_range_size == 0) { goto exit; } cursor += pc_range_size; - + // parse augmentation data String8 aug_data = str8_substr(data, rng_1u64(cursor, cursor + cie->aug_data.size)); cursor += cie->aug_data.size; - + // commit values to out fde_out->format = format; fde_out->cie_pointer = cie_pointer; fde_out->pc_range = rng_1u64(pc_begin, pc_begin + pc_range); fde_out->insts = str8_skip(data, cursor); - + is_parsed = 1; -exit:; + exit:; return is_parsed; } @@ -3509,30 +3516,30 @@ dw_parse_cfi(String8 data, U64 fde_offset, Arch arch, DW_CIE *cie_out, DW_FDE *f } } } - + return is_parsed; } internal DW_CFA_ParseErrorCode dw_parse_cfa_inst(String8 data, - U64 code_align_factor, - S64 data_align_factor, - DW_DecodePtr *decode_ptr_func, - void *decode_ptr_ud, - U64 *bytes_read_out, - DW_CFA_Inst *inst_out) + U64 code_align_factor, + S64 data_align_factor, + DW_DecodePtr *decode_ptr_func, + void *decode_ptr_ud, + U64 *bytes_read_out, + DW_CFA_Inst *inst_out) { *bytes_read_out = 0; - + DW_CFA_ParseErrorCode error_code = DW_CFA_ParseErrorCode_End; U64 cursor = 0; - + // read opcode DW_CFA_Opcode raw_opcode = 0; U64 raw_opcode_size = str8_deserial_read_struct(data, cursor, &raw_opcode); if (raw_opcode_size == 0) { goto exit; } cursor += raw_opcode_size; - + // decode opcode implicit operand U64 opcode = raw_opcode & ~DW_CFA_Mask_OpcodeHi; U64 implicit_operand = 0; @@ -3540,262 +3547,262 @@ dw_parse_cfa_inst(String8 data, opcode = raw_opcode & DW_CFA_Mask_OpcodeHi; implicit_operand = raw_opcode & DW_CFA_Mask_Operand; } - + // decode operands DW_CFA_Operand operands[DW_CFA_OperandMax] = {0}; switch (opcode) { - case DW_CFA_SetLoc: { - U64 address_size = decode_ptr_func(str8_skip(data, cursor), decode_ptr_ud, &operands[0].u64); - if (address_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += address_size; - } break; - case DW_CFA_AdvanceLoc: { - operands[0].u64 = implicit_operand * code_align_factor; - } break; - case DW_CFA_AdvanceLoc1: { - U8 delta = 0; - U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); - if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += delta_size; - operands[0].u64 = delta * code_align_factor; - } break; - case DW_CFA_AdvanceLoc2: { - U16 delta = 0; - U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); - if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += delta_size; - operands[0].u64 = delta * code_align_factor; - } break; - case DW_CFA_AdvanceLoc4: { - U32 delta = 0; - U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); - if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - operands[0].u64 = delta * code_align_factor; - } break; - case DW_CFA_DefCfa: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = reg; - operands[1].u64 = offset; - } break; - case DW_CFA_DefCfaSf: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - S64 offset = 0; - U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = reg; - operands[1].s64 = offset * data_align_factor; - } break; - case DW_CFA_DefCfaRegister: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - operands[0].u64 = reg; - } break; - case DW_CFA_DefCfaOffset: { - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = offset; - } break; - case DW_CFA_DefCfaOffsetSf: { - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = offset * data_align_factor; - } break; - case DW_CFA_DefCfaExpr: { - U64 expr_size = 0; - U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); - if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += expr_size_size; - - if (cursor + expr_size > data.size) { goto exit; } - String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); - - operands[0].block = expr; - cursor += expr_size; - } break; - case DW_CFA_Undefined: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - operands[0].u64 = reg; - } break; - case DW_CFA_SameValue: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - operands[0].u64 = reg; - } break; - case DW_CFA_Offset: { - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = implicit_operand; - operands[1].s64 = (S64)offset * data_align_factor; - } break; - case DW_CFA_OffsetExt: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = reg; - operands[1].u64 = offset * data_align_factor; - } break; - case DW_CFA_OffsetExtSf: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - S64 offset = 0; - U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = reg; - operands[1].s64 = offset * data_align_factor; - } break; - case DW_CFA_ValOffset: { - U64 val = 0; - U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); - if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += val_size; - - U64 offset = 0; - U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = val; - operands[1].u64 = offset * data_align_factor; - } break; - case DW_CFA_ValOffsetSf: { - U64 val = 0; - U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); - if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += val_size; - - S64 offset = 0; - U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); - if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += offset_size; - - operands[0].u64 = val; - operands[1].s64 = offset; - } break; - case DW_CFA_Register: { - U64 dst_reg = 0; - U64 dst_reg_size = str8_deserial_read_uleb128(data, cursor, &dst_reg); - if (dst_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += dst_reg_size; - - U64 src_reg = 0; - U64 src_reg_size = str8_deserial_read_uleb128(data, cursor, &src_reg); - if (src_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += src_reg_size; - - operands[0].u64 = dst_reg; - operands[1].u64 = src_reg; - } break; - case DW_CFA_Expr: { - U64 reg = 0; - U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); - if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += reg_size; - - U64 expr_size = 0; - U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); - if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += expr_size_size; - - if (cursor + expr_size > data.size) { goto exit; } - String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); - cursor += expr_size; - - operands[0].u64 = reg; - operands[1].block = expr; - } break; - case DW_CFA_ValExpr: { - U64 val = 0; - U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); - if (val_size == 0) { goto exit; } - cursor += val_size; - - U64 expr_size = 0; - U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); - if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } - cursor += expr_size_size; - - if (cursor + expr_size > data.size) { goto exit; } - String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); - cursor += expr_size; - - operands[0].u64 = val; - operands[1].block = expr; - } break; - case DW_CFA_Restore: { - operands[0].u64 = implicit_operand; - } break; - case DW_CFA_RestoreExt: {} break; - case DW_CFA_RememberState: {} break; - case DW_CFA_RestoreState: {} break; - case DW_CFA_Nop: {} break; - default: { NotImplemented; goto exit; } break; + case DW_CFA_SetLoc: { + U64 address_size = decode_ptr_func(str8_skip(data, cursor), decode_ptr_ud, &operands[0].u64); + if (address_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += address_size; + } break; + case DW_CFA_AdvanceLoc: { + operands[0].u64 = implicit_operand * code_align_factor; + } break; + case DW_CFA_AdvanceLoc1: { + U8 delta = 0; + U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); + if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += delta_size; + operands[0].u64 = delta * code_align_factor; + } break; + case DW_CFA_AdvanceLoc2: { + U16 delta = 0; + U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); + if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += delta_size; + operands[0].u64 = delta * code_align_factor; + } break; + case DW_CFA_AdvanceLoc4: { + U32 delta = 0; + U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); + if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + operands[0].u64 = delta * code_align_factor; + } break; + case DW_CFA_DefCfa: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = reg; + operands[1].u64 = offset; + } break; + case DW_CFA_DefCfaSf: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + S64 offset = 0; + U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = reg; + operands[1].s64 = offset * data_align_factor; + } break; + case DW_CFA_DefCfaRegister: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + operands[0].u64 = reg; + } break; + case DW_CFA_DefCfaOffset: { + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = offset; + } break; + case DW_CFA_DefCfaOffsetSf: { + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = offset * data_align_factor; + } break; + case DW_CFA_DefCfaExpr: { + U64 expr_size = 0; + U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); + if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += expr_size_size; + + if (cursor + expr_size > data.size) { goto exit; } + String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); + + operands[0].block = expr; + cursor += expr_size; + } break; + case DW_CFA_Undefined: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + operands[0].u64 = reg; + } break; + case DW_CFA_SameValue: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + operands[0].u64 = reg; + } break; + case DW_CFA_Offset: { + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = implicit_operand; + operands[1].s64 = (S64)offset * data_align_factor; + } break; + case DW_CFA_OffsetExt: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = reg; + operands[1].u64 = offset * data_align_factor; + } break; + case DW_CFA_OffsetExtSf: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + S64 offset = 0; + U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = reg; + operands[1].s64 = offset * data_align_factor; + } break; + case DW_CFA_ValOffset: { + U64 val = 0; + U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); + if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += val_size; + + U64 offset = 0; + U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = val; + operands[1].u64 = offset * data_align_factor; + } break; + case DW_CFA_ValOffsetSf: { + U64 val = 0; + U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); + if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += val_size; + + S64 offset = 0; + U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); + if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += offset_size; + + operands[0].u64 = val; + operands[1].s64 = offset; + } break; + case DW_CFA_Register: { + U64 dst_reg = 0; + U64 dst_reg_size = str8_deserial_read_uleb128(data, cursor, &dst_reg); + if (dst_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += dst_reg_size; + + U64 src_reg = 0; + U64 src_reg_size = str8_deserial_read_uleb128(data, cursor, &src_reg); + if (src_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += src_reg_size; + + operands[0].u64 = dst_reg; + operands[1].u64 = src_reg; + } break; + case DW_CFA_Expr: { + U64 reg = 0; + U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); + if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += reg_size; + + U64 expr_size = 0; + U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); + if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += expr_size_size; + + if (cursor + expr_size > data.size) { goto exit; } + String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); + cursor += expr_size; + + operands[0].u64 = reg; + operands[1].block = expr; + } break; + case DW_CFA_ValExpr: { + U64 val = 0; + U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); + if (val_size == 0) { goto exit; } + cursor += val_size; + + U64 expr_size = 0; + U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); + if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } + cursor += expr_size_size; + + if (cursor + expr_size > data.size) { goto exit; } + String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); + cursor += expr_size; + + operands[0].u64 = val; + operands[1].block = expr; + } break; + case DW_CFA_Restore: { + operands[0].u64 = implicit_operand; + } break; + case DW_CFA_RestoreExt: {} break; + case DW_CFA_RememberState: {} break; + case DW_CFA_RestoreState: {} break; + case DW_CFA_Nop: {} break; + default: { NotImplemented; goto exit; } break; } - + // fill out output inst_out->opcode = opcode; MemoryCopyTyped(&inst_out->operands[0], &operands[0], DW_CFA_OperandMax); - + *bytes_read_out = cursor; - + error_code = DW_CFA_ParseErrorCode_NewInst; - -exit:; + + exit:; return error_code; } internal DW_CFA_InstList dw_parse_cfa_inst_list(Arena *arena, - String8 data, - U64 code_align_factor, - S64 data_align_factor, - DW_DecodePtr *decode_ptr_func, - void *decode_ptr_ud) + String8 data, + U64 code_align_factor, + S64 data_align_factor, + DW_DecodePtr *decode_ptr_func, + void *decode_ptr_ud) { U64 pos = arena_pos(arena); DW_CFA_InstList list = {0}; diff --git a/src/elf/elf.h b/src/elf/elf.h index a46413c3..2c15aa15 100644 --- a/src/elf/elf.h +++ b/src/elf/elf.h @@ -171,12 +171,12 @@ enum ELF_ShType_PreinitArray = 16, // Array of ptrs to finish functions ELF_ShType_Group = 17, // Array of ptrs to pre-init funcs ELF_ShType_SymtabShndx = 18, // Section contains a section group - + ELF_ShType_GNU_IncrementalInputs = 0x6fff4700, // Indices for SHN_XINDEX entries ELF_ShType_GNU_Attributes = 0x6ffffff5, // Incremental build data ELF_ShType_GNU_Hash = 0x6ffffff6, // Object attributes ELF_ShType_GNU_LibList = 0x6ffffff7, // GNU style symbol hash table - + ELF_ShType_SUNW_verdef = 0x6ffffffd, ELF_ShType_SUNW_verneed = 0x6ffffffe, // Versions defined by file ELF_ShType_SUNW_versym = 0x6fffffff, // Versions needed by file @@ -216,7 +216,7 @@ enum ELF_SectionIndex_MIPS_SUndefined = 0xff04, }; -typedef U32 ELF_SectionFlag; +typedef U32 ELF_SectionFlags; enum { ELF_Shf_Write = (1 << 0), diff --git a/src/rdi_from_coff/rdi_from_coff.c b/src/rdi_from_coff/rdi_from_coff.c index d10d1b25..04138605 100644 --- a/src/rdi_from_coff/rdi_from_coff.c +++ b/src/rdi_from_coff/rdi_from_coff.c @@ -58,14 +58,11 @@ c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab) { - ProfBeginFunction(); - RDIM_BinarySectionList binary_sections = {0}; - - for (U64 isec = 0; isec < sectab_count; ++isec) { - COFF_SectionHeader *coff_sec = §ab[isec]; - RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); - + for EachIndex(idx, sectab_count) + { + COFF_SectionHeader *coff_sec = §ab[idx]; + RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); sec->name = coff_name_from_section_header(string_table, coff_sec); sec->flags = c2r_rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags); sec->voff_first = coff_sec->voff; @@ -73,7 +70,5 @@ c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, Str sec->foff_first = coff_sec->foff; sec->foff_opl = coff_sec->foff + coff_sec->fsize; } - - ProfEnd(); return binary_sections; } diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index d5bdac94..263c584d 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -45,7 +45,6 @@ d2r_rdi_language_from_dw_language(DW_Language v) switch(v) { default:{}break; - case DW_Language_C89: case DW_Language_C99: case DW_Language_C11: @@ -53,7 +52,6 @@ d2r_rdi_language_from_dw_language(DW_Language v) { result = RDI_Language_C; }break; - case DW_Language_CPlusPlus03: case DW_Language_CPlusPlus11: case DW_Language_CPlusPlus14: @@ -72,7 +70,7 @@ d2r_rdi_reg_code_from_dw_reg_x86(DW_RegX86 v) switch(v) { default:{}break; -#define X(reg_dw, val_dw, reg_rdi, ...) case DW_RegX86_##reg_dw: result = RDI_RegCodeX86_##reg_rdi; break; +#define X(reg_dw, val_dw, reg_rdi, ...) case DW_RegX86_##reg_dw:{result = RDI_RegCodeX86_##reg_rdi;}break; DW_Regs_X86_XList(X) #undef X } @@ -101,6 +99,7 @@ d2r_rdi_reg_code_from_dw_reg(Arch arch, DW_Reg v) { default: case Arch_Null: + {}break; case Arch_x86:{result = d2r_rdi_reg_code_from_dw_reg_x86(v);}break; case Arch_x64:{result = d2r_rdi_reg_code_from_dw_reg_x64(v);}break; } @@ -257,6 +256,7 @@ d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input } //////////////////////////////// +//~ RDIM Bytecode Helpers internal B32 rdim_is_eval_bytecode_static(RDIM_EvalBytecode bc) @@ -1454,14 +1454,6 @@ d2r_transpile_expression(Arena *arena, RDIM_LocationChunkList *locations, DW_Inp return loc; } -internal RDIM_Location * -d2r_location_from_attrib(Arena *arena, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind) -{ - String8 expr = dw_exprloc_from_tag_attrib_kind(input, cu, tag, kind); - RDIM_Location *location = d2r_transpile_expression(arena, locations, input, image_base, cu->address_size, arch, cu->addr_lu, cu, expr); - return location; -} - internal RDIM_LocationCaseList d2r_locset_from_attrib(Arena *arena, RDIM_ScopeChunkList *scopes, @@ -1556,92 +1548,6 @@ d2r_var_locset_from_tag(Arena *arena, return locset; } -internal D2R_CompUnitContribMap -d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 aranges_data = input->sec[DW_Section_ARanges].data; - Rng1U64List unit_range_list = dw_unit_ranges_from_data(scratch.arena, aranges_data); - - D2R_CompUnitContribMap cm = {0}; - cm.count = 0; - cm.info_off_arr = push_array(arena, U64, unit_range_list.count); - cm.voff_range_arr = push_array(arena, RDIM_Rng1U64ChunkList, unit_range_list.count); - - for EachNode(range_n, Rng1U64Node, unit_range_list.first) { - String8 unit_data = str8_substr(aranges_data, range_n->v); - U64 unit_cursor = 0; - - U64 unit_length = 0; - U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, unit_cursor, &unit_length); - if (unit_length_size == 0) { continue; } - unit_cursor += unit_length_size; - - DW_Version version = 0; - U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); - if (version_size == 0) { continue; } - unit_cursor += version; - - if (version != DW_Version_2) { - AssertAlways(!"unknown .debug_aranges version"); - continue; - } - - DW_Format unit_format = DW_FormatFromSize(unit_length); - U64 cu_info_off = 0; - U64 cu_info_off_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, unit_format, &cu_info_off); - if (cu_info_off_size == 0) { continue; } - unit_cursor += cu_info_off_size; - - U8 address_size = 0; - U64 address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &address_size); - if (address_size_size == 0) { continue; } - unit_cursor += address_size_size; - - U8 segment_selector_size = 0; - U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &segment_selector_size); - if (segment_selector_size_size == 0) { continue; } - unit_cursor += segment_selector_size_size; - - U64 tuple_size = address_size * 2 + segment_selector_size; - U64 bytes_too_far_past_boundary = unit_cursor % tuple_size; - if (bytes_too_far_past_boundary > 0) { - unit_cursor += tuple_size - bytes_too_far_past_boundary; - } - - RDIM_Rng1U64ChunkList voff_ranges = {0}; - if (segment_selector_size == 0) { - while (unit_cursor + address_size * 2 <= unit_data.size) { - U64 address = 0; - U64 length = 0; - unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, address_size, address_size); - unit_cursor += str8_deserial_read(unit_data, unit_cursor, &length, address_size, address_size); - - if (address == 0 && length == 0) { break; } - if (address == 0) { continue; } - - // TODO: error handling - AssertAlways(address >= image_base); - - U64 min = address - image_base; - U64 max = min + length; - rdim_rng1u64_chunk_list_push(arena, &voff_ranges, 256, (RDIM_Rng1U64){.min = min, .max = max}); - } - } else { - // TODO: segment relative addressing - NotImplemented; - } - - U64 map_idx = cm.count++; - cm.info_off_arr[map_idx] = cu_info_off; - cm.voff_range_arr[map_idx] = voff_ranges; - } - - scratch_end(scratch); - return cm; -} - //////////////////////////////// //~ rjf: Compilation Unit / Scope Conversion Helpers @@ -1688,7 +1594,7 @@ d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D } //////////////////////////////// -//~ rjf: Main Conversion Entry Point +//~ Tag Iterator internal D2R_TagIterator * d2r_tag_iterator_init(Arena *arena, DW_TagNode *root) @@ -1758,6 +1664,9 @@ d2r_tag_iterator_parent_tag(D2R_TagIterator *iter) return tag_node->tag; } +//////////////////////////////// +//~ Type/UDT/Symbol Conversion + internal void d2r_flag_converted_tag(DW_TagNode *tag_node) { @@ -1823,28 +1732,37 @@ d2r_convert_types(Arena *arena, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); - for (D2R_TagIterator *it = d2r_tag_iterator_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iterator_next(scratch.arena, it)) { + for(D2R_TagIterator *it = d2r_tag_iterator_init(scratch.arena, root); + it->tag_node != 0; + d2r_tag_iterator_next(scratch.arena, it)) + { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; // skip converted tags - if (d2r_is_tag_converted(tag_node)) { + if(d2r_is_tag_converted(tag_node)) + { d2r_tag_iterator_skip_children(it); continue; } + // mark the tag as converted here, because during conversion we may recurse on the same tag d2r_flag_converted_tag(tag_node); - switch (tag.kind) { - case DW_TagKind_ClassType: { + switch(tag.kind) + { + case DW_TagKind_ClassType: + { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { + if(is_decl) + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_IncompleteClass; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - Assert(!tag_node->first_child); d2r_tag_iterator_skip_children(it); - } else { + } + else + { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); @@ -1852,51 +1770,58 @@ d2r_convert_types(Arena *arena, type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); type->direct_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); } - } break; - case DW_TagKind_StructureType: { + }break; + + case DW_TagKind_StructureType: + { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { + if(is_decl) + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteStruct; - - // TODO: error handling - Assert(!tag_node->first_child); d2r_tag_iterator_skip_children(it); - } else { + } + else + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Struct; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); } - } break; - case DW_TagKind_UnionType: { + }break; + + case DW_TagKind_UnionType: + { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { + if(is_decl) + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteUnion; - - // TODO: error handling - Assert(!tag_node->first_child); d2r_tag_iterator_skip_children(it); - } else { + } + else + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Union; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); } - } break; - case DW_TagKind_EnumerationType: { + }break; + + case DW_TagKind_EnumerationType: + { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { + if(is_decl) + { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteEnum; - // TODO: error handling - Assert(!tag_node->first_child); d2r_tag_iterator_skip_children(it); - } else { + } + else + { RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); @@ -1904,8 +1829,10 @@ d2r_convert_types(Arena *arena, type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); type->direct_type = enum_base_type; } - } break; - case DW_TagKind_SubroutineType: { + }break; + + case DW_TagKind_SubroutineType: + { RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); // collect parameters @@ -1931,8 +1858,10 @@ d2r_convert_types(Arena *arena, type->param_types = rdim_array_from_type_list(arena, param_list); d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_Typedef: { + }break; + + case DW_TagKind_Typedef: + { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Alias; @@ -1944,8 +1873,10 @@ d2r_convert_types(Arena *arena, break; } } - } break; - case DW_TagKind_BaseType: { + }break; + + case DW_TagKind_BaseType: + { DW_ATE encoding = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Encoding); U64 byte_size = dw_byte_size_from_tag(input, cu, tag); @@ -2052,8 +1983,10 @@ d2r_convert_types(Arena *arena, type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->direct_type = type_table->builtin_types[kind]; type->byte_size = byte_size; - } break; - case DW_TagKind_PointerType: { + }break; + + case DW_TagKind_PointerType: + { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); // TODO: @@ -2073,8 +2006,10 @@ d2r_convert_types(Arena *arena, type->kind = RDI_TypeKind_Ptr; type->byte_size = byte_size; type->direct_type = direct_type; - } break; - case DW_TagKind_RestrictType: { + }break; + + case DW_TagKind_RestrictType: + { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); @@ -2085,8 +2020,10 @@ d2r_convert_types(Arena *arena, type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Restrict; type->direct_type = direct_type; - } break; - case DW_TagKind_VolatileType: { + }break; + + case DW_TagKind_VolatileType: + { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); @@ -2096,8 +2033,10 @@ d2r_convert_types(Arena *arena, type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Volatile; type->direct_type = direct_type; - } break; - case DW_TagKind_ConstType: { + }break; + + case DW_TagKind_ConstType: + { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); @@ -2108,8 +2047,10 @@ d2r_convert_types(Arena *arena, type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Const; type->direct_type = direct_type; - } break; - case DW_TagKind_ArrayType: { + }break; + + case DW_TagKind_ArrayType: + { // * DWARF vs RDI Array Type Graph * // // For example lets take following decl: @@ -2186,12 +2127,16 @@ d2r_convert_types(Arena *arena, } d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_SubrangeType: { + }break; + + case DW_TagKind_SubrangeType: + { // TODO: error handling AssertAlways(!"unexpected tag"); - } break; - case DW_TagKind_Inheritance: { + }break; + + case DW_TagKind_Inheritance: + { DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); if (parent_tag.kind != DW_TagKind_StructureType && parent_tag.kind != DW_TagKind_ClassType) { // TODO: error handling @@ -2207,7 +2152,8 @@ d2r_convert_types(Arena *arena, member->type = type; member->off = safe_cast_u32(dw_const_u32_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation)); } - } break; + }break; + } } scratch_end(scratch); @@ -2312,28 +2258,26 @@ d2r_convert_udts(Arena *arena, } internal void -d2r_convert_symbols(Arena *arena, - D2R_TypeTable *type_table, - RDIM_Scope *global_scope, - DW_Input *input, - DW_CompUnit *cu, - DW_Language cu_lang, - U64 arch_addr_size, - U64 image_base, - Arch arch, - DW_TagNode *root) +d2r_convert_symbols(Arena *arena, D2R_TypeTable *type_table, RDIM_Scope *global_scope, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, U64 image_base, Arch arch, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); - for (D2R_TagIterator *it = d2r_tag_iterator_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iterator_next(scratch.arena, it)) { + for(D2R_TagIterator *it = d2r_tag_iterator_init(scratch.arena, root); + it->tag_node != 0; + d2r_tag_iterator_next(scratch.arena, it)) + { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; - switch (tag.kind) { - case DW_TagKind_Null: { InvalidPath; } break; + switch(tag.kind) + { + case DW_TagKind_Null:{}break; + case DW_TagKind_ClassType: case DW_TagKind_StructureType: - case DW_TagKind_UnionType: { - // visit children to collect methods and variables - } break; + case DW_TagKind_UnionType: + { + // TODO(rjf): visit children to collect methods and variables + }break; + case DW_TagKind_EnumerationType: case DW_TagKind_SubroutineType: case DW_TagKind_Typedef: @@ -2346,15 +2290,19 @@ d2r_convert_symbols(Arena *arena, case DW_TagKind_SubrangeType: case DW_TagKind_Inheritance: case DW_TagKind_Enumerator: - case DW_TagKind_Member: { + case DW_TagKind_Member: + { d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_SubProgram: { + }break; + + case DW_TagKind_SubProgram: + { DW_InlKind inl = DW_Inl_NotInlined; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Inline)) { inl = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Inline); } - - switch (inl) { - case DW_Inl_NotInlined: { + switch(inl) + { + case DW_Inl_NotInlined: + { U64 param_count = 0; RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); @@ -2418,16 +2366,19 @@ d2r_convert_symbols(Arena *arena, } it->stack->scope = root_scope; - } break; + }break; case DW_Inl_DeclaredNotInlined: case DW_Inl_DeclaredInlined: - case DW_Inl_Inlined: { + case DW_Inl_Inlined: + { d2r_tag_iterator_skip_children(it); - } break; - default: InvalidPath; break; + }break; + default:{}break; } - } break; - case DW_TagKind_InlinedSubroutine: { + }break; + + case DW_TagKind_InlinedSubroutine: + { U64 param_count = 0; RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); @@ -2459,8 +2410,10 @@ d2r_convert_symbols(Arena *arena, Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); root_scope->inline_site = inline_site; - } break; - case DW_TagKind_Variable: { + }break; + + case DW_TagKind_Variable: + { String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); RDIM_Type *type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); @@ -2520,8 +2473,10 @@ d2r_convert_symbols(Arena *arena, var->container_symbol = 0; var->container_type = 0; // TODO: NotImplemented; } - } break; - case DW_TagKind_FormalParameter: { + }break; + + case DW_TagKind_FormalParameter: + { DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); if (parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine) { RDIM_Scope *scope = it->stack->next->scope; @@ -2530,26 +2485,35 @@ d2r_convert_symbols(Arena *arena, param->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); param->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); param->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); - } else { - // TODO: error handling - AssertAlways(!"this is a local variable"); } - } break; - case DW_TagKind_LexicalBlock: { + else + { + // TODO: error handling; this is a local variable + } + }break; + + case DW_TagKind_LexicalBlock: + { DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_SubProgram || - parent_tag.kind == DW_TagKind_InlinedSubroutine || - parent_tag.kind == DW_TagKind_LexicalBlock) { + if(parent_tag.kind == DW_TagKind_SubProgram || + parent_tag.kind == DW_TagKind_InlinedSubroutine || + parent_tag.kind == DW_TagKind_LexicalBlock) + { Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); } - } break; - case DW_TagKind_CallSite: { + }break; + + case DW_TagKind_CallSite: + { // TODO - } break; - case DW_TagKind_CallSiteParameter: { + }break; + + case DW_TagKind_CallSiteParameter: + { // TODO - } break; + }break; + case DW_TagKind_Label: case DW_TagKind_CompileUnit: case DW_TagKind_UnspecifiedParameters: @@ -2557,9 +2521,11 @@ d2r_convert_symbols(Arena *arena, case DW_TagKind_ImportedDeclaration: case DW_TagKind_PtrToMemberType: case DW_TagKind_TemplateTypeParameter: - case DW_TagKind_ReferenceType: { - // TODO: - } break; + case DW_TagKind_ReferenceType: + { + // TODO + }break; + default: { // NotImplemented; @@ -2569,288 +2535,469 @@ d2r_convert_symbols(Arena *arena, scratch_end(scratch); } +//////////////////////////////// +//~ rjf: Main Conversion Entry Point + internal RDIM_BakeParams d2r_convert(Arena *arena, D2R_ConvertParams *params) { Temp scratch = scratch_begin(&arena, 1); - if (lane_idx() == 0) { - //////////////////////////////// - + if(lane_idx() == 0) + { + //////////////////////////// + //- rjf: compute exe hash + // ProfBegin("compute exe hash"); U64 exe_hash = rdi_hash(params->exe_data.str, params->exe_data.size); ProfEnd(); - //////////////////////////////// - - Arch arch = Arch_Null; - U64 image_base = 0; - DW_Input input = {0}; + //////////////////////////// + //- rjf: unpack input image info + // + Arch arch = Arch_Null; + U64 image_base = 0; + DW_Input input = {0}; PathStyle path_style = PathStyle_Null; - - switch(params->exe_kind) { + switch(params->exe_kind) + { default:{}break; - case ExecutableImageKind_CoffPe: { - PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); - String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); + case ExecutableImageKind_CoffPe: + { + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); + String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(raw_sections, 0, sizeof(COFF_SectionHeader) * pe.section_count); - String8 string_table = str8_substr(params->exe_data, pe.string_table_range); - arch = pe.arch; - image_base = pe.image_base; + String8 string_table = str8_substr(params->exe_data, pe.string_table_range); + arch = pe.arch; + image_base = pe.image_base; binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, pe.section_count, section_table); - input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, pe.section_count, section_table); - path_style = PathStyle_WindowsAbsolute; - } break; + input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, pe.section_count, section_table); + path_style = PathStyle_WindowsAbsolute; + }break; case ExecutableImageKind_Elf32: - case ExecutableImageKind_Elf64: { + case ExecutableImageKind_Elf64: + { ELF_Bin bin = elf_bin_from_data(scratch.arena, params->dbg_data); - arch = arch_from_elf_machine(bin.hdr.e_machine); - image_base = bin.hdr.e_type == ELF_Type_Dyn ? 0 : elf_base_addr_from_bin(&bin); - binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs); - input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); - path_style = PathStyle_UnixAbsolute; - } break; + arch = arch_from_elf_machine(bin.hdr.e_machine); + image_base = (bin.hdr.e_type == ELF_Type_Dyn ? 0 : elf_base_addr_from_bin(&bin)); + binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, params->dbg_data, &bin, bin.shdrs); + input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); + path_style = PathStyle_UnixAbsolute; + }break; + } + U64 arch_addr_size = rdi_addr_size_from_arch(arch); + + //////////////////////////// + //- rjf: determine acceptable address range + // + // in many cases, linkers seem to trample over addresses in various DWARF sections, + // potentially due to optimizations. we'd like to filter out those busted addresses + // from our final debug info - a good enough heuristic is to disqualify them by + // whether or not they actually fall into the ranges covered by the binary sections. + // + Rng1U64 acceptable_vaddr_range = {0}; + { + acceptable_vaddr_range.min = max_U64; + acceptable_vaddr_range.max = 0; + for EachNode(n, RDIM_BinarySectionNode, binary_sections.first) + { + acceptable_vaddr_range.min = Min(n->v.voff_first, acceptable_vaddr_range.min); + acceptable_vaddr_range.max = Max(n->v.voff_opl, acceptable_vaddr_range.max); + } } - //////////////////////////////// - + //////////////////////////// + //- rjf: unpack input image info + // top_level_info = rdim_make_top_level_info(params->exe_name, arch, exe_hash, binary_sections); - //////////////////////////////// - - U64 arch_addr_size = rdi_addr_size_from_arch(top_level_info.arch); - - //////////////////////////////// - + //////////////////////////// + //- rjf: build global scope + // RDIM_Scope *global_scope = rdim_scope_chunk_list_push(arena, &scopes, SCOPE_CHUNK_CAP); - //////////////////////////////// - - ProfBegin("Parse Unit Contrib Map"); + //////////////////////////// + //- rjf: parse unit contribution map + // D2R_CompUnitContribMap cu_contrib_map = {0}; - if (input.sec[DW_Section_ARanges].data.size) { - cu_contrib_map = d2r_cu_contrib_map_from_aranges(arena, &input, image_base); - } - ProfEnd(); - - ProfBegin("Parse Comop Unit Ranges"); - 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); - ProfEnd(); - - //////////////////////////////// - - ProfBegin("Parse Compile Unit Headers"); - // TODO(rjf): parse should always be relaxed. any verification checks we do - // should just be logged via log_info(...), and then the caller of this - // converter can collect those & display as necessary. - B32 is_parse_relaxed = 1; - DW_CompUnit *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, is_parse_relaxed); - } - ProfEnd(); - - //////////////////////////////// - - ProfBegin("Parse Line Tables"); - DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); - for EachIndex(cu_idx, cu_ranges.count) { - DW_CompUnit *cu = &cu_arr[cu_idx]; - String8 cu_stmt_list = dw_line_ptr_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_StmtList); - 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); - cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); - } - ProfEnd(); - - //////////////////////////////// - - ProfBegin("Convert Line Tables"); - HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); - RDIM_LineTable **cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); - for EachIndex(cu_idx, cu_ranges.count) { - cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); - - DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; - DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; - DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; - RDIM_SrcFile **src_file_map = push_array(scratch.arena, RDIM_SrcFile *, file_table->count); - for EachIndex(file_idx, file_table->count) { - DW_LineFile *file = &file_table->v[file_idx]; - String8 file_path = dw_path_from_file_idx(scratch.arena, &line_table->vm_header, file_idx); - String8List file_path_split = str8_split_path(scratch.arena, file_path); - str8_path_list_resolve_dots_in_place(&file_path_split, path_style); - String8 file_path_resolved = str8_path_list_join_by_style(scratch.arena, &file_path_split, path_style); - RDIM_SrcFile *src_file = hash_table_search_path_raw(source_file_ht, file_path_resolved); - if (src_file == 0) { - src_file = rdim_src_file_chunk_list_push(arena, &src_files, SRC_FILE_CAP); - src_file->path = push_str8_copy(arena, file_path_resolved); - hash_table_push_path_raw(scratch.arena, source_file_ht, src_file->path, src_file); + ProfScope("parse unit contribution map") + { + String8 aranges_data = input.sec[DW_Section_ARanges].data; + if(aranges_data.size != 0) + { + Temp scratch = scratch_begin(&arena, 1); + + //- rjf: unpack input + Rng1U64List unit_range_list = dw_unit_ranges_from_data(scratch.arena, aranges_data); + + //- rjf: set up map + cu_contrib_map.info_off_arr = push_array(arena, U64, unit_range_list.count); + cu_contrib_map.voff_range_arr = push_array(arena, RDIM_Rng1U64ChunkList, unit_range_list.count); + + //- rjf: convert all units + for EachNode(range_n, Rng1U64Node, unit_range_list.first) + { + //- rjf: unpack unit + String8 unit_data = str8_substr(aranges_data, range_n->v); + U64 unit_cursor = 0; + + //- rjf: read unit data length + U64 unit_length = 0; + U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, unit_cursor, &unit_length); + B32 unit_length_good = (unit_length_size != 0); + unit_cursor += unit_length_size; + DW_Format unit_format = DW_FormatFromSize(unit_length); + + //- rjf: read unit version + DW_Version version = 0; + U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); + B32 version_good = (version_size != 0); + unit_cursor += version_size; + + //- rjf: parse section by version + switch(version) + { + //- rjf: unsupported versions + default: + { + log_infof("Unknown .debug_aranges version (%i).\n", version); + }break; + + //- rjf: version 2 + case DW_Version_2: + { + // rjf: unpack & read unit header info + U64 unit_info_off = 0; + U8 unit_address_size = 0; + U8 unit_segment_selector_size = 0; + B32 unit_good = 0; + { + U64 unit_info_off_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, unit_format, &unit_info_off); + unit_cursor += unit_info_off_size; + U64 unit_address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &unit_address_size); + unit_cursor += unit_address_size_size; + U64 unit_segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &unit_segment_selector_size); + unit_cursor += unit_segment_selector_size_size; + unit_good = (unit_info_off_size != 0 && unit_address_size_size != 0 && unit_segment_selector_size_size != 0); + } + U64 tuple_size = unit_address_size * 2 + unit_segment_selector_size; + + // rjf: align cursor to be divisible by the tuple size (see the February 13, 2017 spec) + { + U64 bytes_too_far_past_boundary = unit_cursor % tuple_size; + if(bytes_too_far_past_boundary > 0) + { + unit_cursor += tuple_size - bytes_too_far_past_boundary; + } + } + + // rjf: read all ranges + RDIM_Rng1U64ChunkList voff_ranges = {0}; + if(unit_segment_selector_size == 0) + { + for(;unit_cursor + unit_address_size*2 <= unit_data.size;) + { + U64 segment = 0; + U64 address = 0; + U64 length = 0; + unit_cursor += str8_deserial_read(unit_data, unit_cursor, &segment, unit_segment_selector_size, Max(unit_segment_selector_size, 1)); + unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, unit_address_size, unit_address_size); + unit_cursor += str8_deserial_read(unit_data, unit_cursor, &length, unit_address_size, unit_address_size); + if((segment != 0 || address != 0 || length != 0) && + (contains_1u64(acceptable_vaddr_range, address) || + contains_1u64(acceptable_vaddr_range, address + length))) + { + RDIM_Rng1U64 range = + { + address - image_base, + address - image_base + length, + }; + rdim_rng1u64_chunk_list_push(arena, &voff_ranges, 256, range); + } + else + { + break; + } + } + } + else + { + log_infof("Segment-relative addressing detected in .debug_aranges; this is not currently supported.\n"); + } + + // rjf: store record + U64 map_idx = cu_contrib_map.count; + cu_contrib_map.info_off_arr[map_idx] = unit_info_off; + cu_contrib_map.voff_range_arr[map_idx] = voff_ranges; + cu_contrib_map.count += 1; + }break; + } } - src_file_map[file_idx] = src_file; + + scratch_end(scratch); } - - for EachNode(line_seq, DW_LineSeqNode, line_table->first_seq) { - if (line_seq->count == 0) { continue; } + } + + //////////////////////////// + //- rjf: parse list of comp units + // + DW_ListUnitInput lu_input = {0}; + ProfScope("parse list of comp units") + { + lu_input = dw_list_unit_input_from_input(scratch.arena, &input); + } + + //////////////////////////// + //- rjf: parse comp unit ranges + // + Rng1U64Array cu_ranges = {0}; + ProfScope("parse comp unit ranges") + { + Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input.sec[DW_Section_Info].data); + cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); + } + + //////////////////////////// + //- rjf: parse comp unit headers + // + DW_CompUnit *cu_arr = 0; + ProfScope("parse comp unit headers") + { + // TODO(rjf): parse should always be relaxed. any verification checks we do + // should just be logged via log_info(...), and then the caller of this + // converter can collect those & display as necessary. + B32 is_parse_relaxed = 1; + 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, is_parse_relaxed); + } + } + + //////////////////////////// + //- rjf: parse line tables + // + DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); + ProfScope("parse line tables") + { + for EachIndex(cu_idx, cu_ranges.count) + { + DW_CompUnit *cu = &cu_arr[cu_idx]; + String8 cu_stmt_list = dw_line_ptr_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_StmtList); + 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); + cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); + } + } + + //////////////////////////// + //- rjf: convert line tables + // + RDIM_LineTable **cu_line_tables_rdi = 0; + ProfScope("convert line tables") + { + HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); + cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); + for EachIndex(cu_idx, cu_ranges.count) + { + cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); - U64 *voffs = push_array(arena, U64, line_seq->count); - U32 *line_nums = push_array(arena, U32, line_seq->count); - U16 *col_nums = 0; - U64 line_idx = 0; + DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; + DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; + DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; + RDIM_SrcFile **src_file_map = push_array(scratch.arena, RDIM_SrcFile *, file_table->count); + for EachIndex(file_idx, file_table->count) + { + DW_LineFile *file = &file_table->v[file_idx]; + String8 file_path = dw_path_from_file_idx(scratch.arena, &line_table->vm_header, file_idx); + String8List file_path_split = str8_split_path(scratch.arena, file_path); + str8_path_list_resolve_dots_in_place(&file_path_split, path_style); + String8 file_path_resolved = str8_path_list_join_by_style(scratch.arena, &file_path_split, path_style); + RDIM_SrcFile *src_file = hash_table_search_path_raw(source_file_ht, file_path_resolved); + if(src_file == 0) + { + src_file = rdim_src_file_chunk_list_push(arena, &src_files, SRC_FILE_CAP); + src_file->path = push_str8_copy(arena, file_path_resolved); + hash_table_push_path_raw(scratch.arena, source_file_ht, src_file->path, src_file); + } + src_file_map[file_idx] = src_file; + } - DW_LineNode *file_line_n = line_seq->first; - U64 file_line_count = 0; - - for EachNode(line_n, DW_LineNode, file_line_n) { - if (file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) { + for EachNode(line_seq, DW_LineSeqNode, line_table->first_seq) + { + if(line_seq->count == 0) {continue;} + + U64 *voffs = push_array(arena, U64, line_seq->count); + U32 *line_nums = push_array(arena, U32, line_seq->count); + U16 *col_nums = 0; + U64 line_idx = 0; + + DW_LineNode *file_line_n = line_seq->first; + U64 file_line_count = 0; + + for EachNode(line_n, DW_LineNode, file_line_n) + { + if(file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) + { + U64 file_index = file_line_n->v.file_index; + U64 *file_voffs = &voffs[line_idx]; + U32 *file_line_nums = &line_nums[line_idx]; + U16 *file_col_nums = 0; + + U64 lines_written = 0; + U64 prev_ln = max_U64; + DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; + for(; file_line_n != sentinel; file_line_n = file_line_n->next) + { + if(file_line_n->v.line != prev_ln) + { + if(file_line_n->v.address == 0) {continue;} + + voffs[line_idx] = file_line_n->v.address; + line_nums[line_idx] = file_line_n->v.line; + + lines_written += 1; + line_idx += 1; + + prev_ln = file_line_n->v.line; + } + } + + RDIM_SrcFile *src_file = src_file_map[file_index]; + RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); + rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); + + file_line_count = 1; + } + else + { + file_line_count += 1; + } + } + + // handle last line + if(file_line_n) + { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - - U64 lines_written = 0; - U64 prev_ln = max_U64; - DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; - for (; file_line_n != sentinel; file_line_n = file_line_n->next) { - if (file_line_n->v.line != prev_ln) { - if (file_line_n->v.address == 0) { continue; } - - voffs[line_idx] = file_line_n->v.address - image_base; - line_nums[line_idx] = file_line_n->v.line; - - ++lines_written; - ++line_idx; - - prev_ln = file_line_n->v.line; - } + for(;file_line_n != 0; file_line_n = file_line_n->next, line_idx += 1) + { + // NOTE(rjf): DWARF encodes line info as "relocatable addresses"; we do *not* + // need to translate from 'addresses' to 'voffs' with the image base here. + voffs[line_idx] = file_line_n->v.address; + line_nums[line_idx] = file_line_n->v.line; } - RDIM_SrcFile *src_file = src_file_map[file_index]; - RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); + RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); - - file_line_count = 1; - } else { - file_line_count += 1; - } - } - - // handle last line - if (file_line_n) { - U64 file_index = file_line_n->v.file_index; - U64 *file_voffs = &voffs[line_idx]; - U32 *file_line_nums = &line_nums[line_idx]; - U16 *file_col_nums = 0; - - for (; file_line_n != 0; file_line_n = file_line_n->next, line_idx += 1) { - // TODO: error handling - AssertAlways(file_line_n->v.address >= image_base); - voffs[line_idx] = file_line_n->v.address - image_base; - line_nums[line_idx] = file_line_n->v.line; } - RDIM_SrcFile *src_file = src_file_map[file_index]; - RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); - rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); + //Assert(line_idx == line_seq->count); } - - //Assert(line_idx == line_seq->count); } } - ProfEnd(); - - //////////////////////////////// + //////////////////////////// + //- rjf: build built-in basic types + // RDIM_Type *builtin_types[RDI_TypeKind_Count] = {0}; - for (RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) { - RDIM_Type *type = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); - type->kind = type_kind; - type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size); - type->byte_size = rdi_size_from_basic_type_kind(type_kind); - builtin_types[type_kind] = type; - } - builtin_types[RDI_TypeKind_Void]->byte_size = arch_addr_size; - builtin_types[RDI_TypeKind_Handle]->byte_size = arch_addr_size; - - builtin_types[RDI_TypeKind_Variadic] = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); - builtin_types[RDI_TypeKind_Variadic]->kind = RDI_TypeKind_Variadic; - - //////////////////////////////// - - ProfBegin("Convert Units"); - for EachIndex(cu_idx, cu_ranges.count) { - Temp comp_temp = temp_begin(scratch.arena); - - DW_CompUnit *cu = &cu_arr[cu_idx]; - - // parse and build tag tree - DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); - - // skip DWO + ProfScope("build built-in basic types") + { + for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) { - if (cu->dwo_id) { goto next_cu; } - - String8 dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_DwoName); - if (dwo_name.size) { goto next_cu; } - - String8 gnu_dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_GNU_DwoName); - if (gnu_dwo_name.size) { goto next_cu; } + RDIM_Type *type = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); + type->kind = type_kind; + type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size); + type->byte_size = rdi_size_from_basic_type_kind(type_kind); + builtin_types[type_kind] = type; } - - // build (info offset -> tag) hash table to resolve tags with abstract origin - cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); - - // extract compile unit info - String8 cu_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Name); - String8 cu_dir = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_CompDir); - String8 cu_prod = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Producer); - DW_Language cu_lang = dw_const_u64_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Language); - - // init type table - D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); - type_table->ht = hash_table_init(comp_temp.arena, 0x4000); - type_table->types = &types; - type_table->type_chunk_cap = TYPE_CHUNK_CAP; - type_table->builtin_types = builtin_types; - - // convert debug info - d2r_convert_types(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); - d2r_convert_udts(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); - d2r_convert_symbols(arena, type_table, global_scope, &input, cu, cu_lang, arch_addr_size, image_base, arch, tag_tree.root); - - RDIM_Rng1U64ChunkList cu_voff_ranges = {0}; - if (cu_idx < cu_contrib_map.count) { - cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); - } else { - Rng1U64List range_list = d2r_range_list_from_tag(scratch.arena, &input, cu, image_base, cu->tag); - for EachNode(n, Rng1U64Node, range_list.first) { - rdim_rng1u64_chunk_list_push(arena, &cu_voff_ranges, 512, (RDIM_Rng1U64){ .min = n->v.min, .max = n->v.max }); + builtin_types[RDI_TypeKind_Void]->byte_size = arch_addr_size; + builtin_types[RDI_TypeKind_Handle]->byte_size = arch_addr_size; + builtin_types[RDI_TypeKind_Variadic] = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); + builtin_types[RDI_TypeKind_Variadic]->kind = RDI_TypeKind_Variadic; + } + + //////////////////////////// + //- rjf: convert units + // + ProfScope("convert units") + { + for EachIndex(cu_idx, cu_ranges.count) + { + Temp comp_temp = temp_begin(scratch.arena); + + DW_CompUnit *cu = &cu_arr[cu_idx]; + + // parse and build tag tree + DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); + + // skip DWO + { + if (cu->dwo_id) { goto next_cu; } + + String8 dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_DwoName); + if (dwo_name.size) { goto next_cu; } + + String8 gnu_dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_GNU_DwoName); + if (gnu_dwo_name.size) { goto next_cu; } } + + // build (info offset -> tag) hash table to resolve tags with abstract origin + cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); + + // extract compile unit info + String8 cu_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Name); + String8 cu_dir = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_CompDir); + String8 cu_prod = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Producer); + DW_Language cu_lang = dw_const_u64_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Language); + + // init type table + D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); + type_table->ht = hash_table_init(comp_temp.arena, 0x4000); + type_table->types = &types; + type_table->type_chunk_cap = TYPE_CHUNK_CAP; + type_table->builtin_types = builtin_types; + + // convert debug info + d2r_convert_types(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); + d2r_convert_udts(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); + d2r_convert_symbols(arena, type_table, global_scope, &input, cu, cu_lang, arch_addr_size, image_base, arch, tag_tree.root); + + RDIM_Rng1U64ChunkList cu_voff_ranges = {0}; + if(cu_idx < cu_contrib_map.count) + { + cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); + } + else + { + Rng1U64List range_list = d2r_range_list_from_tag(scratch.arena, &input, cu, image_base, cu->tag); + for EachNode(n, Rng1U64Node, range_list.first) + { + rdim_rng1u64_chunk_list_push(arena, &cu_voff_ranges, 512, (RDIM_Rng1U64){ .min = n->v.min, .max = n->v.max }); + } + } + + // convert compile unit + { + RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); + unit->unit_name = cu_name; + unit->compiler_name = cu_prod; + unit->source_file = str8_zero(); // TODO + unit->object_file = str8_zero(); // TODO + unit->archive_file = str8_zero(); // TODO + unit->build_path = cu_dir; + unit->language = d2r_rdi_language_from_dw_language(cu_lang); + unit->line_table = cu_line_tables_rdi[cu_idx]; + unit->voff_ranges = cu_voff_ranges; + } + + next_cu:; + temp_end(comp_temp); } - - // convert compile unit - { - RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); - unit->unit_name = cu_name; - unit->compiler_name = cu_prod; - unit->source_file = str8_zero(); // TODO - unit->object_file = str8_zero(); // TODO - unit->archive_file = str8_zero(); // TODO - unit->build_path = cu_dir; - unit->language = d2r_rdi_language_from_dw_language(cu_lang); - unit->line_table = cu_line_tables_rdi[cu_idx]; - unit->voff_ranges = cu_voff_ranges; - } - - next_cu:; - temp_end(comp_temp); } - ProfEnd(); } - lane_sync(); - RDIM_BakeParams bake_params = {0}; bake_params.subset_flags = params->subset_flags; bake_params.top_level_info = top_level_info; @@ -2866,7 +3013,6 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) bake_params.procedures = procs; bake_params.scopes = scopes; bake_params.inline_sites = inline_sites; - scratch_end(scratch); return bake_params; } diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.h b/src/rdi_from_dwarf/rdi_from_dwarf.h index 5b297184..100bd174 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.h +++ b/src/rdi_from_dwarf/rdi_from_dwarf.h @@ -1,7 +1,11 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#pragma once +#ifndef RDI_FROM_DWARF_H +#define RDI_FROM_DWARF_H + +//////////////////////////////// +//~ rjf: Conversion Stage Inputs typedef struct D2R_ConvertParams D2R_ConvertParams; struct D2R_ConvertParams @@ -15,6 +19,9 @@ struct D2R_ConvertParams B32 deterministic; }; +//////////////////////////////// +//~ rjf: Conversion Helper Types + typedef struct D2R_TypeTable { HashTable *ht; @@ -76,7 +83,7 @@ typedef enum D2R_ValueType typedef struct D2R_ValueTypeNode { D2R_ValueType type; - + struct D2R_ValueTypeNode *next; } D2R_ValueTypeNode; @@ -104,9 +111,6 @@ internal RDIM_Type * d2r_type_from_offset(D2R_TypeTable *type_table, U64 i internal RDIM_Type * d2r_type_from_attrib(D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal Rng1U64List d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 image_base, DW_Tag tag); internal RDIM_Type ** d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_TagNode *cur_node, U64 *param_count_out); -internal RDI_TypeKind d2r_unsigned_type_kind_from_size(U64 byte_size); -internal RDI_TypeKind d2r_signed_type_kind_from_size(U64 byte_size); -internal RDI_EvalTypeGroup d2r_type_group_from_type_kind(RDI_TypeKind x); //////////////////////////////// //~ RDIM Bytecode Helpers @@ -134,15 +138,14 @@ internal void d2r_push_relational_op(Arena *arena, D2R_ValueTypeStack * internal RDIM_EvalBytecode d2r_bytecode_from_expression(Arena *arena, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, String8 expr, DW_CompUnit *cu, D2R_ValueType *result_type_out); internal RDIM_Location * d2r_transpile_expression(Arena *arena, RDIM_LocationChunkList *locations, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, DW_CompUnit *cu, String8 expr); -internal RDIM_Location * d2r_location_from_attrib(Arena *arena, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind); internal RDIM_LocationCaseList d2r_locset_from_attrib(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind); internal RDIM_LocationCaseList d2r_var_locset_from_tag(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag); //////////////////////////////// //~ rjf: Compilation Unit / Scope Conversion Helpers -internal D2R_CompUnitContribMap d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base); -internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off); +internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off); +internal RDIM_Scope *d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D2R_TagFrame *tag_stack, Rng1U64List ranges); //////////////////////////////// //~ Tag Iterator @@ -159,6 +162,8 @@ internal DW_Tag d2r_tag_iterator_parent_tag(D2R_TagIterator *iter); internal void d2r_flag_converted_tag(DW_TagNode *tag_node); internal B8 d2r_is_tag_converted(DW_TagNode *tag_node); +internal RDIM_Type *d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_Tag tag, DW_AttribKind kind); + internal void d2r_convert_types(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root); internal void d2r_convert_udts(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root); internal void d2r_convert_symbols(Arena *arena, D2R_TypeTable *type_table, RDIM_Scope *global_scope, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, U64 image_base, Arch arch, DW_TagNode *root); @@ -167,3 +172,5 @@ internal void d2r_convert_symbols(Arena *arena, D2R_TypeTable *type_table, RDIM_ //~ rjf: Main Conversion Entry Point internal RDIM_BakeParams d2r_convert(Arena *arena, D2R_ConvertParams *params); + +#endif // RDI_FROM_DWARF_H diff --git a/src/rdi_from_elf/rdi_from_elf.c b/src/rdi_from_elf/rdi_from_elf.c index ccbb1351..eb85fa89 100644 --- a/src/rdi_from_elf/rdi_from_elf.c +++ b/src/rdi_from_elf/rdi_from_elf.c @@ -1,9 +1,36 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -internal RDIM_BinarySectionList -e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs) +internal RDI_BinarySectionFlags +e2r_rdi_binary_section_flags_from_elf(ELF_SectionFlags f) { + RDI_BinarySectionFlags result = RDI_BinarySectionFlag_Read; + if(f & ELF_Shf_Write) + { + result |= RDI_BinarySectionFlag_Write; + } + if(f & ELF_Shf_ExecInstr) + { + result |= RDI_BinarySectionFlag_Execute; + } + return result; +} + +internal RDIM_BinarySectionList +e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array shdrs) +{ RDIM_BinarySectionList result = {0}; + U64 base_vaddr = elf_base_addr_from_bin(bin); + for EachIndex(idx, shdrs.count) + { + ELF_Shdr64 *src = &shdrs.v[idx]; + RDIM_BinarySection *dst = rdim_binary_section_list_push(arena, &result); + dst->name = elf_name_from_shdr64(data, bin, src); + dst->flags = e2r_rdi_binary_section_flags_from_elf(src->sh_flags); + dst->voff_first = src->sh_addr - base_vaddr; + dst->voff_opl = dst->voff_first + src->sh_size; + dst->foff_first = src->sh_offset; + dst->foff_opl = dst->foff_first + src->sh_size; + } return result; } diff --git a/src/rdi_from_elf/rdi_from_elf.h b/src/rdi_from_elf/rdi_from_elf.h index 3d979c8f..2915e3eb 100644 --- a/src/rdi_from_elf/rdi_from_elf.h +++ b/src/rdi_from_elf/rdi_from_elf.h @@ -4,6 +4,7 @@ #ifndef RDI_FROM_ELF_H #define RDI_FROM_ELF_H -internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs); +internal RDI_BinarySectionFlags e2r_rdi_binary_section_flags_from_elf(ELF_SectionFlags f); +internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array shdrs); #endif // RDI_FROM_ELF_H diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 2f39dd91..97aa831b 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -5,7 +5,7 @@ #define RDI_FROM_PDB_H //////////////////////////////// -//~ rjf: Conversion Stage Inputs/Outputs +//~ rjf: Conversion Stage Inputs typedef struct P2R_ConvertParams P2R_ConvertParams; struct P2R_ConvertParams @@ -19,7 +19,7 @@ struct P2R_ConvertParams }; //////////////////////////////// -//~ rjf: Shared Conversion State +//~ rjf: Conversion Helper Types //- rjf: link name map (voff -> string)