diff --git a/project.4coder b/project.4coder index 2f198477..14cc2147 100644 --- a/project.4coder +++ b/project.4coder @@ -49,7 +49,7 @@ commands = // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - .f1 = { .win = "build torture", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "build raddbg", .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/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index cf494e69..918390fc 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -1746,75 +1746,6 @@ d_cached_sp_from_thread(D_Handle handle) //- rjf: cache lookups -#if 0 // TODO(rjf): @unwind -internal PE_IntelPdata * -d_intel_pdata_from_module_voff(Arena *arena, D_Handle module_handle, U64 voff) -{ - PE_IntelPdata *first_pdata = 0; - { - U64 hash = d_hash_from_handle(module_handle); - U64 slot_idx = hash%d_ctrl_state->module_info_cache.slots_count; - U64 stripe_idx = slot_idx%d_ctrl_state->module_info_cache.stripes_count; - D_ModuleInfoCacheSlot *slot = &d_ctrl_state->module_info_cache.slots[slot_idx]; - D_ModuleInfoCacheStripe *stripe = &d_ctrl_state->module_info_cache.stripes[stripe_idx]; - MutexScopeR(stripe->rw_mutex) for(D_ModuleInfoCacheNode *n = slot->first; n != 0; n = n->next) - { - if(d_handle_match(n->module, module_handle)) - { - PE_IntelPdata *pdatas = n->pdatas; - U64 pdatas_count = n->pdatas_count; - if(n->pdatas_count != 0 && voff >= n->pdatas[0].voff_first) - { - // NOTE(rjf): - // - // binary search: - // find max index s.t. pdata_array[index].voff_first <= voff - // we assume (i < j) -> (pdata_array[i].voff_first < pdata_array[j].voff_first) - U64 index = pdatas_count; - U64 min = 0; - U64 opl = pdatas_count; - for(;;) - { - U64 mid = (min + opl)/2; - PE_IntelPdata *pdata = pdatas + mid; - if(voff < pdata->voff_first) - { - opl = mid; - } - else if(pdata->voff_first < voff) - { - min = mid; - } - else - { - index = mid; - break; - } - if(min + 1 >= opl) - { - index = min; - break; - } - } - - // rjf: if we are in range fill result - { - PE_IntelPdata *pdata = pdatas + index; - if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last) - { - first_pdata = push_array(arena, PE_IntelPdata, 1); - MemoryCopyStruct(first_pdata, pdata); - } - } - } - break; - } - } - } - return first_pdata; -} -#endif - internal D_ModuleInfo * d_info_from_module(Access *access, D_Handle module) { @@ -1859,1146 +1790,6 @@ d_initial_debug_info_path_from_module(Arena *arena, D_Handle module_handle) //////////////////////////////// //~ rjf: Unwinding Functions -#if 0 // TODO(rjf): @unwind - -//- rjf: [dwarf] - -typedef struct D_MemoryReadContextDwarfX64 D_MemoryReadContextDwarfX64; -struct D_MemoryReadContextDwarfX64 -{ - D_Handle process_handle; - U64 endt_us; -}; - -internal MACHINE_OP_MEM_READ(ctrl_machine_mem_read) -{ - D_MemoryReadContextDwarfX64 *ctx = ud; - B32 is_stale = 0; - B32 is_read = d_process_memory_read(ctx->process_handle, r1u64(addr, addr + buffer_size), &is_stale, buffer, ctx->endt_us); - MachineOpResult status = MachineOpResult_Fail; - if(is_stale) - { - status = MachineOpResult_Maybe; - } - else if(is_read) - { - status = MachineOpResult_Ok; - } - return status; -} - -internal D_UnwindStepResult -d_unwind_step_result_from_machine_op_result(MachineOpResult s) -{ - D_UnwindStepResult result = {0}; - switch(s) - { - default:{result.flags |= D_UnwindFlag_Error;}break; - case MachineOpResult_Null:{}break; - case MachineOpResult_Ok: - { - result.flags &= ~(D_UnwindFlag_Error|D_UnwindFlag_Stale); - }break; - case MachineOpResult_Fail: - { - result.flags |= D_UnwindFlag_Error; - }break; - case MachineOpResult_Maybe: - { - result.flags &= ~D_UnwindFlag_Error; - result.flags |= D_UnwindFlag_Stale; - }break; - } - return result; -} - -internal D_UnwindStepResult -d_establish_frame_unwind_context__dwarf(Arena *arena, D_Handle process_handle, D_Handle module_handle, Arch arch, void *regs, U64 endt_us, D_FrameUnwindContext *ctx_out) -{ - Temp scratch = scratch_begin(&arena, 1); - ARCH_Info *arch_info = arch_info_from_arch(arch); - D_UnwindStepResult result = { .flags = D_UnwindFlag_Error }; - - // gather context for virtual stack unwinder - U64 cfi_rebase = 0; - B32 is_unwind_eh = 0; - String8 unwind_data = {0}; - EH_FrameHdr eh_frame_hdr = {0}; - EH_PtrCtx eh_ptr_ctx = {0}; - { - U64 hash = d_hash_from_handle(module_handle); - U64 slot_idx = hash%d_ctrl_state->module_info_cache.slots_count; - U64 stripe_idx = slot_idx%d_ctrl_state->module_info_cache.stripes_count; - D_ModuleInfoCacheSlot *slot = &d_ctrl_state->module_info_cache.slots[slot_idx]; - D_ModuleInfoCacheStripe *stripe = &d_ctrl_state->module_info_cache.stripes[stripe_idx]; - MutexScopeR(stripe->rw_mutex) for EachNode(n, D_ModuleInfoCacheNode, slot->first) - { - if(d_handle_match(n->module, module_handle)) - { - cfi_rebase = n->cfi_rebase; - is_unwind_eh = n->is_unwind_eh; - unwind_data = n->dwarf_unwind_data; - eh_frame_hdr = n->eh_frame_hdr; - eh_ptr_ctx = n->eh_ptr_ctx; - break; - } - } - } - - // grab IP - U64 ip = arch_ip_from_reg_block(arch_info, regs); - - // use .eh_frame_hdr to quickly locate nearest FDE - U64 fde_addr = eh_find_nearest_fde(eh_frame_hdr, &eh_ptr_ctx, ip); - - if(fde_addr != max_U64) - { - // parse call frame info - DW_CIE cie = {0}; - DW_FDE fde = {0}; - B32 is_cfi_parsed = 0; - if(is_unwind_eh) - { - B32 is_stale = 0; - - // extract FDE info - Rng1U64 fde_vrange = {0}; - DW_Format fde_format = DW_Format_Null; - String8 fde_data = {0}; - U64 cie_addr = 0; - { - // parse FDE length - U32 first_four_bytes = 0; - if(!d_process_memory_read_struct(process_handle, fde_addr, &is_stale, &first_four_bytes, endt_us)) { goto eh_parse_exit; } - if(first_four_bytes == max_U32) - { - U64 length = 0; - if(!d_process_memory_read_struct(process_handle, fde_addr + sizeof(first_four_bytes), &is_stale, &length, endt_us)) { goto eh_parse_exit; } - fde_vrange = r1u64(fde_addr, fde_addr + sizeof(first_four_bytes) + length); - fde_format = DW_Format_64Bit; - } - else - { - fde_vrange = r1u64(fde_addr, fde_addr + sizeof(first_four_bytes) + first_four_bytes); - fde_format = DW_Format_32Bit; - } - - // read out whole FDE - void *fde_raw = push_array(scratch.arena, U8, dim_1u64(fde_vrange)); - if(!d_process_memory_read(process_handle, fde_vrange, &is_stale, fde_raw, endt_us)) { goto eh_parse_exit; } - fde_data = str8(fde_raw, dim_1u64(fde_vrange)); - - // compute CIE address - U64 cie_delta_off = fde_format == DW_Format_32Bit ? 4 : 12; - U64 cie_delta = 0; - U64 cie_delta_size = str8_deserial_read_dwarf_uint(fde_data, cie_delta_off, fde_format, &cie_delta); - if (cie_delta_size == 0) { goto eh_parse_exit; } - cie_addr = (fde_addr + cie_delta_off) - cie_delta; - } - - // extract CIE info - Rng1U64 cie_vrange = {0}; - DW_Format cie_format = DW_Format_Null; - String8 cie_data = {0}; - { - // parse CIE length - U32 first_four_bytes = 0; - if(!d_process_memory_read_struct(process_handle, cie_addr, &is_stale, &first_four_bytes, endt_us)) { goto eh_parse_exit; } - if(first_four_bytes == max_U32) - { - U64 length = 0; - if(!d_process_memory_read_struct(process_handle, cie_addr + sizeof(first_four_bytes), &is_stale, &length, endt_us)) { goto eh_parse_exit; } - cie_vrange = r1u64(cie_addr, cie_addr + sizeof(first_four_bytes) + length); - cie_format = DW_Format_64Bit; - } - else - { - cie_vrange = r1u64(cie_addr, cie_addr + sizeof(first_four_bytes) + first_four_bytes); - cie_format = DW_Format_32Bit; - } - - // read out whole CIE - void *cie_raw = push_array(scratch.arena, U8, dim_1u64(cie_vrange)); - if(!d_process_memory_read(process_handle, cie_vrange, &is_stale, cie_raw, endt_us)) { goto eh_parse_exit; } - cie_data = str8(cie_raw, dim_1u64(cie_vrange)); - } - - // parse CIE and FDE - if(eh_parse_cie(cie_data, cie_format, arch, cie_vrange.min, &eh_ptr_ctx, &cie)) - { - is_cfi_parsed = eh_parse_fde(fde_data, fde_format, fde_vrange.min, &cie, &eh_ptr_ctx, &fde); - } - - eh_parse_exit:; - if(is_stale) - { - result.flags = D_UnwindFlag_Stale; - } - } - else - { - is_cfi_parsed = dw_parse_cfi(unwind_data, fde_addr, arch, &cie, &fde); - } - - if(is_cfi_parsed && contains_1u64(fde.pc_range, ip)) - { - // setup pointer decoder ops - DW_DecodePtr *decode_ptr_func = 0; - void *decode_ptr_ctx = 0; - if(is_unwind_eh) - { - EH_DecodePtrCtx *decode_ptr_ctx_eh = push_array(scratch.arena, EH_DecodePtrCtx, 1); - decode_ptr_ctx_eh->ptr_ctx = &eh_ptr_ctx; - decode_ptr_ctx_eh->addr_enc = cie.ext[EH_CIE_Ext_AddrEnc]; - - decode_ptr_func = eh_decode_ptr; - decode_ptr_ctx = decode_ptr_ctx_eh; - } - else - { - decode_ptr_func = dw_decode_ptr_debug_frame; - decode_ptr_ctx = &cie; - } - - // find register rules for IP - DW_CFI_Row *cfi_row = dw_cfi_row_from_pc(arena, arch, &cie, &fde, decode_ptr_func, decode_ptr_ctx, ip); - if(cfi_row) - { - // setup machine ops - void *mem_read_ctx = 0; - MachineOp_MemRead *mem_read_func = 0; - switch(arch) - { - case Arch_Null: break; - case Arch_x64: - { - D_MemoryReadContextDwarfX64 *mem_read_ctx_x64 = push_array(scratch.arena, D_MemoryReadContextDwarfX64, 1); - mem_read_ctx_x64->process_handle = process_handle; - mem_read_ctx_x64->endt_us = endt_us; - mem_read_ctx = mem_read_ctx_x64; - mem_read_func = ctrl_machine_mem_read; - }break; - case Arch_x86: - case Arch_arm64: - case Arch_arm32: - { - NotImplemented; - }break; - default: { InvalidPath; }break; - } - - // compute CFA for the row - U64 cfa = 0; - MachineOpResult unwind_status = dw_compute_cfa(arch, cfi_row, regs, mem_read_func, mem_read_ctx, &cfa); - - // on success fill out output - if(unwind_status == MachineOpResult_Ok) - { - ctx_out->cfa = cfa; - ctx_out->cfi_row = cfi_row; - ctx_out->ret_addr_reg = cie.ret_addr_reg; - } - - // translate unwind status code - result = d_unwind_step_result_from_machine_op_result(unwind_status); - } - } - } - - scratch_end(scratch); - return result; -} - -internal D_UnwindStepResult -d_unwind_step__dwarf(D_Handle process_handle, Arch arch, void *regs, D_FrameUnwindContext *frame_ctx, U64 endt_us) -{ - Temp scratch = scratch_begin(0, 0); - - D_UnwindStepResult result = { .flags = D_UnwindFlag_Error }; - - // setup machine ops - void *mem_read_ctx = 0; - void *reg_read_ctx = 0; - void *reg_write_ctx = 0; - MachineOp_MemRead *mem_read_func = 0; - MachineOp_RegRead *reg_read_func = 0; - MachineOp_RegWrite *reg_write_func = 0; - switch(arch) - { - default: - case Arch_Null:{}break; - case Arch_x64: - { - D_MemoryReadContextDwarfX64 *mem_read_ctx_x64 = push_array(scratch.arena, D_MemoryReadContextDwarfX64, 1); - mem_read_ctx_x64->process_handle = process_handle; - mem_read_ctx_x64->endt_us = endt_us; - mem_read_ctx = mem_read_ctx_x64; - reg_read_ctx = regs; - reg_write_ctx = regs; - mem_read_func = ctrl_machine_mem_read; - }break; - } - - // apply register rules to the context - MachineOpResult unwind_status = dw_cfi_apply_register_rules(arch, frame_ctx->cfa, frame_ctx->cfi_row, regs, mem_read_func, mem_read_ctx); - - // last frame typically has undefined rule for IP - if(frame_ctx->cfi_row->regs[frame_ctx->ret_addr_reg].rule == DW_CFI_RegisterRule_Undefined) - { - ARCH_Info *arch_info = arch_info_from_arch(arch); - arch_reg_block_write_ip(arch_info, regs, 0); - } - - // translate unwind status code - result = d_unwind_step_result_from_machine_op_result(unwind_status); - - scratch_end(scratch); - return result; -} - -//- rjf: [x64] - -internal U64 * -d_unwind_reg_from_pe_gpr_reg__pe_x64(X64_RegBlock *regs, PE_UnwindGprRegX64 gpr_reg) -{ - local_persist U64 dummy = {0}; - U64 *result = &dummy; - switch(gpr_reg) - { - case PE_UnwindGprRegX64_RAX:{result = ®s->rax;}break; - case PE_UnwindGprRegX64_RCX:{result = ®s->rcx;}break; - case PE_UnwindGprRegX64_RDX:{result = ®s->rdx;}break; - case PE_UnwindGprRegX64_RBX:{result = ®s->rbx;}break; - case PE_UnwindGprRegX64_RSP:{result = ®s->rsp;}break; - case PE_UnwindGprRegX64_RBP:{result = ®s->rbp;}break; - case PE_UnwindGprRegX64_RSI:{result = ®s->rsi;}break; - case PE_UnwindGprRegX64_RDI:{result = ®s->rdi;}break; - case PE_UnwindGprRegX64_R8 :{result = ®s->r8 ;}break; - case PE_UnwindGprRegX64_R9 :{result = ®s->r9 ;}break; - case PE_UnwindGprRegX64_R10:{result = ®s->r10;}break; - case PE_UnwindGprRegX64_R11:{result = ®s->r11;}break; - case PE_UnwindGprRegX64_R12:{result = ®s->r12;}break; - case PE_UnwindGprRegX64_R13:{result = ®s->r13;}break; - case PE_UnwindGprRegX64_R14:{result = ®s->r14;}break; - case PE_UnwindGprRegX64_R15:{result = ®s->r15;}break; - } - return result; -} - -internal D_UnwindStepResult -d_unwind_step__pe_x64(D_Handle process_handle, D_Handle module_handle, U64 module_base_vaddr, X64_RegBlock *regs, U64 endt_us) -{ - B32 is_stale = 0; - B32 is_good = 1; - Temp scratch = scratch_begin(0, 0); - - ////////////////////////////// - //- rjf: unpack parameters - // - U64 rip_voff = regs->rip - module_base_vaddr; - - ////////////////////////////// - //- rjf: rip_voff -> first pdata - // - PE_IntelPdata *first_pdata = d_intel_pdata_from_module_voff(scratch.arena, module_handle, rip_voff); - - ////////////////////////////// - //- rjf: pdata -> detect if in epilog - // - B32 has_pdata_and_in_epilog = 0; - if(first_pdata) ProfScope("pdata -> detect if in epilog") - { - // NOTE(allen): There are restrictions placed on how an epilog is allowed - // to be formed (https://docs.microsoft.com/en-us/cpp/build/prolog-and-epilog?view=msvc-160) - // Here we interpret machine code directly according to the rules - // given there to determine if the code we're looking at looks like an epilog. - - //- rjf: set up parsing state - B32 is_epilog = 0; - B32 keep_parsing = 1; - U64 read_vaddr = regs->rip; - U64 read_vaddr_opl = read_vaddr + 256; - - //- rjf: check first instruction - { - B32 inst_good = 0; - U8 inst[4] = {0}; - if(read_vaddr + sizeof(inst) <= read_vaddr_opl) - { - inst_good = d_process_memory_read(process_handle, r1u64(read_vaddr, read_vaddr+sizeof(inst)), &is_stale, inst, endt_us); - inst_good = inst_good && !is_stale; - } - if(!inst_good) - { - keep_parsing = 0; - } - else if((inst[0] & 0xF8) == 0x48) - { - switch(inst[1]) - { - // rjf: add $nnnn,%rsp - case 0x81: - { - if(inst[0] == 0x48 && inst[2] == 0xC4) - { - read_vaddr += 7; - } - else - { - keep_parsing = 0; - } - }break; - - // rjf: add $n,%rsp - case 0x83: - { - if(inst[0] == 0x48 && inst[2] == 0xC4) - { - read_vaddr += 4; - } - else - { - keep_parsing = 0; - } - }break; - - // rjf: lea n(reg),%rsp - case 0x8D: - { - if((inst[0] & 0x06) == 0 && - ((inst[2] >> 3) & 0x07) == 0x04 && - (inst[2] & 0x07) != 0x04) - { - U8 imm_size = (inst[2] >> 6); - - // rjf: 1-byte immediate - if(imm_size == 1) - { - read_vaddr += 4; - } - - // rjf: 4-byte immediate - else if(imm_size == 2) - { - read_vaddr += 7; - } - - // rjf: other case - else - { - keep_parsing = 0; - } - } - else - { - keep_parsing = 0; - } - }break; - } - } - } - - //- rjf: continue parsing instructions - for(;keep_parsing;) - { - // rjf: read next instruction byte - B32 inst_byte_good = 0; - U8 inst_byte = 0; - if(read_vaddr + sizeof(inst_byte) <= read_vaddr_opl) - { - inst_byte_good = d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); - } - if(!inst_byte_good || is_stale) - { - keep_parsing = 0; - } - - // rjf: when (... I don't know ...) rely on the next byte - B32 check_inst_byte_good = inst_byte_good; - U64 check_vaddr = read_vaddr; - U8 check_inst_byte = inst_byte; - if(inst_byte_good && (inst_byte & 0xF0) == 0x40) - { - check_vaddr = read_vaddr + 1; - if(read_vaddr + sizeof(check_inst_byte) <= read_vaddr_opl) - { - check_inst_byte_good = d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &check_inst_byte, endt_us); - } - if(!check_inst_byte_good || is_stale) - { - keep_parsing = 0; - } - } - - // rjf: check instruction byte - if(check_inst_byte_good) - { - switch(check_inst_byte) - { - // rjf: pop - case 0x58:case 0x59:case 0x5A:case 0x5B: - case 0x5C:case 0x5D:case 0x5E:case 0x5F: - { - read_vaddr = check_vaddr + 1; - }break; - - // rjf: ret - case 0xC2: - case 0xC3: - { - is_epilog = 1; - keep_parsing = 0; - }break; - - // rjf: jmp nnnn - case 0xE9: - { - U64 imm_vaddr = check_vaddr + 1; - S32 imm = 0; - B32 imm_good = 0; - if(read_vaddr + sizeof(imm) <= read_vaddr_opl) - { - imm_good = d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us); - } - if(!imm_good || is_stale) - { - keep_parsing = 0; - } - if(imm_good) - { - U64 next_vaddr = (U64)(imm_vaddr + sizeof(imm) + imm); - U64 next_voff = next_vaddr - module_base_vaddr; // TODO(rjf): verify that this offset is from module base vaddr, not section - if(!(first_pdata->voff_first <= next_voff && next_voff < first_pdata->voff_one_past_last)) - { - keep_parsing = 0; - } - else - { - read_vaddr = next_vaddr; - } - } - // TODO(allen): why isn't this just the end of the epilog? - }break; - - // rjf: rep; ret (for amd64 prediction bug) - case 0xF3: - { - U8 next_inst_byte = 0; - B32 next_inst_byte_good = 0; - if(read_vaddr + sizeof(next_inst_byte) <= read_vaddr_opl) - { - next_inst_byte_good = d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &next_inst_byte, endt_us); - } - if(next_inst_byte_good) - { - is_epilog = (next_inst_byte == 0xC3); - } - keep_parsing = 0; - }break; - - default:{keep_parsing = 0;}break; - } - } - } - has_pdata_and_in_epilog = is_epilog; - } - - ////////////////////////////// - //- rjf: pdata & in epilog -> epilog unwind - // - if(first_pdata && has_pdata_and_in_epilog) ProfScope("pdata & in epilog -> epilog unwind") - { - U64 read_vaddr = regs->rip; - for(B32 keep_parsing = 1;keep_parsing != 0;) - { - //- rjf: assume no more parsing after this instruction - keep_parsing = 0; - - //- rjf: read next instruction byte - U8 inst_byte = 0; - is_good = is_good && d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); - is_good = is_good && !is_stale; - read_vaddr += 1; - - //- rjf: extract rex from instruction byte - U8 rex = 0; - if((inst_byte & 0xF0) == 0x40) - { - rex = inst_byte & 0xF; // rex prefix - is_good = is_good && d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); - is_good = is_good && !is_stale; - read_vaddr += 1; - } - - //- rjf: parse remainder of instruction - switch(inst_byte) - { - // rjf: pop - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - { - // rjf: read value at rsp - U64 sp = regs->rsp; - U64 value = 0; - if(!d_process_memory_read_struct(process_handle, sp, &is_stale, &value, endt_us) || - is_stale) - { - is_good = 0; - break; - } - - // rjf: modify registers - PE_UnwindGprRegX64 gpr_reg = (inst_byte - 0x58) + (rex & 1)*8; - U64 *reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, gpr_reg); - reg[0] = value; - regs->rsp = sp + 8; - - // rjf: not a final instruction, so keep mparsing - keep_parsing = 1; - }break; - - // rjf: add $nnnn,%rsp - case 0x81: - { - // rjf: skip one byte (we already know what it is in this scenario) - read_vaddr += 1; - - // rjf: read the 4-byte immediate - S32 imm = 0; - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || - is_stale) - { - is_good = 0; - break; - } - read_vaddr += 4; - - // rjf: update stack pointer - regs->rsp = (U64)(regs->rsp + imm); - - // rjf: not a final instruction; keep parsing - keep_parsing = 1; - }break; - - // rjf: add $n,%rsp - case 0x83: - { - // rjf: skip one byte (we already know what it is in this scenario) - read_vaddr += 1; - - // rjf: read the 4-byte immediate - S8 imm = 0; - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || - is_stale) - { - is_good = 0; - break; - } - read_vaddr += 1; - - // rjf: update stack pointer - regs->rsp = (U64)(regs->rsp + imm); - - // rjf: not a final instruction; keep parsing - keep_parsing = 1; - }break; - - // rjf: lea imm8/imm32,$rsp - case 0x8D: - { - // rjf: read source register - U8 modrm = 0; - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &modrm, endt_us) || - is_stale) - { - is_good = 0; - break; - } - read_vaddr += 1; - PE_UnwindGprRegX64 gpr_reg = (modrm & 7) + (rex & 1)*8; - U64 *reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, gpr_reg); - U64 reg_value = reg[0]; - - // rjf: read immediate - S32 imm = 0; - { - // rjf: read 1-byte immediate - if((modrm >> 6) == 1) - { - S8 imm8 = 0; - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm8, endt_us) || - is_stale) - { - is_good = 0; - break; - } - read_vaddr += 1; - imm = (S32)imm8; - } - - // rjf: read 4-byte immediate - else - { - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || - is_stale) - { - is_good = 0; - break; - } - read_vaddr += 4; - } - } - - // rjf: update stack pointer - regs->rsp = (U64)(reg_value + imm); - - // rjf: not a final instruction; keep parsing - keep_parsing = 1; - }break; - - // rjf: ret $nn - case 0xC2: - { - // rjf: read new ip - U64 sp = regs->rsp; - U64 new_ip = 0; - if(!d_process_memory_read_struct(process_handle, sp, &is_stale, &new_ip, endt_us) || - is_stale) - { - is_good = 0; - break; - } - - // rjf: read 2-byte immediate & advance stack pointer - U16 imm = 0; - if(!d_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || - is_stale) - { - is_good = 0; - break; - } - U64 new_sp = sp + 8 + imm; - - // rjf: commit registers - regs->rip = new_ip; - regs->rsp = new_sp; - }break; - - // rjf: ret / rep; ret - case 0xF3: - { - // Assert(!"Hit me!"); - }break; - case 0xC3: - { - // rjf: read new ip - U64 sp = regs->rsp; - U64 new_ip = 0; - if(!d_process_memory_read_struct(process_handle, sp, &is_stale, &new_ip, endt_us) || - is_stale) - { - is_good = 0; - break; - } - - // rjf: advance stack pointer - U64 new_sp = sp + 8; - - // rjf: commit registers - regs->rip = new_ip; - regs->rsp = new_sp; - }break; - - // rjf: jmp nnnn - case 0xE9: - { - // Assert(!"Hit Me"); - // TODO(allen): general idea: read the immediate, move the ip, leave the sp, done - // we don't have any cases to exercise this right now. no guess implementation! - }break; - - // rjf: Sjmp n - case 0xEB: - { - // Assert(!"Hit Me"); - // TODO(allen): general idea: read the immediate, move the ip, leave the sp, done - // we don't have any cases to exercise this right now. no guess implementation! - }break; - } - } - } - - ////////////////////////////// - //- rjf: pdata & not in epilog -> xdata unwind - // - B32 xdata_unwind_did_machframe = 0; - if(first_pdata && !has_pdata_and_in_epilog) ProfScope("pdata & not in epilog -> xdata unwind") - { - //- rjf: get frame reg - B32 bad_frame_reg_info = 0; - U64 *frame_reg = 0; - U64 frame_off = 0; - { - U64 unwind_info_off = first_pdata->voff_unwind_info; - PE_UnwindInfo unwind_info = {0}; - if(!d_process_memory_read_struct(process_handle, module_base_vaddr+unwind_info_off, &is_stale, &unwind_info, endt_us) || - is_stale) - { - is_good = 0; - } - U32 frame_reg_id = PE_UNWIND_INFO_REG_FROM_FRAME(unwind_info.frame); - U64 frame_off_val = PE_UNWIND_INFO_OFF_FROM_FRAME(unwind_info.frame); - if(frame_reg_id != 0) - { - frame_reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, frame_reg_id); - bad_frame_reg_info = (frame_reg == 0); // NOTE(rjf): frame_reg should never be 0 at this point, in valid exe - } - frame_off = frame_off_val; - } - - //- rjf: iterate pdatas, apply opcodes - PE_IntelPdata *last_pdata = 0; - PE_IntelPdata *pdata = first_pdata; - if(!bad_frame_reg_info) for(B32 keep_parsing = 1; keep_parsing && pdata != last_pdata;) - { - //- rjf: unpack unwind info & codes - B32 good_unwind_info = 1; - U64 unwind_info_off = pdata->voff_unwind_info; - PE_UnwindInfo unwind_info = {0}; - good_unwind_info = good_unwind_info && d_process_memory_read_struct(process_handle, module_base_vaddr+unwind_info_off, &is_stale, &unwind_info, endt_us); - PE_UnwindCode *unwind_codes = push_array(scratch.arena, PE_UnwindCode, unwind_info.codes_num); - good_unwind_info = good_unwind_info && d_process_memory_read(process_handle, r1u64(module_base_vaddr+unwind_info_off+sizeof(unwind_info), - module_base_vaddr+unwind_info_off+sizeof(unwind_info)+sizeof(PE_UnwindCode)*unwind_info.codes_num), - &is_stale, unwind_codes, endt_us); - good_unwind_info = good_unwind_info && !is_stale; - - //- rjf: bad unwind info -> abort - if(!good_unwind_info) - { - is_good = 0; - break; - } - - //- rjf: unpack frame base - U64 frame_base = regs->rsp; - if(frame_reg != 0) - { - U64 raw_frame_base = frame_reg[0]; - U64 adjusted_frame_base = raw_frame_base - frame_off*16; - frame_base = adjusted_frame_base; - } - - //- rjf: apply opcodes - PE_UnwindCode *code_ptr = unwind_codes; - PE_UnwindCode *code_opl = unwind_codes + unwind_info.codes_num; - for(PE_UnwindCode *next_code_ptr = 0; code_ptr < code_opl; code_ptr = next_code_ptr) - { - // rjf: unpack opcode info - U32 op_code = PE_UNWIND_OPCODE_FROM_FLAGS(code_ptr->flags); - U32 op_info = PE_UNWIND_INFO_FROM_FLAGS(code_ptr->flags); - U32 slot_count = pe_slot_count_from_unwind_op_code(op_code); - if(op_code == PE_UnwindOpCode_ALLOC_LARGE && op_info == 1) - { - slot_count += 1; - } - - // rjf: detect bad slot counts - if(slot_count == 0 || code_ptr+slot_count > code_opl) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: set next op code pointer - next_code_ptr = code_ptr + slot_count; - - // rjf: interpret this op code - U64 code_voff = pdata->voff_first + code_ptr->off_in_prolog; - if(code_voff <= rip_voff) - { - switch(op_code) - { - case PE_UnwindOpCode_PUSH_NONVOL: - { - // rjf: read value from stack pointer - U64 rsp = regs->rsp; - U64 value = 0; - if(!d_process_memory_read_struct(process_handle, rsp, &is_stale, &value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: advance stack ptr - U64 new_rsp = rsp + 8; - - // rjf: commit registers - U64 *reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); - reg[0] = value; - regs->rsp = new_rsp; - }break; - - case PE_UnwindOpCode_ALLOC_LARGE: - { - // rjf: read alloc size - U64 size = 0; - if(op_info == 0) - { - size = code_ptr[1].u16*8; - } - else if(op_info == 1) - { - size = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); - } - else - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: advance stack pointer - U64 rsp = regs->rsp; - U64 new_rsp = rsp + size; - - // rjf: advance stack pointer - regs->rsp = new_rsp; - }break; - - case PE_UnwindOpCode_ALLOC_SMALL: - { - // rjf: advance stack pointer - regs->rsp += op_info*8 + 8; - }break; - - case PE_UnwindOpCode_SET_FPREG: - { - // rjf: put stack pointer back to the frame base - regs->rsp = frame_base; - }break; - - case PE_UnwindOpCode_SAVE_NONVOL: - { - // rjf: read value from frame base - U64 off = code_ptr[1].u16*8; - U64 addr = frame_base + off; - U64 value = 0; - if(!d_process_memory_read_struct(process_handle, addr, &is_stale, &value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: commit to register - U64 *reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); - reg[0] = value; - }break; - - case PE_UnwindOpCode_SAVE_NONVOL_FAR: - { - // rjf: read value from frame base - U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); - U64 addr = frame_base + off; - U64 value = 0; - if(!d_process_memory_read_struct(process_handle, addr, &is_stale, &value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: commit to register - U64 *reg = d_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); - reg[0] = value; - }break; - - case PE_UnwindOpCode_EPILOG: - { - keep_parsing = 1; - }break; - - case PE_UnwindOpCode_SPARE_CODE: - { - // TODO(rjf): ??? - keep_parsing = 0; - is_good = 0; - }break; - - case PE_UnwindOpCode_SAVE_XMM128: - { - // rjf: read new register values - U8 buf[16]; - U64 off = code_ptr[1].u16*16; - U64 addr = frame_base + off; - if(!d_process_memory_read(process_handle, r1u64(addr, addr+sizeof(buf)), &is_stale, buf, endt_us)) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: commit to register - void *xmm_reg = (®s->zmm0) + op_info; - MemoryCopy(xmm_reg, buf, sizeof(buf)); - }break; - - case PE_UnwindOpCode_SAVE_XMM128_FAR: - { - // rjf: read new register values - U8 buf[16]; - U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); - U64 addr = frame_base + off; - if(!d_process_memory_read(process_handle, r1u64(addr, addr+16), &is_stale, buf, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: commit to register - void *xmm_reg = (®s->zmm0) + op_info; - MemoryCopy(xmm_reg, buf, sizeof(buf)); - }break; - - case PE_UnwindOpCode_PUSH_MACHFRAME: - { - // NOTE(rjf): this was found by stepping through kernel code after an exception was - // thrown, encountered in the exception_stepping_tests (after the throw) in mule_main - if(op_info > 1) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: read values - U64 sp_og = regs->rsp; - U64 sp_adj = sp_og; - if(op_info == 1) - { - sp_adj += 8; - } - U64 ip_value = 0; - if(!d_process_memory_read_struct(process_handle, sp_adj, &is_stale, &ip_value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - U64 sp_after_ip = sp_adj + 8; - U16 ss_value = 0; - if(!d_process_memory_read_struct(process_handle, sp_after_ip, &is_stale, &ss_value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - U64 sp_after_ss = sp_after_ip + 8; - U64 rflags_value = 0; - if(!d_process_memory_read_struct(process_handle, sp_after_ss, &is_stale, &rflags_value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - U64 sp_after_rflags = sp_after_ss + 8; - U64 sp_value = 0; - if(!d_process_memory_read_struct(process_handle, sp_after_rflags, &is_stale, &sp_value, endt_us) || - is_stale) - { - keep_parsing = 0; - is_good = 0; - break; - } - - // rjf: commit registers - regs->rip = ip_value; - regs->ss = ss_value; - regs->rflags = rflags_value; - regs->rsp = sp_value; - - // rjf: mark machine frame - xdata_unwind_did_machframe = 1; - }break; - } - } - } - - //- rjf: iterate to next pdata - if(keep_parsing) - { - U32 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(unwind_info.header); - if(!(flags & PE_UnwindInfoFlag_CHAINED)) - { - break; - } - U64 code_count_rounded = AlignPow2(unwind_info.codes_num, sizeof(PE_UnwindCode)); - U64 code_size = code_count_rounded*sizeof(PE_UnwindCode); - U64 chained_pdata_off = unwind_info_off + sizeof(PE_UnwindInfo) + code_size; - last_pdata = pdata; - pdata = push_array(scratch.arena, PE_IntelPdata, 1); - if(!d_process_memory_read_struct(process_handle, module_base_vaddr+chained_pdata_off, &is_stale, pdata, endt_us) || - is_stale) - { - is_good = 0; - break; - } - } - } - } - - ////////////////////////////// - //- rjf: no pdata, or didn't do machframe in xdata unwind -> unwind by reading stack pointer - // - if(!first_pdata || (!has_pdata_and_in_epilog && !xdata_unwind_did_machframe)) ProfScope("no pdata, or didn't do machframe in xdata unwind -> unwind by reading stack pointer") - { - // rjf: read rip from stack pointer - U64 rsp = regs->rsp; - U64 new_rip = 0; - if(!d_process_memory_read_struct(process_handle, rsp, &is_stale, &new_rip, endt_us) || - is_stale) - { - is_good = 0; - } - - // rjf: commit registers - if(is_good) - { - U64 new_rsp = rsp + 8; - regs->rip = new_rip; - regs->rsp = new_rsp; - } - } - - ////////////////////////////// - //- rjf: fill & return - // - scratch_end(scratch); - D_UnwindStepResult result = {0}; - if(!is_good) {result.flags |= D_UnwindFlag_Error;} - if(is_stale) {result.flags |= D_UnwindFlag_Stale;} - return result; -} -#endif - -//- rjf: abstracted full unwind - internal D_Unwind d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us) { @@ -3147,76 +1938,6 @@ d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us) { break; } - -#if 0 // TODO(rjf): @unwind - // rip -> module - D_Entity *module_entity = d_module_from_process_vaddr(process_entity, rip); - - // establish frame context - D_FrameUnwindContext frame_ctx = {0}; - D_UnwindStepResult frame_ctx_result = {0}; - switch(process_entity->target_os) - { - case OperatingSystem_Null:{}break; - case OperatingSystem_Windows: - { - // no concept of frame unwind context - }break; - case OperatingSystem_Linux: - { - frame_ctx_result = d_establish_frame_unwind_context__dwarf(arena, process_entity->handle, module_entity->handle, arch, regs_block, endt_us, &frame_ctx); - }break; - case OperatingSystem_Mac: - { - NotImplemented; - }break; - default: { InvalidPath; }break; - } - unwind.flags |= frame_ctx_result.flags; - if(unwind.flags & (D_UnwindFlag_Stale|D_UnwindFlag_Error)) - { - break; - } - - // rjf: valid step -> push frame - D_UnwindFrameNode *frame_node = push_array(scratch.arena, D_UnwindFrameNode, 1); - D_UnwindFrame *frame = &frame_node->v; - frame->cfa = frame_ctx.cfa; - frame->regs = push_array_no_zero(arena, U8, arch_reg_block_size); - MemoryCopy(frame->regs, regs_block, arch_reg_block_size); - DLLPushBack(first_frame_node, last_frame_node, frame_node); - frame_node_count += 1; - - // rjf: unwind one step - D_UnwindStepResult step_result = {0}; - switch(process_entity->target_os) - { - default:{}break; - case OperatingSystem_Windows: - { - switch(arch) - { - default:{}break; - case Arch_x64: - { - step_result = d_unwind_step__pe_x64(process_entity->handle, module_entity->handle, module_entity->vaddr_range.min, regs_block, endt_us); - }break; - } - }break; - case OperatingSystem_Linux: - { - step_result = d_unwind_step__dwarf(process_entity->handle, arch, regs_block, &frame_ctx, endt_us); - }break; - } - - // rjf: stop unwinding on errors or stale data - unwind.flags |= step_result.flags; - if(unwind.flags & (D_UnwindFlag_Stale|D_UnwindFlag_Error) || - (arch_sp_from_reg_block(arch_info, regs_block) == rsp && arch_ip_from_reg_block(arch_info, regs_block) == rip)) - { - break; - } -#endif } } diff --git a/src/dbg_engine/dbg_engine_ctrl.h b/src/dbg_engine/dbg_engine_ctrl.h index 13d0e926..48616ca3 100644 --- a/src/dbg_engine/dbg_engine_ctrl.h +++ b/src/dbg_engine/dbg_engine_ctrl.h @@ -49,17 +49,6 @@ struct D_Unwind D_UnwindFlags flags; }; -#if 0 // TODO(rjf): @unwind -typedef struct D_FrameUnwindContext D_FrameUnwindContext; -struct D_FrameUnwindContext -{ - // DWARF - U64 cfa; - DW_CFI_Row *cfi_row; - U64 ret_addr_reg; -}; -#endif - //////////////////////////////// //~ rjf: Call Stack Types @@ -558,9 +547,6 @@ internal U64 d_cached_sp_from_thread(D_Handle handle); //~ rjf: Module Image Info Functions //- rjf: cache lookups -#if 0 // TODO(rjf): @unwind -internal PE_IntelPdata *d_intel_pdata_from_module_voff(Arena *arena, D_Handle module_handle, U64 voff); -#endif internal D_ModuleInfo *d_info_from_module(Access *access, D_Handle module); internal U64 d_entry_point_voff_from_module(D_Handle module_handle); internal String8 d_initial_debug_info_path_from_module(Arena *arena, D_Handle module_handle); @@ -568,18 +554,6 @@ internal String8 d_initial_debug_info_path_from_module(Arena *arena, D_Handle mo //////////////////////////////// //~ rjf: Unwinding Functions -#if 0 // TODO(rjf): @unwind -//- rjf: [dwarf] -internal D_UnwindStepResult d_unwind_step_result_from_machine_op_result(MachineOpResult s); -internal D_UnwindStepResult d_establish_frame_unwind_context__dwarf(Arena *arena, D_Handle process_handle, D_Handle module_handle, Arch arch, void *regs, U64 endt_us, D_FrameUnwindContext *ctx_out); -internal D_UnwindStepResult d_unwind_step__dwarf(D_Handle process_handle, Arch arch, void *regs, D_FrameUnwindContext *frame_ctx, U64 endt_us); - -//- rjf: [x64] -internal U64 *d_unwind_reg_from_pe_gpr_reg__pe_x64(X64_RegBlock *regs, PE_UnwindGprRegX64 gpr_reg); -internal D_UnwindStepResult d_unwind_step__pe_x64(D_Handle process_handle, D_Handle module_handle, U64 module_base_vaddr, X64_RegBlock *regs, U64 endt_us); -#endif - -//- rjf: abstracted full unwind internal D_Unwind d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us); //////////////////////////////// diff --git a/src/dwarf/dwarf.c b/src/dwarf/dwarf.c index 5d73309e..01e985a0 100644 --- a/src/dwarf/dwarf.c +++ b/src/dwarf/dwarf.c @@ -448,327 +448,3 @@ dw_reg_count_from_arch(Arch arch) } return result; } - -//////////////////////////////// -//~ TODO(rjf): OLD vvvvvvvvvvv - -#if 0 -internal DW_AttribClass -dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k) -{ - DW_AttribClass result = 0; - switch(k) - { - default:{}break; -#define X(name, code, version, ext, class) case DW_FormKind_##name:{result = (class);}break; - DW_FormKind_XList -#undef X - } - return result; -} - -internal U64 -dw_reg_size_from_code(Arch arch, DW_Reg reg_code) -{ - switch (arch) { - case Arch_Null: break; - case Arch_x64: return dw_reg_size_from_code_x64(reg_code); - default: NotImplemented; break; - } - return 0; -} - -internal U64 -dw_reg_pos_from_code(Arch arch, DW_Reg reg_code) -{ - switch (arch) { - case Arch_Null: break; - case Arch_x64: return dw_reg_pos_from_code_x64(reg_code); - default: NotImplemented; break; - } - return max_U64; -} - -internal U64 -dw_reg_count_from_arch(Arch arch) -{ - switch (arch) { - default: { NotImplemented; } // fall-through - case Arch_Null: return 0; - case Arch_x64: return DW_RegX64_Last; - } -} - -internal U64 -dw_reg_max_size_from_arch(Arch arch) -{ - local_persist U64 max_size = 0; - if (max_size == 0) { - U64 max_idx = dw_reg_count_from_arch(arch); - for EachIndex(reg_idx, max_idx) { - U64 reg_size = dw_reg_size_from_code(arch, reg_idx); - max_size = Max(max_size, reg_size); - } - } - return max_size; -} - -internal U64 -dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode) -{ - switch (opcode) { -#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; } - DW_CFA_Kind_XList -#undef X - default: { NotImplemented; } break; - } - return 0; -} - -internal B32 -dw_is_cfa_expr_opcode_invalid(DW_ExprOp opcode) -{ - B32 is_invalid = 0; - switch(opcode) - { - default:{}break; - case DW_ExprOp_Addrx: - case DW_ExprOp_Call2: - case DW_ExprOp_Call4: - case DW_ExprOp_CallRef: - case DW_ExprOp_ConstType: - case DW_ExprOp_Constx: - case DW_ExprOp_Convert: - case DW_ExprOp_DerefType: - case DW_ExprOp_RegvalType: - case DW_ExprOp_Reinterpret: - case DW_ExprOp_PushObjectAddress: - case DW_ExprOp_CallFrameCfa: - { - is_invalid = 1; - }break; - } - return is_invalid; -} - -internal B32 -dw_is_new_row_cfa_opcode(DW_CFA_Opcode opcode) -{ - B32 is_new_row_op = 0; - switch(opcode) - { - default:{}break; - case DW_CFA_SetLoc: - case DW_CFA_AdvanceLoc: - case DW_CFA_AdvanceLoc1: - case DW_CFA_AdvanceLoc2: - case DW_CFA_AdvanceLoc4: - { - is_new_row_op = 1; - }break; - } - return is_new_row_op; -} - -internal DW_CFA_OperandType * -dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode) -{ - switch (opcode) { -#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; } - DW_CFA_Kind_XList -#undef X - default: { NotImplemented; } break; - } - return 0; -} - -internal String8 -dw_string_from_language(Arena *arena, DW_Language kind) -{ - switch (kind) { -#define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N)); - DW_Language_XList -#undef X - } - return push_str8f(arena, "%x", kind); -} - -internal String8 -dw_string_from_comp_unit_kind(Arena *arena, DW_CompUnitKind kind) -{ - switch (kind) { -#define X(_N,_ID) case DW_CompUnitKind_##_N: return str8_lit(Stringify(_N)); - DW_CompUnitKind_XList -#undef X - } - return push_str8f(arena, "%x", kind); -} - -internal String8 -dw_string_from_inl(Arena *arena, DW_InlKind kind) -{ - switch (kind) { -#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); - DW_Inl_XList -#undef X - } - return push_str8f(arena, "%x", kind); -} - -internal String8 -dw_string_from_access_kind(Arena *arena, DW_AccessKind kind) -{ - switch (kind) { -#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); - DW_AccessKind_XList -#undef X - } - return push_str8f(arena, "%llx", kind); -} - -internal String8 -dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind) -{ - switch (kind) { -#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); - DW_CallingConventionKind_XList -#undef X - } - return push_str8f(arena, "%llx", kind); -} - -internal String8 -dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind) -{ - switch (kind) { -#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); - DW_ATE_XList -#undef X - } - return push_str8f(arena, "%llx", kind); -} - -internal String8 -dw_string_from_attrib_visibility(Arena *arena, DW_Vis vis) -{ - switch (vis) { -#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); - DW_Vis_XList -#undef X - } - return push_str8f(arena, "%llx", vis); -} - -internal String8 -dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind) -{ - switch (kind) { -#define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N)); - DW_StdOpcode_XList -#undef X - } - return push_str8f(arena, "%x", kind); -} - -internal String8 -dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind) -{ - switch (kind) { -#define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N)); - DW_ExtOpcode_XList -#undef X - default: InvalidPath; break; - } - return push_str8f(arena, "%x", kind); -} - -internal String8 -dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind) -{ - NotImplemented; - return str8_zero(); -} - -internal String8 -dw_string_from_section_kind(Arena *arena, DW_SectionKind kind) -{ - NotImplemented; - return str8_zero(); -} - -internal String8 -dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind) -{ - NotImplemented; - return str8_zero(); -} - -internal String8 -dw_string_from_register(Arena *arena, Arch arch, U64 reg_id) -{ - String8 reg_str = str8_zero(); - switch (arch) { - case Arch_Null: break; - case Arch_x64: { - switch (reg_id) { -#define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break; - DW_Regs_X64_XList -#undef X - } - } break; - case Arch_arm32: NotImplemented; break; - case Arch_arm64: NotImplemented; break; - case Arch_x86: NotImplemented; break; - default: InvalidPath; break; - } - if (reg_str.size == 0) { - reg_str = push_str8f(arena, "%#llx", reg_id); - } - return reg_str; -} - -internal String8 -dw_string_from_cfa_opcode(DW_CFA_Opcode opcode) -{ - switch (opcode) { -#define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME)); - DW_CFA_Kind_XList -#undef X - default: InvalidPath; break; - } - return str8_zero(); -} - -internal String8 -dw_name_string_from_section_kind(DW_SectionKind k) -{ - switch (k) { -#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_L); - DW_SectionKind_XList -#undef X - } - return str8_zero(); -} - -internal String8 -dw_mach_name_string_from_section_kind(DW_SectionKind k) -{ - switch (k) { -#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_M); - DW_SectionKind_XList -#undef X - } - return str8_zero(); -} - -internal String8 -dw_dwo_name_string_from_section_kind(DW_SectionKind k) -{ - switch (k) { -#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_D); - DW_SectionKind_XList -#undef X - } - return str8_zero(); -} -#endif diff --git a/src/dwarf/dwarf.h b/src/dwarf/dwarf.h index c8bedf7f..3dfce316 100644 --- a/src/dwarf/dwarf.h +++ b/src/dwarf/dwarf.h @@ -65,46 +65,4 @@ internal String8 dw_dwo_name_from_section_kind(DW_SectionKind k); //- rjf: architecture info internal U64 dw_reg_count_from_arch(Arch arch); -//////////////////////////////// -//~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvv - -#if 0 -//////////////////////////////// -// xlist helpers - -// regs -internal U64 dw_reg_size_from_code(Arch arch, DW_Reg reg_code); -internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code); -internal U64 dw_reg_count_from_arch(Arch arch); -internal U64 dw_reg_max_size_from_arch(Arch arch); -internal U64 dw_size_from_format(DW_Format format); - -// CFA -internal U64 dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode); -internal B32 dw_is_cfa_expr_opcode_invalid(DW_ExprOp opcode); -internal B32 dw_is_new_row_cfa_opcode(DW_CFA_Opcode opcode); -internal DW_CFA_OperandType * dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode); - -//////////////////////////////// -//~ rjf: String <=> Enum - -internal String8 dw_string_from_language(Arena *arena, DW_Language kind); -internal String8 dw_string_from_comp_unit_kind(Arena *arena, DW_CompUnitKind kind); -internal String8 dw_string_from_inl(Arena *arena, DW_InlKind kind); -internal String8 dw_string_from_access_kind(Arena *arena, DW_AccessKind kind); -internal String8 dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind); -internal String8 dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind); -internal String8 dw_string_from_attrib_visibility(Arena *arena, DW_Vis vis); -internal String8 dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind); -internal String8 dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind); -internal String8 dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind); -internal String8 dw_string_from_section_kind(Arena *arena, DW_SectionKind kind); -internal String8 dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind); -internal String8 dw_string_from_register(Arena *arena, Arch arch, U64 reg_id); -internal String8 dw_string_from_cfa_opcode(DW_CFA_Opcode opcode); -internal String8 dw_name_string_from_section_kind(DW_SectionKind k); -internal String8 dw_mach_name_string_from_section_kind(DW_SectionKind k); -internal String8 dw_dwo_name_string_from_section_kind (DW_SectionKind k); -#endif - #endif // DWARF_H diff --git a/src/dwarf/dwarf_inc.c b/src/dwarf/dwarf_inc.c index 42a9d935..b5b9efb4 100644 --- a/src/dwarf/dwarf_inc.c +++ b/src/dwarf/dwarf_inc.c @@ -2,11 +2,7 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) #include "dwarf/dwarf.c" -// #include "dwarf/dwarf_parse.c" -// #include "dwarf/dwarf_expr.c" #include "dwarf/dwarf_expr_2.c" -// #include "dwarf/dwarf_unwind.c" -// #include "dwarf/dwarf_dump.c" #include "dwarf/dwarf_parse_2.c" #include "dwarf/dwarf_unwind_2.c" #include "dwarf/dwarf_dump_2.c" @@ -16,7 +12,3 @@ #if defined(ELF_H) # include "dwarf/dwarf_parse_elf.c" #endif - -#if 0 // TODO(rjf): this uses concepts from the old parser -# include "dwarf/dwarf_writer.c" -#endif diff --git a/src/dwarf/dwarf_inc.h b/src/dwarf/dwarf_inc.h index acb0be66..afc74828 100644 --- a/src/dwarf/dwarf_inc.h +++ b/src/dwarf/dwarf_inc.h @@ -5,11 +5,7 @@ #define DWARF_INC_H #include "dwarf/dwarf.h" -// #include "dwarf/dwarf_parse.h" -// #include "dwarf/dwarf_expr.h" #include "dwarf/dwarf_expr_2.h" -// #include "dwarf/dwarf_unwind.h" -// #include "dwarf/dwarf_dump.h" #include "dwarf/dwarf_parse_2.h" #include "dwarf/dwarf_unwind_2.h" #include "dwarf/dwarf_dump_2.h" @@ -20,8 +16,4 @@ # include "dwarf/dwarf_parse_elf.h" #endif -#if 0 // TODO(rjf): this uses concepts from the old parser -# include "dwarf/dwarf_writer.h" -#endif - #endif // DWARF_INC_H diff --git a/src/dwarf/dwarf_writer.c b/src/dwarf/dwarf_writer.c index fa824277..701bb454 100644 --- a/src/dwarf/dwarf_writer.c +++ b/src/dwarf/dwarf_writer.c @@ -1,6 +1,8 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +// TODO(rjf): this uses concepts from the old parser + internal DW_IntEnc dw_int_enc_from_sint(S64 v) { diff --git a/src/dwarf/dwarf_writer.h b/src/dwarf/dwarf_writer.h index aa09c59d..02fde356 100644 --- a/src/dwarf/dwarf_writer.h +++ b/src/dwarf/dwarf_writer.h @@ -4,6 +4,8 @@ #ifndef DWARF_WRITER_H #define DWARF_WRITER_H +// TODO(rjf): this uses concepts from the old parser + //////////////////////////////// typedef enum diff --git a/src/dwarf/tests/dwarf_tests.c b/src/dwarf/tests/dwarf_tests.c index b9d8c194..f6137a08 100644 --- a/src/dwarf/tests/dwarf_tests.c +++ b/src/dwarf/tests/dwarf_tests.c @@ -1,7 +1,7 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#if 0 +#if 0 // TODO(rjf): this uses concepts from the old parser internal U64 t_dw_test_uleb128(U64 v, U64 expected_length) diff --git a/src/eh_frame/eh_frame.c b/src/eh_frame/eh_frame.c index 06fdc93e..141ac5f5 100644 --- a/src/eh_frame/eh_frame.c +++ b/src/eh_frame/eh_frame.c @@ -1,77 +1,8 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#if 0 -internal U64 -eh_parse_ptr(String8 frame_base, U64 off, U64 pc, EH_PtrCtx *ptr_ctx, EH_PtrEnc encoding, U64 *ptr_out) -{ - U64 ptr_off = off; - - if (encoding == EH_PtrEnc_Omit) { - return 0; - } - - // align read offset as needed - if (encoding == EH_PtrEnc_Aligned) { - ptr_off = AlignPow2(ptr_off, ptr_ctx->ptr_align); - encoding = EH_PtrEnc_Ptr; - } - - // decode pointer value - U64 decode_size = 0; - U64 raw_ptr_size = 0; - U64 raw_ptr = 0; - switch (encoding & EH_PtrEnc_TypeMask) { - default: { InvalidPath; } break; - - case EH_PtrEnc_Ptr : { raw_ptr_size = 8; } goto ufixed; - case EH_PtrEnc_UData2: { raw_ptr_size = 2; } goto ufixed; - case EH_PtrEnc_UData4: { raw_ptr_size = 4; } goto ufixed; - case EH_PtrEnc_UData8: { raw_ptr_size = 8; } goto ufixed; - ufixed: { - decode_size += str8_deserial_read(frame_base, ptr_off, &raw_ptr, raw_ptr_size, raw_ptr_size); - } break; - - // TODO: Signed is actually just a flag that indicates this int is negavite. - // There shouldn't be a read for Signed. - // For instance, (EH_PtrEnc_UData2 | EH_PtrEnc_Signed) == EH_PtrEnc_SData etc. - case EH_PtrEnc_Signed: { raw_ptr_size = 8; } goto sfixed; - - case EH_PtrEnc_SData2: { raw_ptr_size = 2; } goto sfixed; - case EH_PtrEnc_SData4: { raw_ptr_size = 4; } goto sfixed; - case EH_PtrEnc_SData8: { raw_ptr_size = 8; } goto sfixed; - sfixed: { - decode_size += str8_deserial_read(frame_base, ptr_off, &raw_ptr, raw_ptr_size, raw_ptr_size); - raw_ptr = extend_sign64(raw_ptr, raw_ptr_size); - } break; - - case EH_PtrEnc_ULEB128: { decode_size += str8_deserial_read_uleb128(frame_base, ptr_off, &raw_ptr); } break; - case EH_PtrEnc_SLEB128: { decode_size += str8_deserial_read_sleb128(frame_base, ptr_off, (S64*)&raw_ptr); } break; - } - - // apply relative bases - if (decode_size > 0) { - U64 ptr = raw_ptr; - switch (encoding & EH_PtrEnc_ModifierMask) { - case 0: break; - case EH_PtrEnc_PcRel: { ptr = pc + raw_ptr; } break; - case EH_PtrEnc_TextRel: { ptr = ptr_ctx->text_vaddr + raw_ptr; } break; - case EH_PtrEnc_DataRel: { ptr = ptr_ctx->data_vaddr + raw_ptr; } break; - case EH_PtrEnc_FuncRel: { - Assert(!"TODO: need a sample to verify implementation"); - ptr = ptr_ctx->func_vaddr + raw_ptr; - } break; - default: { InvalidPath; } break; - } - - if (ptr_out) { - *ptr_out = ptr; - } - } - - return decode_size; -} -#endif +//////////////////////////////// +//~ rjf: .eh_frame Parsing Functions internal EH_FrameHdr eh_parse_frame_hdr(String8 data, U64 address_size, EH_PtrCtx *ptr_ctx) @@ -124,65 +55,6 @@ eh_parse_frame_hdr(String8 data, U64 address_size, EH_PtrCtx *ptr_ctx) return header; } -#if 0 -internal U64 -eh_parse_aug_data(String8 aug_string, String8 aug_data, U64 pc, EH_PtrCtx *ptr_ctx, EH_Augmentation *aug_out) -{ - // TODO: - // Handle "eh" param, it indicates presence of EH Data field. - // On 32bit arch it is a 4-byte and on 64-bit 8-byte value. - // Reference: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html - // Reference doc doesn't clarify structure for EH Data though - - U64 cursor = 0; - - U64 aug_data_size = 0; - EH_AugFlags aug_flags = 0; - EH_PtrEnc lsda_encoding = EH_PtrEnc_Omit; - EH_PtrEnc addr_encoding = EH_PtrEnc_UData8; - EH_PtrEnc handler_encoding = EH_PtrEnc_Omit; - U64 handler_ip = 0; - if (str8_match(str8_prefix(aug_string, 1), str8_lit("z"), 0)) { - cursor = str8_deserial_read_uleb128(aug_data, cursor, &aug_data_size); - - for (U8 *ptr = aug_string.str+1; ptr < (aug_string.str+aug_string.size); ptr += 1) { - switch (*ptr) { - case 'L': { - cursor += str8_deserial_read_struct(aug_data, cursor, &lsda_encoding); - aug_flags |= EH_AugFlag_HasLSDA; - } break; - case 'P': { - cursor += str8_deserial_read_struct(aug_data, cursor, &handler_encoding); - cursor += eh_parse_ptr(aug_data, cursor, pc + cursor, ptr_ctx, handler_encoding, &handler_ip); - aug_flags |= EH_AugFlag_HasHandler; - } break; - case 'R': { - cursor += str8_deserial_read_struct(aug_data, cursor, &addr_encoding); - aug_flags |= EH_AugFlag_HasAddrEnc; - } break; - case 'S': { - aug_flags |= EH_AugFlag_SignalFrame; - } break; - default: { Assert(!"failed to parse augmentation string"); goto exit; } break; - } - } - } - - if (aug_out) { - aug_out->handler_ip = handler_ip; - aug_out->handler_encoding = handler_encoding; - aug_out->lsda_encoding = handler_encoding; - aug_out->addr_encoding = addr_encoding; - aug_out->flags = aug_flags; - aug_out->size = aug_data_size; - } - - exit:; - U64 parse_size = cursor; - return parse_size; -} -#endif - internal U64 eh_read_ptr(String8 data, U64 off, U64 pc, EH_PtrCtx *ptr_ctx, EH_PtrEnc encoding, U64 *ptr_out) { @@ -464,100 +336,6 @@ eh_read_fde(String8 data, U64 off, DW_Format fmt, Arch arch, U64 pc, EH_PtrCtx * return bytes_read; } -#if 0 -internal B32 -eh_parse_fde(String8 data, DW_Format format, U64 pc, DW_CIE *cie, EH_PtrCtx *ptr_ctx, DW_FDE *fde_out) -{ - B32 is_parsed = 0; - U64 cursor = format == DW_Format_32Bit ? 8 : 20; - - U64 pc_begin = 0; - U64 pc_delta = 0; - EH_PtrEnc addr_enc = cie->ext[EH_CIE_Ext_AddrEnc]; - if (addr_enc != EH_PtrEnc_Omit) { - U64 pc_begin_size = eh_parse_ptr(data, cursor, pc + cursor, ptr_ctx, addr_enc, &pc_begin); - if (pc_begin_size == 0) { goto exit; } - cursor += pc_begin_size; - - U64 pc_delta_size = eh_parse_ptr(data, cursor, pc + cursor, ptr_ctx, addr_enc & EH_PtrEnc_TypeMask, &pc_delta); - if (pc_delta_size == 0) { goto exit; } - cursor += pc_delta_size; - } - - if (cursor + cie->aug_data.size > data.size) { goto exit; } - cursor += cie->aug_data.size; - - fde_out->format = format; - fde_out->pc_range = rng_1u64(pc_begin, pc_begin + pc_delta); - fde_out->insts = str8_skip(data, cursor); - - is_parsed = 1; - exit:; - return is_parsed; -} -#endif - -#if 0 -internal U64 -eh_find_nearest_fde(EH_FrameHdr header, EH_PtrCtx *ptr_ctx, U64 pc) -{ - U64 fde_addr = max_U64; - U64 fde_idx = max_U64; - - if (header.version == 1) { - if (header.fde_count > 0) { - U64 first = 0; - U64 first_size = eh_parse_ptr(header.table, 0, ptr_ctx->pc_vaddr, ptr_ctx, header.table_enc, &first); - AssertAlways(first_size); - if (first == pc) { - fde_idx = 0; - goto exit; - } - if (first > pc) { - goto exit; - } - - U64 last_off = header.table.size - header.entry_byte_size; - U64 last = 0; - U64 last_size = eh_parse_ptr(header.table, last_off, ptr_ctx->pc_vaddr + last_off, ptr_ctx, header.table_enc, &last); - AssertAlways(last_size); - if (last <= pc) { - fde_idx = header.fde_count - 1; - goto exit; - } - - U64 l = 0; - U64 r = header.fde_count - 1; - while (l <= r) { - U64 m = l + (r - l) / 2; - U64 m_pc_off = m * header.entry_byte_size; - U64 m_pc = 0; - U64 m_pc_size = eh_parse_ptr(header.table, m_pc_off, ptr_ctx->pc_vaddr + m_pc_off, ptr_ctx, header.table_enc, &m_pc); - Assert(m_pc_size); - if (m_pc > pc) { - r = m - 1; - } else if (m_pc < pc) { - l = m + 1; - } else { - fde_idx = m; - goto exit; - } - } - - fde_idx = l > 0 ? l-1 : 0; - } - } - - exit:; - if (fde_idx < header.fde_count) { - U64 fde_addr_off = (fde_idx * header.entry_byte_size) + header.field_byte_size; - U64 fde_addr_size = eh_parse_ptr(header.table, fde_addr_off, ptr_ctx->pc_vaddr + fde_addr_off, ptr_ctx, header.table_enc, &fde_addr); - Assert(fde_addr_size); - } - return fde_addr; -} -#endif - internal int eh_frame_hdr_entry_sort(void *raw_a, void *raw_b) { @@ -599,52 +377,50 @@ eh_frame_hdr_from_call_frame_info(Arena *arena, U64 fde_count, U64 *fde_offsets, return eh_frame_hdr; } -#if 0 -internal -DW_DECODE_PTR(eh_decode_ptr) -{ - EH_DecodePtrCtx *ctx = ud; - return eh_parse_ptr(data, 0, ctx->ptr_ctx->pc_vaddr, ctx->ptr_ctx, ctx->addr_enc, ptr_out); -} -#endif +//////////////////////////////// +//~ rjf: Enum -> String internal String8 eh_string_from_ptr_enc_type(EH_PtrEnc type) { - switch (type) { - case EH_PtrEnc_Ptr: return str8_lit("Ptr"); - case EH_PtrEnc_ULEB128: return str8_lit("ULEB128"); - case EH_PtrEnc_UData2: return str8_lit("UData2"); - case EH_PtrEnc_UData4: return str8_lit("UData4"); - case EH_PtrEnc_UData8: return str8_lit("UData8"); - case EH_PtrEnc_Signed: return str8_lit("Signed"); - case EH_PtrEnc_SLEB128: return str8_lit("SLEB128"); - case EH_PtrEnc_SData2: return str8_lit("SData2"); - case EH_PtrEnc_SData4: return str8_lit("SData4"); - case EH_PtrEnc_SData8: return str8_lit("SData8"); + String8 result = {0}; + switch(type) + { + case EH_PtrEnc_Ptr: {result = s("Ptr");}break; + case EH_PtrEnc_ULEB128: {result = s("ULEB128");}break; + case EH_PtrEnc_UData2: {result = s("UData2");}break; + case EH_PtrEnc_UData4: {result = s("UData4");}break; + case EH_PtrEnc_UData8: {result = s("UData8");}break; + case EH_PtrEnc_Signed: {result = s("Signed");}break; + case EH_PtrEnc_SLEB128: {result = s("SLEB128");}break; + case EH_PtrEnc_SData2: {result = s("SData2");}break; + case EH_PtrEnc_SData4: {result = s("SData4");}break; + case EH_PtrEnc_SData8: {result = s("SData8");}break; } - return str8_zero(); + return result; } internal String8 eh_string_from_ptr_enc_modifier(EH_PtrEnc modifier) { - switch (modifier) { - case EH_PtrEnc_PcRel: return str8_lit("PcRel"); - case EH_PtrEnc_TextRel: return str8_lit("TextRel"); - case EH_PtrEnc_DataRel: return str8_lit("DataRel"); - case EH_PtrEnc_FuncRel: return str8_lit("FuncRel"); - case EH_PtrEnc_Aligned: return str8_lit("Aligned"); + String8 result = {0}; + switch(modifier) + { + case EH_PtrEnc_PcRel: {result = s("PcRel");}break; + case EH_PtrEnc_TextRel: {result = s("TextRel");}break; + case EH_PtrEnc_DataRel: {result = s("DataRel");}break; + case EH_PtrEnc_FuncRel: {result = s("FuncRel");}break; + case EH_PtrEnc_Aligned: {result = s("Aligned");}break; } - return str8_zero(); + return result; } internal String8 eh_string_from_ptr_enc(Arena *arena, EH_PtrEnc enc) { - String8 type_str = eh_string_from_ptr_enc_type(enc & EH_PtrEnc_TypeMask); + String8 type_str = eh_string_from_ptr_enc_type(enc & EH_PtrEnc_TypeMask); String8 modifer_str = eh_string_from_ptr_enc_modifier(enc & EH_PtrEnc_ModifierMask); - String8 indir_str = enc & EH_PtrEnc_Indirect ? str8_lit("Indirect") : str8_zero(); - String8 result = str8f(arena, "Type: %S, Modifier %S (%S)", type_str, modifer_str, indir_str); + String8 indir_str = enc & EH_PtrEnc_Indirect ? str8_lit("Indirect") : str8_zero(); + String8 result = str8f(arena, "Type: %S, Modifier %S (%S)", type_str, modifer_str, indir_str); return result; } diff --git a/src/eh_frame/eh_frame.h b/src/eh_frame/eh_frame.h index e4517d8a..d4803bab 100644 --- a/src/eh_frame/eh_frame.h +++ b/src/eh_frame/eh_frame.h @@ -106,14 +106,9 @@ typedef struct EH_DecodePtrCtx } EH_DecodePtrCtx; //////////////////////////////// +//~ rjf: .eh_frame Parsing Functions -#if 0 -internal U64 eh_parse_ptr(String8 frame_base, U64 off, U64 pc, EH_PtrCtx *ptr_ctx, EH_PtrEnc encoding, U64 *ptr_out); -#endif internal EH_FrameHdr eh_parse_frame_hdr(String8 data, U64 address_size, EH_PtrCtx *ptr_ctx); -#if 0 -internal U64 eh_parse_aug_data(String8 aug_string, String8 aug_data, U64 pc, EH_PtrCtx *ptr_ctx, EH_Augmentation *aug_out); -#endif internal U64 eh_read_ptr(String8 data, U64 off, U64 pc, EH_PtrCtx *ptr_ctx, EH_PtrEnc encoding, U64 *ptr_out); internal U64 eh_read_aug_data(String8 data, U64 off, String8 string, U64 pc, EH_PtrCtx *ptr_ctx, EH_Augmentation *aug_out); @@ -121,12 +116,11 @@ internal U64 eh_read_cfi_header(String8 data, U64 off, DW_CFIHeader *cfi internal U64 eh_read_cie(String8 data, U64 off, DW_Format fmt, Arch arch, U64 pc, EH_PtrCtx *ptr_ctx, DW_CIE *cie_out); internal U64 eh_read_fde(String8 data, U64 off, DW_Format fmt, Arch arch, U64 pc, EH_PtrCtx *ptr_ctx, DW_CIE *cie, DW_FDE *fde_out); -internal B32 eh_parse_fde(String8 data, DW_Format format, U64 pc, DW_CIE *cie, EH_PtrCtx *ptr_ctx, DW_FDE *fde_out); -internal U64 eh_find_nearest_fde(EH_FrameHdr header, EH_PtrCtx *ptr_ctx, U64 pc); +internal int eh_frame_hdr_entry_sort(void *raw_a, void *raw_b); internal String8 eh_frame_hdr_from_call_frame_info(Arena *arena, U64 fde_count, U64 *fde_offsets, struct DW_FDE *fde); //////////////////////////////// -//~ Enum -> String +//~ rjf: Enum -> String internal String8 eh_string_from_ptr_enc_type(EH_PtrEnc type); internal String8 eh_string_from_ptr_enc_modifier(EH_PtrEnc modifier); diff --git a/src/rdi_from_dwarf/tests/rdi_from_dwarf_tests.c b/src/rdi_from_dwarf/tests/rdi_from_dwarf_tests.c index efd32d87..fa635619 100644 --- a/src/rdi_from_dwarf/tests/rdi_from_dwarf_tests.c +++ b/src/rdi_from_dwarf/tests/rdi_from_dwarf_tests.c @@ -5,7 +5,7 @@ // // [ ] d2r_types alias size and byte size on __float80 typedef mismatch -#if 0 +#if 0 // TODO(rjf): this uses concepts from the old parser - replace with p2r-style exemplar testing to catch regressions internal RDI_Parsed * d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)