* simops.c (trace_result): Fix printf formatting.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 21d07f27759f083b306bcbf7f3c0bbf8af13a7a9..faca42007a2420b625c806c3f52e56964914bb8a 100644 (file)
@@ -1,6 +1,9 @@
-/* Target-struct-independent code to start (run) and stop an inferior process.
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Target-struct-independent code to start (run) and stop an inferior
+   process.
+
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
 
    This file is part of GDB.
 
@@ -29,6 +32,7 @@
 #include "gdb_wait.h"
 #include "gdbcore.h"
 #include "gdbcmd.h"
+#include "cli/cli-script.h"
 #include "target.h"
 #include "gdbthread.h"
 #include "annotate.h"
@@ -37,6 +41,7 @@
 #include <signal.h>
 #include "inf-loop.h"
 #include "regcache.h"
+#include "value.h"
 
 /* Prototypes for local functions */
 
@@ -110,48 +115,6 @@ static ptid_t previous_inferior_ptid;
 
 static int may_follow_exec = MAY_FOLLOW_EXEC;
 
-/* resume and wait_for_inferior use this to ensure that when
-   stepping over a hit breakpoint in a threaded application
-   only the thread that hit the breakpoint is stepped and the
-   other threads don't continue.  This prevents having another
-   thread run past the breakpoint while it is temporarily
-   removed.
-
-   This is not thread-specific, so it isn't saved as part of
-   the infrun state.
-
-   Versions of gdb which don't use the "step == this thread steps
-   and others continue" model but instead use the "step == this
-   thread steps and others wait" shouldn't do this.  */
-
-static int thread_step_needed = 0;
-
-/* This is true if thread_step_needed should actually be used.  At
-   present this is only true for HP-UX native.  */
-
-#ifndef USE_THREAD_STEP_NEEDED
-#define USE_THREAD_STEP_NEEDED (0)
-#endif
-
-static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
-
-/* 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
-
-
-/* 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
-
 /* Dynamic function trampolines are similar to solib trampolines in that they
    are between the caller and the callee.  The difference is that when you
    enter a dynamic trampoline, you can't determine the callee's address.  Some
@@ -180,12 +143,12 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
    The simple approach is to single-step until control leaves the
    dynamic linker.
 
-   However, on some systems (e.g., Red Hat Linux 5.2) the dynamic
-   linker calls functions in the shared C library, so you can't tell
-   from the PC alone whether the dynamic linker is still running.  In
-   this case, we use a step-resume breakpoint to get us past the
-   dynamic linker, as if we were using "next" to step over a function
-   call.
+   However, on some systems (e.g., Red Hat's 5.2 distribution) the
+   dynamic linker calls functions in the shared C library, so you
+   can't tell from the PC alone whether the dynamic linker is still
+   running.  In this case, we use a step-resume breakpoint to get us
+   past the dynamic linker, as if we were using "next" to step over a
+   function call.
 
    IN_SOLIB_DYNSYM_RESOLVE_CODE says whether we're in the dynamic
    linker code or not.  Normally, this means we single-step.  However,
@@ -214,14 +177,6 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 #define SKIP_SOLIB_RESOLVER(pc) 0
 #endif
 
-/* For SVR4 shared libraries, each call goes through a small piece of
-   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_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.  */
 
@@ -269,12 +224,10 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 static void
 default_skip_permanent_breakpoint (void)
 {
-  error_begin ();
-  fprintf_filtered (gdb_stderr, "\
+  error ("\
 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);
+a command like `return' or `jump' to continue execution.");
 }
 #endif
    
@@ -796,7 +749,15 @@ static const char *scheduler_enums[] =
 static void
 set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
 {
-  if (c->type == set_cmd)
+  /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
+     the set command passed as a parameter.  The clone operation will
+     include (BUG?) any ``set'' command callback, if present.
+     Commands like ``info set'' call all the ``show'' command
+     callbacks.  Unfortunatly, for ``show'' commands cloned from
+     ``set'', this includes callbacks belonging to ``set'' commands.
+     Making this worse, this only occures if add_show_from_set() is
+     called after add_cmd_sfunc() (BUG?).  */
+  if (cmd_type (c) == set_cmd)
     if (!target_can_lock_scheduler)
       {
        scheduler_mode = schedlock_off;
@@ -806,8 +767,6 @@ 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
@@ -823,13 +782,8 @@ resume (int step, enum target_signal 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
+  /* FIXME: calling breakpoint_here_p (read_pc ()) three times! */
+
 
   /* Some targets (e.g. Solaris x86) have a kernel bug when stepping
      over an instruction that causes a page fault without triggering
@@ -912,41 +866,34 @@ resume (int step, enum target_signal sig)
     {
       ptid_t resume_ptid;
 
-      if (use_thread_step_needed && thread_step_needed)
+      resume_ptid = RESUME_ALL;                /* Default */
+
+      if ((step || singlestep_breakpoints_inserted_p) &&
+         !breakpoints_inserted && breakpoint_here_p (read_pc ()))
        {
-         /* We stopped on a BPT instruction;
-            don't continue other threads and
-            just step this thread. */
-         thread_step_needed = 0;
+         /* Stepping past a breakpoint without inserting breakpoints.
+            Make sure only the current thread gets to step, so that
+            other threads don't sneak past breakpoints while they are
+            not inserted. */
 
-         if (!breakpoint_here_p (read_pc ()))
-           {
-             /* Breakpoint deleted: ok to do regular resume
-                where all the threads either step or continue. */
-             resume_ptid = RESUME_ALL;
-           }
-         else
-           {
-             if (!step)
-               {
-                 warning ("Internal error, changing continue to step.");
-                 remove_breakpoints ();
-                 breakpoints_inserted = 0;
-                 trap_expected = 1;
-                 step = 1;
-               }
-             resume_ptid = inferior_ptid;
-           }
+         resume_ptid = inferior_ptid;
        }
-      else
+
+      if ((scheduler_mode == schedlock_on) ||
+         (scheduler_mode == schedlock_step && 
+          (step || singlestep_breakpoints_inserted_p)))
        {
-         /* Vanilla resume. */
-         if ((scheduler_mode == schedlock_on) ||
-             (scheduler_mode == schedlock_step && step != 0))
+         /* User-settable 'scheduler' mode requires solo thread resume. */
            resume_ptid = inferior_ptid;
-         else
-           resume_ptid = RESUME_ALL;
        }
+
+#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
       target_resume (resume_ptid, step, sig);
     }
 
@@ -1021,16 +968,6 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   else
     {
       write_pc (addr);
-
-      /* New address; we don't need to single-step a thread
-         over a breakpoint we just hit, 'cause we aren't
-         continuing from there.
-
-         It's not worth worrying about the case where a user
-         asks for a "jump" at the current PC--if they get the
-         hiccup of re-hiting a hit breakpoint, what else do
-         they expect? */
-      thread_step_needed = 0;
     }
 
 #ifdef PREPARE_TO_PROCEED
@@ -1048,7 +985,6 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   if (PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
     {
       oneproc = 1;
-      thread_step_needed = 1;
     }
 
 #endif /* PREPARE_TO_PROCEED */
@@ -1277,7 +1213,7 @@ wait_for_inferior (void)
   struct execution_control_state ecss;
   struct execution_control_state *ecs;
 
-  old_cleanups = make_cleanup (delete_breakpoint_current_contents,
+  old_cleanups = make_cleanup (delete_step_resume_breakpoint,
                               &step_resume_breakpoint);
   make_cleanup (delete_breakpoint_current_contents,
                &through_sigtramp_breakpoint);
@@ -1289,8 +1225,6 @@ wait_for_inferior (void)
   /* Fill in with reasonable starting values.  */
   init_execution_control_state (ecs);
 
-  thread_step_needed = 0;
-
   /* We'll update this if & when we switch to a new thread. */
   previous_inferior_ptid = inferior_ptid;
 
@@ -1341,7 +1275,7 @@ fetch_inferior_event (void *client_data)
 
   if (!async_ecs->wait_some_more)
     {
-      old_cleanups = make_exec_cleanup (delete_breakpoint_current_contents,
+      old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint, 
                                        &step_resume_breakpoint);
       make_exec_cleanup (delete_breakpoint_current_contents,
                         &through_sigtramp_breakpoint);
@@ -1349,8 +1283,6 @@ fetch_inferior_event (void *client_data)
       /* Fill in with reasonable starting values.  */
       init_execution_control_state (async_ecs);
 
-      thread_step_needed = 0;
-
       /* We'll update this if & when we switch to a new thread. */
       previous_inferior_ptid = inferior_ptid;
 
@@ -1433,6 +1365,49 @@ get_last_target_status(ptid_t *ptidp, struct target_waitstatus *status)
   *status = target_last_waitstatus;
 }
 
+/* Switch thread contexts, maintaining "infrun state". */
+
+static void
+context_switch (struct execution_control_state *ecs)
+{
+  /* Caution: it may happen that the new thread (or the old one!)
+     is not in the thread list.  In this case we must not attempt
+     to "switch context", or we run the risk that our context may
+     be lost.  This may happen as a result of the target module
+     mishandling thread creation.  */
+
+  if (in_thread_list (inferior_ptid) && in_thread_list (ecs->ptid))
+    { /* Perform infrun state context switch: */
+      /* Save infrun state for the old thread.  */
+      save_infrun_state (inferior_ptid, prev_pc, 
+                        prev_func_start, prev_func_name, 
+                        trap_expected, step_resume_breakpoint,
+                        through_sigtramp_breakpoint, step_range_start, 
+                        step_range_end, step_frame_address, 
+                        ecs->handling_longjmp, ecs->another_trap,
+                        ecs->stepping_through_solib_after_catch,
+                        ecs->stepping_through_solib_catchpoints,
+                        ecs->stepping_through_sigtramp,
+                        ecs->current_line, ecs->current_symtab, 
+                        step_sp);
+
+      /* Load infrun state for the new thread.  */
+      load_infrun_state (ecs->ptid, &prev_pc, 
+                        &prev_func_start, &prev_func_name, 
+                        &trap_expected, &step_resume_breakpoint,
+                        &through_sigtramp_breakpoint, &step_range_start, 
+                        &step_range_end, &step_frame_address, 
+                        &ecs->handling_longjmp, &ecs->another_trap,
+                        &ecs->stepping_through_solib_after_catch,
+                        &ecs->stepping_through_solib_catchpoints,
+                        &ecs->stepping_through_sigtramp, 
+                        &ecs->current_line, &ecs->current_symtab,
+                        &step_sp);
+    }
+  inferior_ptid = ecs->ptid;
+}
+
+
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
@@ -1451,12 +1426,12 @@ handle_inferior_event (struct execution_control_state *ecs)
   {
     switch (ecs->infwait_state)
       {
-      case infwait_normal_state:
-       /* Since we've done a wait, we have a new event.  Don't
-          carry over any expectations about needing to step over a
-          breakpoint. */
-       thread_step_needed = 0;
+      case infwait_thread_hop_state:
+       /* Cancel the waiton_ptid. */
+       ecs->waiton_ptid = pid_to_ptid (-1);
+       /* Fall thru to the normal_state case. */
 
+      case infwait_normal_state:
        /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event
           is serviced in this loop, below. */
        if (ecs->enable_hw_watchpoints_after_wait)
@@ -1467,21 +1442,6 @@ handle_inferior_event (struct execution_control_state *ecs)
        stepped_after_stopped_by_watchpoint = 0;
        break;
 
-      case infwait_thread_hop_state:
-       insert_breakpoints ();
-
-       /* We need to restart all the threads now,
-        * unless we're running in scheduler-locked mode. 
-        * FIXME: shouldn't we look at currently_stepping ()?
-        */
-       if (scheduler_mode == schedlock_on)
-         target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
-       else
-         target_resume (RESUME_ALL, 0, TARGET_SIGNAL_0);
-       ecs->infwait_state = infwait_normal_state;
-       prepare_to_wait (ecs);
-       return;
-
       case infwait_nullified_state:
        break;
 
@@ -1509,13 +1469,9 @@ handle_inferior_event (struct execution_control_state *ecs)
       {
        add_thread (ecs->ptid);
 
-#ifdef UI_OUT
        ui_out_text (uiout, "[New ");
        ui_out_text (uiout, target_pid_or_tid_to_str (ecs->ptid));
        ui_out_text (uiout, "]\n");
-#else
-       printf_filtered ("[New %s]\n", target_pid_or_tid_to_str (ecs->ptid));
-#endif
 
 #if 0
        /* NOTE: This block is ONLY meant to be invoked in case of a
@@ -1558,15 +1514,12 @@ handle_inferior_event (struct execution_control_state *ecs)
              remove_breakpoints ();
 
            /* Check for any newly added shared libraries if we're
-              supposed to be adding them automatically.  */
-           if (auto_solib_add)
-             {
-               /* Switch terminal for any messages produced by
-                  breakpoint_re_set.  */
-               target_terminal_ours_for_output ();
-               SOLIB_ADD (NULL, 0, NULL);
-               target_terminal_inferior ();
-             }
+              supposed to be adding them automatically.  Switch
+              terminal for any messages produced by
+              breakpoint_re_set.  */
+           target_terminal_ours_for_output ();
+           SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+           target_terminal_inferior ();
 
            /* Reinsert breakpoints and continue.  */
            if (breakpoints_inserted)
@@ -1643,7 +1596,17 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->ptid);
        ecs->saved_inferior_ptid = inferior_ptid;
        inferior_ptid = ecs->ptid;
-       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
+       /* The second argument of bpstat_stop_status is meant to help
+          distinguish between a breakpoint trap and a singlestep trap.
+          This is only important on targets where DECR_PC_AFTER_BREAK
+          is non-zero.  The prev_pc test is meant to distinguish between
+          singlestepping a trap instruction, and singlestepping thru a
+          jump to the instruction following a trap instruction. */
+          
+       stop_bpstat = bpstat_stop_status (&stop_pc, 
+                                         currently_stepping (ecs) &&
+                                         prev_pc != 
+                                         stop_pc - DECR_PC_AFTER_BREAK);
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_ptid = ecs->saved_inferior_ptid;
        goto process_event_stop_test;
@@ -1692,7 +1655,17 @@ handle_inferior_event (struct execution_control_state *ecs)
          }
 
        stop_pc = read_pc ();
-       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
+       /* The second argument of bpstat_stop_status is meant to help
+          distinguish between a breakpoint trap and a singlestep trap.
+          This is only important on targets where DECR_PC_AFTER_BREAK
+          is non-zero.  The prev_pc test is meant to distinguish between
+          singlestepping a trap instruction, and singlestepping thru a
+          jump to the instruction following a trap instruction. */
+          
+       stop_bpstat = bpstat_stop_status (&stop_pc, 
+                                         currently_stepping (ecs) &&
+                                         prev_pc !=
+                                         stop_pc - DECR_PC_AFTER_BREAK);
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        goto process_event_stop_test;
 
@@ -1757,7 +1730,17 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->ptid);
        ecs->saved_inferior_ptid = inferior_ptid;
        inferior_ptid = ecs->ptid;
-       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
+       /* The second argument of bpstat_stop_status is meant to help
+          distinguish between a breakpoint trap and a singlestep trap.
+          This is only important on targets where DECR_PC_AFTER_BREAK
+          is non-zero.  The prev_pc test is meant to distinguish between
+          singlestepping a trap instruction, and singlestepping thru a
+          jump to the instruction following a trap instruction. */
+          
+       stop_bpstat = bpstat_stop_status (&stop_pc, 
+                                         currently_stepping (ecs) &&
+                                         prev_pc !=
+                                         stop_pc - DECR_PC_AFTER_BREAK);
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_ptid = ecs->saved_inferior_ptid;
        goto process_event_stop_test;
@@ -1866,7 +1849,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 
                /* Saw a breakpoint, but it was hit by the wrong thread.
                   Just continue. */
-               write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
+               if (DECR_PC_AFTER_BREAK)
+                 write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
 
                remove_status = remove_breakpoints ();
                /* Did we fail to remove breakpoints?  If so, try
@@ -1878,39 +1862,40 @@ handle_inferior_event (struct execution_control_state *ecs)
                   then either :-) or execs. */
                if (remove_status != 0)
                  {
-                   write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, ecs->ptid);
+                   /* FIXME!  This is obviously non-portable! */
+                   write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 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;
                  }
                else
                  {             /* Single step */
-                   target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
-                   /* FIXME: What if a signal arrives instead of the
-                      single-step happening?  */
-
+                   breakpoints_inserted = 0;
+                   if (!ptid_equal (inferior_ptid, ecs->ptid))
+                     context_switch (ecs);
                    ecs->waiton_ptid = ecs->ptid;
                    ecs->wp = &(ecs->ws);
+                   ecs->another_trap = 1;
+
                    ecs->infwait_state = infwait_thread_hop_state;
-                   prepare_to_wait (ecs);
+                   keep_going (ecs);
+                   registers_changed ();
                    return;
                  }
-
-               /* We need to restart all the threads now,
-                * unles we're running in scheduler-locked mode. 
-                * FIXME: shouldn't we look at currently_stepping ()?
-                */
-               if (scheduler_mode == schedlock_on)
-                 target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
-               else
-                 target_resume (RESUME_ALL, 0, TARGET_SIGNAL_0);
-               prepare_to_wait (ecs);
-               return;
-             }
-           else
-             {
-               /* This breakpoint matches--either it is the right
-                  thread or it's a generic breakpoint for all threads.
-                  Remember that we'll need to step just _this_ thread
-                  on any following user continuation! */
-               thread_step_needed = 1;
              }
          }
       }
@@ -1975,40 +1960,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
           and fall into the rest of wait_for_inferior().  */
 
-       /* Caution: it may happen that the new thread (or the old one!)
-          is not in the thread list.  In this case we must not attempt
-          to "switch context", or we run the risk that our context may
-          be lost.  This may happen as a result of the target module
-          mishandling thread creation.  */
-
-       if (in_thread_list (inferior_ptid) && in_thread_list (ecs->ptid))
-         { /* Perform infrun state context switch: */
-           /* Save infrun state for the old thread.  */
-           save_infrun_state (inferior_ptid, prev_pc,
-                              prev_func_start, prev_func_name,
-                              trap_expected, step_resume_breakpoint,
-                              through_sigtramp_breakpoint,
-                              step_range_start, step_range_end,
-                              step_frame_address, ecs->handling_longjmp,
-                              ecs->another_trap,
-                              ecs->stepping_through_solib_after_catch,
-                              ecs->stepping_through_solib_catchpoints,
-                              ecs->stepping_through_sigtramp);
-
-           /* Load infrun state for the new thread.  */
-           load_infrun_state (ecs->ptid, &prev_pc,
-                              &prev_func_start, &prev_func_name,
-                              &trap_expected, &step_resume_breakpoint,
-                              &through_sigtramp_breakpoint,
-                              &step_range_start, &step_range_end,
-                              &step_frame_address, &ecs->handling_longjmp,
-                              &ecs->another_trap,
-                              &ecs->stepping_through_solib_after_catch,
-                              &ecs->stepping_through_solib_catchpoints,
-                              &ecs->stepping_through_sigtramp);
-         }
-
-       inferior_ptid = ecs->ptid;
+       context_switch (ecs);
 
        if (context_hook)
          context_hook (pid_to_thread_id (ecs->ptid));
@@ -2076,7 +2028,8 @@ handle_inferior_event (struct execution_control_state *ecs)
           includes evaluating watchpoints, things will come to a
           stop in the correct manner.  */
 
-       write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+       if (DECR_PC_AFTER_BREAK)
+         write_pc (stop_pc - DECR_PC_AFTER_BREAK);
 
        remove_breakpoints ();
        registers_changed ();
@@ -2157,6 +2110,14 @@ handle_inferior_event (struct execution_control_state *ecs)
        else
          {
            /* See if there is a breakpoint at the current PC.  */
+
+           /* The second argument of bpstat_stop_status is meant to help
+              distinguish between a breakpoint trap and a singlestep trap.
+              This is only important on targets where DECR_PC_AFTER_BREAK
+              is non-zero.  The prev_pc test is meant to distinguish between
+              singlestepping a trap instruction, and singlestepping thru a
+              jump to the instruction following a trap instruction. */
+
            stop_bpstat = bpstat_stop_status
              (&stop_pc,
            /* Pass TRUE if our reason for stopping is something other
@@ -2166,6 +2127,7 @@ handle_inferior_event (struct execution_control_state *ecs)
               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))))
              );
@@ -2344,7 +2306,8 @@ handle_inferior_event (struct execution_control_state *ecs)
          disable_longjmp_breakpoint ();
          remove_breakpoints ();
          breakpoints_inserted = 0;
-         if (!GET_LONGJMP_TARGET (&jmp_buf_pc))
+         if (!GET_LONGJMP_TARGET_P ()
+             || !GET_LONGJMP_TARGET (&jmp_buf_pc))
            {
              keep_going (ecs);
              return;
@@ -2354,8 +2317,7 @@ handle_inferior_event (struct execution_control_state *ecs)
             interferes with us */
          if (step_resume_breakpoint != NULL)
            {
-             delete_breakpoint (step_resume_breakpoint);
-             step_resume_breakpoint = NULL;
+             delete_step_resume_breakpoint (&step_resume_breakpoint);
            }
          /* Not sure whether we need to blow this away too, but probably
             it is like the step-resume breakpoint.  */
@@ -2401,7 +2363,6 @@ handle_inferior_event (struct execution_control_state *ecs)
        case BPSTAT_WHAT_SINGLE:
          if (breakpoints_inserted)
            {
-             thread_step_needed = 1;
              remove_breakpoints ();
            }
          breakpoints_inserted = 0;
@@ -2453,8 +2414,7 @@ handle_inferior_event (struct execution_control_state *ecs)
              step_resume_breakpoint =
                bpstat_find_step_resume_breakpoint (stop_bpstat);
            }
-         delete_breakpoint (step_resume_breakpoint);
-         step_resume_breakpoint = NULL;
+         delete_step_resume_breakpoint (&step_resume_breakpoint);
          break;
 
        case BPSTAT_WHAT_THROUGH_SIGTRAMP:
@@ -2480,15 +2440,12 @@ handle_inferior_event (struct execution_control_state *ecs)
            breakpoints_inserted = 0;
 
            /* Check for any newly added shared libraries if we're
-              supposed to be adding them automatically.  */
-           if (auto_solib_add)
-             {
-               /* Switch terminal for any messages produced by
-                  breakpoint_re_set.  */
-               target_terminal_ours_for_output ();
-               SOLIB_ADD (NULL, 0, NULL);
-               target_terminal_inferior ();
-             }
+              supposed to be adding them automatically.  Switch
+              terminal for any messages produced by
+              breakpoint_re_set.  */
+           target_terminal_ours_for_output ();
+           SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+           target_terminal_inferior ();
 
            /* Try to reenable shared library breakpoints, additional
               code segments in shared libraries might be mapped in now. */
@@ -2683,8 +2640,8 @@ handle_inferior_event (struct execution_control_state *ecs)
     ecs->update_step_sp = 1;
 
     /* Did we just take a signal?  */
-    if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
-       && !IN_SIGTRAMP (prev_pc, prev_func_name)
+    if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+       && !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
        && INNER_THAN (read_sp (), step_sp))
       {
        /* We've just taken a signal; go until we are back to
@@ -2775,11 +2732,16 @@ handle_inferior_event (struct execution_control_state *ecs)
       {
        /* It's a subroutine call.  */
 
-       if (step_over_calls == STEP_OVER_NONE)
+       if ((step_over_calls == STEP_OVER_NONE)
+           || ((step_range_end == 1)
+               && in_prologue (prev_pc, ecs->stop_func_start)))
          {
            /* I presume that step_over_calls is only 0 when we're
               supposed to be stepping at the assembly language level
               ("stepi").  Just stop.  */
+           /* Also, maybe we just did a "nexti" inside a prolog,
+               so we thought it was a subroutine call but it was not.
+               Stop as well.  FENN */
            stop_step = 1;
            print_stop_reason (END_STEPPING_RANGE, 0);
            stop_stepping (ecs);
@@ -2790,7 +2752,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          {
            /* We're doing a "next".  */
 
-           if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+           if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
                && INNER_THAN (step_frame_address, read_sp()))
              /* We stepped out of a signal handler, and into its
                  calling trampoline.  This is misdetected as a
@@ -2999,8 +2961,8 @@ static void
 check_sigtramp2 (struct execution_control_state *ecs)
 {
   if (trap_expected
-      && IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
-      && !IN_SIGTRAMP (prev_pc, prev_func_name)
+      && PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+      && !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
       && INNER_THAN (read_sp (), step_sp))
     {
       /* What has happened here is that we have just stepped the
@@ -3319,13 +3281,11 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
     case END_STEPPING_RANGE:
       /* We are done with a step/next/si/ni command. */
       /* For now print nothing. */
-#ifdef UI_OUT
       /* Print a message only if not in the middle of doing a "step n"
         operation for n > 1 */
       if (!step_multi || !stop_step)
-       if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       if (ui_out_is_mi_like_p (uiout))
          ui_out_field_string (uiout, "reason", "end-stepping-range");
-#endif
       break;
     case BREAKPOINT_HIT:
       /* We found a breakpoint. */
@@ -3333,9 +3293,8 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
       break;
     case SIGNAL_EXITED:
       /* The inferior was terminated by a signal. */
-#ifdef UI_OUT
       annotate_signalled ();
-      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+      if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string (uiout, "reason", "exited-signalled");
       ui_out_text (uiout, "\nProgram terminated with signal ");
       annotate_signal_name ();
@@ -3347,29 +3306,13 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
       annotate_signal_string_end ();
       ui_out_text (uiout, ".\n");
       ui_out_text (uiout, "The program no longer exists.\n");
-#else
-      annotate_signalled ();
-      printf_filtered ("\nProgram terminated with signal ");
-      annotate_signal_name ();
-      printf_filtered ("%s", target_signal_to_name (stop_info));
-      annotate_signal_name_end ();
-      printf_filtered (", ");
-      annotate_signal_string ();
-      printf_filtered ("%s", target_signal_to_string (stop_info));
-      annotate_signal_string_end ();
-      printf_filtered (".\n");
-
-      printf_filtered ("The program no longer exists.\n");
-      gdb_flush (gdb_stdout);
-#endif
       break;
     case EXITED:
       /* The inferior program is finished. */
-#ifdef UI_OUT
       annotate_exited (stop_info);
       if (stop_info)
        {
-         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+         if (ui_out_is_mi_like_p (uiout))
            ui_out_field_string (uiout, "reason", "exited");
          ui_out_text (uiout, "\nProgram exited with code ");
          ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) stop_info);
@@ -3377,26 +3320,19 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
        }
       else
        {
-         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+         if (ui_out_is_mi_like_p (uiout))
            ui_out_field_string (uiout, "reason", "exited-normally");
          ui_out_text (uiout, "\nProgram exited normally.\n");
        }
-#else
-      annotate_exited (stop_info);
-      if (stop_info)
-       printf_filtered ("\nProgram exited with code 0%o.\n",
-                        (unsigned int) stop_info);
-      else
-       printf_filtered ("\nProgram exited normally.\n");
-#endif
       break;
     case SIGNAL_RECEIVED:
       /* Signal received. The signal table tells us to print about
          it. */
-#ifdef UI_OUT
       annotate_signal ();
       ui_out_text (uiout, "\nProgram received signal ");
       annotate_signal_name ();
+      if (ui_out_is_mi_like_p (uiout))
+       ui_out_field_string (uiout, "reason", "signal-received");
       ui_out_field_string (uiout, "signal-name", target_signal_to_name (stop_info));
       annotate_signal_name_end ();
       ui_out_text (uiout, ", ");
@@ -3404,19 +3340,6 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
       ui_out_field_string (uiout, "signal-meaning", target_signal_to_string (stop_info));
       annotate_signal_string_end ();
       ui_out_text (uiout, ".\n");
-#else
-      annotate_signal ();
-      printf_filtered ("\nProgram received signal ");
-      annotate_signal_name ();
-      printf_filtered ("%s", target_signal_to_name (stop_info));
-      annotate_signal_name_end ();
-      printf_filtered (", ");
-      annotate_signal_string ();
-      printf_filtered ("%s", target_signal_to_string (stop_info));
-      annotate_signal_string_end ();
-      printf_filtered (".\n");
-      gdb_flush (gdb_stdout);      
-#endif
       break;
     default:
       internal_error (__FILE__, __LINE__,
@@ -3499,13 +3422,11 @@ and/or watchpoints.\n");
 
   target_terminal_ours ();
 
-  /* Look up the hook_stop and run it if it exists.  */
-
-  if (stop_command && stop_command->hook_pre)
-    {
-      catch_errors (hook_stop_stub, stop_command->hook_pre,
-                   "Error while running hook_stop:\n", RETURN_MASK_ALL);
-    }
+  /* Look up the hook_stop and run it (CLI internally handles problem
+     of stop_command's pre-hook not existing).  */
+  if (stop_command)
+    catch_errors (hook_stop_stub, stop_command,
+                 "Error while running hook_stop:\n", RETURN_MASK_ALL);
 
   if (!target_has_stack)
     {
@@ -3520,7 +3441,7 @@ and/or watchpoints.\n");
 
   if (!stop_stack_dummy)
     {
-      select_frame (get_current_frame (), 0);
+      select_frame (get_current_frame ());
 
       /* Print current location without a level number, if
          we have changed functions or hit a breakpoint.
@@ -3560,18 +3481,14 @@ and/or watchpoints.\n");
              internal_error (__FILE__, __LINE__,
                              "Unknown value.");
            }
-#ifdef UI_OUT
          /* For mi, have the same behavior every time we stop:
              print everything but the source line. */
-         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+         if (ui_out_is_mi_like_p (uiout))
            source_flag = LOC_AND_ADDRESS;
-#endif
 
-#ifdef UI_OUT
-         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+         if (ui_out_is_mi_like_p (uiout))
            ui_out_field_int (uiout, "thread-id",
                              pid_to_thread_id (inferior_ptid));
-#endif
          /* The behavior of this routine with respect to the source
             flag is:
             SRC_LINE: Print only source line
@@ -3600,12 +3517,9 @@ and/or watchpoints.\n");
          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);
+      select_frame (get_current_frame ());
     }
 
-
-  TUIDO (((TuiOpaqueFuncPtr) tui_vCheckDataValues, selected_frame));
-
 done:
   annotate_stopped ();
 }
@@ -3613,7 +3527,7 @@ done:
 static int
 hook_stop_stub (void *cmd)
 {
-  execute_user_command ((struct cmd_list_element *) cmd, 0);
+  execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
   return (0);
 }
 \f
@@ -3996,7 +3910,6 @@ struct inferior_status
   CORE_ADDR step_resume_break_address;
   int stop_after_trap;
   int stop_soon_quietly;
-  CORE_ADDR selected_frame_address;
   char *stop_registers;
 
   /* These are here because if call_function_by_hand has written some
@@ -4004,7 +3917,9 @@ struct inferior_status
      any registers.  */
   char *registers;
 
-  int selected_level;
+  /* A frame unique identifier.  */
+  struct frame_id selected_frame_id;
+
   int breakpoint_proceeded;
   int restore_stack_info;
   int proceed_to_finish;
@@ -4073,44 +3988,27 @@ save_inferior_status (int restore_stack_info)
 
   read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
 
-  record_selected_frame (&(inf_status->selected_frame_address),
-                        &(inf_status->selected_level));
+  get_frame_id (selected_frame, &inf_status->selected_frame_id);
   return inf_status;
 }
 
-struct restore_selected_frame_args
-{
-  CORE_ADDR frame_address;
-  int level;
-};
-
 static int
 restore_selected_frame (void *args)
 {
-  struct restore_selected_frame_args *fr =
-  (struct restore_selected_frame_args *) args;
+  struct frame_id *fid =  (struct frame_id *) args;
   struct frame_info *frame;
-  int level = fr->level;
 
-  frame = find_relative_frame (get_current_frame (), &level);
+  frame = frame_find_by_id (*fid);
 
   /* If inf_status->selected_frame_address is NULL, there was no
      previously selected frame.  */
-  if (frame == NULL ||
-  /*  FRAME_FP (frame) != fr->frame_address || */
-  /* elz: deleted this check as a quick fix to the problem that
-     for function called by hand gdb creates no internal frame
-     structure and the real stack and gdb's idea of stack are
-     different if nested calls by hands are made.
-
-     mvs: this worries me.  */
-      level != 0)
+  if (frame == NULL)
     {
       warning ("Unable to restore previously selected frame.\n");
       return 0;
     }
 
-  select_frame (frame, fr->level);
+  select_frame (frame);
 
   return (1);
 }
@@ -4152,20 +4050,15 @@ restore_inferior_status (struct inferior_status *inf_status)
 
   if (target_has_stack && inf_status->restore_stack_info)
     {
-      struct restore_selected_frame_args fr;
-      fr.level = inf_status->selected_level;
-      fr.frame_address = inf_status->selected_frame_address;
       /* The point of catch_errors is that if the stack is clobbered,
-         walking the stack might encounter a garbage pointer and error()
-         trying to dereference it.  */
-      if (catch_errors (restore_selected_frame, &fr,
+         walking the stack might encounter a garbage pointer and
+         error() trying to dereference it.  */
+      if (catch_errors (restore_selected_frame, &inf_status->selected_frame_id,
                        "Unable to restore previously selected frame:\n",
                        RETURN_MASK_ERROR) == 0)
        /* Error in restoring the selected frame.  Select the innermost
           frame.  */
-
-
-       select_frame (get_current_frame (), 0);
+       select_frame (get_current_frame ());
 
     }
 
@@ -4192,7 +4085,67 @@ discard_inferior_status (struct inferior_status *inf_status)
   free_inferior_status (inf_status);
 }
 
-/* Helper function for save_inferior_ptid */
+/* Oft used ptids */
+ptid_t null_ptid;
+ptid_t minus_one_ptid;
+
+/* Create a ptid given the necessary PID, LWP, and TID components.  */
+   
+ptid_t
+ptid_build (int pid, long lwp, long tid)
+{
+  ptid_t ptid;
+
+  ptid.pid = pid;
+  ptid.lwp = lwp;
+  ptid.tid = tid;
+  return ptid;
+}
+
+/* Create a ptid from just a pid.  */
+
+ptid_t
+pid_to_ptid (int pid)
+{
+  return ptid_build (pid, 0, 0);
+}
+
+/* Fetch the pid (process id) component from a ptid.  */
+
+int
+ptid_get_pid (ptid_t ptid)
+{
+  return ptid.pid;
+}
+
+/* Fetch the lwp (lightweight process) component from a ptid.  */
+
+long
+ptid_get_lwp (ptid_t ptid)
+{
+  return ptid.lwp;
+}
+
+/* Fetch the tid (thread id) component from a ptid.  */
+
+long
+ptid_get_tid (ptid_t ptid)
+{
+  return ptid.tid;
+}
+
+/* ptid_equal() is used to test equality of two ptids.  */
+
+int
+ptid_equal (ptid_t ptid1, ptid_t ptid2)
+{
+  return (ptid1.pid == ptid2.pid && ptid1.lwp == ptid2.lwp
+          && ptid1.tid == ptid2.tid);
+}
+
+/* restore_inferior_ptid() will be used by the cleanup machinery
+   to restore the inferior_ptid value saved in a call to
+   save_inferior_ptid().  */
 
 static void
 restore_inferior_ptid (void *arg)
@@ -4375,7 +4328,6 @@ A fork or vfork creates a new process.  follow-fork-mode can be:\n\
 For \"parent\" or \"child\", the unfollowed process will run free.\n\
 By default, the debugger will follow the parent process.",
                        &setlist);
-/*  c->function.sfunc = ; */
   add_show_from_set (c, &showlist);
 
   c = add_set_enum_cmd ("scheduler-locking", class_run,
@@ -4389,7 +4341,7 @@ step == scheduler locked during every single-step operation.\n\
        Other threads may run while stepping over a function call ('next').",
                        &setlist);
 
-  c->function.sfunc = set_schedlock_func;      /* traps on target vector */
+  set_cmd_sfunc (c, set_schedlock_func);       /* traps on target vector */
   add_show_from_set (c, &showlist);
 
   c = add_set_cmd ("step-mode", class_run,
@@ -4400,4 +4352,10 @@ instruction of that function. Otherwise, the function is skipped and\n\
 the step command stops at a different source line.",
                        &setlist);
   add_show_from_set (c, &showlist);
+
+  /* ptid initializations */
+  null_ptid = ptid_build (0, 0, 0);
+  minus_one_ptid = ptid_build (-1, 0, 0);
+  inferior_ptid = null_ptid;
+  target_last_wait_ptid = minus_one_ptid;
 }
This page took 0.035435 seconds and 4 git commands to generate.