/* libunwind - a platform-independent unwind library
Copyright (C) 2002-2004 Hewlett-Packard Co
- Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
return 0;
ret = (((w0 & 0xffff) == 0x25ff)
- && (((w0 >> 48) & 0xff) == 0x68)
- && (((w1 >> 24) & 0xff) == 0xe9));
+ && (((w0 >> 48) & 0xff) == 0x68)
+ && (((w1 >> 24) & 0xff) == 0xe9));
Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret);
return ret;
#endif
Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n",
- c, c->dwarf.ip, c->dwarf.cfa);
+ c, c->dwarf.ip, c->dwarf.cfa);
/* Try DWARF-based unwinding... */
c->sigcontext_format = X86_64_SCF_NONE;
if (likely (ret >= 0))
{
/* x86_64 ABI specifies that end of call-chain is marked with a
- NULL RBP. */
- if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
- {
- c->dwarf.ip = 0;
- ret = 0;
- }
+ NULL RBP or undefined return address */
+ if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])
+ || DWARF_IS_NULL_LOC(c->dwarf.loc[c->dwarf.ret_addr_column]))
+ {
+ c->dwarf.ip = 0;
+ ret = 0;
+ }
}
else
{
/* DWARF failed. There isn't much of a usable frame-chain on x86-64,
- but we do need to handle two special-cases:
+ but we do need to handle two special-cases:
- (i) signal trampoline: Old kernels and older libcs don't
- export the vDSO needed to get proper unwind info for the
- trampoline. Recognize that case by looking at the code
- and filling in things by hand.
+ (i) signal trampoline: Old kernels and older libcs don't
+ export the vDSO needed to get proper unwind info for the
+ trampoline. Recognize that case by looking at the code
+ and filling in things by hand.
- (ii) PLT (shared-library) call-stubs: PLT stubs are invoked
- via CALLQ. Try this for all non-signal trampoline
- code. */
+ (ii) PLT (shared-library) call-stubs: PLT stubs are invoked
+ via CALLQ. Try this for all non-signal trampoline
+ code. */
unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa;
struct dwarf_loc rbp_loc, rsp_loc, rip_loc;
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;
- }
- }
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+ }
else if (is_plt_entry (&c->dwarf))
- {
+ {
/* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */
- Debug (2, "found plt entry\n");
+ Debug (2, "found plt entry\n");
c->frame_info.cfa_reg_offset = 8;
c->frame_info.cfa_reg_rsp = -1;
c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD;
c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
c->dwarf.cfa += 8;
- }
+ }
else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
{
- for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
- c->dwarf.loc[i] = DWARF_NULL_LOC;
- }
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+ }
else
- {
- unw_word_t rbp;
-
- ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
- if (ret < 0)
- {
- Debug (2, "returning %d [RBP=0x%lx]\n", ret,
- DWARF_GET_LOC (c->dwarf.loc[RBP]));
- return ret;
- }
-
- if (!rbp)
- {
- /* Looks like we may have reached the end of the call-chain. */
- rbp_loc = DWARF_NULL_LOC;
- rsp_loc = DWARF_NULL_LOC;
- rip_loc = DWARF_NULL_LOC;
- }
- else
- {
- unw_word_t rbp1 = 0;
- rbp_loc = DWARF_LOC(rbp, 0);
- rsp_loc = DWARF_NULL_LOC;
- rip_loc = DWARF_LOC (rbp + 8, 0);
- ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1);
- Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n",
- (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
- rbp, c->dwarf.cfa, rbp1);
-
- /* Heuristic to determine incorrect guess. For RBP to be a
- valid frame it needs to be above current CFA, but don't
- let it go more than a little. Note that we can't deduce
- anything about new RBP (rbp1) since it may not be a frame
- pointer in the frame above. Just check we get the value. */
+ {
+ unw_word_t rbp;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d [RBP=0x%lx]\n", ret,
+ DWARF_GET_LOC (c->dwarf.loc[RBP]));
+ return ret;
+ }
+
+ if (!rbp)
+ {
+ /* Looks like we may have reached the end of the call-chain. */
+ rbp_loc = DWARF_NULL_LOC;
+ rsp_loc = DWARF_NULL_LOC;
+ rip_loc = DWARF_NULL_LOC;
+ }
+ else
+ {
+ unw_word_t rbp1 = 0;
+ rbp_loc = DWARF_LOC(rbp, 0);
+ rsp_loc = DWARF_NULL_LOC;
+ rip_loc = DWARF_LOC (rbp + 8, 0);
+ ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1);
+ Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n",
+ (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
+ rbp, c->dwarf.cfa, rbp1);
+
+ /* Heuristic to determine incorrect guess. For RBP to be a
+ valid frame it needs to be above current CFA, but don't
+ let it go more than a little. Note that we can't deduce
+ anything about new RBP (rbp1) since it may not be a frame
+ pointer in the frame above. Just check we get the value. */
if (ret < 0
- || rbp <= c->dwarf.cfa
- || (rbp - c->dwarf.cfa) > 0x4000)
- {
+ || rbp < c->dwarf.cfa
+ || (rbp - c->dwarf.cfa) > 0x4000)
+ {
rip_loc = DWARF_NULL_LOC;
rbp_loc = DWARF_NULL_LOC;
- }
+ }
c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED;
c->frame_info.cfa_reg_rsp = 0;
c->frame_info.cfa_reg_offset = 16;
c->frame_info.rbp_cfa_offset = -16;
- c->dwarf.cfa += 16;
- }
+ c->dwarf.cfa += 16;
+ }
- /* Mark all registers unsaved */
- for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
- c->dwarf.loc[i] = DWARF_NULL_LOC;
+ /* Mark all registers unsaved */
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
c->dwarf.loc[RBP] = rbp_loc;
c->dwarf.loc[RSP] = rsp_loc;
c->dwarf.loc[RIP] = rip_loc;
- }
+ c->dwarf.use_prev_instr = 1;
+ }
c->dwarf.ret_addr_column = RIP;
if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
{
- ret = 0;
- Debug (2, "NULL %%rbp loc, returning %d\n", ret);
- return ret;
+ ret = 0;
+ Debug (2, "NULL %%rbp loc, returning %d\n", ret);
+ return ret;
}
if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP]))
- {
- ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
- Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
- (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
- (unsigned long long) c->dwarf.ip);
- if (ret < 0)
- {
- Debug (2, "returning %d\n", ret);
- return ret;
- }
- ret = 1;
- }
+ {
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
+ Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
+ (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
+ (unsigned long long) c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ ret = 1;
+ }
else
- c->dwarf.ip = 0;
+ c->dwarf.ip = 0;
if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa)
- return -UNW_EBADFRAME;
+ return -UNW_EBADFRAME;
}
Debug (2, "returning %d\n", ret);
return ret;