From b10a6c5b9f8ce66a23c966e1da5ec6aea69397f8 Mon Sep 17 00:00:00 2001 From: "mostang.com!davidm" Date: Tue, 8 Apr 2003 21:14:16 +0000 Subject: [PATCH] (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) --- src/ia64/Ginit-ia64.c | 74 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/src/ia64/Ginit-ia64.c b/src/ia64/Ginit-ia64.c index 796b081e..e9c53353 100644 --- a/src/ia64/Ginit-ia64.c +++ b/src/ia64/Ginit-ia64.c @@ -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 +#define SYSCALL_CFM_SAVE_REG 11 /* on a syscall, ar.pfs is saved in r11 */ +#define REASON_SYSCALL 0 + static int access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, void *arg) { ucontext_t *uc = arg; unsigned int nat, mask; + unw_word_t cfm, sol; uint64_t value; + uint16_t reason; int ret; + __uc_get_reason (uc, &reason); + switch (reg) { 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; case UNW_IA64_AR ... UNW_IA64_AR + 127: - if (write) - ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val); + if (reg == UNW_IA64_AR_BSP) + { + 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 - 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; 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; case UNW_IA64_IP: - if (write) - ret = __uc_set_ip (uc, *val); + if (reason == REASON_SYSCALL) + { + if (write) + ret = __uc_set_brs (uc, 0, 1, val); + else + ret = __uc_get_brs (uc, 0, 1, val); + } else - ret = __uc_get_ip (uc, val); + { + if (write) + ret = __uc_set_ip (uc, *val); + else + ret = __uc_get_ip (uc, val); + } break; case UNW_IA64_CFM: - if (write) - ret = __uc_set_cfm (uc, *val); + if (reason == REASON_SYSCALL) + { + 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 - ret = __uc_get_cfm (uc, val); + { + if (write) + ret = __uc_set_cfm (uc, *val); + else + ret = __uc_get_cfm (uc, val); + } break; 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) 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; }