]> Git Repo - binutils.git/blobdiff - gdb/infrun.c
* annotate.texi (Breakpoint Info): Document annotation of header
[binutils.git] / gdb / infrun.c
index 8df0248d11fb90f67ca96ced406abbd917ad9f5f..dfe2cc0ae783ac8f14484ab671d260c05bd8987a 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-struct-independent code to start (run) and stop an inferior process.
-   Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993
+   Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -74,15 +74,8 @@ hook_stop_stub PARAMS ((char *));
 #define        SKIP_TRAMPOLINE_CODE(pc)        0
 #endif
 
-/* On Irix 5, some function calls automatically skip the first few
-   instructions, so we need a more complicated test to see if we are
-   the start of a function.  */
-#ifndef AT_FUNCTION_START
-#define AT_FUNCTION_START(pc,func_name,func_addr)      0
-#endif
-
 /* For SVR4 shared libraries, each call goes through a small piece of
-   trampoline code in the ".init" section.  IN_SOLIB_TRAMPOLINE evaluates
+   trampoline code in the ".plt" section.  IN_SOLIB_TRAMPOLINE evaluates
    to nonzero if we are current stopped in one of these. */
 #ifndef IN_SOLIB_TRAMPOLINE
 #define IN_SOLIB_TRAMPOLINE(pc,name)   0
@@ -287,6 +280,15 @@ proceed (addr, siggnal, step)
 
       if (breakpoint_here_p (read_pc ()))
        oneproc = 1;
+
+#ifdef STEP_SKIPS_DELAY
+      /* 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 (breakpoint_here_p (read_pc () + 4)
+         && STEP_SKIPS_DELAY (read_pc ()))
+       oneproc = 1;
+#endif /* STEP_SKIPS_DELAY */
     }
   else
     write_pc (addr);
@@ -317,12 +319,12 @@ The same program may be running in another process.");
       breakpoints_inserted = 1;
     }
 
-  if (siggnal >= 0)
+  if (siggnal != TARGET_SIGNAL_DEFAULT)
     stop_signal = siggnal;
   /* If this signal should not be seen by program,
      give it zero.  Used for debugging signals.  */
   else if (!signal_program[stop_signal])
-    stop_signal0;
+    stop_signal = TARGET_SIGNAL_0;
 
   /* Resume inferior.  */
   resume (oneproc || step || bpstat_should_step (), stop_signal);
@@ -342,6 +344,7 @@ static CORE_ADDR prev_pc;
 static CORE_ADDR prev_sp;
 static CORE_ADDR prev_func_start;
 static char *prev_func_name;
+static CORE_ADDR prev_frame_address;
 
 \f
 /* Start remote-debugging of a machine over a serial link.  */
@@ -367,6 +370,7 @@ init_wait_for_inferior ()
   prev_sp = 0;
   prev_func_start = 0;
   prev_func_name = NULL;
+  prev_frame_address = 0;
 
   trap_expected_after_continue = 0;
   breakpoints_inserted = 0;
@@ -409,20 +413,24 @@ wait_for_inferior ()
   struct symtab *current_symtab;
   int handling_longjmp = 0;    /* FIXME */
   struct breakpoint *step_resume_breakpoint = NULL;
+  struct breakpoint *through_sigtramp_breakpoint = NULL;
   int pid;
 
   old_cleanups = make_cleanup (delete_breakpoint_current_contents,
                               &step_resume_breakpoint);
+  make_cleanup (delete_breakpoint_current_contents,
+               &through_sigtramp_breakpoint);
   sal = find_pc_line(prev_pc, 0);
   current_line = sal.line;
   current_symtab = sal.symtab;
 
   /* Are we stepping?  */
-#define CURRENTLY_STEPPING() ((step_resume_breakpoint == NULL \
-                              && !handling_longjmp \
-                              && (step_range_end \
-                                  || trap_expected)) \
-                             || bpstat_should_step ())
+#define CURRENTLY_STEPPING() \
+  ((through_sigtramp_breakpoint == NULL \
+    && !handling_longjmp \
+    && ((step_range_end && step_resume_breakpoint == NULL) \
+       || trap_expected)) \
+   || bpstat_should_step ())
 
   while (1)
     {
@@ -432,17 +440,23 @@ wait_for_inferior ()
 
       pid = target_wait (-1, &w);
 
-#ifdef SIGTRAP_STOP_AFTER_LOAD
-
-      /* Somebody called load(2), and it gave us a "trap signal after load".
-         Ignore it gracefully. */
+      switch (w.kind)
+       {
+       case TARGET_WAITKIND_LOADED:
+         /* Ignore it gracefully.  */
+         if (breakpoints_inserted)
+           {
+             mark_breakpoints_out ();
+             insert_breakpoints ();
+           }
+         resume (0, TARGET_SIGNAL_0);
+         continue;
 
-      SIGTRAP_STOP_AFTER_LOAD (w);
-#endif
+       case TARGET_WAITKIND_SPURIOUS:
+         resume (0, TARGET_SIGNAL_0);
+         continue;
 
-      /* See if the process still exists; clean up if it doesn't.  */
-      if (w.kind == TARGET_WAITKIND_EXITED)
-       {
+       case TARGET_WAITKIND_EXITED:
          target_terminal_ours ();      /* Must do this before mourn anyway */
          if (w.value.integer)
            printf_filtered ("\nProgram exited with code 0%o.\n", 
@@ -456,12 +470,9 @@ wait_for_inferior ()
          one_stepped = 0;
 #endif
          stop_print_frame = 0;
-         break;
-       }
-      else if (w.kind == TARGET_WAITKIND_SIGNALLED)
-       {
-         char *signame;
+         goto stop_stepping;
 
+       case TARGET_WAITKIND_SIGNALLED:
          stop_print_frame = 0;
          stop_signal = w.value.sig;
          target_terminal_ours ();      /* Must do this before mourn anyway */
@@ -475,6 +486,11 @@ wait_for_inferior ()
 #ifdef NO_SINGLE_STEP
          one_stepped = 0;
 #endif
+         goto stop_stepping;
+
+       case TARGET_WAITKIND_STOPPED:
+         /* This is the only case in which we keep going; the above cases
+            end in a continue or goto.  */
          break;
        }
 
@@ -570,6 +586,15 @@ switch_thread:
                      delete_breakpoint (step_resume_breakpoint);
                      step_resume_breakpoint = NULL;
                    }
+
+                 /* Not sure whether we need to blow this away too,
+                    but probably it is like the step-resume
+                    breakpoint.  */
+                 if (through_sigtramp_breakpoint)
+                   {
+                     delete_breakpoint (through_sigtramp_breakpoint);
+                     through_sigtramp_breakpoint = NULL;
+                   }
                  prev_pc = 0;
                  prev_sp = 0;
                  prev_func_name = NULL;
@@ -599,8 +624,9 @@ switch_thread:
        single_step (0);        /* This actually cleans up the ss */
 #endif /* NO_SINGLE_STEP */
       
-/* If PC is pointing at a nullified instruction, then step beyond it so that
-   the user won't be confused when GDB appears to be ready to execute it. */
+      /* If PC is pointing at a nullified instruction, then step beyond
+        it so that the user won't be confused when GDB appears to be ready
+        to execute it. */
 
       if (INSTRUCTION_NULLIFIED)
        {
@@ -608,7 +634,33 @@ switch_thread:
          continue;
        }
 
-      set_current_frame ( create_new_frame (read_fp (), stop_pc));
+      set_current_frame (create_new_frame (read_fp (), stop_pc));
+      select_frame (get_current_frame (), 0);
+
+#ifdef HAVE_STEPPABLE_WATCHPOINT
+      /* It may not be necessary to disable the watchpoint to stop over
+        it.  For example, the PA can (with some kernel cooperation) 
+        single step over a watchpoint without disabling the watchpoint.  */
+      if (STOPPED_BY_WATCHPOINT (w))
+       {
+         resume (1, 0);
+         continue;
+       }
+#endif
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+      /* It is far more common to need to disable a watchpoint
+        to step the inferior over it.  FIXME.  What else might
+        a debug register or page protection watchpoint scheme need
+        here?  */
+      if (STOPPED_BY_WATCHPOINT (w))
+       {
+         remove_breakpoints ();
+         resume (1, 0);
+         insert_breakpoints ();
+         continue;
+       }
+#endif
 
       stop_frame_address = FRAME_FP (get_current_frame ());
       stop_sp = read_sp ();
@@ -662,11 +714,11 @@ switch_thread:
             if just proceeded over a breakpoint.
 
             However, if we are trying to proceed over a breakpoint
-            and end up in sigtramp, then step_resume_breakpoint
+            and end up in sigtramp, then through_sigtramp_breakpoint
             will be set and we should check whether we've hit the
             step breakpoint.  */
          if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
-             && step_resume_breakpoint == NULL)
+             && through_sigtramp_breakpoint == NULL)
            bpstat_clear (&stop_bpstat);
          else
            {
@@ -785,7 +837,13 @@ switch_thread:
              {
                delete_breakpoint (step_resume_breakpoint);
                step_resume_breakpoint = NULL;
-               what.step_resume = 0;
+             }
+           /* Not sure whether we need to blow this away too, but probably
+              it is like the step-resume breakpoint.  */
+           if (through_sigtramp_breakpoint != NULL)
+             {
+               delete_breakpoint (through_sigtramp_breakpoint);
+               through_sigtramp_breakpoint = NULL;
              }
 
 #if 0
@@ -830,32 +888,42 @@ switch_thread:
 
          case BPSTAT_WHAT_STOP_NOISY:
            stop_print_frame = 1;
-           /* We are about to nuke the step_resume_breakpoint via the
-              cleanup chain, so no need to worry about it here.  */
+
+           /* We are about to nuke the step_resume_breakpoint and
+              through_sigtramp_breakpoint via the cleanup chain, so
+              no need to worry about it here.  */
+
            goto stop_stepping;
 
          case BPSTAT_WHAT_STOP_SILENT:
            stop_print_frame = 0;
-           /* We are about to nuke the step_resume_breakpoint via the
-              cleanup chain, so no need to worry about it here.  */
-           goto stop_stepping;
 
-         case BPSTAT_WHAT_LAST:
-           /* Not a real code, but listed here to shut up gcc -Wall.  */
+           /* We are about to nuke the step_resume_breakpoint and
+              through_sigtramp_breakpoint via the cleanup chain, so
+              no need to worry about it here.  */
 
-         case BPSTAT_WHAT_KEEP_CHECKING:
-           break;
-         }
+           goto stop_stepping;
 
-       if (what.step_resume)
-         {
+         case BPSTAT_WHAT_STEP_RESUME:
            delete_breakpoint (step_resume_breakpoint);
            step_resume_breakpoint = NULL;
+           break;
+
+         case BPSTAT_WHAT_THROUGH_SIGTRAMP:
+           delete_breakpoint (through_sigtramp_breakpoint);
+           through_sigtramp_breakpoint = NULL;
 
            /* If were waiting for a trap, hitting the step_resume_break
               doesn't count as getting it.  */
            if (trap_expected)
              another_trap = 1;
+           break;
+
+         case BPSTAT_WHAT_LAST:
+           /* Not a real code, but listed here to shut up gcc -Wall.  */
+
+         case BPSTAT_WHAT_KEEP_CHECKING:
+           break;
          }
       }
 
@@ -891,10 +959,8 @@ switch_thread:
        /* Having a step-resume breakpoint overrides anything
           else having to do with stepping commands until
           that breakpoint is reached.  */
-       /* I suspect this could/should be keep_going, because if the
-          check_sigtramp2 check succeeds, then it will put in another
-          step_resume_breakpoint, and we aren't (yet) prepared to nest
-          them.  */
+       /* I'm not sure whether this needs to be check_sigtramp2 or
+          whether it could/should be keep_going.  */
        goto check_sigtramp2;
 
       if (step_range_end == 0)
@@ -927,20 +993,29 @@ switch_thread:
       if (IN_SIGTRAMP (stop_pc, stop_func_name)
          && !IN_SIGTRAMP (prev_pc, prev_func_name))
        {
+         /* We've just taken a signal; go until we are back to
+            the point where we took it and one more.  */
+
          /* This code is needed at least in the following case:
             The user types "next" and then a signal arrives (before
             the "next" is done).  */
-         /* We've just taken a signal; go until we are back to
-            the point where we took it and one more.  */
+
+         /* Note that if we are stopped at a breakpoint, then we need
+            the step_resume breakpoint to override any breakpoints at
+            the same location, so that we will still step over the
+            breakpoint even though the signal happened.  */
+
          {
            struct symtab_and_line sr_sal;
 
            sr_sal.pc = prev_pc;
            sr_sal.symtab = NULL;
            sr_sal.line = 0;
+           /* We could probably be setting the frame to
+              prev_frame_address; the reason we don't is that it didn't used
+              to exist.  */
            step_resume_breakpoint =
-             set_momentary_breakpoint (sr_sal, get_current_frame (),
-                                       bp_step_resume);
+             set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
            if (breakpoints_inserted)
              insert_breakpoints ();
          }
@@ -981,15 +1056,6 @@ switch_thread:
 
              /* If we do a call, we will be at the start of a function...  */
              || stop_pc == stop_func_start
-#if 0
-             /* Should be taken care of by the stop_pc < prologue_pc check
-                below.  Also, on irix5 where this checks for stop_pc
-                equal to stop_func_start plus 12, it would seem to be
-                wrong for a function with a 4 byte prologue, and an 8 byte
-                call; a "return" could end up at stop_func_start+12.  */
-
-             || AT_FUNCTION_START (stop_pc, stop_func_name, stop_func_start)
-#endif
 
              /* ...except on the Alpha with -O (and also Irix 5 and
                 perhaps others), in which we might call the address
@@ -1062,6 +1128,7 @@ step_over_function:
            step_resume_breakpoint =
              set_momentary_breakpoint (sr_sal, get_current_frame (),
                                        bp_step_resume);
+           step_resume_breakpoint->frame = prev_frame_address;
            if (breakpoints_inserted)
              insert_breakpoints ();
          }
@@ -1188,9 +1255,11 @@ step_into_function:
          sr_sal.pc = prev_pc;
          sr_sal.symtab = NULL;
          sr_sal.line = 0;
-         step_resume_breakpoint =
-           set_momentary_breakpoint (sr_sal, get_current_frame (),
-                                     bp_step_resume);
+         /* We perhaps could set the frame if we kept track of what
+            the frame corresponding to prev_pc was.  But we don't,
+            so don't.  */
+         through_sigtramp_breakpoint =
+           set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
          if (breakpoints_inserted)
            insert_breakpoints ();
 
@@ -1212,6 +1281,7 @@ step_into_function:
                                          function. */
       prev_func_name = stop_func_name;
       prev_sp = stop_sp;
+      prev_frame_address = stop_frame_address;
 
       /* If we did not do break;, it means we should keep
         running the inferior and not return to debugger.  */
@@ -1238,15 +1308,16 @@ step_into_function:
             to one-proceed past a breakpoint.  */
          /* If we've just finished a special step resume and we don't
             want to hit a breakpoint, pull em out.  */
-         if (step_resume_breakpoint == NULL &&
-             remove_breakpoints_on_following_step)
+         if (step_resume_breakpoint == NULL
+             && through_sigtramp_breakpoint == NULL
+             && remove_breakpoints_on_following_step)
            {
              remove_breakpoints_on_following_step = 0;
              remove_breakpoints ();
              breakpoints_inserted = 0;
            }
          else if (!breakpoints_inserted &&
-                  (step_resume_breakpoint != NULL || !another_trap))
+                  (through_sigtramp_breakpoint != NULL || !another_trap))
            {
              breakpoints_failed = insert_breakpoints ();
              if (breakpoints_failed)
@@ -1286,6 +1357,7 @@ step_into_function:
       prev_func_start = stop_func_start;
       prev_func_name = stop_func_name;
       prev_sp = stop_sp;
+      prev_frame_address = stop_frame_address;
     }
   do_cleanups (old_cleanups);
 }
@@ -1359,8 +1431,6 @@ Further execution is probably impossible.\n");
      if we have one.  */
   if (!stop_stack_dummy)
     {
-      select_frame (get_current_frame (), 0);
-
       if (stop_print_frame)
        {
          int source_only;
@@ -1389,6 +1459,10 @@ Further execution is probably impossible.\n");
          POP_FRAME ends with a setting of the current frame, so we
         can use that next. */
       POP_FRAME;
+      /* Set stop_pc to what it was before we called the function.  Can't rely
+        on restore_inferior_status because that only gets called if we don't
+        stop in the called function.  */
+      stop_pc = read_pc();
       select_frame (get_current_frame (), 0);
     }
 }
@@ -1559,15 +1633,18 @@ handle_command (args, from_tty)
              error ("Signal %d not in range 0-%d", siglast, nsigs - 1);
            }
        }
-      else if ((oursig = target_signal_from_name (*argv))
-              != TARGET_SIGNAL_UNKNOWN)
-       {
-         sigfirst = siglast = (int)oursig;
-       }
       else
        {
-         /* Not a number and not a recognized flag word => complain.  */
-         error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+         oursig = target_signal_from_name (*argv);
+         if (oursig != TARGET_SIGNAL_UNKNOWN)
+           {
+             sigfirst = siglast = (int)oursig;
+           }
+         else
+           {
+             /* Not a number and not a recognized flag word => complain.  */
+             error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+           }
        }
 
       /* If any signal numbers or symbol names were found, set flags for
@@ -1651,7 +1728,8 @@ signals_info (signum_exp, from_tty)
          int i = parse_and_eval_address (signum_exp);
          if (i >= (int)TARGET_SIGNAL_LAST
              || i < 0
-             || i == TARGET_SIGNAL_UNKNOWN)
+             || i == (int)TARGET_SIGNAL_UNKNOWN
+             || i == (int)TARGET_SIGNAL_DEFAULT)
            error ("Signal number out of bounds.");
          oursig = (enum target_signal)i;
        }
@@ -1660,11 +1738,16 @@ signals_info (signum_exp, from_tty)
     }
 
   printf_filtered ("\n");
-  for (oursig = 0; oursig < TARGET_SIGNAL_LAST; ++oursig)
+  /* These ugly casts brought to you by the native VAX compiler.  */
+  for (oursig = TARGET_SIGNAL_FIRST;
+       (int)oursig < (int)TARGET_SIGNAL_LAST;
+       oursig = (enum target_signal)((int)oursig + 1))
     {
       QUIT;
 
-      if (oursig != TARGET_SIGNAL_UNKNOWN)
+      if (oursig != TARGET_SIGNAL_UNKNOWN
+         && oursig != TARGET_SIGNAL_DEFAULT
+         && oursig != TARGET_SIGNAL_0)
        sig_print_info (oursig);
     }
 
@@ -1864,6 +1947,8 @@ of the program stops.", &cmdlist);
   signal_print[TARGET_SIGNAL_CHLD] = 0;
   signal_stop[TARGET_SIGNAL_IO] = 0;
   signal_print[TARGET_SIGNAL_IO] = 0;
+  signal_stop[TARGET_SIGNAL_POLL] = 0;
+  signal_print[TARGET_SIGNAL_POLL] = 0;
   signal_stop[TARGET_SIGNAL_URG] = 0;
   signal_print[TARGET_SIGNAL_URG] = 0;
 }
This page took 0.037509 seconds and 4 git commands to generate.