mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-22 11:33:43 +01:00
powerpc64 implementation
This commit is contained in:
parent
923fa78e79
commit
d1a8ca6d84
7 changed files with 168 additions and 19 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.global _UI_setcontext
|
||||
|
||||
_UI_setcontext:
|
||||
retq
|
||||
blr
|
||||
|
||||
#ifdef __linux__
|
||||
/* We do not need executable stack. */
|
||||
|
|
Loading…
Reference in a new issue