#include "unwind_i.h"
#include "offsets.h"
static int
riscv_handle_signal_frame (unw_cursor_t *cursor)
{
int ret, i;
struct cursor *c = (struct cursor *) cursor;
unw_word_t sp, sp_addr = c->dwarf.cfa;
struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
return -UNW_EUNSPEC;
if (!unw_is_signal_frame (cursor))
return -UNW_EUNSPEC;
#ifdef __linux__
c->sigcontext_format = RISCV_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = sp_addr + sizeof (siginfo_t) + UC_MCONTEXT_REGS_OFF;
c->sigcontext_sp = sp_addr;
c->sigcontext_pc = c->dwarf.ip;
#else
return -UNW_EUNSPEC;
#endif
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;
#define SC_REG_OFFSET(X) (8 * X)
c->dwarf.loc[UNW_TDEP_IP] = DWARF_LOC (c->sigcontext_addr + SC_REG_OFFSET(UNW_RISCV_X0), 0);
for (i = UNW_RISCV_X1; i <= UNW_RISCV_F31; i++)
{
c->dwarf.loc[i] = DWARF_LOC (c->sigcontext_addr + SC_REG_OFFSET(i), 0);
}
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TDEP_SP], &c->dwarf.cfa);
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TDEP_IP], &c->dwarf.ip);
return 1;
}
int
unw_step (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
int validate = c->validate;
int ret;
Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n",
c, c->dwarf.ip, c->dwarf.cfa);
c->validate = 1;
if (unw_is_signal_frame (cursor) > 0)
return riscv_handle_signal_frame (cursor);
c->validate = validate;
ret = dwarf_step (&c->dwarf);
if (unlikely (ret == -UNW_ESTOPUNWIND))
return ret;
if (unlikely (ret < 0))
{
Debug (1, "DWARF unwinding failed (cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", c, c->dwarf.ip, c->dwarf.cfa);
c->dwarf.loc[UNW_RISCV_PC] = c->dwarf.loc[UNW_RISCV_X1];
c->dwarf.loc[UNW_RISCV_X1] = DWARF_NULL_LOC;
if (!DWARF_IS_NULL_LOC (c->dwarf.loc[UNW_RISCV_PC]))
{
ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_RISCV_PC], &c->dwarf.ip);
if (ret < 0)
{
Debug (2, "Failed to get PC from return address: %d\n", ret);
return ret;
}
Debug (2, "ra= 0x%016lx\n", c->dwarf.ip);
ret = 1;
}
else
{
c->dwarf.ip = 0;
}
}
return (c->dwarf.ip == 0) ? 0 : 1;
}