From 99e40580307d91e399af1c0293a6676b10efefea Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Tue, 29 Sep 2009 00:53:04 +0000 Subject: [PATCH] * gdbarch.sh (displaced_step_hw_singlestep): New callback. * gdbarch.c, gdbarch.h: Regenerate. * arch-utils.c (default_displaced_step_hw_singlestep): New function. * arch-utils.h (default_displaced_step_hw_singlestep): Add prototype. * ppc-linux-tdep.c (ppc_displaced_step_hw_singlestep): New function. (rs6000_gdbarch_init): Install it. * infrun.c (displaced_step_fixup): Use new callback to determine whether to "step" or "continue" displaced copy. (resume): Likewise. Do not call maybe_software_singlestep for displaced stepping. (maybe_software_singlestep): Do not handle displaced stepping. --- gdb/ChangeLog | 16 ++++++++++++++++ gdb/arch-utils.c | 6 ++++++ gdb/arch-utils.h | 5 +++++ gdb/gdbarch.c | 24 ++++++++++++++++++++++++ gdb/gdbarch.h | 14 ++++++++++++++ gdb/gdbarch.sh | 11 +++++++++++ gdb/infrun.c | 32 ++++++++++++++++---------------- gdb/rs6000-tdep.c | 11 +++++++++++ 8 files changed, 103 insertions(+), 16 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2447062..e365828 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,21 @@ 2009-09-28 Ulrich Weigand + * gdbarch.sh (displaced_step_hw_singlestep): New callback. + * gdbarch.c, gdbarch.h: Regenerate. + * arch-utils.c (default_displaced_step_hw_singlestep): New function. + * arch-utils.h (default_displaced_step_hw_singlestep): Add prototype. + + * ppc-linux-tdep.c (ppc_displaced_step_hw_singlestep): New function. + (rs6000_gdbarch_init): Install it. + + * infrun.c (displaced_step_fixup): Use new callback to determine + whether to "step" or "continue" displaced copy. + (resume): Likewise. Do not call maybe_software_singlestep + for displaced stepping. + (maybe_software_singlestep): Do not handle displaced stepping. + +2009-09-28 Ulrich Weigand + * eval.c (evaluate_subexp_standard) [OP_OBJC_MSGCALL]: Support platforms that use function descriptors. Prefer to use function pointer types instead of function types. diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 5cf4afd..b58c562 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -67,6 +67,12 @@ simple_displaced_step_free_closure (struct gdbarch *gdbarch, xfree (closure); } +int +default_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + struct displaced_step_closure *closure) +{ + return !gdbarch_software_single_step_p (gdbarch); +} CORE_ADDR displaced_step_at_entry_point (struct gdbarch *gdbarch) diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 9d95d3f..dddae55 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -49,6 +49,11 @@ extern void simple_displaced_step_free_closure (struct gdbarch *gdbarch, struct displaced_step_closure *closure); +/* Default implementation of gdbarch_displaced_hw_singlestep. */ +extern int + default_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + struct displaced_step_closure *closure); + /* Possible value for gdbarch_displaced_step_location: Place displaced instructions at the program's entry point, leaving space for inferior function call return breakpoints. */ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 2ae3835..6c13dc8 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -232,6 +232,7 @@ struct gdbarch gdbarch_skip_permanent_breakpoint_ftype *skip_permanent_breakpoint; ULONGEST max_insn_length; gdbarch_displaced_step_copy_insn_ftype *displaced_step_copy_insn; + gdbarch_displaced_step_hw_singlestep_ftype *displaced_step_hw_singlestep; gdbarch_displaced_step_fixup_ftype *displaced_step_fixup; gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure; gdbarch_displaced_step_location_ftype *displaced_step_location; @@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch = 0, /* skip_permanent_breakpoint */ 0, /* max_insn_length */ 0, /* displaced_step_copy_insn */ + default_displaced_step_hw_singlestep, /* displaced_step_hw_singlestep */ 0, /* displaced_step_fixup */ NULL, /* displaced_step_free_closure */ NULL, /* displaced_step_location */ @@ -464,6 +466,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->elf_make_msymbol_special = default_elf_make_msymbol_special; gdbarch->coff_make_msymbol_special = default_coff_make_msymbol_special; gdbarch->register_reggroup_p = default_register_reggroup_p; + gdbarch->displaced_step_hw_singlestep = default_displaced_step_hw_singlestep; gdbarch->displaced_step_fixup = NULL; gdbarch->displaced_step_free_closure = NULL; gdbarch->displaced_step_location = NULL; @@ -627,6 +630,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of skip_permanent_breakpoint, has predicate */ /* Skip verify of max_insn_length, has predicate */ /* Skip verify of displaced_step_copy_insn, has predicate */ + /* Skip verify of displaced_step_hw_singlestep, invalid_p == 0 */ /* Skip verify of displaced_step_fixup, has predicate */ if ((! gdbarch->displaced_step_free_closure) != (! gdbarch->displaced_step_copy_insn)) fprintf_unfiltered (log, "\n\tdisplaced_step_free_closure"); @@ -791,6 +795,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: displaced_step_free_closure = <%s>\n", host_address_to_string (gdbarch->displaced_step_free_closure)); fprintf_unfiltered (file, + "gdbarch_dump: displaced_step_hw_singlestep = <%s>\n", + host_address_to_string (gdbarch->displaced_step_hw_singlestep)); + fprintf_unfiltered (file, "gdbarch_dump: displaced_step_location = <%s>\n", host_address_to_string (gdbarch->displaced_step_location)); fprintf_unfiltered (file, @@ -3145,6 +3152,23 @@ set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, } int +gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, struct displaced_step_closure *closure) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->displaced_step_hw_singlestep != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_displaced_step_hw_singlestep called\n"); + return gdbarch->displaced_step_hw_singlestep (gdbarch, closure); +} + +void +set_gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + gdbarch_displaced_step_hw_singlestep_ftype displaced_step_hw_singlestep) +{ + gdbarch->displaced_step_hw_singlestep = displaced_step_hw_singlestep; +} + +int gdbarch_displaced_step_fixup_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 950b7ca..f7b0355 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -734,6 +734,20 @@ typedef struct displaced_step_closure * (gdbarch_displaced_step_copy_insn_ftype) extern struct displaced_step_closure * gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs); extern void set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, gdbarch_displaced_step_copy_insn_ftype *displaced_step_copy_insn); +/* Return true if GDB should use hardware single-stepping to execute + the displaced instruction identified by CLOSURE. If false, + GDB will simply restart execution at the displaced instruction + location, and it is up to the target to ensure GDB will receive + control again (e.g. by placing a software breakpoint instruction + into the displaced instruction buffer). + + The default implementation returns false on all targets that + provide a gdbarch_software_single_step routine, and true otherwise. */ + +typedef int (gdbarch_displaced_step_hw_singlestep_ftype) (struct gdbarch *gdbarch, struct displaced_step_closure *closure); +extern int gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, struct displaced_step_closure *closure); +extern void set_gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, gdbarch_displaced_step_hw_singlestep_ftype *displaced_step_hw_singlestep); + /* Fix up the state resulting from successfully single-stepping a displaced instruction, to give the result we would have gotten from stepping the instruction in its original location. diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 1546342..cf43819 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -654,6 +654,17 @@ V:ULONGEST:max_insn_length:::0:0 # here. M:struct displaced_step_closure *:displaced_step_copy_insn:CORE_ADDR from, CORE_ADDR to, struct regcache *regs:from, to, regs +# Return true if GDB should use hardware single-stepping to execute +# the displaced instruction identified by CLOSURE. If false, +# GDB will simply restart execution at the displaced instruction +# location, and it is up to the target to ensure GDB will receive +# control again (e.g. by placing a software breakpoint instruction +# into the displaced instruction buffer). +# +# The default implementation returns false on all targets that +# provide a gdbarch_software_single_step routine, and true otherwise. +m:int:displaced_step_hw_singlestep:struct displaced_step_closure *closure:closure::default_displaced_step_hw_singlestep::0 + # Fix up the state resulting from successfully single-stepping a # displaced instruction, to give the result we would have gotten from # stepping the instruction in its original location. diff --git a/gdb/infrun.c b/gdb/infrun.c index 1a83a25..ff7c6b9 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1002,10 +1002,11 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal) displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf)); } - if (gdbarch_software_single_step_p (gdbarch)) - target_resume (ptid, 0, TARGET_SIGNAL_0); - else + if (gdbarch_displaced_step_hw_singlestep + (gdbarch, displaced_step_closure)) target_resume (ptid, 1, TARGET_SIGNAL_0); + else + target_resume (ptid, 0, TARGET_SIGNAL_0); /* Done, we're stepping a thread. */ break; @@ -1114,19 +1115,15 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc) { int hw_step = 1; - if (gdbarch_software_single_step_p (gdbarch)) + if (gdbarch_software_single_step_p (gdbarch) + && gdbarch_software_single_step (gdbarch, get_current_frame ())) { - if (use_displaced_stepping (gdbarch)) - hw_step = 0; - else if (gdbarch_software_single_step (gdbarch, get_current_frame ())) - { - hw_step = 0; - /* Do not pull these breakpoints until after a `wait' in - `wait_for_inferior' */ - singlestep_breakpoints_inserted_p = 1; - singlestep_ptid = inferior_ptid; - singlestep_pc = pc; - } + hw_step = 0; + /* Do not pull these breakpoints until after a `wait' in + `wait_for_inferior' */ + singlestep_breakpoints_inserted_p = 1; + singlestep_ptid = inferior_ptid; + singlestep_pc = pc; } return hw_step; } @@ -1208,10 +1205,13 @@ a command like `return' or `jump' to continue execution.")); discard_cleanups (old_cleanups); return; } + + step = gdbarch_displaced_step_hw_singlestep + (gdbarch, displaced_step_closure); } /* Do we need to do it the hard way, w/temp breakpoints? */ - if (step) + else if (step) step = maybe_software_singlestep (gdbarch, pc); if (should_resume) diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index fae5c28..26ae109 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1058,6 +1058,15 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, from + offset); } +/* Always use hardware single-stepping to execute the + displaced instruction. */ +static int +ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + struct displaced_step_closure *closure) +{ + return 1; +} + /* Instruction masks used during single-stepping of atomic sequences. */ #define LWARX_MASK 0xfc0007fe #define LWARX_INSTRUCTION 0x7c000028 @@ -3898,6 +3907,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Setup displaced stepping. */ set_gdbarch_displaced_step_copy_insn (gdbarch, simple_displaced_step_copy_insn); + set_gdbarch_displaced_step_hw_singlestep (gdbarch, + ppc_displaced_step_hw_singlestep); set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup); set_gdbarch_displaced_step_free_closure (gdbarch, simple_displaced_step_free_closure); -- 2.7.4