aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c155
1 files changed, 96 insertions, 59 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a46587e..dd569c3 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -35,6 +35,8 @@
#include "top.h"
#include <signal.h>
#include "event-loop.h"
+#include "event-top.h"
+#include "remote.h" /* For cleanup_sigint_signal_handler. */
/* Prototypes for local functions */
@@ -268,6 +270,26 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
#define INSTRUCTION_NULLIFIED 0
#endif
+/* We can't step off a permanent breakpoint in the ordinary way, because we
+ can't remove it. Instead, we have to advance the PC to the next
+ instruction. This macro should expand to a pointer to a function that
+ does that, or zero if we have no such function. If we don't have a
+ definition for it, we have to report an error. */
+#ifndef SKIP_PERMANENT_BREAKPOINT
+#define SKIP_PERMANENT_BREAKPOINT (default_skip_permanent_breakpoint)
+static void
+default_skip_permanent_breakpoint ()
+{
+ error_begin ();
+ fprintf_filtered (gdb_stderr, "\
+The program is stopped at a permanent breakpoint, but GDB does not know\n\
+how to step past a permanent breakpoint on this architecture. Try using\n\
+a command like `return' or `jump' to continue execution.\n");
+ return_to_top_level (RETURN_ERROR);
+}
+#endif
+
+
/* Convert the #defines into values. This is temporary until wfi control
flow is completely sorted out. */
@@ -766,6 +788,8 @@ set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
}
+
+
/* Resume the inferior, but allow a QUIT. This is useful if the user
wants to interrupt some lengthy single-stepping operation
(for child processes, the SIGINT goes to the inferior, and so
@@ -790,6 +814,13 @@ resume (int step, enum target_signal sig)
step = 0;
#endif
+ /* Normally, by the time we reach `resume', the breakpoints are either
+ removed or inserted, as appropriate. The exception is if we're sitting
+ at a permanent breakpoint; we need to step over it, but permanent
+ breakpoints can't be removed. So we have to test for it here. */
+ if (breakpoint_here_p (read_pc ()) == permanent_breakpoint_here)
+ SKIP_PERMANENT_BREAKPOINT ();
+
if (SOFTWARE_SINGLE_STEP_P && step)
{
/* Do it the hard way, w/temp breakpoints */
@@ -1175,6 +1206,7 @@ void init_execution_control_state (struct execution_control_state * ecs);
void handle_inferior_event (struct execution_control_state * ecs);
static void check_sigtramp2 (struct execution_control_state *ecs);
+static void step_into_function (struct execution_control_state *ecs);
static void step_over_function (struct execution_control_state *ecs);
static void stop_stepping (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs);
@@ -1250,7 +1282,8 @@ struct execution_control_state async_ecss;
struct execution_control_state *async_ecs;
void
-fetch_inferior_event (void)
+fetch_inferior_event (client_data)
+ gdb_client_data client_data;
{
static struct cleanup *old_cleanups;
@@ -2761,66 +2794,15 @@ handle_inferior_event (struct execution_control_state *ecs)
tmp_sal = find_pc_line (ecs->stop_func_start, 0);
if (tmp_sal.line != 0)
- goto step_into_function;
+ {
+ step_into_function (ecs);
+ return;
+ }
}
step_over_function (ecs);
keep_going (ecs);
return;
- step_into_function:
- /* Subroutine call with source code we should not step over.
- Do step to the first line of code in it. */
- {
- struct symtab *s;
-
- s = find_pc_symtab (stop_pc);
- if (s && s->language != language_asm)
- ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start);
- }
- ecs->sal = find_pc_line (ecs->stop_func_start, 0);
- /* Use the step_resume_break to step until
- the end of the prologue, even if that involves jumps
- (as it seems to on the vax under 4.2). */
- /* If the prologue ends in the middle of a source line,
- continue to the end of that source line (if it is still
- within the function). Otherwise, just go to end of prologue. */
-#ifdef PROLOGUE_FIRSTLINE_OVERLAP
- /* no, don't either. It skips any code that's
- legitimately on the first line. */
-#else
- if (ecs->sal.end && ecs->sal.pc != ecs->stop_func_start && ecs->sal.end < ecs->stop_func_end)
- ecs->stop_func_start = ecs->sal.end;
-#endif
-
- if (ecs->stop_func_start == stop_pc)
- {
- /* We are already there: stop now. */
- stop_step = 1;
- stop_stepping (ecs);
- return;
- }
- else
- /* Put the step-breakpoint there and go until there. */
- {
- struct symtab_and_line sr_sal;
-
- INIT_SAL (&sr_sal); /* initialize to zeroes */
- sr_sal.pc = ecs->stop_func_start;
- sr_sal.section = find_pc_overlay (ecs->stop_func_start);
- /* Do not specify what the fp should be when we stop
- since on some machines the prologue
- is where the new fp value is established. */
- check_for_old_step_resume_breakpoint ();
- step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
- if (breakpoints_inserted)
- insert_breakpoints ();
-
- /* And make sure stepping stops right away then. */
- step_range_end = step_range_start;
- }
- keep_going (ecs);
- return;
}
/* We've wandered out of the step range. */
@@ -2980,6 +2962,63 @@ check_sigtramp2 (struct execution_control_state *ecs)
}
}
+/* Subroutine call with source code we should not step over. Do step
+ to the first line of code in it. */
+
+static void
+step_into_function (struct execution_control_state *ecs)
+{
+ struct symtab *s;
+ struct symtab_and_line sr_sal;
+
+ s = find_pc_symtab (stop_pc);
+ if (s && s->language != language_asm)
+ ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start);
+
+ ecs->sal = find_pc_line (ecs->stop_func_start, 0);
+ /* Use the step_resume_break to step until the end of the prologue,
+ even if that involves jumps (as it seems to on the vax under
+ 4.2). */
+ /* If the prologue ends in the middle of a source line, continue to
+ the end of that source line (if it is still within the function).
+ Otherwise, just go to end of prologue. */
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+ /* no, don't either. It skips any code that's legitimately on the
+ first line. */
+#else
+ if (ecs->sal.end
+ && ecs->sal.pc != ecs->stop_func_start
+ && ecs->sal.end < ecs->stop_func_end)
+ ecs->stop_func_start = ecs->sal.end;
+#endif
+
+ if (ecs->stop_func_start == stop_pc)
+ {
+ /* We are already there: stop now. */
+ stop_step = 1;
+ stop_stepping (ecs);
+ return;
+ }
+ else
+ {
+ /* Put the step-breakpoint there and go until there. */
+ INIT_SAL (&sr_sal); /* initialize to zeroes */
+ sr_sal.pc = ecs->stop_func_start;
+ sr_sal.section = find_pc_overlay (ecs->stop_func_start);
+ /* Do not specify what the fp should be when we stop since on
+ some machines the prologue is where the new fp value is
+ established. */
+ check_for_old_step_resume_breakpoint ();
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ /* And make sure stepping stops right away then. */
+ step_range_end = step_range_start;
+ }
+ keep_going (ecs);
+}
/* We've just entered a callee, and we wish to resume until it returns
to the caller. Setting a step_resume breakpoint on the return
@@ -3234,12 +3273,10 @@ stopped_for_internal_shlib_event (bpstat bs)
static void
complete_execution (void)
{
- extern int cleanup_sigint_signal_handler (void);
-
target_executing = 0;
if (sync_execution)
{
- add_file_handler (input_fd, call_readline, 0);
+ add_file_handler (input_fd, stdin_event_handler, 0);
pop_prompt ();
sync_execution = 0;
cleanup_sigint_signal_handler ();