From 45ecac4b41626c5f43dd90d0174f56c3d1350cc9 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Sat, 12 May 2007 00:07:45 +0000 Subject: [PATCH] * libunwind-frame.h (struct regcache): Add forward declaration. (libunwind_get_reg_special): Add REGCACHE argument. * libunwind-frame.c (libunwind_get_reg_special): Add REGCACHE argument. Pass it to unw_init_remote_p. * ia64-tdep.c (ia64_pseudo_register_read): Pass regcache to libunwind_get_reg_special. (ia64_access_reg): Remove "write" case. (ia64_access_fpreg): Likewise. Read from next_frame passed as callback argument instead of from current_regcache. (ia64_access_rse_reg): Remove "write" case. Read from regcache passed as callback argument instead of from current_regcache. (ia64_access_rse_fpreg): New function. (ia64_unw_rse_acce): Use it instead of ia64_access_fpreg. --- gdb/ChangeLog | 17 +++ gdb/ia64-tdep.c | 292 +++++++++++++++--------------------------- gdb/libunwind-frame.c | 5 +- gdb/libunwind-frame.h | 5 +- 4 files changed, 130 insertions(+), 189 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d161566227a..ba1b51d7cf6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2007-05-11 Ulrich Weigand + + * libunwind-frame.h (struct regcache): Add forward declaration. + (libunwind_get_reg_special): Add REGCACHE argument. + * libunwind-frame.c (libunwind_get_reg_special): Add REGCACHE + argument. Pass it to unw_init_remote_p. + + * ia64-tdep.c (ia64_pseudo_register_read): Pass regcache to + libunwind_get_reg_special. + (ia64_access_reg): Remove "write" case. + (ia64_access_fpreg): Likewise. Read from next_frame passed + as callback argument instead of from current_regcache. + (ia64_access_rse_reg): Remove "write" case. Read from regcache + passed as callback argument instead of from current_regcache. + (ia64_access_rse_fpreg): New function. + (ia64_unw_rse_acce): Use it instead of ia64_access_fpreg. + 2007-05-11 Ulrich Weigand * NEWS: Mention SPU overlay support. diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index a8af64b1aed..526926ce232 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -692,7 +692,7 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, /* First try and use the libunwind special reg accessor, otherwise fallback to standard logic. */ if (!libunwind_is_initialized () - || libunwind_get_reg_special (gdbarch, regnum, buf) != 0) + || libunwind_get_reg_special (gdbarch, regcache, regnum, buf) != 0) #endif { /* The fallback position is to assume that r32-r127 are found sequentially @@ -2218,106 +2218,53 @@ ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val, long new_sof, old_sof; char buf[MAX_REGISTER_SIZE]; - if (write) - { - if (regnum < 0) - /* ignore writes to pseudo-registers such as UNW_IA64_PROC_STARTI. */ - return 0; - - switch (uw_regnum) - { - case UNW_REG_IP: - ia64_write_pc (*val, inferior_ptid); - break; + /* We never call any libunwind routines that need to write registers. */ + gdb_assert (!write); + + switch (uw_regnum) + { + case UNW_REG_IP: + /* Libunwind expects to see the pc value which means the slot number + from the psr must be merged with the ip word address. */ + frame_unwind_register (next_frame, IA64_IP_REGNUM, buf); + ip = extract_unsigned_integer (buf, 8); + frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf); + psr = extract_unsigned_integer (buf, 8); + *val = ip | ((psr >> 41) & 0x3); + break; + + case UNW_IA64_AR_BSP: + /* Libunwind expects to see the beginning of the current register + frame so we must account for the fact that ptrace() will return a value + for bsp that points *after* the current register frame. */ + frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf); + bsp = extract_unsigned_integer (buf, 8); + frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf); + cfm = extract_unsigned_integer (buf, 8); + sof = (cfm & 0x7f); + *val = ia64_rse_skip_regs (bsp, -sof); + break; - case UNW_IA64_AR_BSPSTORE: - write_register (IA64_BSP_REGNUM, *val); - break; - - case UNW_IA64_AR_BSP: - case UNW_IA64_BSP: - /* Account for the fact that ptrace() expects bsp to point - after the current register frame. */ - cfm = read_register (IA64_CFM_REGNUM); - sof = (cfm & 0x7f); - bsp = ia64_rse_skip_regs (*val, sof); - write_register (IA64_BSP_REGNUM, bsp); - break; - - case UNW_IA64_CFM: - /* If we change CFM, we need to adjust ptrace's notion of - bsp accordingly, so that the real bsp remains - unchanged. */ - bsp = read_register (IA64_BSP_REGNUM); - cfm = read_register (IA64_CFM_REGNUM); - old_sof = (cfm & 0x7f); - new_sof = (*val & 0x7f); - if (old_sof != new_sof) - { - bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof); - write_register (IA64_BSP_REGNUM, bsp); - } - write_register (IA64_CFM_REGNUM, *val); - break; - - default: - write_register (regnum, *val); - break; - } - if (gdbarch_debug >= 1) - fprintf_unfiltered (gdb_stdlog, - " access_reg: to cache: %4s=0x%s\n", - (((unsigned) regnum <= IA64_NAT127_REGNUM) - ? ia64_register_names[regnum] : "r??"), - paddr_nz (*val)); - } - else - { - switch (uw_regnum) - { - case UNW_REG_IP: - /* Libunwind expects to see the pc value which means the slot number - from the psr must be merged with the ip word address. */ - frame_unwind_register (next_frame, IA64_IP_REGNUM, buf); - ip = extract_unsigned_integer (buf, 8); - frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf); - psr = extract_unsigned_integer (buf, 8); - *val = ip | ((psr >> 41) & 0x3); - break; - - case UNW_IA64_AR_BSP: - /* Libunwind expects to see the beginning of the current register - frame so we must account for the fact that ptrace() will return a value - for bsp that points *after* the current register frame. */ - frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf); - bsp = extract_unsigned_integer (buf, 8); - frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf); - cfm = extract_unsigned_integer (buf, 8); - sof = (cfm & 0x7f); - *val = ia64_rse_skip_regs (bsp, -sof); - break; - - case UNW_IA64_AR_BSPSTORE: - /* Libunwind wants bspstore to be after the current register frame. - This is what ptrace() and gdb treats as the regular bsp value. */ - frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf); - *val = extract_unsigned_integer (buf, 8); - break; + case UNW_IA64_AR_BSPSTORE: + /* Libunwind wants bspstore to be after the current register frame. + This is what ptrace() and gdb treats as the regular bsp value. */ + frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf); + *val = extract_unsigned_integer (buf, 8); + break; - default: - /* For all other registers, just unwind the value directly. */ - frame_unwind_register (next_frame, regnum, buf); - *val = extract_unsigned_integer (buf, 8); - break; - } - - if (gdbarch_debug >= 1) - fprintf_unfiltered (gdb_stdlog, - " access_reg: from cache: %4s=0x%s\n", - (((unsigned) regnum <= IA64_NAT127_REGNUM) - ? ia64_register_names[regnum] : "r??"), - paddr_nz (*val)); + default: + /* For all other registers, just unwind the value directly. */ + frame_unwind_register (next_frame, regnum, buf); + *val = extract_unsigned_integer (buf, 8); + break; } + + if (gdbarch_debug >= 1) + fprintf_unfiltered (gdb_stdlog, + " access_reg: from cache: %4s=0x%s\n", + (((unsigned) regnum <= IA64_NAT127_REGNUM) + ? ia64_register_names[regnum] : "r??"), + paddr_nz (*val)); return 0; } @@ -2327,11 +2274,13 @@ ia64_access_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_fpreg_t *val int write, void *arg) { int regnum = ia64_uw2gdb_regnum (uw_regnum); + struct frame_info *next_frame = arg; - if (write) - regcache_cooked_write (current_regcache, regnum, (char *) val); - else - regcache_cooked_read (current_regcache, regnum, (char *) val); + /* We never call any libunwind routines that need to write registers. */ + gdb_assert (!write); + + frame_unwind_register (next_frame, regnum, (char *) val); + return 0; } @@ -2342,94 +2291,49 @@ ia64_access_rse_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *va { int regnum = ia64_uw2gdb_regnum (uw_regnum); unw_word_t bsp, sof, sol, cfm, psr, ip; + struct regcache *regcache = arg; long new_sof, old_sof; + char buf[MAX_REGISTER_SIZE]; - if (write) - { - if (regnum < 0) - /* ignore writes to pseudo-registers such as UNW_IA64_PROC_STARTI. */ - return 0; - - switch (uw_regnum) - { - case UNW_REG_IP: - ia64_write_pc (*val, inferior_ptid); - break; - - case UNW_IA64_AR_BSPSTORE: - write_register (IA64_BSP_REGNUM, *val); - break; - - case UNW_IA64_AR_BSP: - case UNW_IA64_BSP: - /* Account for the fact that ptrace() expects bsp to point - after the current register frame. */ - cfm = read_register (IA64_CFM_REGNUM); - sof = (cfm & 0x7f); - bsp = ia64_rse_skip_regs (*val, sof); - write_register (IA64_BSP_REGNUM, bsp); - break; - - case UNW_IA64_CFM: - /* If we change CFM, we need to adjust ptrace's notion of - bsp accordingly, so that the real bsp remains - unchanged. */ - bsp = read_register (IA64_BSP_REGNUM); - cfm = read_register (IA64_CFM_REGNUM); - old_sof = (cfm & 0x7f); - new_sof = (*val & 0x7f); - if (old_sof != new_sof) - { - bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof); - write_register (IA64_BSP_REGNUM, bsp); - } - write_register (IA64_CFM_REGNUM, *val); - break; - - default: - write_register (regnum, *val); - break; - } - if (gdbarch_debug >= 1) - fprintf_unfiltered (gdb_stdlog, - " access_rse_reg: to cache: %4s=0x%s\n", - (((unsigned) regnum <= IA64_NAT127_REGNUM) - ? ia64_register_names[regnum] : "r??"), - paddr_nz (*val)); - } - else - { - switch (uw_regnum) - { - case UNW_REG_IP: - /* Libunwind expects to see the pc value which means the slot number - from the psr must be merged with the ip word address. */ - ip = read_register (IA64_IP_REGNUM); - psr = read_register (IA64_PSR_REGNUM); - *val = ip | ((psr >> 41) & 0x3); - break; + /* We never call any libunwind routines that need to write registers. */ + gdb_assert (!write); + + switch (uw_regnum) + { + case UNW_REG_IP: + /* Libunwind expects to see the pc value which means the slot number + from the psr must be merged with the ip word address. */ + regcache_cooked_read (regcache, IA64_IP_REGNUM, buf); + ip = extract_unsigned_integer (buf, 8); + regcache_cooked_read (regcache, IA64_PSR_REGNUM, buf); + psr = extract_unsigned_integer (buf, 8); + *val = ip | ((psr >> 41) & 0x3); + break; - case UNW_IA64_AR_BSP: - /* Libunwind expects to see the beginning of the current register - frame so we must account for the fact that ptrace() will return a value - for bsp that points *after* the current register frame. */ - bsp = read_register (IA64_BSP_REGNUM); - cfm = read_register (IA64_CFM_REGNUM); - sof = (cfm & 0x7f); - *val = ia64_rse_skip_regs (bsp, -sof); - break; + case UNW_IA64_AR_BSP: + /* Libunwind expects to see the beginning of the current register + frame so we must account for the fact that ptrace() will return a value + for bsp that points *after* the current register frame. */ + regcache_cooked_read (regcache, IA64_BSP_REGNUM, buf); + bsp = extract_unsigned_integer (buf, 8); + regcache_cooked_read (regcache, IA64_CFM_REGNUM, buf); + cfm = extract_unsigned_integer (buf, 8); + sof = (cfm & 0x7f); + *val = ia64_rse_skip_regs (bsp, -sof); + break; - case UNW_IA64_AR_BSPSTORE: - /* Libunwind wants bspstore to be after the current register frame. - This is what ptrace() and gdb treats as the regular bsp value. */ - *val = read_register (IA64_BSP_REGNUM); - break; + case UNW_IA64_AR_BSPSTORE: + /* Libunwind wants bspstore to be after the current register frame. + This is what ptrace() and gdb treats as the regular bsp value. */ + regcache_cooked_read (regcache, IA64_BSP_REGNUM, buf); + *val = extract_unsigned_integer (buf, 8); + break; - default: - /* For all other registers, just read the value directly. */ - *val = read_register (regnum); - break; - } + default: + /* For all other registers, just unwind the value directly. */ + regcache_cooked_read (regcache, regnum, buf); + *val = extract_unsigned_integer (buf, 8); + break; } if (gdbarch_debug >= 1) @@ -2442,6 +2346,22 @@ ia64_access_rse_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *va return 0; } +/* Libunwind callback accessor function for top-level fp registers. */ +static int +ia64_access_rse_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, + unw_fpreg_t *val, int write, void *arg) +{ + int regnum = ia64_uw2gdb_regnum (uw_regnum); + struct regcache *regcache = arg; + + /* We never call any libunwind routines that need to write registers. */ + gdb_assert (!write); + + regcache_cooked_read (regcache, regnum, (char *) val); + + return 0; +} + /* Libunwind callback accessor function for accessing memory. */ static int ia64_access_mem (unw_addr_space_t as, @@ -2976,7 +2896,7 @@ static unw_accessors_t ia64_unw_rse_accessors = ia64_get_dyn_info_list, ia64_access_mem, ia64_access_rse_reg, - ia64_access_fpreg, + ia64_access_rse_fpreg, /* resume */ /* get_proc_name */ }; diff --git a/gdb/libunwind-frame.c b/gdb/libunwind-frame.c index 66ffb8ea29d..0b928535fcc 100644 --- a/gdb/libunwind-frame.c +++ b/gdb/libunwind-frame.c @@ -395,7 +395,8 @@ libunwind_sigtramp_frame_sniffer (struct frame_info *next_frame) are usually located at BOF, this is not always true and only the libunwind info can decipher where they actually are. */ int -libunwind_get_reg_special (struct gdbarch *gdbarch, int regnum, void *buf) +libunwind_get_reg_special (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, void *buf) { unw_cursor_t cursor; unw_accessors_t *acc; @@ -415,7 +416,7 @@ libunwind_get_reg_special (struct gdbarch *gdbarch, int regnum, void *buf) ? __BIG_ENDIAN : __LITTLE_ENDIAN); - ret = unw_init_remote_p (&cursor, as, NULL); + ret = unw_init_remote_p (&cursor, as, regcache); if (ret < 0) return -1; diff --git a/gdb/libunwind-frame.h b/gdb/libunwind-frame.h index f32e4c4b65e..499055ac98d 100644 --- a/gdb/libunwind-frame.h +++ b/gdb/libunwind-frame.h @@ -25,6 +25,7 @@ struct frame_info; struct frame_id; +struct regcache; struct gdbarch; #ifndef LIBUNWIND_FRAME_H @@ -62,7 +63,9 @@ int libunwind_search_unwind_table (void *as, long ip, void *di, unw_word_t libunwind_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *, void *); -int libunwind_get_reg_special (struct gdbarch *gdbarch, int regnum, void *buf); +int libunwind_get_reg_special (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum, void *buf); #endif /* libunwind-frame.h */ -- 2.30.2