Skip to content

Commit

Permalink
Improve unw_step fallback method on Aarch64.
Browse files Browse the repository at this point in the history
In case when the dwarf_step fails due to the previous frame is not
dwarf annotated try to fallback to a frame pointer based unwind method.
Normally, most of OS (libc) exposed functions are dwarf annotated,
however some are not. I.e., _init and _fini can't be annotated due to
its nature.
To allow to unwind through such functions OS (Glibc) adds a standart
prologue and epilogue code to it.
  • Loading branch information
lemul authored and bregma committed Jul 5, 2023
1 parent 72c03e4 commit d7ca80c
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/aarch64/Gstep.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ unw_step (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
int validate = c->validate;
unw_word_t fp;
int ret;

Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
Expand Down Expand Up @@ -250,8 +251,45 @@ unw_step (unw_cursor_t *cursor)
}
else
{
Debug (2, "fallback\n");
/* Try use frame pointer (X29). */
c->frame_info.frame_type = UNW_AARCH64_FRAME_GUESSED;

ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_X29], &fp);
if (likely (ret == 0))
{
if (fp == 0)
{
/* Procedure Call Standard for the ARM 64-bit Architecture (AArch64)
* specifies that the end of the frame record chain is indicated by
* the address zero in the address for the previous frame.
*/
c->dwarf.ip = 0;
Debug (2, "NULL frame pointer X29 loc, returning 0\n");
return 0;
}

Debug (2, "fallback, x29 = 0x%016lx\n", fp);
for (int i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;

c->dwarf.loc[UNW_AARCH64_SP] = DWARF_MEM_LOC (c->dwarf, fp);
c->dwarf.loc[UNW_AARCH64_X30] = DWARF_MEM_LOC (c->dwarf, fp + 8);

/* Set SP/CFA and PC/IP. */
ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
if (ret < 0)
return ret;
ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_X30], &c->dwarf.ip);
if (ret == 0)
{
ret = 1;
c->dwarf.loc[UNW_AARCH64_X29] = c->dwarf.loc[UNW_AARCH64_SP];
c->dwarf.loc[UNW_AARCH64_PC] = c->dwarf.loc[UNW_AARCH64_X30];
}
Debug (2, "fallback, CFA = 0x%016lx, IP = 0x%016lx returning %d\n",
c->dwarf.cfa, c->dwarf.ip, ret);
return ret;
}
}
/* Use link register (X30). */
c->frame_info.cfa_reg_offset = 0;
Expand Down

0 comments on commit d7ca80c

Please sign in to comment.