* 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.
This commit is contained in:
Mark Kettenis 2006-01-22 20:07:38 +00:00
parent 0a8f48b9a8
commit c893be758b
6 changed files with 87 additions and 10 deletions

View file

@ -1,5 +1,22 @@
2006-01-22 Mark Kettenis <kettenis@gnu.org> 2006-01-22 Mark Kettenis <kettenis@gnu.org>
* 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 * sparc-tdep.c (sparc32_return_value): Convert to use
RETURN_VALUE_ABI_PRESERVES_ADDRESS instead of RETURN_VALUE_ABI_PRESERVES_ADDRESS instead of
RETURN_VALUE_STRUCT_CONVENTION. RETURN_VALUE_STRUCT_CONVENTION.

View file

@ -170,7 +170,7 @@ sparc_fetch_wcookie (void)
/* Return the contents if register REGNUM as an address. */ /* Return the contents if register REGNUM as an address. */
static CORE_ADDR CORE_ADDR
sparc_address_from_register (int regnum) sparc_address_from_register (int regnum)
{ {
ULONGEST addr; ULONGEST addr;
@ -1000,7 +1000,8 @@ sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
software single-step mechanism. */ software single-step mechanism. */
static CORE_ADDR 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); unsigned long insn = sparc_fetch_instruction (pc);
int conditional_p = X_COND (insn) & 0x7; int conditional_p = X_COND (insn) & 0x7;
@ -1038,11 +1039,14 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
branch_p = 1; branch_p = 1;
offset = 4 * X_DISP19 (insn); 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 DONE and RETRY instructions. */
/* FIXME: Handle the Trap instruction. */
if (branch_p) if (branch_p)
{ {
if (conditional_p) if (conditional_p)
@ -1070,10 +1074,17 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
return 0; return 0;
} }
static CORE_ADDR
sparc_step_trap (unsigned long insn)
{
return 0;
}
void void
sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p) 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 CORE_ADDR npc, nnpc;
static gdb_byte npc_save[4], nnpc_save[4]; 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); orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
/* Analyze the instruction at PC. */ /* Analyze the instruction at PC. */
nnpc = sparc_analyze_control_transfer (pc, &npc); nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
if (npc != 0) if (npc != 0)
target_insert_breakpoint (npc, npc_save); target_insert_breakpoint (npc, npc_save);
if (nnpc != 0) if (nnpc != 0)
@ -1188,6 +1199,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->fpregset = NULL; tdep->fpregset = NULL;
tdep->sizeof_fpregset = 0; tdep->sizeof_fpregset = 0;
tdep->plt_entry_size = 0; tdep->plt_entry_size = 0;
tdep->step_trap = sparc_step_trap;
set_gdbarch_long_double_bit (gdbarch, 128); set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad); set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad);

View file

@ -1,6 +1,6 @@
/* Target-dependent code for SPARC. /* 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. 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 /* Size of an Procedure Linkage Table (PLT) entry, 0 if we shouldn't
treat the PLT special when doing prologue analysis. */ treat the PLT special when doing prologue analysis. */
size_t plt_entry_size; 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. */ /* Register numbers of various important registers. */
@ -147,6 +150,9 @@ struct sparc_frame_cache
/* Fetch the instruction at PC. */ /* Fetch the instruction at PC. */
extern unsigned long sparc_fetch_instruction (CORE_ADDR 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. */ /* Fetch StackGhost Per-Process XOR cookie. */
extern ULONGEST sparc_fetch_wcookie (void); extern ULONGEST sparc_fetch_wcookie (void);
@ -198,6 +204,10 @@ extern void sparc32_sol2_init_abi (struct gdbarch_info info,
/* Register offsets for NetBSD. */ /* Register offsets for NetBSD. */
extern const struct sparc_gregset sparc32nbsd_gregset; 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, extern void sparc32nbsd_elf_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch); struct gdbarch *gdbarch);

View file

@ -1,6 +1,6 @@
/* Target-dependent code for NetBSD/sparc64. /* 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. Based on code contributed by Wasabi Systems, Inc.
This file is part of GDB. 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->fpregset = regset_alloc (gdbarch, sparc64nbsd_supply_fpregset, NULL);
tdep->sizeof_fpregset = 272; 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); frame_unwind_append_sniffer (gdbarch, sparc64nbsd_sigtramp_frame_sniffer);
sparc64_init_abi (info, gdbarch); sparc64_init_abi (info, gdbarch);

View file

@ -1,6 +1,6 @@
/* Target-dependent code for OpenBSD/sparc64. /* 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. 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->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL);
tdep->sizeof_gregset = 832; 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); frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
sparc64_init_abi (info, gdbarch); sparc64_init_abi (info, gdbarch);

View file

@ -1,6 +1,6 @@
/* Target-dependent code for NetBSD/sparc. /* 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. Contributed by Wasabi Systems, Inc.
This file is part of GDB. This file is part of GDB.
@ -38,6 +38,11 @@
#include "sparc-tdep.h" #include "sparc-tdep.h"
#include "nbsd-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 = const struct sparc_gregset sparc32nbsd_gregset =
{ {
0 * 4, /* %psr */ 0 * 4, /* %psr */
@ -256,6 +261,30 @@ sparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
return NULL; 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 static void
sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 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->fpregset = regset_alloc (gdbarch, sparc32nbsd_supply_fpregset, NULL);
tdep->sizeof_fpregset = 33 * 4; 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); frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
} }