mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-02-17 10:41:42 +01:00
(ia64_scratch_loc): Use c->as->abi to select appropriate behavior. Implement
support for HP-UX. (access_nat): Check for uc-location and pass it on to ia64_put()/ia64_get() if it is. Handle NaT-bit-saved-in-scratch-register only for Linux. (ia64_access_reg): Change dprintf() into debug() statement. (ia64_access_fpreg): Move fph-partition initialization code to ia64_scratch_loc(). Change dprintf() into debug() statement. (Logical change 1.87)
This commit is contained in:
parent
8b7c7e322a
commit
bd28baa280
1 changed files with 77 additions and 63 deletions
|
@ -37,6 +37,14 @@ ia64_scratch_loc (struct cursor *c, unw_regnum_t reg)
|
||||||
|
|
||||||
if (sc_addr)
|
if (sc_addr)
|
||||||
{
|
{
|
||||||
|
switch (c->as->abi)
|
||||||
|
{
|
||||||
|
#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
|
||||||
|
case ABI_LINUX:
|
||||||
|
{
|
||||||
|
unw_word_t flags, tmp_addr;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
|
case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
|
||||||
|
@ -54,6 +62,28 @@ ia64_scratch_loc (struct cursor *c, unw_regnum_t reg)
|
||||||
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
|
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
|
||||||
|
|
||||||
case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
|
case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
|
||||||
|
if ((ret = ia64_get (c, IA64_LOC_ADDR (sc_addr
|
||||||
|
+ LINUX_SC_FLAGS_OFF,
|
||||||
|
0), &flags)) < 0)
|
||||||
|
return IA64_NULL_LOC;
|
||||||
|
|
||||||
|
if (!(flags & IA64_SC_FLAG_FPH_VALID))
|
||||||
|
{
|
||||||
|
/* initialize fph partition: */
|
||||||
|
tmp_addr = sc_addr + LINUX_SC_FR_OFF + 32*16;
|
||||||
|
for (i = 32; i < 128; ++i, tmp_addr += 16)
|
||||||
|
if ((ret = ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0),
|
||||||
|
unw.f0)) < 0)
|
||||||
|
return IA64_NULL_LOC;
|
||||||
|
/* mark fph partition as valid: */
|
||||||
|
if ((ret = ia64_put (c,
|
||||||
|
IA64_LOC_ADDR (sc_addr
|
||||||
|
+ LINUX_SC_FLAGS_OFF,
|
||||||
|
0),
|
||||||
|
flags | IA64_SC_FLAG_FPH_VALID)) < 0)
|
||||||
|
return IA64_NULL_LOC;
|
||||||
|
}
|
||||||
|
|
||||||
sc_addr += LINUX_SC_FR_OFF + 16*(reg - UNW_IA64_FR);
|
sc_addr += LINUX_SC_FR_OFF + 16*(reg - UNW_IA64_FR);
|
||||||
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
|
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
|
||||||
|
|
||||||
|
@ -67,6 +97,17 @@ ia64_scratch_loc (struct cursor *c, unw_regnum_t reg)
|
||||||
}
|
}
|
||||||
return IA64_LOC_ADDR (sc_addr, 0);
|
return IA64_LOC_ADDR (sc_addr, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(UNW_LOCAL_ONLY) || defined(__hpux)
|
||||||
|
case ABI_HPUX:
|
||||||
|
return IA64_LOC_UC_REG (reg, sc_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return IA64_NULL_LOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return IA64_REG_LOC (c, reg);
|
return IA64_REG_LOC (c, reg);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +145,14 @@ access_nat (struct cursor *c, ia64_loc_t loc, ia64_loc_t reg_loc,
|
||||||
unw_fpreg_t tmp;
|
unw_fpreg_t tmp;
|
||||||
int ret, reg;
|
int ret, reg;
|
||||||
|
|
||||||
|
if (IA64_IS_UC_LOC (reg_loc))
|
||||||
|
{
|
||||||
|
if (write)
|
||||||
|
return ia64_put (c, loc, *valp);
|
||||||
|
else
|
||||||
|
return ia64_get (c, loc, valp);
|
||||||
|
}
|
||||||
|
|
||||||
if (IA64_IS_FP_LOC (reg_loc))
|
if (IA64_IS_FP_LOC (reg_loc))
|
||||||
{
|
{
|
||||||
/* NaT bit is saved as a NaTVal. This happens when a general
|
/* NaT bit is saved as a NaTVal. This happens when a general
|
||||||
|
@ -206,13 +255,15 @@ access_nat (struct cursor *c, ia64_loc_t loc, ia64_loc_t reg_loc,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* NaT bit is saved in a scratch register. */
|
/* NaT bit is saved in a scratch register. */
|
||||||
|
#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
|
||||||
sc_addr = c->sigcontext_addr;
|
sc_addr = c->sigcontext_addr;
|
||||||
if (sc_addr)
|
if (sc_addr && c->as->abi == ABI_LINUX)
|
||||||
{
|
{
|
||||||
nat_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_NAT_OFF, 0);
|
nat_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_NAT_OFF, 0);
|
||||||
mask = (unw_word_t) 1 << reg;
|
mask = (unw_word_t) 1 << reg;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (write)
|
if (write)
|
||||||
return ia64_put (c, loc, *valp);
|
return ia64_put (c, loc, *valp);
|
||||||
|
@ -418,7 +469,7 @@ ia64_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf ("%s: bad register number %d\n", __FUNCTION__, reg);
|
debug (1, "%s: bad register number %d\n", __FUNCTION__, reg);
|
||||||
return -UNW_EBADREG;
|
return -UNW_EBADREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +487,7 @@ HIDDEN int
|
||||||
ia64_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
|
ia64_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
|
||||||
int write)
|
int write)
|
||||||
{
|
{
|
||||||
unw_word_t flags, tmp_addr, sc_addr;
|
|
||||||
ia64_loc_t loc;
|
ia64_loc_t loc;
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
|
@ -471,47 +520,12 @@ ia64_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
|
case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
|
||||||
sc_addr = c->sigcontext_addr;
|
|
||||||
if (sc_addr)
|
|
||||||
{
|
|
||||||
ret = ia64_get (c, IA64_LOC_ADDR (sc_addr + LINUX_SC_FLAGS_OFF, 0),
|
|
||||||
&flags);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!(flags & IA64_SC_FLAG_FPH_VALID))
|
|
||||||
{
|
|
||||||
if (write)
|
|
||||||
{
|
|
||||||
/* initialize fph partition: */
|
|
||||||
tmp_addr = sc_addr + LINUX_SC_FR_OFF + 32*16;
|
|
||||||
for (i = 32; i < 128; ++i, tmp_addr += 16)
|
|
||||||
{
|
|
||||||
ret = ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0),
|
|
||||||
unw.f0);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/* mark fph partition as valid: */
|
|
||||||
ret = ia64_put (c, IA64_LOC_ADDR (sc_addr
|
|
||||||
+ LINUX_SC_FLAGS_OFF, 0),
|
|
||||||
flags | IA64_SC_FLAG_FPH_VALID);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*valp = unw.f0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR;
|
reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR;
|
||||||
loc = ia64_scratch_loc (c, reg);
|
loc = ia64_scratch_loc (c, reg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf ("%s: bad register number %d\n", __FUNCTION__, reg);
|
debug (1, "%s: bad register number %d\n", __FUNCTION__, reg);
|
||||||
return -UNW_EBADREG;
|
return -UNW_EBADREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue