Removed superflous code.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 850f88fa04a4fff943a9dbd20c3a44e4df72101e..f1eaaabbf4a8a25fd67531b914df1affd6482891 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-struct-independent code to start (run) and stop an inferior process.
-   Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994
-   Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -16,10 +16,10 @@ GNU General Public License for more details.
 
 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.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
 #include <ctype.h>
 #include "symtab.h"
 #include "frame.h"
@@ -29,18 +29,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "target.h"
-#include "thread.h"
+#include "gdbthread.h"
 #include "annotate.h"
+#include "symfile.h" /* for overlay functions */
 
 #include <signal.h>
 
-/* unistd.h is needed to #define X_OK */
-#ifdef USG
-#include <unistd.h>
-#else
-#include <sys/file.h>
-#endif
-
 /* Prototypes for local functions */
 
 static void signals_info PARAMS ((char *, int));
@@ -55,6 +49,8 @@ static void resume_cleanups PARAMS ((int));
 
 static int hook_stop_stub PARAMS ((char *));
 
+static void delete_breakpoint_current_contents PARAMS ((PTR));
+
 /* 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. */
@@ -72,6 +68,30 @@ static int hook_stop_stub PARAMS ((char *));
 #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
+   (usually complex) code needs to run in the dynamic trampoline to figure out
+   the callee's address.  This macro is usually called twice.  First, when we
+   enter the trampoline (looks like a normal function call at that point).  It
+   should return the PC of a point within the trampoline where the callee's
+   address is known.  Second, when we hit the breakpoint, this routine returns
+   the callee's address.  At that point, things proceed as per a step resume
+   breakpoint.  */
+
+#ifndef DYNAMIC_TRAMPOLINE_NEXTPC
+#define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0
+#endif
+
+/* On SVR4 based systems, determining the callee's address is exceedingly
+   difficult and depends on the implementation of the run time loader.
+   If we are stepping at the source level, we single step until we exit
+   the run time loader code and reach the callee's address.  */
+
+#ifndef IN_SOLIB_DYNSYM_RESOLVE_CODE
+#define IN_SOLIB_DYNSYM_RESOLVE_CODE(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. */
@@ -87,6 +107,14 @@ static int hook_stop_stub PARAMS ((char *));
 #define IN_SOLIB_RETURN_TRAMPOLINE(pc,name)    0
 #endif
 
+/* On MIPS16, a function that returns a floating point value may call
+   a library helper function to copy the return value to a floating point
+   register.  The IGNORE_HELPER_CALL macro returns non-zero if we
+   should ignore (i.e. step over) this function call.  */
+#ifndef IGNORE_HELPER_CALL
+#define IGNORE_HELPER_CALL(pc) 0
+#endif
+
 /* On some systems, the PC may be left pointing at an instruction that  won't
    actually be executed.  This is usually indicated by a bit in the PSW.  If
    we find ourselves in such a state, then we step the target beyond the
@@ -136,11 +164,19 @@ static struct symbol *step_start_function;
 
 static int trap_expected;
 
+#ifdef SOLIB_ADD
+/* Nonzero if we want to give control to the user when we're notified
+   of shared library events by the dynamic linker.  */
+static int stop_on_solib_events;
+#endif
+
+#ifdef HP_OS_BUG
 /* Nonzero if the next time we try to continue the inferior, it will
    step one instruction and generate a spurious trace trap.
    This is used to compensate for a bug in HP-UX.  */
 
 static int trap_expected_after_continue;
+#endif
 
 /* Nonzero means expecting a trace trap
    and should stop the inferior and return silently when it happens.  */
@@ -174,11 +210,6 @@ static int breakpoints_failed;
 
 static int stop_print_frame;
 
-#ifdef NO_SINGLE_STEP
-extern int one_stepped;                /* From machine dependent code */
-extern void single_step ();    /* Same. */
-#endif /* NO_SINGLE_STEP */
-
 \f
 /* Things to clean up if we QUIT out of resume ().  */
 /* ARGSUSED */
@@ -284,7 +315,7 @@ proceed (addr, siggnal, step)
         step one instruction before inserting breakpoints
         so that we do not stop right away.  */
 
-      if (breakpoint_here_p (read_pc ()))
+      if (read_pc () == stop_pc && breakpoint_here_p (read_pc ()))
        oneproc = 1;
 
 #ifdef STEP_SKIPS_DELAY
@@ -317,6 +348,7 @@ proceed (addr, siggnal, step)
     oneproc = 1;
 #endif /* PREPARE_TO_PROCEED */
 
+#ifdef HP_OS_BUG
   if (trap_expected_after_continue)
     {
       /* If (step == 0), a trap will be automatically generated after
@@ -326,6 +358,7 @@ proceed (addr, siggnal, step)
       oneproc = 1;
       trap_expected_after_continue = 0;
     }
+#endif /* HP_OS_BUG */
 
   if (oneproc)
     /* We will get a trace trap after one instruction.
@@ -352,6 +385,10 @@ The same program may be running in another process.");
 
   annotate_starting ();
 
+  /* Make sure that output from GDB appears before output from the
+     inferior.  */
+  gdb_flush (gdb_stdout);
+
   /* Resume inferior.  */
   resume (oneproc || step || bpstat_should_step (), stop_signal);
 
@@ -395,7 +432,9 @@ init_wait_for_inferior ()
   prev_func_start = 0;
   prev_func_name = NULL;
 
+#ifdef HP_OS_BUG
   trap_expected_after_continue = 0;
+#endif
   breakpoints_inserted = 0;
   breakpoint_init_inferior ();
 
@@ -424,11 +463,14 @@ wait_for_inferior ()
   struct cleanup *old_cleanups;
   struct target_waitstatus w;
   int another_trap;
-  int random_signal;
+  int random_signal = 0;
   CORE_ADDR stop_func_start;
   CORE_ADDR stop_func_end;
   char *stop_func_name;
-  CORE_ADDR prologue_pc = 0, tmp;
+#if 0
+  CORE_ADDR prologue_pc = 0;
+#endif
+  CORE_ADDR tmp;
   struct symtab_and_line sal;
   int remove_breakpoints_on_following_step = 0;
   int current_line;
@@ -457,6 +499,10 @@ wait_for_inferior ()
 
   while (1)
     {
+      extern int overlay_cache_invalid; /* declared in symfile.h */
+
+      overlay_cache_invalid = 1;
+
       /* We have to invalidate the registers BEFORE calling target_wait because
         they can be loaded from the target while in target_wait.  This makes
         remote debugging a bit more efficient for those targets that provide
@@ -469,15 +515,23 @@ wait_for_inferior ()
       else
        pid = target_wait (-1, &w);
 
+    /* Gross.
+
+       We goto this label from elsewhere in wait_for_inferior when we want
+       to continue the main loop without calling "wait" and trashing the
+       waitstatus contained in W.  */
+    have_waited:
+
       flush_cached_frames ();
 
       /* If it's a new process, add it to the thread database */
 
-      if (pid != inferior_pid
+      if (w.kind != TARGET_WAITKIND_EXITED
+         && pid != inferior_pid
          && !in_thread_list (pid))
        {
-         fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
          add_thread (pid);
+         printf_filtered ("[New %s]\n", target_pid_to_str (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
@@ -494,12 +548,35 @@ wait_for_inferior ()
       switch (w.kind)
        {
        case TARGET_WAITKIND_LOADED:
-         /* Ignore it gracefully.  */
-         if (breakpoints_inserted)
+         /* Ignore gracefully during startup of the inferior, as it
+            might be the shell which has just loaded some objects,
+            otherwise add the symbols for the newly loaded objects.  */
+#ifdef SOLIB_ADD
+         if (!stop_soon_quietly)
            {
-             mark_breakpoints_out ();
-             insert_breakpoints ();
+             extern int auto_solib_add;
+
+             /* Remove breakpoints, SOLIB_ADD might adjust
+                breakpoint addresses via breakpoint_re_set.  */
+             if (breakpoints_inserted)
+               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 ();
+               }
+
+             /* Reinsert breakpoints and continue.  */
+             if (breakpoints_inserted)
+               insert_breakpoints ();
            }
+#endif
          resume (0, TARGET_SIGNAL_0);
          continue;
 
@@ -515,6 +592,12 @@ wait_for_inferior ()
                             (unsigned int)w.value.integer);
          else
            printf_filtered ("\nProgram exited normally.\n");
+
+         /* Record the exit code in the convenience variable $_exitcode, so
+            that the user can inspect this again later.  */
+         set_internalvar (lookup_internalvar ("_exitcode"),
+                          value_from_longest (builtin_type_int, 
+                                              (LONGEST) w.value.integer));
          gdb_flush (gdb_stdout);
          target_mourn_inferior ();
 #ifdef NO_SINGLE_STEP
@@ -567,29 +650,38 @@ wait_for_inferior ()
         another thread.  If so, then step that thread past the breakpoint,
         and continue it.  */
 
-      if (stop_signal == TARGET_SIGNAL_TRAP
-         && breakpoints_inserted
-         && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+      if (stop_signal == TARGET_SIGNAL_TRAP)
        {
-         random_signal = 0;
-         if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
-           {
-             /* Saw a breakpoint, but it was hit by the wrong thread.  Just continue. */
-             write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+#ifdef NO_SINGLE_STEP
+         if (one_stepped)
+           random_signal = 0;
+         else
+#endif
+           if (breakpoints_inserted
+               && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+             {
+               random_signal = 0;
+               if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
+                 {
+                   /* Saw a breakpoint, but it was hit by the wrong thread.  Just continue. */
+                   write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
 
-             remove_breakpoints ();
-             target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
-             /* FIXME: What if a signal arrives instead of the single-step
-                happening?  */
+                   remove_breakpoints ();
+                   target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+                   /* FIXME: What if a signal arrives instead of the single-step
+                      happening?  */
 
-             if (target_wait_hook)
-               target_wait_hook (pid, &w);
-             else
-               target_wait (pid, &w);
-             insert_breakpoints ();
-             target_resume (pid, 0, TARGET_SIGNAL_0);
-             continue;
-           }
+                   if (target_wait_hook)
+                     target_wait_hook (pid, &w);
+                   else
+                     target_wait (pid, &w);
+                   insert_breakpoints ();
+
+                   /* We need to restart all the threads now.  */
+                   target_resume (-1, 0, TARGET_SIGNAL_0);
+                   continue;
+                 }
+             }
        }
       else
        random_signal = 1;
@@ -636,32 +728,27 @@ wait_for_inferior ()
          /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
             and fall into the rest of wait_for_inferior().  */
 
+         /* Save infrun state for the old thread.  */
+         save_infrun_state (inferior_pid, 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, handling_longjmp,
+                            another_trap);
+
          inferior_pid = pid;
-         printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
 
+         /* Load infrun state for the new thread.  */
+         load_infrun_state (inferior_pid, &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, &handling_longjmp,
+                            &another_trap);
+         printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
          flush_cached_frames ();
-         trap_expected = 0;
-         if (step_resume_breakpoint)
-           {
-             delete_breakpoint (step_resume_breakpoint);
-             step_resume_breakpoint = NULL;
-           }
-
-         /* Not sure whether we need to blow this away too,
-            but probably it is like the step-resume
-            breakpoint.  */
-         if (through_sigtramp_breakpoint)
-           {
-             delete_breakpoint (through_sigtramp_breakpoint);
-             through_sigtramp_breakpoint = NULL;
-           }
-         prev_pc = 0;
-         prev_func_name = NULL;
-         step_range_start = 0;
-         step_range_end = 0;
-         step_frame_address = 0;
-         handling_longjmp = 0;
-         another_trap = 0;
        }
 
 #ifdef NO_SINGLE_STEP
@@ -675,8 +762,22 @@ wait_for_inferior ()
 
       if (INSTRUCTION_NULLIFIED)
        {
-         resume (1, 0);
-         continue;
+         struct target_waitstatus tmpstatus;
+
+         registers_changed ();
+         target_resume (pid, 1, TARGET_SIGNAL_0);
+
+         /* We may have received a signal that we want to pass to
+            the inferior; therefore, we must not clobber the waitstatus
+            in W.  So we call wait ourselves, then continue the loop
+            at the "have_waited" label.  */
+         if (target_wait_hook)
+           target_wait_hook (pid, &tmpstatus);
+         else
+           target_wait (pid, &tmpstatus);
+
+
+         goto have_waited;
        }
 
 #ifdef HAVE_STEPPABLE_WATCHPOINT
@@ -697,19 +798,35 @@ wait_for_inferior ()
         here?  */
       if (STOPPED_BY_WATCHPOINT (w))
        {
+/* At this point, we are stopped at an instruction which has attempted to write
+   to a piece of memory under control of a watchpoint.  The instruction hasn't
+   actually executed yet.  If we were to evaluate the watchpoint expression
+   now, we would get the old value, and therefore no change would seem to have
+   occurred.
+
+   In order to make watchpoints work `right', we really need to complete the
+   memory write, and then evaluate the watchpoint expression.  The following
+   code does that by removing the watchpoint (actually, all watchpoints and
+   breakpoints), single-stepping the target, re-inserting watchpoints, and then
+   falling through to let normal single-step processing handle proceed.  Since
+   this includes evaluating watchpoints, things will come to a stop in the
+   correct manner.  */
+
+         write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
          remove_breakpoints ();
-         resume (1, 0);
+         registers_changed();
+         target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
 
-         /* FIXME: This is bogus.  You can't interact with the
-            inferior except when it is stopped.  It apparently
-            happens to work on Irix4, but it depends on /proc
-            allowing us to muck with the memory of a running process,
-            and the kernel deciding to run one instruction of the
-            inferior before it executes our insert_breakpoints code,
-            which seems like an awfully dubious assumption.  */
+         if (target_wait_hook)
+           target_wait_hook (pid, &w);
+         else
+           target_wait (pid, &w);
          insert_breakpoints ();
-
-         continue;
+         /* FIXME-maybe: is this cleaner than setting a flag?  Does it
+            handle things like signals arriving and other things happening
+            in combination correctly?  */
+         goto have_waited;
        }
 #endif
 
@@ -719,6 +836,7 @@ wait_for_inferior ()
 #endif
 
       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.  */
@@ -779,18 +897,22 @@ wait_for_inferior ()
              /* See if there is a breakpoint at the current PC.  */
              stop_bpstat = bpstat_stop_status
                (&stop_pc,
-#if DECR_PC_AFTER_BREAK
+                (DECR_PC_AFTER_BREAK ?
                 /* Notice the case of stepping through a jump
                    that lands just after a breakpoint.
                    Don't confuse that with hitting the breakpoint.
                    What we check for is that 1) stepping is going on
                    and 2) the pc before the last insn does not match
-                   the address of the breakpoint before the current pc.  */
-                (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-                 && CURRENTLY_STEPPING ())
-#else /* DECR_PC_AFTER_BREAK zero */
-                0
-#endif /* DECR_PC_AFTER_BREAK zero */
+                   the address of the breakpoint before the current pc
+                   and 3) we didn't hit a breakpoint in a signal handler
+                   without an intervening stop in sigtramp, which is
+                   detected by a new stack pointer value below
+                   any usual function calling stack adjustments.  */
+                (CURRENTLY_STEPPING ()
+                 && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+                 && !(step_range_end
+                      && read_sp () INNER_THAN (step_sp - 16))) :
+                0)
                 );
              /* Following in case break condition called a
                 function.  */
@@ -982,6 +1104,52 @@ wait_for_inferior ()
              another_trap = 1;
            break;
 
+         case BPSTAT_WHAT_CHECK_SHLIBS:
+#ifdef SOLIB_ADD
+           {
+             extern int auto_solib_add;
+
+             /* Remove breakpoints, we eventually want to step over the
+                shlib event breakpoint, and SOLIB_ADD might adjust
+                breakpoint addresses via breakpoint_re_set.  */
+             if (breakpoints_inserted)
+               remove_breakpoints ();
+             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 ();
+               }
+
+             /* Try to reenable shared library breakpoints, additional
+                code segments in shared libraries might be mapped in now. */
+             re_enable_breakpoints_in_shlibs ();
+
+             /* If requested, stop when the dynamic linker notifies
+                gdb of events.  This allows the user to get control
+                and place breakpoints in initializer routines for
+                dynamically loaded objects (among other things).  */
+             if (stop_on_solib_events)
+               {
+                 stop_print_frame = 0;
+                 goto stop_stepping;
+               }
+             else
+               {
+                 /* We want to step over this breakpoint, then keep going.  */
+                 another_trap = 1;
+                 break;
+               }
+           }
+#endif
+         break;
+
          case BPSTAT_WHAT_LAST:
            /* Not a real code, but listed here to shut up gcc -Wall.  */
 
@@ -1035,6 +1203,10 @@ wait_for_inferior ()
       /* If stepping through a line, keep going if still within it.  */
       if (stop_pc >= step_range_start
          && stop_pc < step_range_end
+#if 0
+/* I haven't a clue what might trigger this clause, and it seems wrong anyway,
+   so I've disabled it until someone complains.  -Stu 10/24/95 */
+
          /* The step range might include the start of the
             function, so if we are at the start of the
             step range and either the stack or frame pointers
@@ -1042,7 +1214,9 @@ wait_for_inferior ()
          && !(stop_pc == step_range_start
               && FRAME_FP (get_current_frame ())
               && (read_sp () INNER_THAN step_sp
-                  || FRAME_FP (get_current_frame ()) != step_frame_address)))
+                  || FRAME_FP (get_current_frame ()) != step_frame_address))
+#endif
+)
        {
          /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
             So definately need to check for sigtramp here.  */
@@ -1051,6 +1225,13 @@ wait_for_inferior ()
 
       /* We stepped out of the stepping range.  */
 
+      /* If we are stepping at the source level and entered the runtime
+         loader dynamic symbol resolution code, we keep on single stepping
+        until we exit the run time loader code and reach the callee's
+        address.  */
+      if (step_over_calls < 0 && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
+       goto keep_going;
+
       /* 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.  */
@@ -1058,7 +1239,8 @@ wait_for_inferior ()
 
       /* Did we just take a signal?  */
       if (IN_SIGTRAMP (stop_pc, stop_func_name)
-         && !IN_SIGTRAMP (prev_pc, prev_func_name))
+         && !IN_SIGTRAMP (prev_pc, prev_func_name)
+         && read_sp () INNER_THAN step_sp)
        {
          /* We've just taken a signal; go until we are back to
             the point where we took it and one more.  */
@@ -1075,9 +1257,9 @@ wait_for_inferior ()
          {
            struct symtab_and_line sr_sal;
 
-           sr_sal.pc = prev_pc;
-           sr_sal.symtab = NULL;
-           sr_sal.line = 0;
+           INIT_SAL (&sr_sal);         /* initialize to zeroes */
+           sr_sal.pc      = prev_pc;
+           sr_sal.section = find_pc_overlay (sr_sal.pc);
            /* We could probably be setting the frame to
               step_frame_address; I don't think anyone thought to try it.  */
            step_resume_breakpoint =
@@ -1098,7 +1280,13 @@ wait_for_inferior ()
          goto keep_going;
        }
 
-#if 1
+#if 0
+      /* I disabled this test because it was too complicated and slow.  The
+        SKIP_PROLOGUE was especially slow, because it caused unnecessary
+        prologue examination on various architectures.  The code in the #else
+        clause has been tested on the Sparc, Mips, PA, and Power
+        architectures, so it's pretty likely to be correct.  -Stu 10/24/95 */
+
       /* See if we left the step range due to a subroutine call that
         we should proceed to the end of.  */
 
@@ -1116,16 +1304,17 @@ wait_for_inferior ()
            SKIP_PROLOGUE (prologue_pc);
        }
 
-      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
-          || read_sp () != step_sp)
+      if (!(step_sp INNER_THAN read_sp ())     /* don't mistake (sig)return as a call */
+         && (/* 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
+             || read_sp () != step_sp)
          && (/* PC is completely out of bounds of any known objfiles.  Treat
                 like a subroutine call. */
              ! stop_func_start
@@ -1163,13 +1352,16 @@ wait_for_inferior ()
                 handling_longjmp stuff is working.  */
              ))
 #else
-/* This is experimental code which greatly simplifies the subroutine call
-   test.  I've actually tested on the Alpha, and it works great. -Stu */
-
-       if (in_prologue (stop_pc, NULL)
-           || (prev_func_start != 0
-               && stop_func_start == 0))
+       /* This test is a much more streamlined, (but hopefully correct)
+          replacement for the code above.  It's been tested on the Sparc,
+          Mips, PA, and Power architectures with good results.  */
+
+       if (stop_pc == stop_func_start /* Quick test */
+           || in_prologue (stop_pc, stop_func_start)
+           || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
+           || stop_func_start == 0)
 #endif
+
        {
          /* It's a subroutine call.  */
 
@@ -1182,7 +1374,7 @@ wait_for_inferior ()
              break;
            }
 
-         if (step_over_calls > 0)
+         if (step_over_calls > 0 || IGNORE_HELPER_CALL (stop_pc))
            /* We're doing a "next".  */
            goto step_over_function;
 
@@ -1194,6 +1386,23 @@ wait_for_inferior ()
          tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
          if (tmp != 0)
            stop_func_start = tmp;
+         else
+           {
+             tmp = DYNAMIC_TRAMPOLINE_NEXTPC (stop_pc);
+             if (tmp)
+               {
+                 struct symtab_and_line xxx;
+                 /* Why isn't this s_a_l called "sr_sal", like all of the
+                    other s_a_l's where this code is duplicated?  */
+                 INIT_SAL (&xxx);      /* initialize to zeroes */
+                 xxx.pc      = tmp;
+                 xxx.section = find_pc_overlay (xxx.pc);
+                 step_resume_breakpoint = 
+                   set_momentary_breakpoint (xxx, NULL, bp_step_resume);
+                 insert_breakpoints ();
+                 goto keep_going;
+               }
+           }
 
          /* If we have line number information for the function we
             are thinking of stepping into, step into it.
@@ -1214,15 +1423,16 @@ step_over_function:
          {
            /* Set a special breakpoint after the return */
            struct symtab_and_line sr_sal;
+
+           INIT_SAL (&sr_sal);         /* initialize to zeroes */
            sr_sal.pc = 
-             ADDR_BITS_REMOVE
-               (SAVED_PC_AFTER_CALL (get_current_frame ()));
-           sr_sal.symtab = NULL;
-           sr_sal.line = 0;
+             ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ()));
+           sr_sal.section = find_pc_overlay (sr_sal.pc);
            step_resume_breakpoint =
              set_momentary_breakpoint (sr_sal, get_current_frame (),
                                        bp_step_resume);
-           step_resume_breakpoint->frame = step_frame_address;
+           if (!IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+             step_resume_breakpoint->frame = step_frame_address;
            if (breakpoints_inserted)
              insert_breakpoints ();
          }
@@ -1264,9 +1474,9 @@ step_into_function:
            {
              struct symtab_and_line sr_sal;
 
-             sr_sal.pc = stop_func_start;
-             sr_sal.symtab = NULL;
-             sr_sal.line = 0;
+             INIT_SAL (&sr_sal);       /* initialize to zeroes */
+             sr_sal.pc      = stop_func_start;
+             sr_sal.section = find_pc_overlay (stop_func_start);
              /* 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.  */
@@ -1308,9 +1518,9 @@ step_into_function:
              /* 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;
+             INIT_SAL (&sr_sal);       /* initialize to zeroes */
+             sr_sal.pc      = tmp;
+             sr_sal.section = find_pc_overlay (sr_sal.pc);
              /* 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.  */
@@ -1365,12 +1575,16 @@ step_into_function:
        }
       step_range_start = sal.pc;
       step_range_end = sal.end;
+      step_frame_address = FRAME_FP (get_current_frame ());
+      current_line = sal.line;
+      current_symtab = sal.symtab;
       goto keep_going;
 
     check_sigtramp2:
       if (trap_expected
          && IN_SIGTRAMP (stop_pc, stop_func_name)
-         && !IN_SIGTRAMP (prev_pc, prev_func_name))
+         && !IN_SIGTRAMP (prev_pc, prev_func_name)
+         && read_sp () INNER_THAN step_sp)
        {
          /* What has happened here is that we have just stepped the inferior
             with a signal (because it is a signal which shouldn't make
@@ -1384,9 +1598,9 @@ step_into_function:
             it says "exceedingly difficult").  */
          struct symtab_and_line sr_sal;
 
-         sr_sal.pc = prev_pc;
-         sr_sal.symtab = NULL;
-         sr_sal.line = 0;
+         INIT_SAL (&sr_sal);           /* initialize to zeroes */
+         sr_sal.pc      = prev_pc;
+         sr_sal.section = find_pc_overlay (sr_sal.pc);
          /* We perhaps could set the frame if we kept track of what
             the frame corresponding to prev_pc was.  But we don't,
             so don't.  */
@@ -1546,6 +1760,11 @@ Further execution is probably impossible.\n");
 
   target_terminal_ours ();
 
+  if (stop_bpstat
+      && stop_bpstat->breakpoint_at
+      && stop_bpstat->breakpoint_at->type == bp_shlib_event)
+    printf_filtered ("Stopped due to shared library event\n");
+
   /* Look up the hook_stop and run it if it exists.  */
 
   if (stop_command->hook)
@@ -1641,9 +1860,12 @@ sig_print_info (oursig)
      enum target_signal oursig;
 {
   char *name = target_signal_to_name (oursig);
+  int name_padding = 13 - strlen (name);
+  if (name_padding <= 0)
+    name_padding = 0;
+
   printf_filtered ("%s", name);
-  printf_filtered ("%*.*s ", 13 - strlen (name), 13 - strlen (name),
-                  "                 ");
+  printf_filtered ("%*.*s ", name_padding, name_padding, "                 ");
   printf_filtered ("%s\t", signal_stop[oursig] ? "Yes" : "No");
   printf_filtered ("%s\t", signal_print[oursig] ? "Yes" : "No");
   printf_filtered ("%s\t\t", signal_program[oursig] ? "Yes" : "No");
@@ -1748,10 +1970,11 @@ handle_command (args, from_tty)
             anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc.
             will work right anyway.  */
 
-         sigfirst = siglast = atoi (*argv);
+         sigfirst = siglast = (int) target_signal_from_command (atoi (*argv));
          if ((*argv)[digits] == '-')
            {
-             siglast = atoi ((*argv) + digits + 1);
+             siglast =
+               (int) target_signal_from_command (atoi ((*argv) + digits + 1));
            }
          if (sigfirst > siglast)
            {
@@ -1760,14 +1983,6 @@ handle_command (args, from_tty)
              sigfirst = siglast;
              siglast = signum;
            }
-         if (sigfirst < 0 || sigfirst >= nsigs)
-           {
-             error ("Signal %d not in range 0-%d", sigfirst, nsigs - 1);
-           }
-         if (siglast < 0 || siglast >= nsigs)
-           {
-             error ("Signal %d not in range 0-%d", siglast, nsigs - 1);
-           }
        }
       else
        {
@@ -1808,6 +2023,11 @@ Are you sure you want to change it? ",
                      }
                  }
                break;
+             case TARGET_SIGNAL_0:
+             case TARGET_SIGNAL_DEFAULT:
+             case TARGET_SIGNAL_UNKNOWN:
+               /* Make sure that "all" doesn't print these.  */
+               break;
              default:
                sigs[signum] = 1;
                break;
@@ -1854,20 +2074,9 @@ signals_info (signum_exp, from_tty)
       oursig = target_signal_from_name (signum_exp);
       if (oursig == TARGET_SIGNAL_UNKNOWN)
        {
-         /* Nope, maybe it's an address which evaluates to a signal
-            number.  */
-         /* The numeric signal refers to our own internal
-            signal numbering from target.h, not to host/target signal number.
-            This is a feature; users really should be using symbolic names
-            anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc.
-            will work right anyway.  */
-         int i = parse_and_eval_address (signum_exp);
-         if (i >= (int)TARGET_SIGNAL_LAST
-             || i < 0
-             || i == (int)TARGET_SIGNAL_UNKNOWN
-             || i == (int)TARGET_SIGNAL_DEFAULT)
-           error ("Signal number out of bounds.");
-         oursig = (enum target_signal)i;
+         /* No, try numeric.  */
+         oursig =
+           target_signal_from_command (parse_and_eval_address (signum_exp));
        }
       sig_print_info (oursig);
       return;
@@ -2029,23 +2238,24 @@ _initialize_infrun ()
 
   add_info ("signals", signals_info,
            "What debugger does when program gets various signals.\n\
-Specify a signal number as argument to print info on that signal only.");
+Specify a signal as argument to print info on that signal only.");
   add_info_alias ("handle", "signals", 0);
 
   add_com ("handle", class_run, handle_command,
-          "Specify how to handle a signal.\n\
-Args are signal numbers and actions to apply to those signals.\n\
-Signal numbers may be numeric (ex. 11) or symbolic (ex. SIGSEGV).\n\
-Numeric ranges may be specified with the form LOW-HIGH (ex. 14-21).\n\
+          concat ("Specify how to handle a signal.\n\
+Args are signals and actions to apply to those signals.\n\
+Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
+from 1-15 are allowed for compatibility with old versions of GDB.\n\
+Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\n\
 The special arg \"all\" is recognized to mean all signals except those\n\
-used by the debugger, typically SIGTRAP and SIGINT.\n\
-Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
+used by the debugger, typically SIGTRAP and SIGINT.\n",
+"Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
 \"pass\", \"nopass\", \"ignore\", or \"noignore\".\n\
 Stop means reenter debugger if this signal happens (implies print).\n\
 Print means print a message if this signal happens.\n\
 Pass means let program see this signal; otherwise program doesn't know.\n\
 Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
-Pass and Stop may be combined.");
+Pass and Stop may be combined.", NULL));
 
   stop_command = add_cmd ("stop", class_obscure, not_just_help_class_command,
           "There is no `stop' command, but you can set a hook on `stop'.\n\
@@ -2086,4 +2296,16 @@ of the program stops.", &cmdlist);
   signal_print[TARGET_SIGNAL_POLL] = 0;
   signal_stop[TARGET_SIGNAL_URG] = 0;
   signal_print[TARGET_SIGNAL_URG] = 0;
+
+#ifdef SOLIB_ADD
+  add_show_from_set
+    (add_set_cmd ("stop-on-solib-events", class_support, var_zinteger,
+                  (char *) &stop_on_solib_events,
+                 "Set stopping for shared library events.\n\
+If nonzero, gdb will give control to the user when the dynamic linker\n\
+notifies gdb of shared library events.  The most common event of interest\n\
+to the user would be loading/unloading of a new library.\n",
+                  &setlist),
+     &showlist);
+#endif
 }
This page took 0.035213 seconds and 4 git commands to generate.