* 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.
This commit is contained in:
parent
69368a60a4
commit
99e4058030
8 changed files with 103 additions and 16 deletions
|
@ -1,3 +1,19 @@
|
|||
2009-09-28 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* 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 <uweigand@de.ibm.com>
|
||||
|
||||
* eval.c (evaluate_subexp_standard) [OP_OBJC_MSGCALL]: Support
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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");
|
||||
|
@ -790,6 +794,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
|||
fprintf_unfiltered (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));
|
||||
|
@ -3144,6 +3151,23 @@ set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch,
|
|||
gdbarch->displaced_step_copy_insn = displaced_step_copy_insn;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
32
gdb/infrun.c
32
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue