mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-10-01 10:59:31 +02:00
(SYSCALL_CFM_SAVE_REG): New macro.
(REASON_SYSCALL): Ditto. (access_reg): Use __uc_get_reason() to determine how ucontext_t was created. Handle UNW_IA64_AR_BSP differently depending on whether or not ucontext_t was created by a syscall. Ditto for UNW_IA64_IP and UNW_IA64_CFM. Add debug statement. (Logical change 1.77)
This commit is contained in:
parent
0802cd49ad
commit
b10a6c5b9f
1 changed files with 65 additions and 9 deletions
|
@ -136,15 +136,22 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||||
|
|
||||||
#ifdef HAVE_SYS_UC_ACCESS_H
|
#ifdef HAVE_SYS_UC_ACCESS_H
|
||||||
|
|
||||||
|
#define SYSCALL_CFM_SAVE_REG 11 /* on a syscall, ar.pfs is saved in r11 */
|
||||||
|
#define REASON_SYSCALL 0
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
ucontext_t *uc = arg;
|
ucontext_t *uc = arg;
|
||||||
unsigned int nat, mask;
|
unsigned int nat, mask;
|
||||||
|
unw_word_t cfm, sol;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
uint16_t reason;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
__uc_get_reason (uc, &reason);
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case UNW_IA64_GR ... UNW_IA64_GR + 31:
|
case UNW_IA64_GR ... UNW_IA64_GR + 31:
|
||||||
|
@ -176,10 +183,32 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_AR ... UNW_IA64_AR + 127:
|
case UNW_IA64_AR ... UNW_IA64_AR + 127:
|
||||||
if (write)
|
if (reg == UNW_IA64_AR_BSP)
|
||||||
ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val);
|
{
|
||||||
|
if (reason == REASON_SYSCALL)
|
||||||
|
ret = __uc_get_grs (uc, SYSCALL_CFM_SAVE_REG, 1, &cfm, &nat);
|
||||||
|
else
|
||||||
|
ret = __uc_get_cfm (uc, &cfm);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
sol = (cfm >> 7) & 0x7f;
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
ret = __uc_set_ar (uc, (reg - UNW_IA64_AR),
|
||||||
|
ia64_rse_skip_regs (*val, sol));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val);
|
||||||
|
*val = ia64_rse_skip_regs (*val, -sol);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val);
|
{
|
||||||
|
if (write)
|
||||||
|
ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val);
|
||||||
|
else
|
||||||
|
ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_BR ... UNW_IA64_BR + 7:
|
case UNW_IA64_BR ... UNW_IA64_BR + 7:
|
||||||
|
@ -197,17 +226,40 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_IP:
|
case UNW_IA64_IP:
|
||||||
if (write)
|
if (reason == REASON_SYSCALL)
|
||||||
ret = __uc_set_ip (uc, *val);
|
{
|
||||||
|
if (write)
|
||||||
|
ret = __uc_set_brs (uc, 0, 1, val);
|
||||||
|
else
|
||||||
|
ret = __uc_get_brs (uc, 0, 1, val);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret = __uc_get_ip (uc, val);
|
{
|
||||||
|
if (write)
|
||||||
|
ret = __uc_set_ip (uc, *val);
|
||||||
|
else
|
||||||
|
ret = __uc_get_ip (uc, val);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_CFM:
|
case UNW_IA64_CFM:
|
||||||
if (write)
|
if (reason == REASON_SYSCALL)
|
||||||
ret = __uc_set_cfm (uc, *val);
|
{
|
||||||
|
ret = __uc_get_grs (uc, SYSCALL_CFM_SAVE_REG, 1, &cfm, &nat);
|
||||||
|
if (write)
|
||||||
|
{
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
ret = __uc_set_grs (uc, SYSCALL_CFM_SAVE_REG, 1, &cfm, nat);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret = __uc_get_cfm (uc, val);
|
{
|
||||||
|
if (write)
|
||||||
|
ret = __uc_set_cfm (uc, *val);
|
||||||
|
else
|
||||||
|
ret = __uc_get_cfm (uc, val);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_IA64_FR ... UNW_IA64_FR + 127:
|
case UNW_IA64_FR ... UNW_IA64_FR + 127:
|
||||||
|
@ -219,6 +271,10 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return -UNW_EBADREG;
|
return -UNW_EBADREG;
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
debug (100, "%s: %s <- %lx\n", __FUNCTION__, unw_regname (reg), *val);
|
||||||
|
else
|
||||||
|
debug (100, "%s: %s -> %lx\n", __FUNCTION__, unw_regname (reg), *val);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue