* Makefile.in (c-exp.tab.o): Remove notice about shift/reduce conflicts
[binutils-gdb.git] / gdb / infrun.c
index b3484a157c024b9f28cf96ce551f71b2544fa017..85ebb38f108699b5e3d90290c2ef1786e077e571 100644 (file)
@@ -18,90 +18,6 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-/* Notes on the algorithm used in wait_for_inferior to determine if we
-   just did a subroutine call when stepping.  We have the following
-   information at that point:
-
-                  Current and previous (just before this step) pc.
-                 Current and previous sp.
-                 Current and previous start of current function.
-
-   If the starts of the functions don't match, then
-
-       a) We did a subroutine call.
-
-   In this case, the pc will be at the beginning of a function.
-
-       b) We did a subroutine return.
-
-   Otherwise.
-
-       c) We did a longjmp.
-
-   If we did a longjump, we were doing "nexti", since a next would
-   have attempted to skip over the assembly language routine in which
-   the longjmp is coded and would have simply been the equivalent of a
-   continue.  I consider this ok behaivior.  We'd like one of two
-   things to happen if we are doing a nexti through the longjmp()
-   routine: 1) It behaves as a stepi, or 2) It acts like a continue as
-   above.  Given that this is a special case, and that anybody who
-   thinks that the concept of sub calls is meaningful in the context
-   of a longjmp, I'll take either one.  Let's see what happens.  
-
-   Acts like a subroutine return.  I can handle that with no problem
-   at all.
-
-   -->So: If the current and previous beginnings of the current
-   function don't match, *and* the pc is at the start of a function,
-   we've done a subroutine call.  If the pc is not at the start of a
-   function, we *didn't* do a subroutine call.  
-
-   -->If the beginnings of the current and previous function do match,
-   either: 
-
-       a) We just did a recursive call.
-
-          In this case, we would be at the very beginning of a
-          function and 1) it will have a prologue (don't jump to
-          before prologue, or 2) (we assume here that it doesn't have
-          a prologue) there will have been a change in the stack
-          pointer over the last instruction.  (Ie. it's got to put
-          the saved pc somewhere.  The stack is the usual place.  In
-          a recursive call a register is only an option if there's a
-          prologue to do something with it.  This is even true on
-          register window machines; the prologue sets up the new
-          window.  It might not be true on a register window machine
-          where the call instruction moved the register window
-          itself.  Hmmm.  One would hope that the stack pointer would
-          also change.  If it doesn't, somebody send me a note, and
-          I'll work out a more general theory.
-          bug-gdb@prep.ai.mit.edu).  This is true (albeit slipperly
-          so) on all machines I'm aware of:
-
-             m68k:     Call changes stack pointer.  Regular jumps don't.
-
-             sparc:    Recursive calls must have frames and therefor,
-                       prologues.
-
-             vax:      All calls have frames and hence change the
-                       stack pointer.
-
-       b) We did a return from a recursive call.  I don't see that we
-          have either the ability or the need to distinguish this
-          from an ordinary jump.  The stack frame will be printed
-          when and if the frame pointer changes; if we are in a
-          function without a frame pointer, it's the users own
-          lookout.
-
-       c) We did a jump within a function.  We assume that this is
-          true if we didn't do a recursive call.
-
-       d) We are in no-man's land ("I see no symbols here").  We
-          don't worry about this; it will make calls look like simple
-          jumps (and the stack frames will be printed when the frame
-          pointer moves), which is a reasonably non-violent response.
-*/
-
 #include "defs.h"
 #include <string.h>
 #include <ctype.h>
@@ -113,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "target.h"
+#include "thread.h"
 
 #include <signal.h>
 
@@ -283,6 +200,14 @@ resume (step, sig)
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   QUIT;
 
+#ifdef CANNOT_STEP_BREAKPOINT
+  /* Most targets can step a breakpoint instruction, thus executing it
+     normally.  But if this one cannot, just continue and we will hit
+     it anyway.  */
+  if (step && breakpoints_inserted && breakpoint_here_p (read_pc ()))
+    step = 0;
+#endif
+
 #ifdef NO_SINGLE_STEP
   if (step) {
     single_step(sig);  /* Do it the hard way, w/temp breakpoints */
@@ -295,7 +220,10 @@ resume (step, sig)
   DO_DEFERRED_STORES;
 #endif
 
-  target_resume (inferior_pid, step, sig);
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  target_resume (-1, step, sig);
   discard_cleanups (old_cleanups);
 }
 
@@ -383,9 +311,6 @@ The same program may be running in another process.");
       breakpoints_inserted = 1;
     }
 
-  /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
-
   if (siggnal >= 0)
     stop_signal = siggnal;
   /* If this signal should not be seen by program,
@@ -439,7 +364,7 @@ init_wait_for_inferior ()
 
   trap_expected_after_continue = 0;
   breakpoints_inserted = 0;
-  mark_breakpoints_out ();
+  breakpoint_init_inferior ();
   stop_signal = 0;             /* Don't confuse first call to proceed(). */
 }
 
@@ -467,6 +392,7 @@ wait_for_inferior ()
   int random_signal;
   CORE_ADDR stop_sp = 0;
   CORE_ADDR stop_func_start;
+  CORE_ADDR stop_func_end;
   char *stop_func_name;
   CORE_ADDR prologue_pc = 0, tmp;
   struct symtab_and_line sal;
@@ -494,7 +420,7 @@ wait_for_inferior ()
       flush_cached_frames ();
       registers_changed ();
 
-      pid = target_wait (&w);
+      pid = target_wait (-1, &w);
 
 #ifdef SIGTRAP_STOP_AFTER_LOAD
 
@@ -550,7 +476,43 @@ wait_for_inferior ()
 #endif
          break;
        }
-      
+
+      stop_signal = WSTOPSIG (w);
+
+      if (pid != inferior_pid)
+       {
+         int save_pid = inferior_pid;
+
+         inferior_pid = pid;   /* Setup for target memory/regs */
+         registers_changed ();
+         stop_pc = read_pc ();
+         inferior_pid = save_pid;
+         registers_changed ();
+       }
+      else
+       stop_pc = read_pc ();
+
+      if (stop_signal == SIGTRAP
+         && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+       if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
+         {
+           /* Saw a breakpoint, but it was hit by the wrong thread.  Just continue. */
+           if (breakpoints_inserted)
+             {
+               remove_breakpoints ();
+               target_resume (pid, 1, 0); /* Single step */
+               /* FIXME: What if a signal arrives instead of the single-step
+                  happening?  */
+               target_wait (pid, NULL);
+               insert_breakpoints ();
+             }
+           target_resume (-1, 0, 0);
+           continue;
+         }
+       else
+         if (pid != inferior_pid)
+           goto switch_thread;
+
       if (pid != inferior_pid)
        {
          int printed = 0;
@@ -560,13 +522,11 @@ wait_for_inferior ()
              fprintf (stderr, "[New %s]\n", target_pid_to_str (pid));
              add_thread (pid);
 
-             target_resume (pid, 0, 0);
+             target_resume (-1, 0, 0);
              continue;
            }
          else
            {
-             stop_signal = WSTOPSIG (w);
-
              if (stop_signal >= NSIG || signal_print[stop_signal])
                {
                  char *signame;
@@ -584,8 +544,11 @@ wait_for_inferior ()
                  fflush (stdout);
                }
 
-             if (stop_signal >= NSIG || signal_stop[stop_signal])
+             if (stop_signal == SIGTRAP
+                 || stop_signal >= NSIG
+                 || signal_stop[stop_signal])
                {
+switch_thread:
                  inferior_pid = pid;
                  printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
 
@@ -615,7 +578,7 @@ wait_for_inferior ()
                  if (signal_program[stop_signal] == 0)
                    stop_signal = 0;
 
-                 target_resume (pid, 0, stop_signal);
+                 target_resume (-1, 0, stop_signal);
                  continue;
                }
            }
@@ -635,17 +598,17 @@ wait_for_inferior ()
          continue;
        }
 
-      stop_pc = read_pc ();
       set_current_frame ( create_new_frame (read_fp (), stop_pc));
 
       stop_frame_address = FRAME_FP (get_current_frame ());
       stop_sp = read_sp ();
       stop_func_start = 0;
+      stop_func_end = 0;
       stop_func_name = 0;
       /* Don't care about return value; stop_func_start and stop_func_name
         will both be 0 if it doesn't work.  */
       find_pc_partial_function (stop_pc, &stop_func_name, &stop_func_start,
-                               (CORE_ADDR *)NULL);
+                               &stop_func_end);
       stop_func_start += FUNCTION_START_OFFSET;
       another_trap = 0;
       bpstat_clear (&stop_bpstat);
@@ -664,8 +627,6 @@ wait_for_inferior ()
         3) set random_signal to 1, and the decision between 1 and 2
         will be made according to the signal handling tables.  */
       
-      stop_signal = WSTOPSIG (w);
-      
       /* First, distinguish signals caused by the debugger from signals
         that have to do with the program's own actions.
         Note that breakpoint insns may cause SIGTRAP or SIGILL
@@ -883,6 +844,9 @@ wait_for_inferior ()
               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.  */
+
          case BPSTAT_WHAT_KEEP_CHECKING:
            break;
          }
@@ -1005,13 +969,48 @@ wait_for_inferior ()
          SKIP_PROLOGUE (prologue_pc);
        }
 
-      /* ==> See comments at top of file on this algorithm.  <==*/
+      if ((/* Might be a non-recursive call.  If the symbols are missing
+             enough that stop_func_start == prev_func_start even though
+             they are really two functions, we will treat some calls as
+             jumps.  */
+          stop_func_start != prev_func_start
+
+          /* Might be a recursive call if either we have a prologue
+             or the call instruction itself saves the PC on the stack.  */
+          || prologue_pc != stop_func_start
+          || stop_sp != prev_sp)
+         && (/* I think this can only happen if stop_func_start is zero
+                (e.g. stop_pc is in some objfile we don't know about).
+                If the stop_pc does that (ends up someplace unknown), it
+                must be some sort of subroutine call.  */
+             stop_pc < stop_func_start
+             || stop_pc >= stop_func_end
+
+             /* If we do a call, we will be at the start of a function.  */
+             || stop_pc == stop_func_start
 
-      if ((stop_pc == stop_func_start
-          || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name))
-         && (stop_func_start != prev_func_start
-             || prologue_pc != stop_func_start
-             || stop_sp != prev_sp))
+#if 0
+             /* Not conservative enough for 4.11.  FIXME: enable this
+                after 4.11.  */
+             /* Except on the Alpha with -O (and perhaps other machines
+                with similar calling conventions), in which we might
+                call the address after the load of gp.  Since prologues
+                don't contain calls, we can't return to within one, and
+                we don't jump back into them, so this check is OK.  */
+             || stop_pc < prologue_pc
+#endif
+
+             /* If we end up in certain places, it means we did a subroutine
+                call.  I'm not completely sure this is necessary now that we
+                have the above checks with stop_func_start (and now that
+                find_pc_partial_function is pickier).  */
+             || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name)
+
+             /* If none of the above apply, it is a jump within a function,
+                or a return from a subroutine.  The other case is longjmp,
+                which can no longer happen here as long as the
+                handling_longjmp stuff is working.  */
+             ))
        {
          /* It's a subroutine call.  */
 
@@ -1255,19 +1254,13 @@ step_into_function:
          /* I'm not sure when this following segment applies.  I do know, now,
             that we shouldn't rewrite the regs when we were stopped by a
             random signal from the inferior process.  */
+         /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
+            (this is only used on the 88k).  */
 
           if (!bpstat_explains_signal (stop_bpstat)
              && (stop_signal != SIGCLD) 
               && !stopped_by_random_signal)
-            {
-            CORE_ADDR pc_contents = read_register (PC_REGNUM);
-            CORE_ADDR npc_contents = read_register (NPC_REGNUM);
-            if (pc_contents != npc_contents)
-              {
-              write_register (NNPC_REGNUM, npc_contents);
-              write_register (NPC_REGNUM, pc_contents);
-             }
-            }
+            SHIFT_INST_REGS();
 #endif /* SHIFT_INST_REGS */
 
          resume (CURRENTLY_STEPPING (), stop_signal);
@@ -1302,7 +1295,7 @@ normal_stop ()
   /* Make sure that the current_frame's pc is correct.  This
      is a correction for setting up the frame info before doing
      DECR_PC_AFTER_BREAK */
-  if (target_has_execution)
+  if (target_has_execution && get_current_frame())
     (get_current_frame ())->pc = read_pc ();
   
   if (breakpoints_failed)
@@ -1592,7 +1585,7 @@ handle_command (args, from_tty)
       argv++;
     }
 
-  target_notice_signals();
+  target_notice_signals(inferior_pid);
 
   if (from_tty)
     {