summaryrefslogtreecommitdiff
path: root/gdb/sparcnbsd-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2006-01-22 20:07:38 +0000
committerMark Kettenis <kettenis@gnu.org>2006-01-22 20:07:38 +0000
commitd8e05b164cd8e270ae6897e0a4127677c922beec (patch)
tree02bcdfa5ee6e49dcc407ed5b81b1a91fcb026db4 /gdb/sparcnbsd-tdep.c
parent097f6ab4652c0d540eb530874c9060d3d308ee6d (diff)
downloadgdb-d8e05b164cd8e270ae6897e0a4127677c922beec.tar.gz
* sparc-tdep.h (struct gdbarch_tdep): Add step_trap member.
(sparc_address_from_register): New prototype. (sparcnbsd_step_trap): New prototype. * sparc-tdep.c (sparc_address_from_register): Make globally visible. (sparc_analyze_control_transfer): Change prototype to accept `struct gdbarch *' as first argument. Allow for optional hnadling for trap instructions. (sparc_step_trap): New function. (sparc_software_single_step): Adjust call to sparc_analyze_control_trabsfer. (sparc32_gdbarch_init): Initialize TDEP->step_trap. * sparcnbsd-tdep.c (sparcnbsd_step_trap): New function. (sparc32nbsd_init_abi): Set TDEP->step_trap. * sparc64obsd-tdep.c (sparc64obsd_init_abi): Set TDEP->step_trap. * sparc64nbsd-tdep.c (sparc64nbsd_init_abi): Set TDEP->step_trap.
Diffstat (limited to 'gdb/sparcnbsd-tdep.c')
-rw-r--r--gdb/sparcnbsd-tdep.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/gdb/sparcnbsd-tdep.c b/gdb/sparcnbsd-tdep.c
index 6862bdce3c3..73dee1409b9 100644
--- a/gdb/sparcnbsd-tdep.c
+++ b/gdb/sparcnbsd-tdep.c
@@ -1,6 +1,6 @@
/* Target-dependent code for NetBSD/sparc.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
Contributed by Wasabi Systems, Inc.
This file is part of GDB.
@@ -38,6 +38,11 @@
#include "sparc-tdep.h"
#include "nbsd-tdep.h"
+/* Macros to extract fields from SPARC instructions. */
+#define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_RS2(i) ((i) & 0x1f)
+#define X_I(i) (((i) >> 13) & 1)
+
const struct sparc_gregset sparc32nbsd_gregset =
{
0 * 4, /* %psr */
@@ -256,6 +261,30 @@ sparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
return NULL;
}
+/* Return the address of a system call's alternative return
+ address. */
+
+CORE_ADDR
+sparcnbsd_step_trap (unsigned long insn)
+{
+ if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0)
+ || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0))
+ {
+ /* "New" system call. */
+ ULONGEST number;
+
+ regcache_cooked_read_unsigned (current_regcache,
+ SPARC_G1_REGNUM, &number);
+
+ if (number & 0x400)
+ return sparc_address_from_register (SPARC_G2_REGNUM);
+ if (number & 0x800)
+ return sparc_address_from_register (SPARC_G7_REGNUM);
+ }
+
+ return 0;
+}
+
static void
sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -272,6 +301,9 @@ sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->fpregset = regset_alloc (gdbarch, sparc32nbsd_supply_fpregset, NULL);
tdep->sizeof_fpregset = 33 * 4;
+ /* Make sure we can single-step "new" syscalls. */
+ tdep->step_trap = sparcnbsd_step_trap;
+
frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
}