mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
pull failed-unwind-step register-block-restore out of each impl, just do it on the caller side; pull out module-less read-the-stack-pointer unwind fallback from pe/x64 unwinder, use in module-less unwinds in all cases; call into from pe/x64 unwinder in fallback case
This commit is contained in:
@@ -1797,6 +1797,7 @@ d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us)
|
|||||||
//
|
//
|
||||||
void *regs_block = d_cached_reg_block_from_thread(scratch.arena, thread);
|
void *regs_block = d_cached_reg_block_from_thread(scratch.arena, thread);
|
||||||
B32 regs_block_good = (arch != Arch_Null && regs_block != 0);
|
B32 regs_block_good = (arch != Arch_Null && regs_block != 0);
|
||||||
|
void *regs_block_restore = push_array(scratch.arena, U8, arch_reg_block_size);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: grab initial memory
|
//- rjf: grab initial memory
|
||||||
@@ -1858,10 +1859,19 @@ d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us)
|
|||||||
B32 step_is_good = 0;
|
B32 step_is_good = 0;
|
||||||
for(;!unwind.flags;)
|
for(;!unwind.flags;)
|
||||||
{
|
{
|
||||||
|
// rjf: remember registers pre-step
|
||||||
|
MemoryCopy(regs_block_restore, regs_block, arch_reg_block_size);
|
||||||
|
|
||||||
// rjf: try step
|
// rjf: try step
|
||||||
U64 cfa = 0;
|
U64 cfa = 0;
|
||||||
UWND_StepResult step = uwnd_step(unwinder, arch, &memory_map, &unwinder_module_info, tls_vaddr, regs_block, &cfa);
|
UWND_StepResult step = uwnd_step(unwinder, arch, &memory_map, &unwinder_module_info, tls_vaddr, regs_block, &cfa);
|
||||||
|
|
||||||
|
// rjf: if the step failed -> restore original register values
|
||||||
|
if(step.status != UWND_StepStatus_Good)
|
||||||
|
{
|
||||||
|
MemoryCopy(regs_block, regs_block_restore, arch_reg_block_size);
|
||||||
|
}
|
||||||
|
|
||||||
// rjf: if we failed to read memory, try to read that memory, equip to memory map.
|
// rjf: if we failed to read memory, try to read that memory, equip to memory map.
|
||||||
// if it is stale and we run out of time, we will need to mark the whole unwind as
|
// if it is stale and we run out of time, we will need to mark the whole unwind as
|
||||||
// stale. if it can't be read, the unwind fails.
|
// stale. if it can't be read, the unwind fails.
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
U64 pc = arch_ip_from_reg_block(arch_info, regs);
|
U64 pc = arch_ip_from_reg_block(arch_info, regs);
|
||||||
|
|
||||||
//- rjf: set up new register values
|
|
||||||
void *new_regs = push_array(scratch.arena, U8, arch_info->reg_block_size);
|
|
||||||
MemoryCopy(new_regs, regs, arch_info->reg_block_size);
|
|
||||||
|
|
||||||
//- rjf: find nearest FDE entry to the IP
|
//- rjf: find nearest FDE entry to the IP
|
||||||
U64 fde_vaddr = 0;
|
U64 fde_vaddr = 0;
|
||||||
if(header->version == 1 && header->fde_count != 0)
|
if(header->version == 1 && header->fde_count != 0)
|
||||||
@@ -590,7 +586,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
}
|
}
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
arch_reg_block_write_range(arch_info, new_regs, reg_rng, reg_value_buffer);
|
arch_reg_block_write_range(arch_info, regs, reg_rng, reg_value_buffer);
|
||||||
}
|
}
|
||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
}break;
|
}break;
|
||||||
@@ -598,7 +594,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
{
|
{
|
||||||
U64 reg_value = cfa + rule->s64;
|
U64 reg_value = cfa + rule->s64;
|
||||||
Rng1U16 write_range = r1u16(reg_rng.min, Min(reg_rng.max, reg_rng.min + sizeof(reg_value)));
|
Rng1U16 write_range = r1u16(reg_rng.min, Min(reg_rng.max, reg_rng.min + sizeof(reg_value)));
|
||||||
arch_reg_block_write_range(arch_info, new_regs, write_range, ®_value);
|
arch_reg_block_write_range(arch_info, regs, write_range, ®_value);
|
||||||
}break;
|
}break;
|
||||||
case DW_UnwindRuleCode_Reg:
|
case DW_UnwindRuleCode_Reg:
|
||||||
{
|
{
|
||||||
@@ -610,7 +606,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
U64 read_size = Min(src_reg_size, reg_size);
|
U64 read_size = Min(src_reg_size, reg_size);
|
||||||
U8 *src_reg_val_buffer = push_array(temp.arena, U8, read_size);
|
U8 *src_reg_val_buffer = push_array(temp.arena, U8, read_size);
|
||||||
arch_reg_block_read_range(arch_info, regs, src_reg_rng, src_reg_val_buffer);
|
arch_reg_block_read_range(arch_info, regs, src_reg_rng, src_reg_val_buffer);
|
||||||
arch_reg_block_write_range(arch_info, new_regs, reg_rng, src_reg_val_buffer);
|
arch_reg_block_write_range(arch_info, regs, reg_rng, src_reg_val_buffer);
|
||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
}break;
|
}break;
|
||||||
case DW_UnwindRuleCode_Expr:
|
case DW_UnwindRuleCode_Expr:
|
||||||
@@ -638,7 +634,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
arch_reg_block_write_range(arch_info, new_regs, reg_rng, reg_value_buffer);
|
arch_reg_block_write_range(arch_info, regs, reg_rng, reg_value_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
@@ -658,7 +654,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
U512 reg_val = eval.val.u512;
|
U512 reg_val = eval.val.u512;
|
||||||
arch_reg_block_write_range(arch_info, new_regs, reg_rng, ®_val);
|
arch_reg_block_write_range(arch_info, regs, reg_rng, ®_val);
|
||||||
}
|
}
|
||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
}break;
|
}break;
|
||||||
@@ -681,14 +677,13 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
|||||||
//
|
//
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
arch_reg_block_write_sp(arch_info, new_regs, cfa);
|
arch_reg_block_write_sp(arch_info, regs, cfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: commit new register values, if we succeeded
|
//- rjf: commit new register values, if we succeeded
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
result.status = UWND_StepStatus_Good;
|
result.status = UWND_StepStatus_Good;
|
||||||
MemoryCopy(regs, new_regs, arch_info->reg_block_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|||||||
@@ -98,18 +98,16 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
{
|
{
|
||||||
B32 done = 0;
|
B32 done = 0;
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
X64_RegBlock *new_regs = push_array(scratch.arena, X64_RegBlock, 1);
|
|
||||||
MemoryCopyStruct(new_regs, regs);
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: on PE/x64, the frame base address is always RSP
|
//- rjf: on PE/x64, the frame base address is always RSP
|
||||||
//
|
//
|
||||||
cfa_out[0] = new_regs->rsp;
|
cfa_out[0] = regs->rsp;
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: unpack context from rip
|
//- rjf: unpack context from rip
|
||||||
//
|
//
|
||||||
U64 rip_voff = new_regs->rip - module_info->base_vaddr;
|
U64 rip_voff = regs->rip - module_info->base_vaddr;
|
||||||
PE_IntelPdata *first_pdata = pe_x64_uwnd_intel_pdata_from_voff(unwind_info, rip_voff);
|
PE_IntelPdata *first_pdata = pe_x64_uwnd_intel_pdata_from_voff(unwind_info, rip_voff);
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@@ -117,7 +115,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
//
|
//
|
||||||
B32 has_pdata_and_in_epilog = 0;
|
B32 has_pdata_and_in_epilog = 0;
|
||||||
U64 instruction_data_size_cap = 256;
|
U64 instruction_data_size_cap = 256;
|
||||||
Rng1U64 instruction_data_vaddr_range = r1u64(new_regs->rip, new_regs->rip+instruction_data_size_cap);
|
Rng1U64 instruction_data_vaddr_range = r1u64(regs->rip, regs->rip+instruction_data_size_cap);
|
||||||
String8 instruction_data = {0};
|
String8 instruction_data = {0};
|
||||||
if(!done && first_pdata)
|
if(!done && first_pdata)
|
||||||
{
|
{
|
||||||
@@ -346,7 +344,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
case 0x5C:case 0x5D:case 0x5E:case 0x5F:
|
case 0x5C:case 0x5D:case 0x5E:case 0x5F:
|
||||||
{
|
{
|
||||||
// rjf: read value at rsp
|
// rjf: read value at rsp
|
||||||
U64 sp = new_regs->rsp;
|
U64 sp = regs->rsp;
|
||||||
U64 value = 0;
|
U64 value = 0;
|
||||||
if(memory_map_read_struct(memory_map, sp, &value) != sizeof(value))
|
if(memory_map_read_struct(memory_map, sp, &value) != sizeof(value))
|
||||||
{
|
{
|
||||||
@@ -361,9 +359,9 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
PE_UnwindGprRegX64 gpr_reg = (inst_byte - 0x58) + (rex & 1)*8;
|
PE_UnwindGprRegX64 gpr_reg = (inst_byte - 0x58) + (rex & 1)*8;
|
||||||
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(gpr_reg);
|
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(gpr_reg);
|
||||||
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
||||||
U64 *reg_ptr = (U64 *)((U8 *)&new_regs + reg_rng.min);
|
U64 *reg_ptr = (U64 *)((U8 *)®s + reg_rng.min);
|
||||||
reg_ptr[0] = value;
|
reg_ptr[0] = value;
|
||||||
new_regs->rsp = sp + 8;
|
regs->rsp = sp + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: not a final instruction, so keep parsing
|
// rjf: not a final instruction, so keep parsing
|
||||||
@@ -386,7 +384,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
read_off += sizeof(imm);
|
read_off += sizeof(imm);
|
||||||
|
|
||||||
// rjf: update stack pointer
|
// rjf: update stack pointer
|
||||||
new_regs->rsp = (U64)(new_regs->rsp + imm);
|
regs->rsp = (U64)(regs->rsp + imm);
|
||||||
|
|
||||||
// rjf: not a final instruction; keep parsing
|
// rjf: not a final instruction; keep parsing
|
||||||
keep_parsing = 1;
|
keep_parsing = 1;
|
||||||
@@ -408,7 +406,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
read_off += sizeof(imm);
|
read_off += sizeof(imm);
|
||||||
|
|
||||||
// rjf: update stack pointer
|
// rjf: update stack pointer
|
||||||
new_regs->rsp = (U64)(new_regs->rsp + imm);
|
regs->rsp = (U64)(regs->rsp + imm);
|
||||||
|
|
||||||
// rjf: not a final instruction; keep parsing
|
// rjf: not a final instruction; keep parsing
|
||||||
keep_parsing = 1;
|
keep_parsing = 1;
|
||||||
@@ -430,7 +428,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
PE_UnwindGprRegX64 gpr_reg = (modrm & 7) + (rex & 1)*8;
|
PE_UnwindGprRegX64 gpr_reg = (modrm & 7) + (rex & 1)*8;
|
||||||
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(gpr_reg);
|
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(gpr_reg);
|
||||||
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
||||||
U64 *reg_ptr = (U64 *)((U8 *)&new_regs + reg_rng.min);
|
U64 *reg_ptr = (U64 *)((U8 *)®s + reg_rng.min);
|
||||||
U64 reg_value = reg_ptr[0];
|
U64 reg_value = reg_ptr[0];
|
||||||
|
|
||||||
// rjf: read immediate
|
// rjf: read immediate
|
||||||
@@ -462,7 +460,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: update stack pointer
|
// rjf: update stack pointer
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
new_regs->rsp = (U64)(reg_value + imm);
|
regs->rsp = (U64)(reg_value + imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: not a final instruction; keep parsing
|
// rjf: not a final instruction; keep parsing
|
||||||
@@ -473,7 +471,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
case 0xC2:
|
case 0xC2:
|
||||||
{
|
{
|
||||||
// rjf: read new ip
|
// rjf: read new ip
|
||||||
U64 sp = new_regs->rsp;
|
U64 sp = regs->rsp;
|
||||||
U64 new_ip = 0;
|
U64 new_ip = 0;
|
||||||
if(memory_map_read_struct(memory_map, sp, &new_ip) != sizeof(new_ip))
|
if(memory_map_read_struct(memory_map, sp, &new_ip) != sizeof(new_ip))
|
||||||
{
|
{
|
||||||
@@ -493,8 +491,8 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: commit registers
|
// rjf: commit registers
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
new_regs->rip = new_ip;
|
regs->rip = new_ip;
|
||||||
new_regs->rsp = new_sp;
|
regs->rsp = new_sp;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -506,7 +504,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
case 0xC3:
|
case 0xC3:
|
||||||
{
|
{
|
||||||
// rjf: read new ip
|
// rjf: read new ip
|
||||||
U64 sp = new_regs->rsp;
|
U64 sp = regs->rsp;
|
||||||
U64 new_ip = 0;
|
U64 new_ip = 0;
|
||||||
if(memory_map_read_struct(memory_map, sp, &new_ip) != sizeof(new_ip))
|
if(memory_map_read_struct(memory_map, sp, &new_ip) != sizeof(new_ip))
|
||||||
{
|
{
|
||||||
@@ -521,8 +519,8 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: commit registers
|
// rjf: commit registers
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
new_regs->rip = new_ip;
|
regs->rip = new_ip;
|
||||||
new_regs->rsp = new_sp;
|
regs->rsp = new_sp;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -604,11 +602,11 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: unpack frame base
|
//- rjf: unpack frame base
|
||||||
U64 frame_base = new_regs->rsp;
|
U64 frame_base = regs->rsp;
|
||||||
if(frame_reg_code != X64_RegCode_nil)
|
if(frame_reg_code != X64_RegCode_nil)
|
||||||
{
|
{
|
||||||
Rng1U16 frame_reg_rng = x64_reg_code_rng_table[frame_reg_code];
|
Rng1U16 frame_reg_rng = x64_reg_code_rng_table[frame_reg_code];
|
||||||
U64 raw_frame_base = *(U64 *)((U8 *)new_regs + frame_reg_rng.min);
|
U64 raw_frame_base = *(U64 *)((U8 *)regs + frame_reg_rng.min);
|
||||||
U64 adjusted_frame_base = raw_frame_base - frame_off*16;
|
U64 adjusted_frame_base = raw_frame_base - frame_off*16;
|
||||||
frame_base = adjusted_frame_base;
|
frame_base = adjusted_frame_base;
|
||||||
}
|
}
|
||||||
@@ -647,7 +645,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
case PE_UnwindOpCode_PUSH_NONVOL:
|
case PE_UnwindOpCode_PUSH_NONVOL:
|
||||||
{
|
{
|
||||||
// rjf: read value from stack pointer
|
// rjf: read value from stack pointer
|
||||||
U64 rsp = new_regs->rsp;
|
U64 rsp = regs->rsp;
|
||||||
U64 value = 0;
|
U64 value = 0;
|
||||||
if(memory_map_read_struct(memory_map, rsp, &value) != sizeof(value))
|
if(memory_map_read_struct(memory_map, rsp, &value) != sizeof(value))
|
||||||
{
|
{
|
||||||
@@ -661,8 +659,8 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
{
|
{
|
||||||
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
||||||
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
||||||
*(U64 *)((U8 *)new_regs + reg_rng.min) = value;
|
*(U64 *)((U8 *)regs + reg_rng.min) = value;
|
||||||
new_regs->rsp = rsp + 8;
|
regs->rsp = rsp + 8;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -686,20 +684,20 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: advance stack pointer
|
// rjf: advance stack pointer
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
new_regs->rsp += size;
|
regs->rsp += size;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case PE_UnwindOpCode_ALLOC_SMALL:
|
case PE_UnwindOpCode_ALLOC_SMALL:
|
||||||
{
|
{
|
||||||
// rjf: advance stack pointer
|
// rjf: advance stack pointer
|
||||||
new_regs->rsp += op_info*8 + 8;
|
regs->rsp += op_info*8 + 8;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case PE_UnwindOpCode_SET_FPREG:
|
case PE_UnwindOpCode_SET_FPREG:
|
||||||
{
|
{
|
||||||
// rjf: put stack pointer back to the frame base
|
// rjf: put stack pointer back to the frame base
|
||||||
new_regs->rsp = frame_base;
|
regs->rsp = frame_base;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case PE_UnwindOpCode_SAVE_NONVOL:
|
case PE_UnwindOpCode_SAVE_NONVOL:
|
||||||
@@ -720,7 +718,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
{
|
{
|
||||||
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
||||||
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
||||||
*(U64 *)((U8 *)new_regs + reg_rng.min) = value;
|
*(U64 *)((U8 *)regs + reg_rng.min) = value;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -742,7 +740,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
{
|
{
|
||||||
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
X64_RegCode reg_code = pe_x64_uwnd_reg_code_from_pe_gpr_reg(op_info);
|
||||||
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
Rng1U16 reg_rng = x64_reg_code_rng_table[reg_code];
|
||||||
*(U64 *)((U8 *)new_regs + reg_rng.min) = value;
|
*(U64 *)((U8 *)regs + reg_rng.min) = value;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -775,7 +773,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: commit to register
|
// rjf: commit to register
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
void *xmm_reg = (&new_regs->zmm0) + op_info;
|
void *xmm_reg = (®s->zmm0) + op_info;
|
||||||
MemoryCopy(xmm_reg, buf, sizeof(buf));
|
MemoryCopy(xmm_reg, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
@@ -797,7 +795,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: commit to register
|
// rjf: commit to register
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
void *xmm_reg = (&new_regs->zmm0) + op_info;
|
void *xmm_reg = (®s->zmm0) + op_info;
|
||||||
MemoryCopy(xmm_reg, buf, sizeof(buf));
|
MemoryCopy(xmm_reg, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
@@ -812,7 +810,7 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rjf: unpack stack pointer
|
// rjf: unpack stack pointer
|
||||||
U64 sp_og = new_regs->rsp;
|
U64 sp_og = regs->rsp;
|
||||||
U64 sp_adj = sp_og;
|
U64 sp_adj = sp_og;
|
||||||
if(op_info == 1)
|
if(op_info == 1)
|
||||||
{
|
{
|
||||||
@@ -861,10 +859,10 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
// rjf: commit registers
|
// rjf: commit registers
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
new_regs->rip = ip_value;
|
regs->rip = ip_value;
|
||||||
new_regs->ss = ss_value;
|
regs->ss = ss_value;
|
||||||
new_regs->rflags = rflags_value;
|
regs->rflags = rflags_value;
|
||||||
new_regs->rsp = sp_value;
|
regs->rsp = sp_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: mark machine frame
|
// rjf: mark machine frame
|
||||||
@@ -898,27 +896,12 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: no pdata, or didn't do machframe in xdata unwind -> unwind by reading stack pointer
|
//- rjf: no pdata, or didn't do machframe in xdata unwind -> module-less unwind
|
||||||
//
|
//
|
||||||
if(!done && (!first_pdata || (!has_pdata_and_in_epilog && !xdata_unwind_did_machframe)))
|
if(!done && (!first_pdata || (!has_pdata_and_in_epilog && !xdata_unwind_did_machframe)))
|
||||||
{
|
{
|
||||||
// rjf: read new ip
|
result = uwnd_step_moduleless(arch, memory_map, regs);
|
||||||
U64 sp = new_regs->rsp;
|
done = (result.status != UWND_StepStatus_Good);
|
||||||
U64 new_ip = 0;
|
|
||||||
if(memory_map_read_struct(memory_map, sp, &new_ip) != sizeof(new_ip))
|
|
||||||
{
|
|
||||||
done = 1;
|
|
||||||
result.status = UWND_StepStatus_FailedMemoryRead;
|
|
||||||
result.missed_read_vaddr_range = r1u64(sp, sp+sizeof(new_ip));
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: commit
|
|
||||||
if(!done)
|
|
||||||
{
|
|
||||||
U64 new_sp = sp+8;
|
|
||||||
new_regs->rip = new_ip;
|
|
||||||
new_regs->rsp = new_sp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -927,7 +910,6 @@ pe_x64_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info,
|
|||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
result.status = UWND_StepStatus_Good;
|
result.status = UWND_StepStatus_Good;
|
||||||
MemoryCopyStruct(regs, new_regs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|||||||
+36
-1
@@ -6,6 +6,41 @@
|
|||||||
|
|
||||||
#include "unwind/generated/unwind.meta.c"
|
#include "unwind/generated/unwind.meta.c"
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Moduleless Unwinder
|
||||||
|
|
||||||
|
internal UWND_StepResult
|
||||||
|
uwnd_step_moduleless(Arch arch, MemoryMap *memory_map, void *regs)
|
||||||
|
{
|
||||||
|
UWND_StepResult result = {UWND_StepStatus_Error};
|
||||||
|
{
|
||||||
|
B32 done = 0;
|
||||||
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
|
U64 addr_size = byte_size_from_arch(arch);
|
||||||
|
|
||||||
|
// rjf: read new ip from stack pointer
|
||||||
|
U64 sp = arch_sp_from_reg_block(arch_info, regs);
|
||||||
|
U64 new_ip = 0;
|
||||||
|
Rng1U64 new_ip_vaddr_range = r1u64(sp, sp+addr_size);
|
||||||
|
if(memory_map_read(memory_map, new_ip_vaddr_range, &new_ip) != addr_size)
|
||||||
|
{
|
||||||
|
done = 1;
|
||||||
|
result.status = UWND_StepStatus_FailedMemoryRead;
|
||||||
|
result.missed_read_vaddr_range = new_ip_vaddr_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: commit
|
||||||
|
if(!done)
|
||||||
|
{
|
||||||
|
U64 new_sp = sp+addr_size;
|
||||||
|
arch_reg_block_write_ip(arch_info, regs, new_ip);
|
||||||
|
arch_reg_block_write_sp(arch_info, regs, new_sp);
|
||||||
|
result.status = UWND_StepStatus_Good;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Abstracted Unwind Step Functions
|
//~ rjf: Abstracted Unwind Step Functions
|
||||||
|
|
||||||
@@ -15,7 +50,7 @@ uwnd_step(UWND_Unwinder unwinder, Arch arch, MemoryMap *memory_map, UWND_ModuleI
|
|||||||
UWND_StepResult result = {UWND_StepStatus_Error};
|
UWND_StepResult result = {UWND_StepStatus_Error};
|
||||||
switch(unwinder)
|
switch(unwinder)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{result = uwnd_step_moduleless(arch, memory_map, regs);}break;
|
||||||
#define X(name, namespace_lower) case UWND_Unwinder_##name:{result = namespace_lower##_uwnd_step(arch, memory_map, module_info, tls_vaddr, regs, cfa_out);}break;
|
#define X(name, namespace_lower) case UWND_Unwinder_##name:{result = namespace_lower##_uwnd_step(arch, memory_map, module_info, tls_vaddr, regs, cfa_out);}break;
|
||||||
UWND_Unwinder_XList
|
UWND_Unwinder_XList
|
||||||
#undef X
|
#undef X
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ struct UWND_ModuleInfo
|
|||||||
void *unwind_info;
|
void *unwind_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Moduleless Unwinder
|
||||||
|
|
||||||
|
internal UWND_StepResult uwnd_step_moduleless(Arch arch, MemoryMap *memory_map, void *regs);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Abstracted Unwind Step Functions
|
//~ rjf: Abstracted Unwind Step Functions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user