1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-06-29 04:31:45 +02:00

(unw_step): If dwarf_step() fails, fall back on using the frame-chain.

In theory, this may not be needed.  In practice, I find that
	Red Hat Enterprise Linux AS release 3, the _start() routine has
	no unwind-info, but we need to be able to unwind into this
	routine to find the end-of-frame-chain marker (RBP == 0).

(Logical change 1.253)
This commit is contained in:
homeip.net!davidm 2004-08-20 11:23:15 +00:00
parent be2bed2712
commit 6058013abe

View file

@ -35,20 +35,29 @@ unw_step (unw_cursor_t *cursor)
struct cursor *c = (struct cursor *) cursor;
int ret, i;
/* Only attempt DWARF based unwinding since DWARF frame info is
always expected to be there. With the exception of signal frames. */
/* Try DWARF-based unwinding... */
ret = dwarf_step (&c->dwarf);
if (!unw_is_signal_frame (cursor))
{
if ((ret = dwarf_step (&c->dwarf)) < 0)
{
Debug(1, "dwarf step failed\n");
if (unlikely (ret == -UNW_ESTOPUNWIND))
return ret;
}
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;
}
else
{
/* DWARF failed, let's see if we can follow the frame-chain
or skip over the signal trampoline. */
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))
{
unw_word_t ucontext = c->dwarf.cfa;
Debug(1, "signal frame, skip over trampoline\n");
@ -63,6 +72,22 @@ unw_step (unw_cursor_t *cursor)
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
if (ret < 0)
return ret;
}
else
{
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &c->dwarf.cfa);
if (ret < 0)
return ret;
Debug (13, "[RBP=0x%Lx] = 0x%Lx\n",
(unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
(unsigned long long) c->dwarf.cfa);
rbp_loc = DWARF_LOC (c->dwarf.cfa, 0);
rsp_loc = DWARF_NULL_LOC;
rip_loc = DWARF_LOC (c->dwarf.cfa + 8, 0);
c->dwarf.cfa += 16;
}
/* Mark all registers unsaved */
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)