From c893be758be8844753c7e545525d76b7cb789f52 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sun, 22 Jan 2006 20:07:38 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 17 +++++++++++++++++ gdb/sparc-tdep.c | 24 ++++++++++++++++++------ gdb/sparc-tdep.h | 12 +++++++++++- gdb/sparc64nbsd-tdep.c | 5 ++++- gdb/sparc64obsd-tdep.c | 5 ++++- gdb/sparcnbsd-tdep.c | 34 +++++++++++++++++++++++++++++++++- 6 files changed, 87 insertions(+), 10 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 94ad4e7e65f..830d4a9434b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2006-01-22 Mark Kettenis + * 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. + * sparc-tdep.c (sparc32_return_value): Convert to use RETURN_VALUE_ABI_PRESERVES_ADDRESS instead of RETURN_VALUE_STRUCT_CONVENTION. diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index ab9f1044c10..dc6c5347a55 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -170,7 +170,7 @@ sparc_fetch_wcookie (void) /* Return the contents if register REGNUM as an address. */ -static CORE_ADDR +CORE_ADDR sparc_address_from_register (int regnum) { ULONGEST addr; @@ -1000,7 +1000,8 @@ sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type) software single-step mechanism. */ static CORE_ADDR -sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc) +sparc_analyze_control_transfer (struct gdbarch *arch, + CORE_ADDR pc, CORE_ADDR *npc) { unsigned long insn = sparc_fetch_instruction (pc); int conditional_p = X_COND (insn) & 0x7; @@ -1038,11 +1039,14 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc) branch_p = 1; offset = 4 * X_DISP19 (insn); } + else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a) + { + /* Trap instruction (TRAP). */ + return gdbarch_tdep (arch)->step_trap (insn); + } /* FIXME: Handle DONE and RETRY instructions. */ - /* FIXME: Handle the Trap instruction. */ - if (branch_p) { if (conditional_p) @@ -1070,10 +1074,17 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc) return 0; } +static CORE_ADDR +sparc_step_trap (unsigned long insn) +{ + return 0; +} + void sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch *arch = current_gdbarch; + struct gdbarch_tdep *tdep = gdbarch_tdep (arch); static CORE_ADDR npc, nnpc; static gdb_byte npc_save[4], nnpc_save[4]; @@ -1085,7 +1096,7 @@ sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p) orig_npc = npc = sparc_address_from_register (tdep->npc_regnum); /* Analyze the instruction at PC. */ - nnpc = sparc_analyze_control_transfer (pc, &npc); + nnpc = sparc_analyze_control_transfer (arch, pc, &npc); if (npc != 0) target_insert_breakpoint (npc, npc_save); if (nnpc != 0) @@ -1188,6 +1199,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->fpregset = NULL; tdep->sizeof_fpregset = 0; tdep->plt_entry_size = 0; + tdep->step_trap = sparc_step_trap; set_gdbarch_long_double_bit (gdbarch, 128); set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad); diff --git a/gdb/sparc-tdep.h b/gdb/sparc-tdep.h index 502b5244bdb..06555e9b89b 100644 --- a/gdb/sparc-tdep.h +++ b/gdb/sparc-tdep.h @@ -1,6 +1,6 @@ /* Target-dependent code for SPARC. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of GDB. @@ -65,6 +65,9 @@ struct gdbarch_tdep /* Size of an Procedure Linkage Table (PLT) entry, 0 if we shouldn't treat the PLT special when doing prologue analysis. */ size_t plt_entry_size; + + /* Alternative location for trap return. Used for single-stepping. */ + CORE_ADDR (*step_trap) (unsigned long insn); }; /* Register numbers of various important registers. */ @@ -147,6 +150,9 @@ struct sparc_frame_cache /* Fetch the instruction at PC. */ extern unsigned long sparc_fetch_instruction (CORE_ADDR pc); +/* Return the contents if register REGNUM as an address. */ +extern CORE_ADDR sparc_address_from_register (int regnum); + /* Fetch StackGhost Per-Process XOR cookie. */ extern ULONGEST sparc_fetch_wcookie (void); @@ -198,6 +204,10 @@ extern void sparc32_sol2_init_abi (struct gdbarch_info info, /* Register offsets for NetBSD. */ extern const struct sparc_gregset sparc32nbsd_gregset; +/* Return the address of a system call's alternative return + address. */ +extern CORE_ADDR sparcnbsd_step_trap (unsigned long insn); + extern void sparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); diff --git a/gdb/sparc64nbsd-tdep.c b/gdb/sparc64nbsd-tdep.c index 22bafcbfa9b..5c7ef168449 100644 --- a/gdb/sparc64nbsd-tdep.c +++ b/gdb/sparc64nbsd-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for NetBSD/sparc64. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Based on code contributed by Wasabi Systems, Inc. This file is part of GDB. @@ -249,6 +249,9 @@ sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->fpregset = regset_alloc (gdbarch, sparc64nbsd_supply_fpregset, NULL); tdep->sizeof_fpregset = 272; + /* Make sure we can single-step "new" syscalls. */ + tdep->step_trap = sparcnbsd_step_trap; + frame_unwind_append_sniffer (gdbarch, sparc64nbsd_sigtramp_frame_sniffer); sparc64_init_abi (info, gdbarch); diff --git a/gdb/sparc64obsd-tdep.c b/gdb/sparc64obsd-tdep.c index bc21df282cf..d2e10fdf067 100644 --- a/gdb/sparc64obsd-tdep.c +++ b/gdb/sparc64obsd-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for OpenBSD/sparc64. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GDB. @@ -295,6 +295,9 @@ sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL); tdep->sizeof_gregset = 832; + /* Make sure we can single-step "new" syscalls. */ + tdep->step_trap = sparcnbsd_step_trap; + frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer); sparc64_init_abi (info, gdbarch); 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); } -- 2.30.2