1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-05 01:09:27 +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:
mostang.com!davidm 2003-04-24 20:45:07 +00:00
parent 8b7c7e322a
commit bd28baa280

View file

@ -37,35 +37,76 @@ ia64_scratch_loc (struct cursor *c, unw_regnum_t reg)
if (sc_addr)
{
switch (reg)
switch (c->as->abi)
{
case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
sc_addr += LINUX_SC_NAT_OFF;
break;
#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
case ABI_LINUX:
{
unw_word_t flags, tmp_addr;
int i, ret;
case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31:
sc_addr += LINUX_SC_GR_OFF + 8*reg;
break;
switch (reg)
{
case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
sc_addr += LINUX_SC_NAT_OFF;
break;
case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
sc_addr += LINUX_SC_FR_OFF + 16*(reg - UNW_IA64_FR);
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31:
sc_addr += LINUX_SC_GR_OFF + 8*reg;
break;
case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
sc_addr += LINUX_SC_FR_OFF + 16*(reg - UNW_IA64_FR);
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
sc_addr += LINUX_SC_FR_OFF + 16*(reg - UNW_IA64_FR);
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
case UNW_IA64_BR + 0: sc_addr += LINUX_SC_BR_OFF + 0; break;
case UNW_IA64_BR + 6: sc_addr += LINUX_SC_BR_OFF + 6*8; break;
case UNW_IA64_BR + 7: sc_addr += LINUX_SC_BR_OFF + 7*8; break;
case UNW_IA64_AR_RSC: sc_addr += LINUX_SC_AR_RSC_OFF; break;
case UNW_IA64_AR_CSD: sc_addr += LINUX_SC_AR_CSD_OFF; break;
case UNW_IA64_AR_26: sc_addr += LINUX_SC_AR_26_OFF; break;
case UNW_IA64_AR_CCV: sc_addr += LINUX_SC_AR_CCV; break;
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);
return IA64_LOC_ADDR (sc_addr, IA64_LOC_TYPE_FP);
case UNW_IA64_BR + 0: sc_addr += LINUX_SC_BR_OFF + 0; break;
case UNW_IA64_BR + 6: sc_addr += LINUX_SC_BR_OFF + 6*8; break;
case UNW_IA64_BR + 7: sc_addr += LINUX_SC_BR_OFF + 7*8; break;
case UNW_IA64_AR_RSC: sc_addr += LINUX_SC_AR_RSC_OFF; break;
case UNW_IA64_AR_CSD: sc_addr += LINUX_SC_AR_CSD_OFF; break;
case UNW_IA64_AR_26: sc_addr += LINUX_SC_AR_26_OFF; break;
case UNW_IA64_AR_CCV: sc_addr += LINUX_SC_AR_CCV; break;
}
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;
}
return IA64_LOC_ADDR (sc_addr, 0);
}
else
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;
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))
{
/* 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
{
/* NaT bit is saved in a scratch register. */
#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
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);
mask = (unw_word_t) 1 << reg;
}
else
#endif
{
if (write)
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;
default:
dprintf ("%s: bad register number %d\n", __FUNCTION__, reg);
debug (1, "%s: bad register number %d\n", __FUNCTION__, reg);
return -UNW_EBADREG;
}
@ -436,9 +487,7 @@ HIDDEN int
ia64_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
int write)
{
unw_word_t flags, tmp_addr, sc_addr;
ia64_loc_t loc;
int ret, i;
switch (reg)
{
@ -471,47 +520,12 @@ ia64_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
break;
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;
loc = ia64_scratch_loc (c, reg);
break;
default:
dprintf ("%s: bad register number %d\n", __FUNCTION__, reg);
debug (1, "%s: bad register number %d\n", __FUNCTION__, reg);
return -UNW_EBADREG;
}