* Support debugging using native MACH primitives on hppa*-*-osf*.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 9a9e35c7e0805e752dc46e37e3f8cbc8a4487803..850f88fa04a4fff943a9dbd20c3a44e4df72101e 100644 (file)
@@ -43,26 +43,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Prototypes for local functions */
 
-static void
-signals_info PARAMS ((char *, int));
+static void signals_info PARAMS ((char *, int));
 
-static void
-handle_command PARAMS ((char *, int));
+static void handle_command PARAMS ((char *, int));
 
 static void sig_print_info PARAMS ((enum target_signal));
 
-static void
-sig_print_header PARAMS ((void));
+static void sig_print_header PARAMS ((void));
 
-static void
-resume_cleanups PARAMS ((int));
+static void resume_cleanups PARAMS ((int));
 
-static int
-hook_stop_stub PARAMS ((char *));
+static int hook_stop_stub PARAMS ((char *));
 
 /* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
    program.  It needs to examine the jmp_buf argument and extract the PC
    from it.  The return value is non-zero on success, zero otherwise. */
+
 #ifndef GET_LONGJMP_TARGET
 #define GET_LONGJMP_TARGET(PC_ADDR) 0
 #endif
@@ -71,15 +67,24 @@ hook_stop_stub PARAMS ((char *));
 /* Some machines have trampoline code that sits between function callers
    and the actual functions themselves.  If this machine doesn't have
    such things, disable their processing.  */
+
 #ifndef SKIP_TRAMPOLINE_CODE
 #define        SKIP_TRAMPOLINE_CODE(pc)        0
 #endif
 
 /* For SVR4 shared libraries, each call goes through a small piece of
-   trampoline code in the ".plt" section.  IN_SOLIB_TRAMPOLINE evaluates
+   trampoline code in the ".plt" section.  IN_SOLIB_CALL_TRAMPOLINE evaluates
    to nonzero if we are current stopped in one of these. */
-#ifndef IN_SOLIB_TRAMPOLINE
-#define IN_SOLIB_TRAMPOLINE(pc,name)   0
+
+#ifndef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc,name)      0
+#endif
+
+/* In some shared library schemes, the return path from a shared library
+   call may need to go through a trampoline too.  */
+
+#ifndef IN_SOLIB_RETURN_TRAMPOLINE
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc,name)    0
 #endif
 
 /* On some systems, the PC may be left pointing at an instruction that  won't
@@ -308,7 +313,7 @@ proceed (addr, siggnal, step)
      breakpoint to be hit again, but you can always continue, so it's not
      a big deal.)  */
 
-  if (! step && PREPARE_TO_PROCEED && breakpoint_here_p (read_pc ()))
+  if (! step && PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
     oneproc = 1;
 #endif /* PREPARE_TO_PROCEED */
 
@@ -362,10 +367,8 @@ The same program may be running in another process.");
    to be preserved over calls to it and cleared when the inferior
    is started.  */
 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.  */
@@ -373,6 +376,7 @@ static CORE_ADDR prev_frame_address;
 void
 start_remote ()
 {
+  init_thread_list ();
   init_wait_for_inferior ();
   clear_proceed_status ();
   stop_soon_quietly = 1;
@@ -388,10 +392,8 @@ init_wait_for_inferior ()
 {
   /* These are meaningless until the first time through wait_for_inferior.  */
   prev_pc = 0;
-  prev_sp = 0;
   prev_func_start = 0;
   prev_func_name = NULL;
-  prev_frame_address = 0;
 
   trap_expected_after_continue = 0;
   breakpoints_inserted = 0;
@@ -423,7 +425,6 @@ wait_for_inferior ()
   struct target_waitstatus w;
   int another_trap;
   int random_signal;
-  CORE_ADDR stop_sp = 0;
   CORE_ADDR stop_func_start;
   CORE_ADDR stop_func_end;
   char *stop_func_name;
@@ -436,6 +437,7 @@ wait_for_inferior ()
   struct breakpoint *step_resume_breakpoint = NULL;
   struct breakpoint *through_sigtramp_breakpoint = NULL;
   int pid;
+  int update_step_sp = 0;
 
   old_cleanups = make_cleanup (delete_breakpoint_current_contents,
                               &step_resume_breakpoint);
@@ -462,7 +464,10 @@ wait_for_inferior ()
 
       registers_changed ();
 
-      pid = target_wait (-1, &w);
+      if (target_wait_hook)
+       pid = target_wait_hook (-1, &w);
+      else
+       pid = target_wait (-1, &w);
 
       flush_cached_frames ();
 
@@ -473,6 +478,17 @@ wait_for_inferior ()
        {
          fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
          add_thread (pid);
+
+         /* We may want to consider not doing a resume here in order to give
+            the user a chance to play with the new thread.  It might be good
+            to make that a user-settable option.  */
+
+         /* At this point, all threads are stopped (happens automatically in
+            either the OS or the native code).  Therefore we need to continue
+            all threads in order to make progress.  */
+
+         target_resume (-1, 0, TARGET_SIGNAL_0);
+         continue;
        }
 
       switch (w.kind)
@@ -498,8 +514,7 @@ wait_for_inferior ()
            printf_filtered ("\nProgram exited with code 0%o.\n", 
                             (unsigned int)w.value.integer);
          else
-           if (!batch_mode())
-             printf_filtered ("\nProgram exited normally.\n");
+           printf_filtered ("\nProgram exited normally.\n");
          gdb_flush (gdb_stdout);
          target_mourn_inferior ();
 #ifdef NO_SINGLE_STEP
@@ -513,7 +528,14 @@ wait_for_inferior ()
          stop_signal = w.value.sig;
          target_terminal_ours ();      /* Must do this before mourn anyway */
          annotate_signalled ();
+
+         /* This looks pretty bogus to me.  Doesn't TARGET_WAITKIND_SIGNALLED
+            mean it is already dead?  This has been here since GDB 2.8, so
+            perhaps it means rms didn't understand unix waitstatuses?
+            For the moment I'm just kludging around this in remote.c
+            rather than trying to change it here --kingdon, 5 Dec 1994.  */
          target_kill ();               /* kill mourns as well */
+
          printf_filtered ("\nProgram terminated with signal ");
          annotate_signal_name ();
          printf_filtered ("%s", target_signal_to_name (stop_signal));
@@ -559,7 +581,11 @@ wait_for_inferior ()
              target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
              /* FIXME: What if a signal arrives instead of the single-step
                 happening?  */
-             target_wait (pid, &w);
+
+             if (target_wait_hook)
+               target_wait_hook (pid, &w);
+             else
+               target_wait (pid, &w);
              insert_breakpoints ();
              target_resume (pid, 0, TARGET_SIGNAL_0);
              continue;
@@ -630,7 +656,6 @@ wait_for_inferior ()
              through_sigtramp_breakpoint = NULL;
            }
          prev_pc = 0;
-         prev_sp = 0;
          prev_func_name = NULL;
          step_range_start = 0;
          step_range_end = 0;
@@ -654,9 +679,6 @@ wait_for_inferior ()
          continue;
        }
 
-      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) 
@@ -696,8 +718,6 @@ wait_for_inferior ()
       STOPPED_BY_WATCHPOINT (w);
 #endif
 
-      stop_frame_address = FRAME_FP (get_current_frame ());
-      stop_sp = read_sp ();
       stop_func_start = 0;
       stop_func_name = 0;
       /* Don't care about return value; stop_func_start and stop_func_name
@@ -758,7 +778,7 @@ wait_for_inferior ()
            {
              /* See if there is a breakpoint at the current PC.  */
              stop_bpstat = bpstat_stop_status
-               (&stop_pc, stop_frame_address,
+               (&stop_pc,
 #if DECR_PC_AFTER_BREAK
                 /* Notice the case of stepping through a jump
                    that lands just after a breakpoint.
@@ -782,7 +802,8 @@ wait_for_inferior ()
              = !(bpstat_explains_signal (stop_bpstat)
                  || trap_expected
 #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
-                 || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                 || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+                                      FRAME_FP (get_current_frame ()))
 #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                  || (step_range_end && step_resume_breakpoint == NULL));
          else
@@ -793,7 +814,8 @@ wait_for_inferior ()
                       news) give another signal besides SIGTRAP,
                       so check here as well as above.  */
 #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
-                   || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                   || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+                                        FRAME_FP (get_current_frame ()))
 #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                    );
              if (!random_signal)
@@ -904,7 +926,7 @@ wait_for_inferior ()
 #if 0
            /* FIXME - Need to implement nested temporary breakpoints */
            if (step_over_calls
-               && (stop_frame_address
+               && (FRAME_FP (get_current_frame ())
                    INNER_THAN step_frame_address))
              {
                another_trap = 1;
@@ -950,7 +972,8 @@ wait_for_inferior ()
            break;
 
          case BPSTAT_WHAT_THROUGH_SIGTRAMP:
-           delete_breakpoint (through_sigtramp_breakpoint);
+           if (through_sigtramp_breakpoint)
+             delete_breakpoint (through_sigtramp_breakpoint);
            through_sigtramp_breakpoint = NULL;
 
            /* If were waiting for a trap, hitting the step_resume_break
@@ -983,7 +1006,7 @@ wait_for_inferior ()
         just stop silently, unless the user was doing an si/ni, in which
         case she'd better know what she's doing.  */
 
-      if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+      if (PC_IN_CALL_DUMMY (stop_pc, read_sp (), FRAME_FP (get_current_frame ()))
          && !step_range_end)
        {
          stop_print_frame = 0;
@@ -1017,17 +1040,21 @@ wait_for_inferior ()
             step range and either the stack or frame pointers
             just changed, we've stepped outside */
          && !(stop_pc == step_range_start
-              && stop_frame_address
-              && (stop_sp INNER_THAN prev_sp
-                  || stop_frame_address != step_frame_address)))
+              && FRAME_FP (get_current_frame ())
+              && (read_sp () INNER_THAN step_sp
+                  || FRAME_FP (get_current_frame ()) != step_frame_address)))
        {
          /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
             So definately need to check for sigtramp here.  */
          goto check_sigtramp2;
        }
 
-      /* We stepped out of the stepping range.  See if that was due
-        to a subroutine call that we should proceed to the end of.  */
+      /* We stepped out of the stepping range.  */
+
+      /* We can't update step_sp every time through the loop, because
+        reading the stack pointer would slow down stepping too much.
+        But we can update it every time we leave the step range.  */
+      update_step_sp = 1;
 
       /* Did we just take a signal?  */
       if (IN_SIGTRAMP (stop_pc, stop_func_name)
@@ -1052,8 +1079,7 @@ wait_for_inferior ()
            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_frame_address; I don't think anyone thought to try it.  */
            step_resume_breakpoint =
              set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
            if (breakpoints_inserted)
@@ -1073,6 +1099,9 @@ wait_for_inferior ()
        }
 
 #if 1
+      /* See if we left the step range due to a subroutine call that
+        we should proceed to the end of.  */
+
       if (stop_func_start)
        {
          struct symtab *s;
@@ -1096,7 +1125,7 @@ wait_for_inferior ()
           /* 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)
+          || read_sp () != step_sp)
          && (/* PC is completely out of bounds of any known objfiles.  Treat
                 like a subroutine call. */
              ! stop_func_start
@@ -1112,11 +1141,21 @@ wait_for_inferior ()
 
              || stop_pc < prologue_pc
 
+             /* ...and if it is a leaf function, the prologue might
+                consist of gp loading only, so the call transfers to
+                the first instruction after the prologue.  */
+             || (stop_pc == prologue_pc
+
+                 /* Distinguish this from the case where we jump back
+                    to the first instruction after the prologue,
+                    within a function.  */
+                  && stop_func_start != prev_func_start)
+
              /* 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)
+             || IN_SOLIB_CALL_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,
@@ -1183,7 +1222,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;
+           step_resume_breakpoint->frame = step_frame_address;
            if (breakpoints_inserted)
              insert_breakpoints ();
          }
@@ -1254,6 +1293,38 @@ step_into_function:
          break;
        }
 
+      /* If we're in the return path from a shared library trampoline,
+        we want to proceed through the trampoline when stepping.  */
+      if (IN_SOLIB_RETURN_TRAMPOLINE(stop_pc, stop_func_name))
+       {
+         CORE_ADDR tmp;
+
+         /* Determine where this trampoline returns.  */
+         tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+         /* Only proceed through if we know where it's going.  */
+         if (tmp)
+           {
+             /* And put the step-breakpoint there and go until there. */
+             struct symtab_and_line sr_sal;
+
+             sr_sal.pc = tmp;
+             sr_sal.symtab = NULL;
+             sr_sal.line = 0;
+             /* 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.  */
+             step_resume_breakpoint =
+               set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+             if (breakpoints_inserted)
+               insert_breakpoints ();
+
+             /* Restart without fiddling with the step ranges or
+                other state.  */
+             goto keep_going;
+           }
+       }
+        
       if (sal.line == 0)
        {
          /* We have no line number information.  That means to stop
@@ -1341,8 +1412,10 @@ step_into_function:
                                          been at the start of a
                                          function. */
       prev_func_name = stop_func_name;
-      prev_sp = stop_sp;
-      prev_frame_address = stop_frame_address;
+
+      if (update_step_sp)
+       step_sp = read_sp ();
+      update_step_sp = 0;
 
       /* If we did not do break;, it means we should keep
         running the inferior and not return to debugger.  */
@@ -1417,8 +1490,6 @@ step_into_function:
       prev_pc = read_pc ();
       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);
 }
@@ -1492,6 +1563,8 @@ 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;
@@ -1499,7 +1572,7 @@ Further execution is probably impossible.\n");
          source_only = bpstat_print (stop_bpstat);
          source_only = source_only ||
                (   stop_step
-                && step_frame_address == stop_frame_address
+                && step_frame_address == FRAME_FP (get_current_frame ())
                 && step_start_function == find_pc_function (stop_pc));
 
           print_stack_frame (selected_frame, -1, source_only? -1: 1);
@@ -1828,7 +1901,6 @@ save_inferior_status (inf_status, restore_stack_info)
 {
   inf_status->stop_signal = stop_signal;
   inf_status->stop_pc = stop_pc;
-  inf_status->stop_frame_address = stop_frame_address;
   inf_status->stop_step = stop_step;
   inf_status->stop_stack_dummy = stop_stack_dummy;
   inf_status->stopped_by_random_signal = stopped_by_random_signal;
@@ -1858,7 +1930,7 @@ save_inferior_status (inf_status, restore_stack_info)
 }
 
 struct restore_selected_frame_args {
-  FRAME_ADDR frame_address;
+  CORE_ADDR frame_address;
   int level;
 };
 
@@ -1868,27 +1940,28 @@ static int restore_selected_frame PARAMS ((char *));
    restore_selected_frame_args * (declared as char * for catch_errors)
    telling us what frame to restore.  Returns 1 for success, or 0 for
    failure.  An error message will have been printed on error.  */
+
 static int
 restore_selected_frame (args)
      char *args;
 {
   struct restore_selected_frame_args *fr =
     (struct restore_selected_frame_args *) args;
-  FRAME fid;
+  struct frame_info *frame;
   int level = fr->level;
 
-  fid = find_relative_frame (get_current_frame (), &level);
+  frame = find_relative_frame (get_current_frame (), &level);
 
   /* If inf_status->selected_frame_address is NULL, there was no
      previously selected frame.  */
-  if (fid == 0 ||
-      FRAME_FP (fid) != fr->frame_address ||
+  if (frame == NULL ||
+      FRAME_FP (frame) != fr->frame_address ||
       level != 0)
     {
       warning ("Unable to restore previously selected frame.\n");
       return 0;
     }
-  select_frame (fid, fr->level);
+  select_frame (frame, fr->level);
   return(1);
 }
 
@@ -1898,7 +1971,6 @@ restore_inferior_status (inf_status)
 {
   stop_signal = inf_status->stop_signal;
   stop_pc = inf_status->stop_pc;
-  stop_frame_address = inf_status->stop_frame_address;
   stop_step = inf_status->stop_step;
   stop_stack_dummy = inf_status->stop_stack_dummy;
   stopped_by_random_signal = inf_status->stopped_by_random_signal;
This page took 0.029764 seconds and 4 git commands to generate.