aboutsummaryrefslogtreecommitdiff
path: root/gdb/ia64-tdep.c
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2011-01-13 16:24:27 +0000
committerJoel Brobecker <brobecker@gnat.com>2011-01-13 16:24:27 +0000
commit77ca787b12516ebb1b0d23710021b26b9c81b018 (patch)
treec566d4c91a59e95671e251887b36d704ec6e8d1a /gdb/ia64-tdep.c
parent92c9a4639bb3294d74a36b6d0c0cb07771bbe906 (diff)
downloadgdb-77ca787b12516ebb1b0d23710021b26b9c81b018.zip
gdb-77ca787b12516ebb1b0d23710021b26b9c81b018.tar.gz
gdb-77ca787b12516ebb1b0d23710021b26b9c81b018.tar.bz2
[ia64-hpux] unwinding bsp value from system call
This fixes unwinding from a thread that is stopped inside a system call. This can be seen when switching to a thread that is stopped doing a pthread_cond_wait, for instance... The comments inside the code should explain what is happening in our case (the HP-UX exception in the case of system calls): Under certain circumstances (program stopped inside syscall), the offset to apply to the current BSP in order to compute the previous BSP is not the usual CFM & 0x7f. We parts in this patch: 1. Figuring out that we are stopped inside a syscal: This requires a TT_LWP_RUREGS ttrace call, which is not directly possible from ia64-tdep.c. So use defined a new TARGET_OBJECT_HPUX_UREGS object to request it from the -nat side. 2. Add a gdbarch_tdep method that allows us to change the default behavior on ia64-hpux, permitting us to have a different "size of register frame" in that one particular case. gdb/ChangeLog: * target.h (enum target_object): Add TARGET_OBJECT_HPUX_UREGS. * ia64-tdep.h (struct frame_info): forward declaration. (struct gdbarch_tdep): Add field size_of_register_frame. * ia64-tdep.c (ia64_access_reg): Use tdep->size_of_register_frame to determine the size of the register frame. (ia64_size_of_register_frame): New function. (ia64_gdbarch_init): Set tdep->size_of_register_frame. * ia64-hpux-tdep.c: Include "target.h" and "frame.h". (IA64_HPUX_UREG_REASON): New macro. (ia64_hpux_stopped_in_syscall, ia64_hpux_size_of_register_frame): New functions. (ia64_hpux_init_abi): Set tdep->size_of_register_frame. * ia64-hpux-nat.c (ia64_hpux_xfer_uregs): New function. (ia64_hpux_xfer_partial): Add handling of TARGET_OBJECT_HPUX_UREGS objects.
Diffstat (limited to 'gdb/ia64-tdep.c')
-rw-r--r--gdb/ia64-tdep.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 05ca3a1..2529897 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2452,7 +2452,7 @@ ia64_is_fpreg (int uw_regnum)
{
return unw_is_fpreg (uw_regnum);
}
-
+
/* Libunwind callback accessor function for general registers. */
static int
ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,
@@ -2490,7 +2490,7 @@ ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,
bsp = extract_unsigned_integer (buf, 8, byte_order);
get_frame_register (this_frame, IA64_CFM_REGNUM, buf);
cfm = extract_unsigned_integer (buf, 8, byte_order);
- sof = (cfm & 0x7f);
+ sof = gdbarch_tdep (gdbarch)->size_of_register_frame (this_frame, cfm);
*val = ia64_rse_skip_regs (bsp, -sof);
break;
@@ -3848,6 +3848,14 @@ ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info)
return print_insn_ia64 (memaddr, info);
}
+/* The default "size_of_register_frame" gdbarch_tdep routine for ia64. */
+
+static int
+ia64_size_of_register_frame (struct frame_info *this_frame, ULONGEST cfm)
+{
+ return (cfm & 0x7f);
+}
+
static struct gdbarch *
ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
@@ -3862,6 +3870,8 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = xzalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
+ tdep->size_of_register_frame = ia64_size_of_register_frame;
+
/* According to the ia64 specs, instructions that store long double
floats in memory use a long-double format different than that
used in the floating registers. The memory format matches the