diff options
author | Mark Kettenis <kettenis@gnu.org> | 2006-01-22 20:07:38 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2006-01-22 20:07:38 +0000 |
commit | c893be758be8844753c7e545525d76b7cb789f52 (patch) | |
tree | 1f275536aa849adacab46fd3097beed797ed74d3 /gdb/sparcnbsd-tdep.c | |
parent | 0a8f48b9a8bf7b3e00a676b6068db20dd96f4390 (diff) | |
download | gdb-c893be758be8844753c7e545525d76b7cb789f52.zip gdb-c893be758be8844753c7e545525d76b7cb789f52.tar.gz gdb-c893be758be8844753c7e545525d76b7cb789f52.tar.bz2 |
* 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.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); } |