mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-05 09:19:27 +01:00
(unw_step): If dwarf_step() fails and the frame doesn't look like
a signal-trampoline, assume that it's a PLT stub. If non-DWARF stepping fails to change IP and CFA, declare it a bad frame. 2004/11/23 16:59:56-08:00 mostang.com!davidm (unw_step): Also print IP as part of the function-trace. 2004/11/23 16:17:37-08:00 mostang.com!davidm (unw_step): When dwarf_step() fails on a signal-frame, fill in all the known locations because dwarf_step() fails on older kernels which don't export the kernel vDSO even though every- thing else may be providing proper DWARF unwind-info. 2004/10/25 17:43:57+02:00 homeip.net!davidm Add Debug statement for return-value. (Logical change 1.290)
This commit is contained in:
parent
fa0828ac7d
commit
17bf4d0af8
1 changed files with 82 additions and 21 deletions
|
@ -1,5 +1,5 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2003 Hewlett-Packard Co
|
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>
|
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
||||||
|
@ -35,11 +35,17 @@ unw_step (unw_cursor_t *cursor)
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
Debug (1, "(cursor=%p, ip=0x%016llx)\n",
|
||||||
|
c, (unsigned long long) c->dwarf.ip);
|
||||||
|
|
||||||
/* Try DWARF-based unwinding... */
|
/* Try DWARF-based unwinding... */
|
||||||
ret = dwarf_step (&c->dwarf);
|
ret = dwarf_step (&c->dwarf);
|
||||||
|
|
||||||
if (unlikely (ret == -UNW_ESTOPUNWIND))
|
if (ret < 0 && ret != -UNW_ENOINFO)
|
||||||
return ret;
|
{
|
||||||
|
Debug (2, "returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (likely (ret >= 0))
|
if (likely (ret >= 0))
|
||||||
{
|
{
|
||||||
|
@ -50,8 +56,19 @@ unw_step (unw_cursor_t *cursor)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* DWARF failed, let's see if we can follow the frame-chain
|
/* DWARF failed. There isn't much of a usable frame-chain on x86-64,
|
||||||
or skip over the signal trampoline. */
|
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.
|
||||||
|
|
||||||
|
(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;
|
struct dwarf_loc rbp_loc, rsp_loc, rip_loc;
|
||||||
|
|
||||||
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
|
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
|
||||||
|
@ -71,28 +88,64 @@ unw_step (unw_cursor_t *cursor)
|
||||||
|
|
||||||
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
|
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
{
|
||||||
|
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[ 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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &c->dwarf.cfa);
|
unw_word_t rbp;
|
||||||
|
|
||||||
|
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
{
|
||||||
|
Debug (2, "returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Debug (13, "[RBP=0x%Lx] = 0x%Lx\n",
|
if (!rbp)
|
||||||
(unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
|
{
|
||||||
(unsigned long long) c->dwarf.cfa);
|
/* 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
|
||||||
|
{
|
||||||
|
Debug (1, "[RBP=0x%Lx] = 0x%Lx (cfa = 0x%Lx)\n",
|
||||||
|
(unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
|
||||||
|
(unsigned long long) rbp,
|
||||||
|
(unsigned long long) c->dwarf.cfa);
|
||||||
|
|
||||||
rbp_loc = DWARF_LOC (c->dwarf.cfa, 0);
|
rbp_loc = c->dwarf.loc[RBP];
|
||||||
rsp_loc = DWARF_NULL_LOC;
|
rsp_loc = DWARF_NULL_LOC;
|
||||||
rip_loc = DWARF_LOC (c->dwarf.cfa + 8, 0);
|
rip_loc = DWARF_LOC (c->dwarf.cfa + 8, 0);
|
||||||
c->dwarf.cfa += 16;
|
c->dwarf.cfa += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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[RBP] = rbp_loc;
|
||||||
c->dwarf.loc[RSP] = rsp_loc;
|
c->dwarf.loc[RSP] = rsp_loc;
|
||||||
c->dwarf.loc[RIP] = rip_loc;
|
c->dwarf.loc[RIP] = rip_loc;
|
||||||
|
@ -102,10 +155,18 @@ unw_step (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
|
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
{
|
||||||
|
Debug (2, "returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c->dwarf.ip = 0;
|
c->dwarf.ip = 0;
|
||||||
|
|
||||||
|
if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa)
|
||||||
|
return -UNW_EBADFRAME;
|
||||||
}
|
}
|
||||||
return (c->dwarf.ip == 0) ? 0 : 1;
|
ret = (c->dwarf.ip == 0) ? 0 : 1;
|
||||||
|
Debug (2, "returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue