forked from Imagelibrary/binutils-gdb
Implement displaced stepping.
gdb/ * gdbarch.sh (max_insn_length): New 'variable'. (displaced_step_copy, displaced_step_fixup) (displaced_step_free_closure, displaced_step_location): New functions. (struct displaced_step_closure): Add forward declaration. * gdbarch.c, gdbarch.h: Regenerated. * arch-utils.c: #include "objfiles.h". (simple_displaced_step_copy_insn) (simple_displaced_step_free_closure) (displaced_step_at_entry_point): New functions. * arch-utils.h (simple_displaced_step_copy_insn) (simple_displaced_step_free_closure) (displaced_step_at_entry_point): New prototypes. * i386-tdep.c (I386_MAX_INSN_LEN): Rename to... (I386_MAX_MATCHED_INSN_LEN): ... this. (i386_absolute_jmp_p, i386_absolute_call_p) (i386_ret_p, i386_call_p, i386_breakpoint_p, i386_syscall_p) (i386_displaced_step_fixup): New functions. (struct i386_insn, i386_match_insn): Update. (i386_gdbarch_init): Set gdbarch_max_insn_length. * i386-tdep.h (I386_MAX_INSN_LEN): New. (i386_displaced_step_fixup): New prototype. * i386-linux-tdep.c (i386_linux_init_abi): Include "arch-utils.h". Register gdbarch_displaced_step_copy, gdbarch_displaced_step_fixup, gdbarch_displaced_step_free_closure, and gdbarch_displaced_step_location functions. * infrun.c (debug_displaced): New variable. (show_debug_displaced): New function. (struct displaced_step_request): New struct. (displaced_step_request_queue, displaced_step_ptid) (displaced_step_gdbarch, displaced_step_closure) (displaced_step_original, displaced_step_copy) (displaced_step_saved_copy, can_use_displaced_stepping): New variables. (show_can_use_displaced_stepping, use_displaced_stepping) (displaced_step_clear, cleanup_displaced_step_closure) (displaced_step_dump_bytes, displaced_step_prepare) (displaced_step_clear_cleanup, write_memory_ptid) (displaced_step_fixup): New functions. (resume): Call displaced_step_prepare. (proceed): Call read_pc once, and remember the value. If using displaced stepping, don't remove breakpoints. (handle_inferior_event): Call displaced_step_fixup. Add some debugging output. When we try to step over a breakpoint, but get a signal to deliver to the thread instead, ensure the step-resume breakpoint is actually inserted. If a thread hop is needed, and displaced stepping is enabled, don't remove breakpoints. (init_wait_for_inferior): Call displaced_step_clear. (_initialize_infrun): Add "set debug displaced" command. Add "maint set can-use-displaced-stepping" command. Clear displaced_step_ptid. * inferior.h (debug_displaced): Declare variable. (displaced_step_dump_bytes): Declare function. * Makefile.in (arch-utils.o, i386-linux-tdep.o): Update dependencies. gdb/testsuite/ * gdb.asm/asmsrc1.s: Add scratch space. gdb/doc/ * gdb.texinfo (Debugging Output): Document "set/show debug displaced". (Maintenance Commands): Document "maint set/show can-use-displaced-stepping".
This commit is contained in:
@@ -50,6 +50,7 @@ struct target_ops;
|
||||
struct obstack;
|
||||
struct bp_target_info;
|
||||
struct target_desc;
|
||||
struct displaced_step_closure;
|
||||
|
||||
extern struct gdbarch *current_gdbarch;
|
||||
|
||||
@@ -663,6 +664,95 @@ typedef void (gdbarch_skip_permanent_breakpoint_ftype) (struct regcache *regcach
|
||||
extern void gdbarch_skip_permanent_breakpoint (struct gdbarch *gdbarch, struct regcache *regcache);
|
||||
extern void set_gdbarch_skip_permanent_breakpoint (struct gdbarch *gdbarch, gdbarch_skip_permanent_breakpoint_ftype *skip_permanent_breakpoint);
|
||||
|
||||
/* The maximum length of an instruction on this architecture. */
|
||||
|
||||
extern int gdbarch_max_insn_length_p (struct gdbarch *gdbarch);
|
||||
|
||||
extern ULONGEST gdbarch_max_insn_length (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_max_insn_length (struct gdbarch *gdbarch, ULONGEST max_insn_length);
|
||||
|
||||
/* Copy the instruction at FROM to TO, and make any adjustments
|
||||
necessary to single-step it at that address.
|
||||
|
||||
REGS holds the state the thread's registers will have before
|
||||
executing the copied instruction; the PC in REGS will refer to FROM,
|
||||
not the copy at TO. The caller should update it to point at TO later.
|
||||
|
||||
Return a pointer to data of the architecture's choice to be passed
|
||||
to gdbarch_displaced_step_fixup. Or, return NULL to indicate that
|
||||
the instruction's effects have been completely simulated, with the
|
||||
resulting state written back to REGS.
|
||||
|
||||
For a general explanation of displaced stepping and how GDB uses it,
|
||||
see the comments in infrun.c.
|
||||
|
||||
The TO area is only guaranteed to have space for
|
||||
gdbarch_max_insn_length (arch) bytes, so this function must not
|
||||
write more bytes than that to that area.
|
||||
|
||||
If you do not provide this function, GDB assumes that the
|
||||
architecture does not support displaced stepping.
|
||||
|
||||
If your architecture doesn't need to adjust instructions before
|
||||
single-stepping them, consider using simple_displaced_step_copy_insn
|
||||
here. */
|
||||
|
||||
extern int gdbarch_displaced_step_copy_insn_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef struct displaced_step_closure * (gdbarch_displaced_step_copy_insn_ftype) (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs);
|
||||
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);
|
||||
|
||||
/* 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.
|
||||
|
||||
REGS is the register state resulting from single-stepping the
|
||||
displaced instruction.
|
||||
|
||||
CLOSURE is the result from the matching call to
|
||||
gdbarch_displaced_step_copy_insn.
|
||||
|
||||
If you provide gdbarch_displaced_step_copy_insn.but not this
|
||||
function, then GDB assumes that no fixup is needed after
|
||||
single-stepping the instruction.
|
||||
|
||||
For a general explanation of displaced stepping and how GDB uses it,
|
||||
see the comments in infrun.c. */
|
||||
|
||||
extern int gdbarch_displaced_step_fixup_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef void (gdbarch_displaced_step_fixup_ftype) (struct gdbarch *gdbarch, struct displaced_step_closure *closure, CORE_ADDR from, CORE_ADDR to, struct regcache *regs);
|
||||
extern void gdbarch_displaced_step_fixup (struct gdbarch *gdbarch, struct displaced_step_closure *closure, CORE_ADDR from, CORE_ADDR to, struct regcache *regs);
|
||||
extern void set_gdbarch_displaced_step_fixup (struct gdbarch *gdbarch, gdbarch_displaced_step_fixup_ftype *displaced_step_fixup);
|
||||
|
||||
/* Free a closure returned by gdbarch_displaced_step_copy_insn.
|
||||
|
||||
If you provide gdbarch_displaced_step_copy_insn, you must provide
|
||||
this function as well.
|
||||
|
||||
If your architecture uses closures that don't need to be freed, then
|
||||
you can use simple_displaced_step_free_closure here.
|
||||
|
||||
For a general explanation of displaced stepping and how GDB uses it,
|
||||
see the comments in infrun.c. */
|
||||
|
||||
typedef void (gdbarch_displaced_step_free_closure_ftype) (struct gdbarch *gdbarch, struct displaced_step_closure *closure);
|
||||
extern void gdbarch_displaced_step_free_closure (struct gdbarch *gdbarch, struct displaced_step_closure *closure);
|
||||
extern void set_gdbarch_displaced_step_free_closure (struct gdbarch *gdbarch, gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure);
|
||||
|
||||
/* Return the address of an appropriate place to put displaced
|
||||
instructions while we step over them. There need only be one such
|
||||
place, since we're only stepping one thread over a breakpoint at a
|
||||
time.
|
||||
|
||||
For a general explanation of displaced stepping and how GDB uses it,
|
||||
see the comments in infrun.c. */
|
||||
|
||||
typedef CORE_ADDR (gdbarch_displaced_step_location_ftype) (struct gdbarch *gdbarch);
|
||||
extern CORE_ADDR gdbarch_displaced_step_location (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_displaced_step_location (struct gdbarch *gdbarch, gdbarch_displaced_step_location_ftype *displaced_step_location);
|
||||
|
||||
/* Refresh overlay mapped state for section OSECT. */
|
||||
|
||||
extern int gdbarch_overlay_update_p (struct gdbarch *gdbarch);
|
||||
|
||||
Reference in New Issue
Block a user