1
0
Fork 0
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:
mostang.com!davidm 2005-05-03 09:13:17 +00:00
parent fa0828ac7d
commit 17bf4d0af8

View file

@ -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;
} }