diff options
Diffstat (limited to 'gdb/sparcnbsd-tdep.c')
-rw-r--r-- | gdb/sparcnbsd-tdep.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/gdb/sparcnbsd-tdep.c b/gdb/sparcnbsd-tdep.c index 6862bdc..73dee14 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); } |