1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-21 23:27:39 +01:00

powerpc64 implementation

This commit is contained in:
Alexander Esilevich 2015-09-01 04:25:18 +06:00 committed by Arun Sharma
parent 923fa78e79
commit d1a8ca6d84
7 changed files with 168 additions and 19 deletions

View file

@ -88,15 +88,68 @@ struct cursor
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
# define DWARF_IS_REG_LOC(l) 0
# define DWARF_IS_FP_LOC(l) 0
# define DWARF_IS_V_LOC(l) 0
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
static inline int
dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
static inline int
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
#else /* !UNW_LOCAL_ONLY */
# define DWARF_LOC_TYPE_FP (1 << 0)
@ -116,8 +169,6 @@ struct cursor
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
| DWARF_LOC_TYPE_V))
#endif /* !UNW_LOCAL_ONLY */
static inline int
dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
{
@ -253,6 +304,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
1, c->as_arg);
}
#endif /* !UNW_LOCAL_ONLY */
#define tdep_getcontext_trace unw_getcontext
#define tdep_init_done UNW_OBJ(init_done)
#define tdep_init UNW_OBJ(init)

View file

@ -29,6 +29,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
PROTECTED int
unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
{
/* XXX: empty stub. */
return -UNW_EINVAL;
struct cursor *c = (struct cursor *) cursor;
int ret;
ret = dwarf_make_proc_info (&c->dwarf);
if (ret < 0)
return ret;
*pi = c->dwarf.pi;
return 0;
}

View file

@ -169,7 +169,7 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
ucontext_t *uc = arg;
unw_fpreg_t *addr;
if ((unsigned) (reg - UNW_PPC64_F0) < 0)
if ((reg - UNW_PPC64_F0) < 0)
goto badreg;
if ((unsigned) (reg - UNW_PPC64_V0) >= 32)

View file

@ -35,6 +35,54 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
switch (reg)
{
case UNW_PPC64_R0:
case UNW_PPC64_R2:
case UNW_PPC64_R3:
case UNW_PPC64_R4:
case UNW_PPC64_R5:
case UNW_PPC64_R6:
case UNW_PPC64_R7:
case UNW_PPC64_R8:
case UNW_PPC64_R9:
case UNW_PPC64_R10:
case UNW_PPC64_R11:
case UNW_PPC64_R12:
case UNW_PPC64_R13:
case UNW_PPC64_R14:
case UNW_PPC64_R15:
case UNW_PPC64_R16:
case UNW_PPC64_R17:
case UNW_PPC64_R18:
case UNW_PPC64_R19:
case UNW_PPC64_R20:
case UNW_PPC64_R21:
case UNW_PPC64_R22:
case UNW_PPC64_R23:
case UNW_PPC64_R24:
case UNW_PPC64_R25:
case UNW_PPC64_R26:
case UNW_PPC64_R27:
case UNW_PPC64_R28:
case UNW_PPC64_R29:
case UNW_PPC64_R30:
case UNW_PPC64_R31:
case UNW_PPC64_LR:
case UNW_PPC64_CTR:
case UNW_PPC64_CR0:
case UNW_PPC64_CR1:
case UNW_PPC64_CR2:
case UNW_PPC64_CR3:
case UNW_PPC64_CR4:
case UNW_PPC64_CR5:
case UNW_PPC64_CR6:
case UNW_PPC64_CR7:
case UNW_PPC64_VRSAVE:
case UNW_PPC64_VSCR:
case UNW_PPC64_SPE_ACC:
case UNW_PPC64_SPEFSCR:
loc = c->dwarf.loc[reg];
break;
case UNW_TDEP_IP:
if (write)
{
@ -53,18 +101,11 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
*valp = c->dwarf.cfa;
return 0;
default:
return -UNW_EBADREG;
break;
}
/* make sure it's not an FP or VR register */
if ((((unsigned) (reg - UNW_PPC64_F0)) <= 31) ||
(((unsigned) (reg - UNW_PPC64_V0)) <= 31))
return -UNW_EBADREG;
loc = c->dwarf.loc[reg];
if (write)
return dwarf_put (&c->dwarf, loc, *valp);
else

View file

@ -45,7 +45,20 @@ my_rt_sigreturn (void *new_sp)
HIDDEN inline int
ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
/* XXX: empty stub. */
struct cursor *c = (struct cursor *) cursor;
ucontext_t *uc = (ucontext_t *)c->dwarf.as_arg;
if (unlikely (c->sigcontext_format != PPC_SCF_NONE))
{
my_rt_sigreturn(cursor);
abort();
}
else
{
Debug (8, "resuming at ip=%llx via setcontext()\n",
(unsigned long long) c->dwarf.ip);
setcontext (uc);
}
return -UNW_EINVAL;
}
@ -57,7 +70,28 @@ ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
static inline int
establish_machine_state (struct cursor *c)
{
/* XXX: empty stub. */
unw_addr_space_t as = c->dwarf.as;
void *arg = c->dwarf.as_arg;
unw_fpreg_t fpval;
unw_word_t val;
int reg;
Debug (8, "copying out cursor state\n");
for (reg = 0; reg <= UNW_REG_LAST; ++reg)
{
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
if (unw_is_fpreg (reg))
{
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
}
else
{
if (tdep_access_reg (c, reg, &val, 0) >= 0)
as->acc.access_reg (as, reg, &val, 1, arg);
}
}
return 0;
}

View file

@ -432,5 +432,19 @@ unw_step (unw_cursor_t * cursor)
ret = 1;
}
}
// on ppc64, R2 register is used as pointer to TOC
// section which is used for symbol lookup in PIC code
// ppc64 linker generates "ld r2, 24(r1)" instruction after each
// @plt call. We need restore R2, but only for @plt calls
{
unsigned int *inst = (unw_word_t*)c->dwarf.ip;
if (*inst == (0xE8410000 + 24)) {
// @plt call, restoring R2 from CFA+24
c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + 24, 0);
}
}
Debug (2, "returning %d with last return statement\n", ret);
return ret;
}

View file

@ -1,7 +1,7 @@
.global _UI_setcontext
_UI_setcontext:
retq
blr
#ifdef __linux__
/* We do not need executable stack. */