bool native_is_frame_exists(UnwindContext* context, Registers* regs) { // Check for frame layout and stack values if ((regs->ebp < regs->esp) || !native_is_in_stack(context, (void*)regs->ebp)) return false; // Invalid frame void** frame_ptr = (void**)regs->ebp; void* eip = frame_ptr[1]; // Return address // Check return address for meaning return (native_is_in_code(context, eip) && native_check_caller(context, regs, frame_ptr + 1)); }
bool native_unwind_special(UnwindContext* context, Registers* regs) { for (void** cur_sp = (void**)regs->esp; (char*)cur_sp < ((char*)regs->esp + MAX_SPECIAL_DEPTH) && native_is_in_stack(context, cur_sp); ++cur_sp) { if (!native_is_in_code(context, *cur_sp)) continue; #if (!NATIVE_STRICT_UNWINDING) return fill_regs_from_sp(context, regs, cur_sp); #else if (native_check_caller(context, regs, cur_sp)) return fill_regs_from_sp(context, regs, cur_sp); #endif } return false; }
static unsigned native_dec_instr(UnwindContext* context, void* addr, void** target) { Inst inst; if (!native_is_in_code(context, addr)) return 0; U_32 len = DecoderBase::decode(addr, &inst); if (len == 0 || inst.mn != Mnemonic_CALL || inst.argc != 1) return 0; if (target && inst.operands[0].is_imm()) *target = (void*)((U_32)addr + len + inst.operands[0].imm()); return len; }
bool native_unwind_stack_frame(UnwindContext* context, Registers* regs) { void** frame = (void**)regs->ebp; void* ebp = frame[0]; void* eip = frame[1]; // void* esp = (void*)(frame + 2); void* esp = &frame[2]; if (native_is_in_stack(context, esp) && (native_is_in_code(context, eip))) { regs->ebp = (U_32)ebp; regs->esp = (U_32)esp; regs->eip = (U_32)eip; return true; } return false; }
bool native_unwind_stack_frame(UnwindContext* context, Registers* regs) { void** frame = (void**)regs->rbp; void* rbp = frame[0]; void* rip = frame[1]; // void* rsp = (void*)(frame + 2); void* rsp = &frame[2]; if (native_is_in_stack(context, rsp) && (native_is_in_code(context, rip))) { regs->rbp = (uint64)rbp; regs->rsp = (uint64)rsp; regs->rip = (uint64)rip; return true; } return false; }