PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; unw_word_t ucontext; int ret; if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) { ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); c->sigcontext_addr = c->dwarf.cfa; Debug(1, "signal frame, skip over trampoline\n"); struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); return 0; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret = -UNW_EUNSPEC; Debug (1, "(cursor=%p)\n", c); /* Check if this is a signal frame. */ if (unw_is_signal_frame (cursor)) return unw_handle_signal_frame (cursor); #ifdef CONFIG_DEBUG_FRAME /* First, try DWARF-based unwinding. */ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) { ret = dwarf_step (&c->dwarf); Debug(1, "dwarf_step()=%d\n", ret); if (likely (ret > 0)) return 1; else if (unlikely (ret == -UNW_ESTOPUNWIND)) return ret; if (ret < 0 && ret != -UNW_ENOINFO) { Debug (2, "returning %d\n", ret); return ret; } } #endif /* CONFIG_DEBUG_FRAME */ /* Next, try extbl-based unwinding. */ if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) { ret = arm_exidx_step (c); if (ret > 0) return 1; if (ret == -UNW_ESTOPUNWIND || ret == 0) return ret; } /* Fall back on APCS frame parsing. Note: This won't work in case the ARM EABI is used. */ if (unlikely (ret < 0)) { if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) { ret = UNW_ESUCCESS; /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ unw_word_t instr, i; Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); dwarf_loc_t ip_loc, fp_loc; unw_word_t frame; /* Mark all registers unsaved, since we don't know where they are saved (if at all), except for the EBP and EIP. */ if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0) { return 0; } for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { c->dwarf.loc[i] = DWARF_NULL_LOC; } if (frame) { if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0) { return 0; } instr -= 8; if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0) { return 0; } if ((instr & 0xFFFFD800) == 0xE92DD800) { /* Standard APCS frame. */ ip_loc = DWARF_LOC(frame - 4, 0); fp_loc = DWARF_LOC(frame - 12, 0); } else { /* Codesourcery optimized normal frame. */ ip_loc = DWARF_LOC(frame, 0); fp_loc = DWARF_LOC(frame - 4, 0); } if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0) { return 0; } c->dwarf.loc[UNW_ARM_R12] = ip_loc; c->dwarf.loc[UNW_ARM_R11] = fp_loc; Debug(15, "ip=%lx\n", c->dwarf.ip); } else { ret = -UNW_ENOINFO; } } } return ret == -UNW_ENOINFO ? 0 : 1; }
PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) return -UNW_EUNSPEC; /* Obtain signal frame type (non-RT or RT). */ ret = unw_is_signal_frame (cursor); /* Save the SP and PC to be able to return execution at this point later in time (unw_resume). */ c->sigcontext_sp = c->dwarf.cfa; c->sigcontext_pc = c->dwarf.ip; /* Since kernel version 2.6.18 the non-RT signal frame starts with a ucontext while the RT signal frame starts with a siginfo, followed by a sigframe whose first element is an ucontext. Prior 2.6.18 the non-RT signal frame starts with a sigcontext while the RT signal frame starts with two pointers followed by a siginfo and an ucontext. The first pointer points to the start of the siginfo structure and the second one to the ucontext structure. */ if (ret == 1) { /* Handle non-RT signal frames. Check if the first word on the stack is the magic number. */ if (sp == 0x5ac3c35a) { c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME; sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; } else { c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME; sc_addr = sp_addr; } c->sigcontext_addr = sp_addr; } else if (ret == 2) { /* Handle RT signal frames. Check if the first word on the stack is a pointer to the siginfo structure. */ if (sp == sp_addr + 8) { c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME; c->sigcontext_addr = sp_addr + 8 + sizeof (siginfo_t); } else { c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME; c->sigcontext_addr = sp_addr + sizeof (siginfo_t); } sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF; } else return -UNW_EUNSPEC; /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0); c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0); c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0); c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); /* Set SP/CFA and PC/IP. */ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa); dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); return 1; }
PROTECTED int unw_step (unw_cursor_t * cursor) { struct cursor *c = (struct cursor *) cursor; stack_frame_t dummy; unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr; struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc; int ret; Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip); if (c->dwarf.ip == 0) { /* Unless the cursor or stack is corrupt or uninitialized, we've most likely hit the top of the stack */ return 0; } /* Try DWARF-based unwinding... */ ret = dwarf_step (&c->dwarf); if (ret < 0 && ret != -UNW_ENOINFO) { Debug (2, "returning %d\n", ret); return ret; } if (unlikely (ret < 0)) { if (likely (!unw_is_signal_frame (cursor))) { /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode produces the mandatory level of traceback record in the code, but I get the impression that this is transitory, that eventually gcc will not produce any traceback records at all. So, for now, we won't bother to try to find and use these records. We can, however, attempt to unwind the frame by using the callback chain. This is very crude, however, and won't be able to unwind any registers besides the IP, SP, and LR . */ back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy); lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy); back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0); if ((ret = dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0) { Debug ("Unable to retrieve CFA from back chain in stack frame - %d\n", ret); return ret; } if (c->dwarf.cfa == 0) /* Unless the cursor or stack is corrupt or uninitialized we've most likely hit the top of the stack */ return 0; lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0); if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0) { Debug ("Unable to retrieve IP from lr save in stack frame - %d\n", ret); return ret; } ret = 1; } else { /* Find the sigcontext record by taking the CFA and adjusting by the dummy signal frame size. Note that there isn't any way to determined if SA_SIGINFO was set in the sa_flags parameter to sigaction when the signal handler was established. If it was not set, the ucontext record is not required to be on the stack, in which case the following code will likely cause a seg fault or other crash condition. */ unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE; Debug (1, "signal frame, skip over trampoline\n"); c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME; c->sigcontext_addr = ucontext; sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } /* Instead of just restoring the non-volatile registers, do all of the registers for now. This will incur a performance hit, but it's rare enough not to cause too much of a problem, and might be useful in some cases. */ c->dwarf.loc[UNW_PPC64_R0] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0); c->dwarf.loc[UNW_PPC64_R1] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0); c->dwarf.loc[UNW_PPC64_R3] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0); c->dwarf.loc[UNW_PPC64_R4] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0); c->dwarf.loc[UNW_PPC64_R5] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0); c->dwarf.loc[UNW_PPC64_R6] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0); c->dwarf.loc[UNW_PPC64_R7] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0); c->dwarf.loc[UNW_PPC64_R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); c->dwarf.loc[UNW_PPC64_R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); c->dwarf.loc[UNW_PPC64_R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); c->dwarf.loc[UNW_PPC64_R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); c->dwarf.loc[UNW_PPC64_R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); c->dwarf.loc[UNW_PPC64_R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); c->dwarf.loc[UNW_PPC64_R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); c->dwarf.loc[UNW_PPC64_R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); c->dwarf.loc[UNW_PPC64_R16] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0); c->dwarf.loc[UNW_PPC64_R17] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0); c->dwarf.loc[UNW_PPC64_R18] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0); c->dwarf.loc[UNW_PPC64_R19] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0); c->dwarf.loc[UNW_PPC64_R20] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0); c->dwarf.loc[UNW_PPC64_R21] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0); c->dwarf.loc[UNW_PPC64_R22] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0); c->dwarf.loc[UNW_PPC64_R23] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0); c->dwarf.loc[UNW_PPC64_R24] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0); c->dwarf.loc[UNW_PPC64_R25] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0); c->dwarf.loc[UNW_PPC64_R26] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0); c->dwarf.loc[UNW_PPC64_R27] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0); c->dwarf.loc[UNW_PPC64_R28] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0); c->dwarf.loc[UNW_PPC64_R29] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0); c->dwarf.loc[UNW_PPC64_R30] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0); c->dwarf.loc[UNW_PPC64_R31] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0); c->dwarf.loc[UNW_PPC64_LR] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); c->dwarf.loc[UNW_PPC64_CTR] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0); /* This CR0 assignment is probably wrong. There are 8 dwarf columns assigned to the CR registers, but only one CR register in the mcontext structure */ c->dwarf.loc[UNW_PPC64_CR0] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0); c->dwarf.loc[UNW_PPC64_XER] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0); c->dwarf.loc[UNW_PPC64_NIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); /* TODO: Is there a way of obtaining the value of the pseudo frame pointer (which is sp + some fixed offset, I assume), based on the contents of the ucontext record structure? For now, set this loc to null. */ c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_F0] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0); c->dwarf.loc[UNW_PPC64_F1] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0); c->dwarf.loc[UNW_PPC64_F2] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0); c->dwarf.loc[UNW_PPC64_F3] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0); c->dwarf.loc[UNW_PPC64_F4] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0); c->dwarf.loc[UNW_PPC64_F5] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0); c->dwarf.loc[UNW_PPC64_F6] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0); c->dwarf.loc[UNW_PPC64_F7] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0); c->dwarf.loc[UNW_PPC64_F8] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0); c->dwarf.loc[UNW_PPC64_F9] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0); c->dwarf.loc[UNW_PPC64_F10] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0); c->dwarf.loc[UNW_PPC64_F11] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0); c->dwarf.loc[UNW_PPC64_F12] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0); c->dwarf.loc[UNW_PPC64_F13] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0); c->dwarf.loc[UNW_PPC64_F14] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0); c->dwarf.loc[UNW_PPC64_F15] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0); c->dwarf.loc[UNW_PPC64_F16] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0); c->dwarf.loc[UNW_PPC64_F17] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0); c->dwarf.loc[UNW_PPC64_F18] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0); c->dwarf.loc[UNW_PPC64_F19] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0); c->dwarf.loc[UNW_PPC64_F20] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0); c->dwarf.loc[UNW_PPC64_F21] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0); c->dwarf.loc[UNW_PPC64_F22] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0); c->dwarf.loc[UNW_PPC64_F23] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0); c->dwarf.loc[UNW_PPC64_F24] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0); c->dwarf.loc[UNW_PPC64_F25] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0); c->dwarf.loc[UNW_PPC64_F26] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0); c->dwarf.loc[UNW_PPC64_F27] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0); c->dwarf.loc[UNW_PPC64_F28] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0); c->dwarf.loc[UNW_PPC64_F29] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0); c->dwarf.loc[UNW_PPC64_F30] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0); c->dwarf.loc[UNW_PPC64_F31] = DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0); /* Note that there is no .eh_section register column for the FPSCR register. I don't know why this is. */ v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0); ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } if (v_regs_ptr != 0) { /* The v_regs_ptr is not null. Set all of the AltiVec locs */ c->dwarf.loc[UNW_PPC64_V0] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0); c->dwarf.loc[UNW_PPC64_V1] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0); c->dwarf.loc[UNW_PPC64_V2] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0); c->dwarf.loc[UNW_PPC64_V3] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0); c->dwarf.loc[UNW_PPC64_V4] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0); c->dwarf.loc[UNW_PPC64_V5] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0); c->dwarf.loc[UNW_PPC64_V6] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0); c->dwarf.loc[UNW_PPC64_V7] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0); c->dwarf.loc[UNW_PPC64_V8] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0); c->dwarf.loc[UNW_PPC64_V9] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0); c->dwarf.loc[UNW_PPC64_V10] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0); c->dwarf.loc[UNW_PPC64_V11] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0); c->dwarf.loc[UNW_PPC64_V12] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0); c->dwarf.loc[UNW_PPC64_V13] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0); c->dwarf.loc[UNW_PPC64_V14] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0); c->dwarf.loc[UNW_PPC64_V15] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0); c->dwarf.loc[UNW_PPC64_V16] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0); c->dwarf.loc[UNW_PPC64_V17] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0); c->dwarf.loc[UNW_PPC64_V18] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0); c->dwarf.loc[UNW_PPC64_V19] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0); c->dwarf.loc[UNW_PPC64_V20] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0); c->dwarf.loc[UNW_PPC64_V21] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0); c->dwarf.loc[UNW_PPC64_V22] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0); c->dwarf.loc[UNW_PPC64_V23] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0); c->dwarf.loc[UNW_PPC64_V24] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0); c->dwarf.loc[UNW_PPC64_V25] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0); c->dwarf.loc[UNW_PPC64_V26] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0); c->dwarf.loc[UNW_PPC64_V27] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0); c->dwarf.loc[UNW_PPC64_V28] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0); c->dwarf.loc[UNW_PPC64_V29] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0); c->dwarf.loc[UNW_PPC64_V30] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0); c->dwarf.loc[UNW_PPC64_V31] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0); c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0); c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0); } else { c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC; c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC; } ret = 1; } } return ret; }
PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) return -UNW_EUNSPEC; ret = unw_is_signal_frame (cursor); Debug(1, "unw_is_signal_frame()=%d\n", ret); /* Save the SP and PC to be able to return execution at this point later in time (unw_resume). */ c->sigcontext_sp = c->dwarf.cfa; c->sigcontext_pc = c->dwarf.ip; if (ret) { c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME; sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; } else return -UNW_EUNSPEC; c->sigcontext_addr = sc_addr; /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0); c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0); c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0); c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0); c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0); c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0); c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0); c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0); c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0); c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0); c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0); c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0); c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0); c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0); c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0); c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0); c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0); c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0); c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0); c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0); c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0); c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0); c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0); c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0); c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0); c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0); c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0); c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0); c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0); c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0); c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0); c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0); /* Set SP/CFA and PC/IP. */ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); c->dwarf.pi_valid = 0; return 1; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); /* Try DWARF-based unwinding... */ ret = dwarf_step (&c->dwarf); if (ret < 0 && ret != -UNW_ENOINFO) { Debug (2, "returning %d\n", ret); return ret; } if (unlikely (ret < 0)) { /* DWARF failed, let's see if we can follow the frame-chain or skip over the signal trampoline. */ struct dwarf_loc ebp_loc, eip_loc; /* We could get here because of missing/bad unwind information. Validate all addresses before dereferencing. */ c->validate = 1; Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); if (unw_is_signal_frame (cursor)) { ret = unw_handle_signal_frame(cursor); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } } else { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]), c->dwarf.cfa); ebp_loc = DWARF_LOC (c->dwarf.cfa, 0); eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0); c->dwarf.cfa += 8; /* Mark all registers unsaved, since we don't know where they are saved (if at all), except for the EBP and EIP. */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[EBP] = ebp_loc; c->dwarf.loc[EIP] = eip_loc; } c->dwarf.ret_addr_column = EIP; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip); if (ret < 0) { Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP])); Debug (2, "returning %d\n", ret); return ret; } else { Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]), c->dwarf.ip); } } else c->dwarf.ip = 0; } ret = (c->dwarf.ip == 0) ? 0 : 1; Debug (2, "returning %d\n", ret); return ret; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); /* ANDROID support update. */ /* Save the current ip/cfa to prevent looping if the decode yields the same ip/cfa as before. */ unw_word_t old_ip = c->dwarf.ip; unw_word_t old_cfa = c->dwarf.cfa; /* End of ANDROID update. */ /* Try DWARF-based unwinding... */ ret = dwarf_step (&c->dwarf); #if !defined(UNW_LOCAL_ONLY) /* Do not use this method on a local unwind. There is a very high * probability this method will try to access unmapped memory, which * will crash the process. Since this almost never actually works, * it should be okay to skip. */ if (ret < 0) { /* DWARF failed, let's see if we can follow the frame-chain or skip over the signal trampoline. */ struct dwarf_loc ebp_loc, eip_loc; /* We could get here because of missing/bad unwind information. Validate all addresses before dereferencing. */ c->validate = 1; Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); if (unw_is_signal_frame (cursor)) { ret = unw_handle_signal_frame(cursor); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } } else { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning %d\n", ret); return ret; } Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]), c->dwarf.cfa); ebp_loc = DWARF_LOC (c->dwarf.cfa, 0); eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0); c->dwarf.cfa += 8; /* Mark all registers unsaved, since we don't know where they are saved (if at all), except for the EBP and EIP. */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[EBP] = ebp_loc; c->dwarf.loc[EIP] = eip_loc; } c->dwarf.ret_addr_column = EIP; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip); if (ret < 0) { Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP])); Debug (2, "returning %d\n", ret); return ret; } else { Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]), c->dwarf.ip); } } else c->dwarf.ip = 0; } #endif /* ANDROID support update. */ if (ret >= 0) { if (c->dwarf.ip) { /* Adjust the pc to the instruction before. */ c->dwarf.ip--; } /* If the decode yields the exact same ip/cfa as before, then indicate the unwind is complete. */ if (old_ip == c->dwarf.ip && old_cfa == c->dwarf.cfa) { Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", __FUNCTION__, (long) c->dwarf.ip); return -UNW_EBADFRAME; } c->dwarf.frame++; } /* End of ANDROID update. */ if (unlikely (ret <= 0)) return 0; return (c->dwarf.ip == 0) ? 0 : 1; }
PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { struct sigframe *sf; uintptr_t uc_addr; struct dwarf_loc esp_loc; sf = (struct sigframe *)c->dwarf.cfa; uc_addr = (uintptr_t)&(sf->sf_uc); c->sigcontext_addr = c->dwarf.cfa; esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0); c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0); c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0); c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0); c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0); c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0); c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0); c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0); c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0); c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0); c->dwarf.loc[ST0] = DWARF_NULL_LOC; } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) { c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0); c->dwarf.loc[EAX] = DWARF_NULL_LOC; c->dwarf.cfa += 4; c->dwarf.use_prev_instr = 1; } else { Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format); abort(); } return 0; }
static int mips_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; unw_word_t sc_addr, sp_addr = c->dwarf.cfa; unw_word_t ra, fp; int ret; switch (unw_is_signal_frame (cursor)) { case 1: sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; break; case 2: sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; break; default: return -UNW_EUNSPEC; } if (tdep_big_endian(c->dwarf.as)) sc_addr += 4; c->sigcontext_addr = sc_addr; /* Update the dwarf cursor. */ c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); c->dwarf.loc[UNW_MIPS_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); c->dwarf.loc[UNW_MIPS_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); c->dwarf.loc[UNW_MIPS_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); c->dwarf.loc[UNW_MIPS_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); c->dwarf.loc[UNW_MIPS_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); c->dwarf.loc[UNW_MIPS_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); c->dwarf.loc[UNW_MIPS_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); c->dwarf.loc[UNW_MIPS_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); /* Set SP/CFA and PC/IP. */ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa); if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), &c->dwarf.ip)) < 0) return ret; if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), &ra)) < 0) return ret; if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), &fp)) < 0) return ret; Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", (unsigned long long)c->dwarf.ip, (unsigned long long)ra, (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); c->dwarf.pi_valid = 0; c->dwarf.use_prev_instr = 0; return 1; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret = -UNW_EUNSPEC; Debug (1, "(cursor=%p)\n", c); /* Try DWARF-based unwinding... this is the only method likely to work for ARM. */ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) { ret = dwarf_step (&c->dwarf); Debug(1, "dwarf_step()=%d\n", ret); if (unlikely (ret == -UNW_ESTOPUNWIND)) return ret; if (ret < 0 && ret != -UNW_ENOINFO) { Debug (2, "returning %d\n", ret); return ret; } } if (unlikely (ret < 0)) { if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) { ret = UNW_ESUCCESS; /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ unw_word_t instr, i; Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); dwarf_loc_t ip_loc, fp_loc; unw_word_t frame; /* Mark all registers unsaved, since we don't know where they are saved (if at all), except for the EBP and EIP. */ if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0) { return 0; } for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { c->dwarf.loc[i] = DWARF_NULL_LOC; } if (frame) { if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0) { return 0; } instr -= 8; if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0) { return 0; } if ((instr & 0xFFFFD800) == 0xE92DD800) { /* Standard APCS frame. */ ip_loc = DWARF_LOC(frame - 4, 0); fp_loc = DWARF_LOC(frame - 12, 0); } else { /* Codesourcery optimized normal frame. */ ip_loc = DWARF_LOC(frame, 0); fp_loc = DWARF_LOC(frame - 4, 0); } if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0) { return 0; } c->dwarf.loc[UNW_ARM_R12] = ip_loc; c->dwarf.loc[UNW_ARM_R11] = fp_loc; Debug(15, "ip=%lx\n", c->dwarf.ip); } else { ret = -UNW_ENOINFO; } } } return ret == -UNW_ENOINFO ? 0 : 1; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); /* Try DWARF-based unwinding... */ ret = dwarf_step (&c->dwarf); if (ret < 0 && ret != -UNW_ENOINFO) { Debug (2, "returning %d\n", ret); return ret; } if (unlikely (ret < 0)) { /* DWARF failed, let's see if we can follow the frame-chain or skip over the signal trampoline. */ Debug (13, "dwarf_step() failed (ret=%d), trying fallback\n", ret); if (unw_is_signal_frame (cursor)) { #ifdef __linux__ /* Assume that the trampoline is at the beginning of the sigframe. */ unw_word_t ip, sc_addr = c->dwarf.ip + LINUX_RT_SIGFRAME_UC_OFF; dwarf_loc_t iaoq_loc = DWARF_LOC (sc_addr + LINUX_SC_IAOQ_OFF, 0); c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME; c->sigcontext_addr = sc_addr; c->dwarf.ret_addr_column = UNW_HPPA_RP; if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) , 0) { Debug (2, "failed to read IAOQ[1] (ret=%d)\n", ret); return ret; } c->dwarf.ip = ip & ~0x3; /* mask out the privilege level */ for (i = 0; i < 32; ++i) { c->dwarf.loc[UNW_HPPA_GR + i] = DWARF_LOC (sc_addr + LINUX_SC_GR_OFF + 4*i, 0); c->dwarf.loc[UNW_HPPA_FR + i] = DWARF_LOC (sc_addr + LINUX_SC_FR_OFF + 4*i, 0); } if ((ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], &c->dwarf.cfa)) < 0) { Debug (2, "failed to read SP (ret=%d)\n", ret); return ret; } #else # error Implement me! #endif } else c->dwarf.ip = 0; } ret = (c->dwarf.ip == 0) ? 0 : 1; Debug (2, "returning %d\n", ret); return ret; }
PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; /* c->esp points at the arguments to the handler. Without SA_SIGINFO, the arguments consist of a signal number followed by a struct sigcontext. With SA_SIGINFO, the arguments consist a signal number, a siginfo *, and a ucontext *. */ unw_word_t sc_addr; unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4; unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8; unw_word_t siginfo_ptr, sigcontext_ptr; struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc; siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0); sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0); ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr) | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr)); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } if (siginfo_ptr < c->dwarf.cfa || siginfo_ptr > c->dwarf.cfa + 256 || sigcontext_ptr < c->dwarf.cfa || sigcontext_ptr > c->dwarf.cfa + 256) { /* Not plausible for SA_SIGINFO signal */ c->sigcontext_format = X86_SCF_LINUX_SIGFRAME; c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4; } else { /* If SA_SIGINFO were not specified, we actually read various segment pointers instead. We believe that at least fs and _fsh are always zero for linux, so it is not just unlikely, but impossible that we would end up here. */ c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME; c->sigcontext_addr = sigcontext_ptr; sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF; } esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0); c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0); c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0); c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0); c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0); c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0); c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; c->dwarf.loc[ST0] = DWARF_NULL_LOC; c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0); c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); return 0; }