PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", c, c->dwarf.ip, c->dwarf.cfa); /* Special handling the singal frame. */ if (unw_is_signal_frame (cursor)) return unw_handle_signal_frame (cursor); /* Try DWARF-based unwinding... */ ret = dwarf_step (&c->dwarf); if (unlikely (ret == -UNW_ESTOPUNWIND)) return ret; /* Dwarf unwinding didn't work, stop. */ if (unlikely (ret < 0)) return 0; return (c->dwarf.ip == 0) ? 0 : 1; }
PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret; Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n", c, c->dwarf.ip, c->dwarf.cfa); /* Check if this is a signal frame. */ if (unw_is_signal_frame (cursor)) return unw_handle_signal_frame (cursor); ret = dwarf_step (&c->dwarf); Debug(1, "dwarf_step()=%d\n", ret); if (unlikely (ret == -UNW_ESTOPUNWIND)) return ret; if (unlikely (ret < 0)) return 0; return (c->dwarf.ip == 0) ? 0 : 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); /* 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_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_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; }