mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
* breakpoint.c (software_breakpoint_inserted_here_p): New function.
(bpstat_stop_status): Don't decrement PC. * breakpoint.h (software_breakpoint_inserted_here_p): Add prototype. * infrun.c (adjust_pc_after_break): New function. (handle_inferior_event): Call it, early. Remove later references to DECR_PC_AFTER_BREAK. (normal_stop): Add commentary.
This commit is contained in:
@ -1,3 +1,14 @@
|
|||||||
|
2004-01-31 Daniel Jacobowitz <drow@mvista.com>
|
||||||
|
|
||||||
|
* breakpoint.c (software_breakpoint_inserted_here_p): New function.
|
||||||
|
(bpstat_stop_status): Don't decrement PC.
|
||||||
|
* breakpoint.h (software_breakpoint_inserted_here_p): Add
|
||||||
|
prototype.
|
||||||
|
* infrun.c (adjust_pc_after_break): New function.
|
||||||
|
(handle_inferior_event): Call it, early. Remove later references
|
||||||
|
to DECR_PC_AFTER_BREAK.
|
||||||
|
(normal_stop): Add commentary.
|
||||||
|
|
||||||
2004-01-31 Daniel Jacobowitz <drow@mvista.com>
|
2004-01-31 Daniel Jacobowitz <drow@mvista.com>
|
||||||
|
|
||||||
* breakpoint.c (breakpoint_re_set_one): Add missing chunk of
|
* breakpoint.c (breakpoint_re_set_one): Add missing chunk of
|
||||||
|
@ -1717,6 +1717,37 @@ breakpoint_inserted_here_p (CORE_ADDR pc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function returns non-zero iff there is a software breakpoint
|
||||||
|
inserted at PC. */
|
||||||
|
|
||||||
|
int
|
||||||
|
software_breakpoint_inserted_here_p (CORE_ADDR pc)
|
||||||
|
{
|
||||||
|
struct bp_location *bpt;
|
||||||
|
int any_breakpoint_here = 0;
|
||||||
|
|
||||||
|
ALL_BP_LOCATIONS (bpt)
|
||||||
|
{
|
||||||
|
if (bpt->loc_type != bp_loc_software_breakpoint)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((breakpoint_enabled (bpt->owner)
|
||||||
|
|| bpt->owner->enable_state == bp_permanent)
|
||||||
|
&& bpt->inserted
|
||||||
|
&& bpt->address == pc) /* bp is enabled and matches pc */
|
||||||
|
{
|
||||||
|
if (overlay_debugging
|
||||||
|
&& section_is_overlay (bpt->section)
|
||||||
|
&& !section_is_mapped (bpt->section))
|
||||||
|
continue; /* unmapped overlay -- can't be a match */
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return nonzero if FRAME is a dummy frame. We can't use
|
/* Return nonzero if FRAME is a dummy frame. We can't use
|
||||||
DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would
|
DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would
|
||||||
take too much time, at least using frame_register() on the 68k.
|
take too much time, at least using frame_register() on the 68k.
|
||||||
@ -2571,13 +2602,7 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint)
|
|||||||
/* Pointer to the last thing in the chain currently. */
|
/* Pointer to the last thing in the chain currently. */
|
||||||
bpstat bs = root_bs;
|
bpstat bs = root_bs;
|
||||||
|
|
||||||
/* Get the address where the breakpoint would have been. The
|
bp_addr = *pc;
|
||||||
"not_a_sw_breakpoint" argument is meant to distinguish between a
|
|
||||||
breakpoint trap event and a trace/singlestep trap event. For a
|
|
||||||
trace/singlestep trap event, we would not want to subtract
|
|
||||||
DECR_PC_AFTER_BREAK from the PC. */
|
|
||||||
|
|
||||||
bp_addr = *pc - (not_a_sw_breakpoint ? 0 : DECR_PC_AFTER_BREAK);
|
|
||||||
|
|
||||||
ALL_BREAKPOINTS_SAFE (b, temp)
|
ALL_BREAKPOINTS_SAFE (b, temp)
|
||||||
{
|
{
|
||||||
@ -2863,18 +2888,6 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint)
|
|||||||
bs->next = NULL; /* Terminate the chain */
|
bs->next = NULL; /* Terminate the chain */
|
||||||
bs = root_bs->next; /* Re-grab the head of the chain */
|
bs = root_bs->next; /* Re-grab the head of the chain */
|
||||||
|
|
||||||
if (real_breakpoint && bs)
|
|
||||||
{
|
|
||||||
if (bs->breakpoint_at->type != bp_hardware_breakpoint)
|
|
||||||
{
|
|
||||||
if (DECR_PC_AFTER_BREAK != 0)
|
|
||||||
{
|
|
||||||
*pc = bp_addr;
|
|
||||||
write_pc (bp_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The value of a hardware watchpoint hasn't changed, but the
|
/* The value of a hardware watchpoint hasn't changed, but the
|
||||||
intermediate memory locations we are watching may have. */
|
intermediate memory locations we are watching may have. */
|
||||||
if (bs && !bs->stop &&
|
if (bs && !bs->stop &&
|
||||||
|
@ -605,6 +605,8 @@ extern enum breakpoint_here breakpoint_here_p (CORE_ADDR);
|
|||||||
|
|
||||||
extern int breakpoint_inserted_here_p (CORE_ADDR);
|
extern int breakpoint_inserted_here_p (CORE_ADDR);
|
||||||
|
|
||||||
|
extern int software_breakpoint_inserted_here_p (CORE_ADDR);
|
||||||
|
|
||||||
/* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
|
/* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
|
||||||
implements a functional superset of this function. The only reason
|
implements a functional superset of this function. The only reason
|
||||||
it hasn't been removed is because some architectures still don't
|
it hasn't been removed is because some architectures still don't
|
||||||
|
95
gdb/infrun.c
95
gdb/infrun.c
@ -1313,6 +1313,74 @@ handle_step_into_function (struct execution_control_state *ecs)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adjust_pc_after_break (struct execution_control_state *ecs)
|
||||||
|
{
|
||||||
|
CORE_ADDR stop_pc;
|
||||||
|
|
||||||
|
/* If this target does not decrement the PC after breakpoints, then
|
||||||
|
we have nothing to do. */
|
||||||
|
if (DECR_PC_AFTER_BREAK == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP. If
|
||||||
|
we aren't, just return.
|
||||||
|
|
||||||
|
NOTE drow/2004-01-31: On some targets, breakpoints may generate
|
||||||
|
different signals (SIGILL or SIGEMT for instance), but it is less
|
||||||
|
clear where the PC is pointing afterwards. It may not match
|
||||||
|
DECR_PC_AFTER_BREAK. I don't know any specific target that generates
|
||||||
|
these signals at breakpoints (the code has been in GDB since at least
|
||||||
|
1992) so I can not guess how to handle them here.
|
||||||
|
|
||||||
|
In earlier versions of GDB, a target with HAVE_NONSTEPPABLE_WATCHPOINTS
|
||||||
|
would have the PC after hitting a watchpoint affected by
|
||||||
|
DECR_PC_AFTER_BREAK. I haven't found any target with both of these set
|
||||||
|
in GDB history, and it seems unlikely to be correct, so
|
||||||
|
HAVE_NONSTEPPABLE_WATCHPOINTS is not checked here. */
|
||||||
|
|
||||||
|
if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Find the location where (if we've hit a breakpoint) the breakpoint would
|
||||||
|
be. */
|
||||||
|
stop_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
|
||||||
|
|
||||||
|
/* If we're software-single-stepping, then assume this is a breakpoint.
|
||||||
|
NOTE drow/2004-01-17: This doesn't check that the PC matches, or that
|
||||||
|
we're even in the right thread. The software-single-step code needs
|
||||||
|
some modernization.
|
||||||
|
|
||||||
|
If we're not software-single-stepping, then we first check that there
|
||||||
|
is an enabled software breakpoint at this address. If there is, and
|
||||||
|
we weren't using hardware-single-step, then we've hit the breakpoint.
|
||||||
|
|
||||||
|
If we were using hardware-single-step, we check prev_pc; if we just
|
||||||
|
stepped over an inserted software breakpoint, then we should decrement
|
||||||
|
the PC and eventually report hitting the breakpoint. The prev_pc check
|
||||||
|
prevents us from decrementing the PC if we just stepped over a jump
|
||||||
|
instruction and landed on the instruction after a breakpoint.
|
||||||
|
|
||||||
|
The last bit checks that we didn't hit a breakpoint in a signal handler
|
||||||
|
without an intervening stop in sigtramp, which is detected by a new
|
||||||
|
stack pointer value below any usual function calling stack adjustments.
|
||||||
|
|
||||||
|
NOTE drow/2004-01-17: I'm not sure that this is necessary. The check
|
||||||
|
predates checking for software single step at the same time. Also,
|
||||||
|
if we've moved into a signal handler we should have seen the
|
||||||
|
signal. */
|
||||||
|
|
||||||
|
if ((SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
|
||||||
|
|| (software_breakpoint_inserted_here_p (stop_pc)
|
||||||
|
&& !(currently_stepping (ecs)
|
||||||
|
&& prev_pc != stop_pc
|
||||||
|
&& !(step_range_end && INNER_THAN (read_sp (), (step_sp - 16))))))
|
||||||
|
write_pc_pid (stop_pc, ecs->ptid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Given an execution control state that has been freshly filled in
|
/* Given an execution control state that has been freshly filled in
|
||||||
by an event from the inferior, figure out what it means and take
|
by an event from the inferior, figure out what it means and take
|
||||||
appropriate action. */
|
appropriate action. */
|
||||||
@ -1332,6 +1400,8 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
target_last_wait_ptid = ecs->ptid;
|
target_last_wait_ptid = ecs->ptid;
|
||||||
target_last_waitstatus = *ecs->wp;
|
target_last_waitstatus = *ecs->wp;
|
||||||
|
|
||||||
|
adjust_pc_after_break (ecs);
|
||||||
|
|
||||||
switch (ecs->infwait_state)
|
switch (ecs->infwait_state)
|
||||||
{
|
{
|
||||||
case infwait_thread_hop_state:
|
case infwait_thread_hop_state:
|
||||||
@ -1685,19 +1755,15 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
/* Check if a regular breakpoint has been hit before checking
|
/* Check if a regular breakpoint has been hit before checking
|
||||||
for a potential single step breakpoint. Otherwise, GDB will
|
for a potential single step breakpoint. Otherwise, GDB will
|
||||||
not see this breakpoint hit when stepping onto breakpoints. */
|
not see this breakpoint hit when stepping onto breakpoints. */
|
||||||
if (breakpoints_inserted
|
if (breakpoints_inserted && breakpoint_here_p (stop_pc))
|
||||||
&& breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
|
|
||||||
{
|
{
|
||||||
ecs->random_signal = 0;
|
ecs->random_signal = 0;
|
||||||
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
|
if (!breakpoint_thread_match (stop_pc, ecs->ptid))
|
||||||
ecs->ptid))
|
|
||||||
{
|
{
|
||||||
int remove_status;
|
int remove_status;
|
||||||
|
|
||||||
/* Saw a breakpoint, but it was hit by the wrong thread.
|
/* Saw a breakpoint, but it was hit by the wrong thread.
|
||||||
Just continue. */
|
Just continue. */
|
||||||
if (DECR_PC_AFTER_BREAK)
|
|
||||||
write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
|
|
||||||
|
|
||||||
remove_status = remove_breakpoints ();
|
remove_status = remove_breakpoints ();
|
||||||
/* Did we fail to remove breakpoints? If so, try
|
/* Did we fail to remove breakpoints? If so, try
|
||||||
@ -1710,7 +1776,7 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
if (remove_status != 0)
|
if (remove_status != 0)
|
||||||
{
|
{
|
||||||
/* FIXME! This is obviously non-portable! */
|
/* FIXME! This is obviously non-portable! */
|
||||||
write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, ecs->ptid);
|
write_pc_pid (stop_pc + 4, ecs->ptid);
|
||||||
/* We need to restart all the threads now,
|
/* We need to restart all the threads now,
|
||||||
* unles we're running in scheduler-locked mode.
|
* unles we're running in scheduler-locked mode.
|
||||||
* Use currently_stepping to determine whether to
|
* Use currently_stepping to determine whether to
|
||||||
@ -1744,17 +1810,6 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
}
|
}
|
||||||
else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
|
else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
|
||||||
{
|
{
|
||||||
/* Readjust the stop_pc as it is off by DECR_PC_AFTER_BREAK
|
|
||||||
compared to the value it would have if the system stepping
|
|
||||||
capability was used. This allows the rest of the code in
|
|
||||||
this function to use this address without having to worry
|
|
||||||
whether software single step is in use or not. */
|
|
||||||
if (DECR_PC_AFTER_BREAK)
|
|
||||||
{
|
|
||||||
stop_pc -= DECR_PC_AFTER_BREAK;
|
|
||||||
write_pc_pid (stop_pc, ecs->ptid);
|
|
||||||
}
|
|
||||||
|
|
||||||
sw_single_step_trap_p = 1;
|
sw_single_step_trap_p = 1;
|
||||||
ecs->random_signal = 0;
|
ecs->random_signal = 0;
|
||||||
}
|
}
|
||||||
@ -1886,9 +1941,6 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
includes evaluating watchpoints, things will come to a
|
includes evaluating watchpoints, things will come to a
|
||||||
stop in the correct manner. */
|
stop in the correct manner. */
|
||||||
|
|
||||||
if (DECR_PC_AFTER_BREAK)
|
|
||||||
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
|
|
||||||
|
|
||||||
remove_breakpoints ();
|
remove_breakpoints ();
|
||||||
registers_changed ();
|
registers_changed ();
|
||||||
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
|
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
|
||||||
@ -3121,6 +3173,7 @@ normal_stop (void)
|
|||||||
previous_inferior_ptid = inferior_ptid;
|
previous_inferior_ptid = inferior_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE drow/2004-01-17: Is this still necessary? */
|
||||||
/* Make sure that the current_frame's pc is correct. This
|
/* Make sure that the current_frame's pc is correct. This
|
||||||
is a correction for setting up the frame info before doing
|
is a correction for setting up the frame info before doing
|
||||||
DECR_PC_AFTER_BREAK */
|
DECR_PC_AFTER_BREAK */
|
||||||
|
Reference in New Issue
Block a user