* gdbarch.sh: Document the return_value method. Explain that
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 5428a058e5bf5401560d652b125a45d90e952fc8..f576a59123d3b0d1cdb7def6b7596c16b7df8be3 100644 (file)
@@ -2,8 +2,8 @@
    process.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -82,8 +82,6 @@ static int prepare_to_proceed (int);
 
 void _initialize_infrun (void);
 
-int inferior_ignoring_leading_exec_events = 0;
-
 /* When set, stop the 'step' command if we enter a function which has
    no line number information.  The normal behavior is that we step
    over such function.  */
@@ -105,15 +103,6 @@ int sync_execution = 0;
 
 static ptid_t previous_inferior_ptid;
 
-/* This is true for configurations that may follow through execl() and
-   similar functions.  At present this is only true for HP-UX native.  */
-
-#ifndef MAY_FOLLOW_EXEC
-#define MAY_FOLLOW_EXEC (0)
-#endif
-
-static int may_follow_exec = MAY_FOLLOW_EXEC;
-
 static int debug_infrun = 0;
 static void
 show_debug_infrun (struct ui_file *file, int from_tty,
@@ -369,9 +358,6 @@ follow_exec (int pid, char *execd_pathname)
   int saved_pid = pid;
   struct target_ops *tgt;
 
-  if (!may_follow_exec)
-    return;
-
   /* This is an exec event that we actually wish to pay attention to.
      Refresh our symbol table to the newly exec'd program, remove any
      momentary bp's, etc.
@@ -406,17 +392,20 @@ follow_exec (int pid, char *execd_pathname)
   /* We've followed the inferior through an exec.  Therefore, the
      inferior has essentially been killed & reborn. */
 
-  /* First collect the run target in effect.  */
-  tgt = find_run_target ();
-  /* If we can't find one, things are in a very strange state...  */
-  if (tgt == NULL)
-    error (_("Could find run target to save before following exec"));
-
   gdb_flush (gdb_stdout);
-  target_mourn_inferior ();
-  inferior_ptid = pid_to_ptid (saved_pid);
+  generic_mourn_inferior ();
   /* Because mourn_inferior resets inferior_ptid. */
-  push_target (tgt);
+  inferior_ptid = pid_to_ptid (saved_pid);
+
+  if (gdb_sysroot && *gdb_sysroot)
+    {
+      char *name = alloca (strlen (gdb_sysroot)
+                           + strlen (execd_pathname)
+                           + 1);
+      strcpy (name, gdb_sysroot);
+      strcat (name, execd_pathname);
+      execd_pathname = name;
+    }
 
   /* That a.out is now the one to use. */
   exec_file_attach (execd_pathname, 0);
@@ -427,9 +416,7 @@ follow_exec (int pid, char *execd_pathname)
   /* Reset the shared library package.  This ensures that we get
      a shlib event when the child reaches "_start", at which point
      the dld will have had a chance to initialize the child. */
-#if defined(SOLIB_RESTART)
-  SOLIB_RESTART ();
-#endif
+  no_shared_libraries (NULL, 0);
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
   SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
 #else
@@ -627,19 +614,18 @@ a command like `return' or `jump' to continue execution."));
        }
 
       if ((step || singlestep_breakpoints_inserted_p)
-         && breakpoint_here_p (read_pc ())
-         && !breakpoint_inserted_here_p (read_pc ()))
+         && stepping_over_breakpoint)
        {
-         /* We're stepping, have breakpoint at PC, and it's 
-            not inserted.  Most likely, proceed has noticed that
-            we have breakpoint and tries to single-step over it,
-            so that it's not hit.  In which case, we need to
-            single-step only this thread, and keep others stopped,
-            as they can miss this breakpoint if allowed to run.  
-
-            The current code either has all breakpoints inserted, 
-            or all removed, so if we let other threads run,
-            we can actually miss any breakpoint, not the one at PC.  */
+         /* We're allowing a thread to run past a breakpoint it has
+            hit, by single-stepping the thread with the breakpoint
+            removed.  In which case, we need to single-step only this
+            thread, and keep others stopped, as they can miss this
+            breakpoint if allowed to run.
+
+            The current code actually removes all breakpoints when
+            doing this, not just the one being stepped over, so if we
+            let other threads run, we can actually miss any
+            breakpoint, not just the one at PC.  */
          resume_ptid = inferior_ptid;
        }
 
@@ -800,9 +786,17 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
     oneproc = 1;
 
   if (oneproc)
-    /* We will get a trace trap after one instruction.
-       Continue it automatically and insert breakpoints then.  */
-    stepping_over_breakpoint = 1;
+    {
+      /* We will get a trace trap after one instruction.
+        Continue it automatically and insert breakpoints then.  */
+      stepping_over_breakpoint = 1;
+      /* FIXME: if breakpoints are always inserted, we'll trap
+       if trying to single-step over breakpoint.  Disable
+      all breakpoints.  In future, we'd need to invent some
+      smart way of stepping over breakpoint instruction without
+      hitting breakpoint.  */
+      remove_breakpoints ();
+    }
   else
     insert_breakpoints ();
 
@@ -852,7 +846,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      does not support asynchronous execution. */
   if (!target_can_async_p ())
     {
-      wait_for_inferior ();
+      wait_for_inferior (0);
       normal_stop ();
     }
 }
@@ -882,7 +876,7 @@ start_remote (int from_tty)
      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 ();
+  wait_for_inferior (0);
 
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
@@ -912,6 +906,8 @@ init_wait_for_inferior (void)
 
   stepping_past_singlestep_breakpoint = 0;
   deferred_step_ptid = null_ptid;
+
+  target_last_wait_ptid = minus_one_ptid;
 }
 \f
 /* This enum encodes possible reasons for doing a target_wait, so that
@@ -987,20 +983,28 @@ static void print_stop_reason (enum inferior_stop_reason stop_reason,
                               int stop_info);
 
 /* Wait for control to return from inferior to debugger.
+
+   If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
+   as if they were SIGTRAP signals.  This can be useful during
+   the startup sequence on some targets such as HP/UX, where
+   we receive an EXEC event instead of the expected SIGTRAP.
+
    If inferior gets a signal, we may decide to start it up again
    instead of returning.  That is why there is a loop in this function.
    When this function actually returns it means the inferior
    should be left stopped and GDB should read more commands.  */
 
 void
-wait_for_inferior (void)
+wait_for_inferior (int treat_exec_as_sigtrap)
 {
   struct cleanup *old_cleanups;
   struct execution_control_state ecss;
   struct execution_control_state *ecs;
 
   if (debug_infrun)
-    fprintf_unfiltered (gdb_stdlog, "infrun: wait_for_inferior\n");
+    fprintf_unfiltered
+      (gdb_stdlog, "infrun: wait_for_inferior (treat_exec_as_sigtrap=%d)\n",
+       treat_exec_as_sigtrap);
 
   old_cleanups = make_cleanup (delete_step_resume_breakpoint,
                               &step_resume_breakpoint);
@@ -1032,6 +1036,13 @@ wait_for_inferior (void)
       else
        ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
 
+      if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
+        {
+          xfree (ecs->ws.value.execd_pathname);
+          ecs->ws.kind = TARGET_WAITKIND_STOPPED;
+          ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
+        }
+
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
 
@@ -1062,9 +1073,6 @@ fetch_inferior_event (void *client_data)
 
   if (!async_ecs->wait_some_more)
     {
-      old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint,
-                                       &step_resume_breakpoint);
-
       /* Fill in with reasonable starting values.  */
       init_execution_control_state (async_ecs);
 
@@ -1093,10 +1101,8 @@ fetch_inferior_event (void *client_data)
 
   if (!async_ecs->wait_some_more)
     {
-      /* Do only the cleanups that have been added by this
-         function. Let the continuations for the commands do the rest,
-         if there are any. */
-      do_exec_cleanups (old_cleanups);
+      delete_step_resume_breakpoint (&step_resume_breakpoint);
+
       normal_stop ();
       if (step_multi && stop_step)
        inferior_event_handler (INF_EXEC_CONTINUE, NULL);
@@ -1275,6 +1281,9 @@ handle_inferior_event (struct execution_control_state *ecs)
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = *ecs->wp;
 
+  /* Always clear state belonging to the previous time we stopped.  */
+  stop_stack_dummy = 0;
+
   adjust_pc_after_break (ecs);
 
   switch (ecs->infwait_state)
@@ -1326,13 +1335,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   if (ecs->ws.kind != TARGET_WAITKIND_EXITED
       && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event)
-    {
-      add_thread (ecs->ptid);
-
-      ui_out_text (uiout, "[New ");
-      ui_out_text (uiout, target_pid_or_tid_to_str (ecs->ptid));
-      ui_out_text (uiout, "]\n");
-    }
+    add_thread (ecs->ptid);
 
   switch (ecs->ws.kind)
     {
@@ -1347,10 +1350,6 @@ handle_inferior_event (struct execution_control_state *ecs)
          established.  */
       if (stop_soon == NO_STOP_QUIETLY)
        {
-         /* Remove breakpoints, SOLIB_ADD might adjust
-            breakpoint addresses via breakpoint_re_set.  */
-         remove_breakpoints ();
-
          /* Check for any newly added shared libraries if we're
             supposed to be adding them automatically.  Switch
             terminal for any messages produced by
@@ -1390,9 +1389,6 @@ handle_inferior_event (struct execution_control_state *ecs)
 
          /* NOTE drow/2007-05-11: This might be a good place to check
             for "catch load".  */
-
-         /* Reinsert breakpoints and continue.  */
-         insert_breakpoints ();
        }
 
       /* If we are skipping through a shell, or through shared library
@@ -1401,6 +1397,10 @@ handle_inferior_event (struct execution_control_state *ecs)
         we're attaching or setting up a remote connection.  */
       if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
        {
+         /* Loading of shared libraries might have changed breakpoint
+            addresses.  Make sure new breakpoints are inserted.  */
+         if (!breakpoints_always_inserted_mode ())
+           insert_breakpoints ();
          resume (0, TARGET_SIGNAL_0);
          prepare_to_wait (ecs);
          return;
@@ -1490,23 +1490,6 @@ handle_inferior_event (struct execution_control_state *ecs)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
       stop_signal = TARGET_SIGNAL_TRAP;
 
-      /* NOTE drow/2002-12-05: This code should be pushed down into the
-         target_wait function.  Until then following vfork on HP/UX 10.20
-         is probably broken by this.  Of course, it's broken anyway.  */
-      /* Is this a target which reports multiple exec events per actual
-         call to exec()?  (HP-UX using ptrace does, for example.)  If so,
-         ignore all but the last one.  Just resume the exec'r, and wait
-         for the next exec event. */
-      if (inferior_ignoring_leading_exec_events)
-       {
-         inferior_ignoring_leading_exec_events--;
-         target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
-         prepare_to_wait (ecs);
-         return;
-       }
-      inferior_ignoring_leading_exec_events =
-       target_reported_exec_events_per_exec_call () - 1;
-
       pending_follow.execd_pathname =
        savestring (ecs->ws.value.execd_pathname,
                    strlen (ecs->ws.value.execd_pathname));
@@ -1772,24 +1755,7 @@ handle_inferior_event (struct execution_control_state *ecs)
             process until the child exits (well, okay, not
             then either :-) or execs. */
          if (remove_status != 0)
-           {
-             /* FIXME!  This is obviously non-portable! */
-             write_pc_pid (stop_pc + 4, ecs->ptid);
-             /* We need to restart all the threads now,
-              * unles we're running in scheduler-locked mode. 
-              * Use currently_stepping to determine whether to 
-              * step or continue.
-              */
-             /* FIXME MVS: is there any reason not to call resume()? */
-             if (scheduler_mode == schedlock_on)
-               target_resume (ecs->ptid,
-                              currently_stepping (ecs), TARGET_SIGNAL_0);
-             else
-               target_resume (RESUME_ALL,
-                              currently_stepping (ecs), TARGET_SIGNAL_0);
-             prepare_to_wait (ecs);
-             return;
-           }
+           error (_("Cannot step over breakpoint hit in wrong thread"));
          else
            {                   /* Single step */
              if (!ptid_equal (inferior_ptid, ecs->ptid))
@@ -1893,7 +1859,6 @@ handle_inferior_event (struct execution_control_state *ecs)
   ecs->stepping_over_breakpoint = 0;
   bpstat_clear (&stop_bpstat);
   stop_step = 0;
-  stop_stack_dummy = 0;
   stop_print_frame = 1;
   ecs->random_signal = 0;
   stopped_by_random_signal = 0;
@@ -1903,7 +1868,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       && gdbarch_single_step_through_delay_p (current_gdbarch)
       && currently_stepping (ecs))
     {
-      /* We're trying to step of a breakpoint.  Turns out that we're
+      /* We're trying to step off a breakpoint.  Turns out that we're
         also on an instruction that needs to be stepped multiple
         times before it's been fully executing. E.g., architectures
         with a delay slot.  It needs to be stepped twice, once for
@@ -2073,8 +2038,7 @@ process_event_stop_test:
        stop_signal = TARGET_SIGNAL_0;
 
       if (prev_pc == read_pc ()
-         && breakpoint_here_p (read_pc ())
-         && !breakpoint_inserted_here_p (read_pc ())
+         && stepping_over_breakpoint
          && step_resume_breakpoint == NULL)
        {
          /* We were just starting a new sequence, attempting to
@@ -2146,7 +2110,6 @@ process_event_stop_test:
         if (debug_infrun)
          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
        disable_longjmp_breakpoint ();
-       remove_breakpoints ();
        if (!gdbarch_get_longjmp_target_p (current_gdbarch)
            || !gdbarch_get_longjmp_target (current_gdbarch,
                                            get_current_frame (), &jmp_buf_pc))
@@ -2168,20 +2131,15 @@ process_event_stop_test:
        return;
 
       case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
-      case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE:
         if (debug_infrun)
          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
-       remove_breakpoints ();
        disable_longjmp_breakpoint ();
        ecs->handling_longjmp = 0;      /* FIXME */
-       if (what.main_action == BPSTAT_WHAT_CLEAR_LONGJMP_RESUME)
-         break;
-       /* else fallthrough */
+       break;
 
       case BPSTAT_WHAT_SINGLE:
         if (debug_infrun)
          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
-       remove_breakpoints ();
        ecs->stepping_over_breakpoint = 1;
        /* Still need to check other stuff, at least the case
           where we are stepping and step out of the right range.  */
@@ -2242,7 +2200,6 @@ process_event_stop_test:
               were trying to single-step off a breakpoint.  Go back
               to doing that.  */
            ecs->step_after_step_resume_breakpoint = 0;
-           remove_breakpoints ();
            ecs->stepping_over_breakpoint = 1;
            keep_going (ecs);
            return;
@@ -2254,10 +2211,6 @@ process_event_stop_test:
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
-         /* Remove breakpoints, we eventually want to step over the
-            shlib event breakpoint, and SOLIB_ADD might adjust
-            breakpoint addresses via breakpoint_re_set.  */
-         remove_breakpoints ();
 
          /* Check for any newly added shared libraries if we're
             supposed to be adding them automatically.  Switch
@@ -2702,20 +2655,6 @@ process_event_stop_test:
      new line in mid-statement, we continue stepping.  This makes
      things like for(;;) statements work better.)  */
 
-  if (ecs->stop_func_end && ecs->sal.end >= ecs->stop_func_end)
-    {
-      /* If this is the last line of the function, don't keep stepping
-         (it would probably step us out of the function).
-         This is particularly necessary for a one-line function,
-         in which after skipping the prologue we better stop even though
-         we will be in mid-line.  */
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different function\n");
-      stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
-      stop_stepping (ecs);
-      return;
-    }
   step_range_start = ecs->sal.pc;
   step_range_end = ecs->sal.end;
   step_frame_id = get_frame_id (get_current_frame ());
@@ -2962,7 +2901,11 @@ keep_going (struct execution_control_state *ecs)
         already inserted breakpoints.  Therefore, we don't
         care if breakpoints were already inserted, or not.  */
       
-      if (!ecs->stepping_over_breakpoint)
+      if (ecs->stepping_over_breakpoint)
+       {
+         remove_breakpoints ();
+       }
+      else
        {
          struct gdb_exception e;
          /* Stop stepping when inserting breakpoints
@@ -3153,7 +3096,7 @@ normal_stop (void)
     {
       target_terminal_ours_for_output ();
       printf_filtered (_("[Switching to %s]\n"),
-                      target_pid_or_tid_to_str (inferior_ptid));
+                      target_pid_to_str (inferior_ptid));
       previous_inferior_ptid = inferior_ptid;
     }
 
@@ -3168,7 +3111,7 @@ normal_stop (void)
        gdbarch_decr_pc_after_break needs to just go away.  */
     deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
 
-  if (target_has_execution)
+  if (!breakpoints_always_inserted_mode () && target_has_execution)
     {
       if (remove_breakpoints ())
        {
@@ -3180,11 +3123,6 @@ Further execution is probably impossible.\n"));
        }
     }
 
-  /* Delete the breakpoint we stopped at, if it wants to be deleted.
-     Delete any breakpoint that is to be deleted at the next stop.  */
-
-  breakpoint_auto_delete (stop_bpstat);
-
   /* If an auto-display called a function and that got a signal,
      delete that auto-display to avoid an infinite recursion.  */
 
@@ -3323,6 +3261,9 @@ Further execution is probably impossible.\n"));
 done:
   annotate_stopped ();
   observer_notify_normal_stop (stop_bpstat);
+  /* Delete the breakpoint we stopped at, if it wants to be deleted.
+     Delete any breakpoint that is to be deleted at the next stop.  */
+  breakpoint_auto_delete (stop_bpstat);
 }
 
 static int
This page took 0.035853 seconds and 4 git commands to generate.