import gdb-1999-09-28 snapshot
[deliverable/binutils-gdb.git] / gdb / infrun.c
index a46587ecb24576266675a75021456629346bf3a4..48fe87413140e7095428540465a86dc00991bfe8 100644 (file)
@@ -35,6 +35,7 @@
 #include "top.h"
 #include <signal.h>
 #include "event-loop.h"
+#include "event-top.h"
 
 /* Prototypes for local functions */
 
@@ -268,6 +269,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 +787,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 +813,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 */
@@ -1039,7 +1069,7 @@ The same program may be running in another process.");
      and in any case decode why it stopped, and act accordingly.  */
   /* Do this only if we are not using the event loop, or if the target
      does not support asynchronous execution. */
-  if (!async_p || !target_has_async)
+  if (!event_loop_p || !target_can_async_p ())
     {
       wait_for_inferior ();
       normal_stop ();
@@ -1065,23 +1095,22 @@ start_remote (void)
   stop_soon_quietly = 1;
   trap_expected = 0;
 
-  /* Go on waiting only in case gdb is not started in async mode, or
-     in case the target doesn't support async execution. */
-  if (!async_p || !target_has_async)
-    {
-      wait_for_inferior ();
-      normal_stop ();
-    }
-  else
-    {
-      /* The 'tar rem' command should always look synchronous,
-         i.e. display the prompt only once it has connected and
-         started the target. */
-      sync_execution = 1;
-      push_prompt ("", "", "");
-      delete_file_handler (input_fd);
-      target_executing = 1;
-    }
+  /* Always go on waiting for the target, regardless of the mode. */
+  /* FIXME: cagney/1999-09-23: At present it isn't possible to
+     indicate th wait_for_inferior that a target should timeout if
+     nothing is returned (instead of just blocking).  Because of this,
+     targets expecting an immediate response need to, internally, set
+     things up so that the target_wait() is forced to eventually
+     timeout. */
+  /* FIXME: cagney/1999-09-24: It isn't possible for target_open() to
+     differentiate to its caller what the state of the target is after
+     the initial open has been performed.  Here we're assuming that
+     the target has stopped.  It should be possible to eventually have
+     target_open() return to the caller an indication that the target
+     is currently running and GDB state should be set to the same as
+     for an async run. */
+  wait_for_inferior ();
+  normal_stop ();
 }
 
 /* Initialize static vars when a new inferior begins.  */
@@ -1175,6 +1204,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 +1280,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;
 
@@ -1555,13 +1586,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->pid);
        ecs->saved_inferior_pid = inferior_pid;
        inferior_pid = ecs->pid;
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_pid = ecs->saved_inferior_pid;
        goto process_event_stop_test;
@@ -1609,13 +1634,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          }
 
        stop_pc = read_pc ();
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        goto process_event_stop_test;
 
@@ -1680,13 +1699,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->pid);
        ecs->saved_inferior_pid = inferior_pid;
        inferior_pid = ecs->pid;
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_pid = ecs->saved_inferior_pid;
        goto process_event_stop_test;
@@ -2072,22 +2085,15 @@ handle_inferior_event (struct execution_control_state *ecs)
            /* See if there is a breakpoint at the current PC.  */
            stop_bpstat = bpstat_stop_status
              (&stop_pc,
-              (DECR_PC_AFTER_BREAK ?
-           /* Notice the case of stepping through a jump
-              that lands just after a breakpoint.
-              Don't confuse that with hitting the breakpoint.
-              What we check for is that 1) stepping is going on
-              and 2) the pc before the last insn does not match
-              the address of the breakpoint before the current pc
-              and 3) 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.  */
+           /* Pass TRUE if our reason for stopping is something other
+              than hitting a breakpoint.  We do this by checking that
+              1) stepping is going on and 2) 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.  */
                (currently_stepping (ecs)
-                && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
                 && !(step_range_end
-                     && INNER_THAN (read_sp (), (step_sp - 16)))) :
-               0)
+                     && INNER_THAN (read_sp (), (step_sp - 16))))
              );
            /* Following in case break condition called a
               function.  */
@@ -2761,66 +2767,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 +2935,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,15 +3246,11 @@ 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);
-      pop_prompt ();
-      sync_execution = 0;
-      cleanup_sigint_signal_handler ();
+      do_exec_error_cleanups (ALL_CLEANUPS);
       display_gdb_prompt (0);
     }
   else
This page took 0.026604 seconds and 4 git commands to generate.