2004-10-31 Orjan Friberg <organ.friberg@axis.com>
Andrew Cagney <cagney@gnu.org> * gdbarch.sh (single_step_through_delay): Add. * gdbarch.h, gdbarch.c: Re-generate. * config/mips/tm-mips.h (STEP_SKIPS_DELAY_P, STEP_SKIPS_DELAY) (mips_step_skips_delay): Delete. * mips-tdep.c (mips_single_step_through_delay): Replace mips_step_skips_delay. (mips_gdbarch_init): Set single_step_through_delay. (mips_dump_tdep): Do not print STEP_SKIPS_DELAY.
This commit is contained in:
parent
2440b685a7
commit
3352ef37c2
7 changed files with 107 additions and 28 deletions
|
@ -1,3 +1,15 @@
|
|||
2004-10-31 Orjan Friberg <organ.friberg@axis.com>
|
||||
Andrew Cagney <cagney@gnu.org>
|
||||
|
||||
* gdbarch.sh (single_step_through_delay): Add.
|
||||
* gdbarch.h, gdbarch.c: Re-generate.
|
||||
* config/mips/tm-mips.h (STEP_SKIPS_DELAY_P, STEP_SKIPS_DELAY)
|
||||
(mips_step_skips_delay): Delete.
|
||||
* mips-tdep.c (mips_single_step_through_delay): Replace
|
||||
mips_step_skips_delay.
|
||||
(mips_gdbarch_init): Set single_step_through_delay.
|
||||
(mips_dump_tdep): Do not print STEP_SKIPS_DELAY.
|
||||
|
||||
2004-10-31 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* tramp-frame.c (tramp_frame_prepend_unwinder): Set unwinder type
|
||||
|
|
|
@ -33,12 +33,6 @@ struct symbol;
|
|||
struct type;
|
||||
struct value;
|
||||
|
||||
/* Return non-zero if PC points to an instruction which will cause a step
|
||||
to execute both the instruction at PC and an instruction at PC+4. */
|
||||
extern int mips_step_skips_delay (CORE_ADDR);
|
||||
#define STEP_SKIPS_DELAY_P (1)
|
||||
#define STEP_SKIPS_DELAY(pc) (mips_step_skips_delay (pc))
|
||||
|
||||
/* Special symbol found in blocks associated with routines. We can
|
||||
hang mdebug_extra_func_info's off of this. */
|
||||
|
||||
|
|
|
@ -211,6 +211,7 @@ struct gdbarch
|
|||
gdbarch_addr_bits_remove_ftype *addr_bits_remove;
|
||||
gdbarch_smash_text_address_ftype *smash_text_address;
|
||||
gdbarch_software_single_step_ftype *software_single_step;
|
||||
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
|
||||
gdbarch_print_insn_ftype *print_insn;
|
||||
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
|
||||
gdbarch_skip_solib_resolver_ftype *skip_solib_resolver;
|
||||
|
@ -337,6 +338,7 @@ struct gdbarch startup_gdbarch =
|
|||
0, /* addr_bits_remove */
|
||||
0, /* smash_text_address */
|
||||
0, /* software_single_step */
|
||||
0, /* single_step_through_delay */
|
||||
0, /* print_insn */
|
||||
0, /* skip_trampoline_code */
|
||||
generic_skip_solib_resolver, /* skip_solib_resolver */
|
||||
|
@ -591,6 +593,7 @@ verify_gdbarch (struct gdbarch *current_gdbarch)
|
|||
/* Skip verify of addr_bits_remove, invalid_p == 0 */
|
||||
/* Skip verify of smash_text_address, invalid_p == 0 */
|
||||
/* Skip verify of software_single_step, has predicate */
|
||||
/* Skip verify of single_step_through_delay, has predicate */
|
||||
if (current_gdbarch->print_insn == 0)
|
||||
fprintf_unfiltered (log, "\n\tprint_insn");
|
||||
/* Skip verify of skip_trampoline_code, invalid_p == 0 */
|
||||
|
@ -1516,6 +1519,12 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
|
|||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: short_bit = %s\n",
|
||||
paddr_d (current_gdbarch->short_bit));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_single_step_through_delay_p() = %d\n",
|
||||
gdbarch_single_step_through_delay_p (current_gdbarch));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: single_step_through_delay = <0x%lx>\n",
|
||||
(long) current_gdbarch->single_step_through_delay);
|
||||
#ifdef SKIP_PROLOGUE
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: %s # %s\n",
|
||||
|
@ -3345,6 +3354,30 @@ set_gdbarch_software_single_step (struct gdbarch *gdbarch,
|
|||
gdbarch->software_single_step = software_single_step;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_single_step_through_delay_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
return gdbarch->single_step_through_delay != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *frame)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->single_step_through_delay != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_single_step_through_delay called\n");
|
||||
return gdbarch->single_step_through_delay (gdbarch, frame);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_single_step_through_delay (struct gdbarch *gdbarch,
|
||||
gdbarch_single_step_through_delay_ftype single_step_through_delay)
|
||||
{
|
||||
gdbarch->single_step_through_delay = single_step_through_delay;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_print_insn (struct gdbarch *gdbarch, bfd_vma vma, struct disassemble_info *info)
|
||||
{
|
||||
|
|
|
@ -1218,6 +1218,15 @@ extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_s
|
|||
#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
|
||||
#endif
|
||||
|
||||
/* Return non-zero if the processor is executing a delay slot and a
|
||||
further single-step is needed before the instruction finishes. */
|
||||
|
||||
extern int gdbarch_single_step_through_delay_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef int (gdbarch_single_step_through_delay_ftype) (struct gdbarch *gdbarch, struct frame_info *frame);
|
||||
extern int gdbarch_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *frame);
|
||||
extern void set_gdbarch_single_step_through_delay (struct gdbarch *gdbarch, gdbarch_single_step_through_delay_ftype *single_step_through_delay);
|
||||
|
||||
/* FIXME: cagney/2003-08-28: Need to find a better way of selecting the
|
||||
disassembler. Perhaps objdump can handle it? */
|
||||
|
||||
|
|
|
@ -611,6 +611,9 @@ f:=:CORE_ADDR:smash_text_address:CORE_ADDR addr:addr::core_addr_identity::0
|
|||
# FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the target can
|
||||
# single step. If not, then implement single step using breakpoints.
|
||||
F:=:void:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
|
||||
# Return non-zero if the processor is executing a delay slot and a
|
||||
# further single-step is needed before the instruction finishes.
|
||||
M::int:single_step_through_delay:struct frame_info *frame:frame
|
||||
# FIXME: cagney/2003-08-28: Need to find a better way of selecting the
|
||||
# disassembler. Perhaps objdump can handle it?
|
||||
f:TARGET_PRINT_INSN:int:print_insn:bfd_vma vma, struct disassemble_info *info:vma, info::0:
|
||||
|
|
58
gdb/infrun.c
58
gdb/infrun.c
|
@ -714,24 +714,17 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
|
|||
|
||||
if (addr == (CORE_ADDR) -1)
|
||||
{
|
||||
/* If there is a breakpoint at the address we will resume at,
|
||||
step one instruction before inserting breakpoints
|
||||
so that we do not stop right away (and report a second
|
||||
hit at this breakpoint). */
|
||||
|
||||
if (read_pc () == stop_pc && breakpoint_here_p (read_pc ()))
|
||||
/* There is a breakpoint at the address we will resume at,
|
||||
step one instruction before inserting breakpoints so that
|
||||
we do not stop right away (and report a second hit at this
|
||||
breakpoint). */
|
||||
oneproc = 1;
|
||||
|
||||
#ifndef STEP_SKIPS_DELAY
|
||||
#define STEP_SKIPS_DELAY(pc) (0)
|
||||
#define STEP_SKIPS_DELAY_P (0)
|
||||
#endif
|
||||
/* Check breakpoint_here_p first, because breakpoint_here_p is fast
|
||||
(it just checks internal GDB data structures) and STEP_SKIPS_DELAY
|
||||
is slow (it needs to read memory from the target). */
|
||||
if (STEP_SKIPS_DELAY_P
|
||||
&& breakpoint_here_p (read_pc () + 4)
|
||||
&& STEP_SKIPS_DELAY (read_pc ()))
|
||||
else if (gdbarch_single_step_through_delay_p (current_gdbarch)
|
||||
&& gdbarch_single_step_through_delay (current_gdbarch,
|
||||
get_current_frame ()))
|
||||
/* We stepped onto an instruction that needs to be stepped
|
||||
again before re-inserting the breakpoint, do so. */
|
||||
oneproc = 1;
|
||||
}
|
||||
else
|
||||
|
@ -1781,6 +1774,39 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||
stopped_by_random_signal = 0;
|
||||
breakpoints_failed = 0;
|
||||
|
||||
if (stop_signal == TARGET_SIGNAL_TRAP
|
||||
&& trap_expected
|
||||
&& gdbarch_single_step_through_delay_p (current_gdbarch)
|
||||
&& currently_stepping (ecs))
|
||||
{
|
||||
/* We're trying to step of a breakpoint. Turns out that we're
|
||||
also on an instruction that needs to be stepped multiple
|
||||
times before it's been fully executing. E.g., architectures
|
||||
with a delay slot. It needs to be stepped twice, once for
|
||||
the instruction and once for the delay slot. */
|
||||
int step_through_delay
|
||||
= gdbarch_single_step_through_delay (current_gdbarch,
|
||||
get_current_frame ());
|
||||
if (step_range_end == 0 && step_through_delay)
|
||||
{
|
||||
/* The user issued a continue when stopped at a breakpoint.
|
||||
Set up for another trap and get out of here. */
|
||||
ecs->another_trap = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
else if (step_through_delay)
|
||||
{
|
||||
/* The user issued a step when stopped at a breakpoint.
|
||||
Maybe we should stop, maybe we should not - the delay
|
||||
slot *might* correspond to a line of source. In any
|
||||
case, don't decide that here, just set ecs->another_trap,
|
||||
making sure we single-step again before breakpoints are
|
||||
re-inserted. */
|
||||
ecs->another_trap = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at the cause of the stop, and decide what to do.
|
||||
The alternatives are:
|
||||
1) break; to really stop and return to the debugger,
|
||||
|
|
|
@ -4142,16 +4142,19 @@ is_delayed (unsigned long insn)
|
|||
}
|
||||
|
||||
int
|
||||
mips_step_skips_delay (CORE_ADDR pc)
|
||||
mips_single_step_through_delay (struct gdbarch *gdbarch,
|
||||
struct frame_info *frame)
|
||||
{
|
||||
CORE_ADDR pc = get_frame_pc (frame);
|
||||
char buf[MIPS_INSN32_SIZE];
|
||||
|
||||
/* There is no branch delay slot on MIPS16. */
|
||||
if (mips_pc_is_mips16 (pc))
|
||||
return 0;
|
||||
|
||||
if (target_read_memory (pc, buf, sizeof buf) != 0)
|
||||
/* If error reading memory, guess that it is not a delayed branch. */
|
||||
if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
|
||||
/* If error reading memory, guess that it is not a delayed
|
||||
branch. */
|
||||
return 0;
|
||||
return is_delayed (extract_unsigned_integer (buf, sizeof buf));
|
||||
}
|
||||
|
@ -5097,6 +5100,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_solib_return_trampoline);
|
||||
}
|
||||
|
||||
set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
|
||||
|
||||
/* Hook in OS ABI-specific overrides, if they have been registered. */
|
||||
gdbarch_init_osabi (info, gdbarch);
|
||||
|
||||
|
@ -5304,9 +5309,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
|
|||
fprintf_unfiltered (file,
|
||||
"mips_dump_tdep: STEP_SKIPS_DELAY # %s\n",
|
||||
XSTRING (STEP_SKIPS_DELAY (PC)));
|
||||
fprintf_unfiltered (file,
|
||||
"mips_dump_tdep: STEP_SKIPS_DELAY_P = %d\n",
|
||||
STEP_SKIPS_DELAY_P);
|
||||
fprintf_unfiltered (file,
|
||||
"mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
|
||||
XSTRING (STOPPED_BY_WATCHPOINT (WS)));
|
||||
|
|
Loading…
Reference in a new issue