zero out IP when reached last frame

This commit is contained in:
Nikita Smith
2025-11-07 14:39:45 -08:00
committed by Ryan Fleury
parent 16232b98d8
commit 793cd90604
2 changed files with 29 additions and 23 deletions
+24 -18
View File
@@ -1906,7 +1906,7 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
CTRL_UnwindStepResult result = { .flags = CTRL_UnwindFlag_Error }; CTRL_UnwindStepResult result = { .flags = CTRL_UnwindFlag_Error };
// gather context for virtual stack unwinder // gather context for virtual stack unwinder
U64 rebase = 0; U64 cfi_rebase = 0;
B32 is_unwind_eh = 0; B32 is_unwind_eh = 0;
String8 unwind_data = {0}; String8 unwind_data = {0};
EH_FrameHdr eh_frame_hdr = {0}; EH_FrameHdr eh_frame_hdr = {0};
@@ -1921,7 +1921,7 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
{ {
if(ctrl_handle_match(n->module, module_handle)) if(ctrl_handle_match(n->module, module_handle))
{ {
rebase = n->rebase; cfi_rebase = n->cfi_rebase;
is_unwind_eh = n->is_unwind_eh; is_unwind_eh = n->is_unwind_eh;
unwind_data = n->dwarf_unwind_data; unwind_data = n->dwarf_unwind_data;
eh_frame_hdr = n->eh_frame_hdr; eh_frame_hdr = n->eh_frame_hdr;
@@ -1931,12 +1931,11 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
} }
} }
// rebase IP to the base used for linking the module // grab IP
U64 ip = regs_rip_from_arch_block(arch, regs); U64 ip = regs_rip_from_arch_block(arch, regs);
U64 cfi_ip = ip + rebase;
// use .eh_frame_hdr to quickly locate nearest FDE offset // use .eh_frame_hdr to quickly locate nearest FDE
U64 fde_addr = eh_find_nearest_fde(eh_frame_hdr, &eh_ptr_ctx, cfi_ip); U64 fde_addr = eh_find_nearest_fde(eh_frame_hdr, &eh_ptr_ctx, ip);
if(fde_addr != max_U64) if(fde_addr != max_U64)
{ {
@@ -2029,6 +2028,8 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
if(is_cfi_parsed) if(is_cfi_parsed)
{ {
Assert(contains_1u64(fde.pc_range, ip));
// setup pointer decoder ops // setup pointer decoder ops
DW_DecodePtr *decode_ptr_func = 0; DW_DecodePtr *decode_ptr_func = 0;
void *decode_ptr_ctx = 0; void *decode_ptr_ctx = 0;
@@ -2048,7 +2049,7 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
} }
// find register rules for IP // find register rules for IP
DW_CFI_Row *cfi_row = dw_cfi_row_from_pc(scratch.arena, arch, &cie, &fde, decode_ptr_func, decode_ptr_ctx, cfi_ip); DW_CFI_Row *cfi_row = dw_cfi_row_from_pc(scratch.arena, arch, &cie, &fde, decode_ptr_func, decode_ptr_ctx, ip);
if(cfi_row) if(cfi_row)
{ {
// setup machine ops // setup machine ops
@@ -2095,6 +2096,12 @@ ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, A
reg_write_func, reg_write_func,
reg_write_ctx); reg_write_ctx);
// last frame typically has undefined rule for IP
if(cfi_row->regs[cie.ret_addr_reg].rule == DW_CFI_RegisterRule_Undefined)
{
regs_arch_block_write_rip(arch, regs, 0);
}
// translate unwind status code to control layer's result flags // translate unwind status code to control layer's result flags
switch(cfi_uw_status) switch(cfi_uw_status)
{ {
@@ -3744,10 +3751,10 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
Guid pdb_dbg_guid = {0}; Guid pdb_dbg_guid = {0};
String8 pdb_dbg_path = {0}; String8 pdb_dbg_path = {0};
U64 rebase = 0; U64 cfi_rebase = 0;
B32 is_unwind_eh = 0; B32 is_unwind_eh = 0;
EH_FrameHdr eh_frame_hdr = {0}; EH_FrameHdr eh_frame_hdr = {0};
EH_PtrCtx eh_ptr_ctx = { .raw_base_vaddr = max_U64, .text_vaddr = max_U64, .data_vaddr = max_U64, .func_vaddr = max_U64, .ptr_align = 0 }; EH_PtrCtx eh_ptr_ctx = { .pc_vaddr = max_U64, .text_vaddr = max_U64, .data_vaddr = max_U64, .func_vaddr = max_U64, .ptr_align = 0 };
// read module's signature bytes // read module's signature bytes
U64 module_sig_size = Max(elf_magic_string.size, sizeof(PE_DosMagic)); U64 module_sig_size = Max(elf_magic_string.size, sizeof(PE_DosMagic));
@@ -4018,6 +4025,11 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
} }
} }
if(e_type == ELF_Type_Dyn)
{
cfi_rebase = vaddr_range.min;
}
// find and parse .eh_frame_hdr // find and parse .eh_frame_hdr
Rng1U64 eh_frame_hdr_vrange = {0}; Rng1U64 eh_frame_hdr_vrange = {0};
String8 eh_frame_hdr_data = {0}; String8 eh_frame_hdr_data = {0};
@@ -4038,7 +4050,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
ELF_Phdr64 *phdr = phdrs64 + phdr_idx; ELF_Phdr64 *phdr = phdrs64 + phdr_idx;
if(phdr->p_type == ELF_PType_GnuEHFrame) if(phdr->p_type == ELF_PType_GnuEHFrame)
{ {
eh_frame_hdr_vrange = r1u64(phdr->p_vaddr, phdr->p_vaddr + phdr->p_memsz); eh_frame_hdr_vrange = r1u64(cfi_rebase + phdr->p_vaddr, cfi_rebase + phdr->p_vaddr + phdr->p_memsz);
eh_frame_hdr_data = dmn_process_read_block(arena, process.dmn_handle, eh_frame_hdr_vrange); eh_frame_hdr_data = dmn_process_read_block(arena, process.dmn_handle, eh_frame_hdr_vrange);
is_unwind_eh = 1; is_unwind_eh = 1;
break; break;
@@ -4049,7 +4061,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
// parse .eh_frame_hdr // parse .eh_frame_hdr
Arch arch = ctrl_arch_from_process_handle(process); Arch arch = ctrl_arch_from_process_handle(process);
eh_ptr_ctx.raw_base_vaddr = eh_frame_hdr_vrange.min; eh_ptr_ctx.pc_vaddr = eh_frame_hdr_vrange.min;
eh_ptr_ctx.data_vaddr = eh_frame_hdr_vrange.min; eh_ptr_ctx.data_vaddr = eh_frame_hdr_vrange.min;
eh_frame_hdr = eh_parse_frame_hdr(eh_frame_hdr_data, byte_size_from_arch(arch), &eh_ptr_ctx); eh_frame_hdr = eh_parse_frame_hdr(eh_frame_hdr_data, byte_size_from_arch(arch), &eh_ptr_ctx);
@@ -4064,12 +4076,6 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
{ {
exe_dbg_path = path; exe_dbg_path = path;
} }
if(e_type == ELF_Type_Dyn)
{
rebase = -vaddr_range.min;
}
elf_exit:; elf_exit:;
} }
@@ -4148,7 +4154,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
node->arena = arena; node->arena = arena;
node->pdatas = pdatas; node->pdatas = pdatas;
node->pdatas_count = pdatas_count; node->pdatas_count = pdatas_count;
node->rebase = rebase; node->cfi_rebase = cfi_rebase;
node->is_unwind_eh = is_unwind_eh; node->is_unwind_eh = is_unwind_eh;
node->eh_frame_hdr = eh_frame_hdr; node->eh_frame_hdr = eh_frame_hdr;
node->eh_ptr_ctx = eh_ptr_ctx; node->eh_ptr_ctx = eh_ptr_ctx;
+1 -1
View File
@@ -597,7 +597,7 @@ struct CTRL_ModuleImageInfoCacheNode
Arena *arena; Arena *arena;
PE_IntelPdata *pdatas; PE_IntelPdata *pdatas;
U64 pdatas_count; U64 pdatas_count;
U64 rebase; U64 cfi_rebase;
B32 is_unwind_eh; B32 is_unwind_eh;
String8 dwarf_unwind_data; String8 dwarf_unwind_data;
EH_FrameHdr eh_frame_hdr; EH_FrameHdr eh_frame_hdr;