2002-11-29 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / stack.c
index d34e57174f4771c9a18640d7779b2d7309220817..999de6fde4c6acb0577b3d00fe3f796db730d165 100644 (file)
@@ -33,6 +33,7 @@
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "target.h"
+#include "source.h"
 #include "breakpoint.h"
 #include "demangle.h"
 #include "inferior.h"
@@ -49,9 +50,9 @@ void (*selected_frame_level_changed_hook) (int);
 
 void _initialize_stack (void);
 
-/* Prototypes for local functions. */
+void return_command (char *, int);
 
-static void return_command (char *, int);
+/* Prototypes for local functions. */
 
 static void down_command (char *, int);
 
@@ -108,29 +109,12 @@ struct frame_info *parse_frame_specification (char *);
 static void frame_info (char *, int);
 
 extern int addressprint;       /* Print addresses, or stay symbolic only? */
-extern int lines_to_list;      /* # of lines "list" command shows by default */
 
 /* The "selected" stack frame is used by default for local and arg access.
    May be zero, for no selected frame.  */
 
 struct frame_info *selected_frame;
 
-/* Level of the selected frame:
-   0 for innermost, 1 for its caller, ...
-   or -1 for frame specified by address with no defined level.  */
-
-/* Level of the selected frame: 0 for innermost, 1 for its caller, ...
-   or -1 for NULL frame.  */
-
-int
-frame_relative_level (struct frame_info *fi)
-{
-  if (fi == NULL)
-    return -1;
-  else
-    return fi->level;
-}
-
 /* Zero means do things normally; we are interacting directly with the
    user.  One means print the full filename and linenumber when a
    frame is printed, and do so in a format emacs18/emacs19.22 can
@@ -333,45 +317,33 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
   int source_print;
   int location_print;
 
-#if 0
-  char buf[MAX_REGISTER_RAW_SIZE];
-  CORE_ADDR sp;
-
-  /* On the 68k, this spends too much time in m68k_find_saved_regs.  */
-
-  /* Get the value of SP_REGNUM relative to the frame.  */
-  get_saved_register (buf, (int *) NULL, (CORE_ADDR *) NULL,
-                   FRAME_INFO_ID (fi), SP_REGNUM, (enum lval_type *) NULL);
-  sp = extract_address (buf, REGISTER_RAW_SIZE (SP_REGNUM));
-
-  /* This is not a perfect test, because if a function alloca's some
-     memory, puts some code there, and then jumps into it, then the test
-     will succeed even though there is no call dummy.  Probably best is
-     to check for a bp_call_dummy breakpoint.  */
-  if (PC_IN_CALL_DUMMY (fi->pc, sp, fi->frame))
-#else
-  if (frame_in_dummy (fi))
-#endif
+  if (get_frame_type (fi) == DUMMY_FRAME)
     {
       annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
 
       /* Do this regardless of SOURCE because we don't have any source
          to list for this frame.  */
       if (level >= 0)
-       printf_filtered ("#%-2d ", level);
+        {
+          ui_out_text (uiout, "#");
+          ui_out_field_fmt_int (uiout, 2, ui_left, "level", level);
+        }
       annotate_function_call ();
       printf_filtered ("<function called from gdb>\n");
       annotate_frame_end ();
       return;
     }
-  if (fi->signal_handler_caller)
+  if ((get_frame_type (fi) == SIGTRAMP_FRAME))
     {
       annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
 
       /* Do this regardless of SOURCE because we don't have any source
          to list for this frame.  */
       if (level >= 0)
-       printf_filtered ("#%-2d ", level);
+        {
+          ui_out_text (uiout, "#");
+          ui_out_field_fmt_int (uiout, 2, ui_left, "level", level);
+        }
       annotate_signal_handler_caller ();
       printf_filtered ("<signal handler called>\n");
       annotate_frame_end ();
@@ -379,16 +351,12 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
     }
 
   /* If fi is not the innermost frame, that normally means that fi->pc
-     points to *after* the call instruction, and we want to get the line
-     containing the call, never the next line.  But if the next frame is
-     a signal_handler_caller or a dummy frame, then the next frame was
-     not entered as the result of a call, and we want to get the line
-     containing fi->pc.  */
-  sal =
-    find_pc_line (fi->pc,
-                 fi->next != NULL
-                 && !fi->next->signal_handler_caller
-                 && !frame_in_dummy (fi->next));
+     points to *after* the call instruction, and we want to get the
+     line containing the call, never the next line.  But if the next
+     frame is a SIGTRAMP_FRAME or a DUMMY_FRAME, then the next frame
+     was not entered as the result of a call, and we want to get the
+     line containing fi->pc.  */
+  find_frame_sal (fi, &sal);
 
   location_print = (source == LOCATION 
                    || source == LOC_AND_ADDRESS
@@ -399,8 +367,12 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
 
   source_print = (source == SRC_LINE || source == SRC_AND_LOC);
 
+  if (sal.symtab)
+    set_current_source_symtab_and_line (&sal);
+
   if (source_print && sal.symtab)
     {
+      struct symtab_and_line cursal;
       int done = 0;
       int mid_statement = (source == SRC_LINE) && (fi->pc != sal.pc);
 
@@ -410,10 +382,7 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
       if (!done)
        {
          if (print_frame_info_listing_hook)
-           {
-             print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
-             current_source_symtab = sal.symtab;
-           }
+           print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
          else
            {
              /* We used to do this earlier, but that is clearly
@@ -433,7 +402,11 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
              print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
            }
        }
-      current_source_line = max (sal.line - lines_to_list / 2, 1);
+      /* Make sure we have at least a default source file */
+      set_default_source_symtab_and_line ();
+      cursal = get_current_source_symtab_and_line ();
+      cursal.line = max (sal.line - get_lines_to_list () / 2, 1);
+      set_current_source_symtab_and_line (&cursal);
     }
 
   if (source != 0)
@@ -461,7 +434,7 @@ print_frame (struct frame_info *fi,
   stb = ui_out_stream_new (uiout);
   old_chain = make_cleanup_ui_out_stream_delete (stb);
 
-  func = find_pc_function (fi->pc);
+  func = find_pc_function (frame_address_in_block (fi));
   if (func)
     {
       /* In certain pathological cases, the symtabs give the wrong
@@ -480,7 +453,7 @@ print_frame (struct frame_info *fi,
          ever changed many parts of GDB will need to be changed (and we'll
          create a find_pc_minimal_function or some such).  */
 
-      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (frame_address_in_block (fi));
       if (msymbol != NULL
          && (SYMBOL_VALUE_ADDRESS (msymbol)
              > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
@@ -528,7 +501,7 @@ print_frame (struct frame_info *fi,
     }
   else
     {
-      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (frame_address_in_block (fi));
       if (msymbol != NULL)
        {
          funname = SYMBOL_NAME (msymbol);
@@ -543,8 +516,7 @@ print_frame (struct frame_info *fi,
   if (level >= 0)
     {
       ui_out_text (uiout, "#");
-      ui_out_field_fmt (uiout, "level", "%-2d", level);
-      ui_out_spaces (uiout, 1);
+      ui_out_field_fmt_int (uiout, 2, ui_left, "level", level);
     }
   if (addressprint)
     if (fi->pc != sal.pc || !sal.symtab || source == LOC_AND_ADDRESS)
@@ -781,11 +753,10 @@ frame_info (char *addr_exp, int from_tty)
   if (fi == NULL)
     error ("Invalid frame specified.");
 
-  sal = find_pc_line (fi->pc,
-                     fi->next != NULL
-                     && !fi->next->signal_handler_caller
-                     && !frame_in_dummy (fi->next));
+  find_frame_sal (fi, &sal);
   func = get_frame_function (fi);
+  /* FIXME: cagney/2002-11-28: Why bother?  Won't sal.symtab contain
+     the same value.  */
   s = find_pc_symtab (fi->pc);
   if (func)
     {
@@ -856,7 +827,7 @@ frame_info (char *addr_exp, int from_tty)
   puts_filtered ("; ");
   wrap_here ("    ");
   printf_filtered ("saved %s ", REGISTER_NAME (PC_REGNUM));
-  print_address_numeric (FRAME_SAVED_PC (fi), 1, gdb_stdout);
+  print_address_numeric (frame_pc_unwind (fi), 1, gdb_stdout);
   printf_filtered ("\n");
 
   {
@@ -882,7 +853,8 @@ frame_info (char *addr_exp, int from_tty)
   if (fi->next || calling_frame_info)
     puts_filtered ("\n");
   if (s)
-    printf_filtered (" source language %s.\n", language_str (s->language));
+    printf_filtered (" source language %s.\n",
+                    language_str (s->language));
 
 #ifdef PRINT_EXTRA_FRAME_INFO
   PRINT_EXTRA_FRAME_INFO (fi);
@@ -929,39 +901,84 @@ frame_info (char *addr_exp, int from_tty)
       }
   }
 
-  FRAME_INIT_SAVED_REGS (fi);
-  if (fi->saved_regs != NULL)
-    {
-      /* The sp is special; what's returned isn't the save address, but
-         actually the value of the previous frame's sp.  */
-      printf_filtered (" Previous frame's sp is ");
-      print_address_numeric (fi->saved_regs[SP_REGNUM], 1, gdb_stdout);
-      printf_filtered ("\n");
-      count = 0;
-      numregs = NUM_REGS + NUM_PSEUDO_REGS;
-      for (i = 0; i < numregs; i++)
-       if (fi->saved_regs[i] && i != SP_REGNUM)
+  if (fi->saved_regs == NULL)
+    FRAME_INIT_SAVED_REGS (fi);
+  /* Print as much information as possible on the location of all the
+     registers.  */
+  {
+    enum lval_type lval;
+    int optimized;
+    CORE_ADDR addr;
+    int realnum;
+    int count;
+    int i;
+    int need_nl = 1;
+
+    /* The sp is special; what's displayed isn't the save address, but
+       the value of the previous frame's sp.  This is a legacy thing,
+       at one stage the frame cached the previous frame's SP instead
+       of its address, hence it was easiest to just display the cached
+       value.  */
+    if (SP_REGNUM >= 0)
+      {
+       /* Find out the location of the saved stack pointer with out
+           actually evaluating it.  */
+       frame_register_unwind (fi, SP_REGNUM, &optimized, &lval, &addr,
+                              &realnum, NULL);
+       if (!optimized && lval == not_lval)
          {
-           if (count == 0)
-             puts_filtered (" Saved registers:\n ");
-           else
-             puts_filtered (",");
-           wrap_here (" ");
-           printf_filtered (" %s at ", REGISTER_NAME (i));
-           print_address_numeric (fi->saved_regs[i], 1, gdb_stdout);
-           count++;
+           void *value = alloca (MAX_REGISTER_RAW_SIZE);
+           CORE_ADDR sp;
+           frame_register_unwind (fi, SP_REGNUM, &optimized, &lval, &addr,
+                                  &realnum, value);
+           sp = extract_address (value, REGISTER_RAW_SIZE (SP_REGNUM));
+           printf_filtered (" Previous frame's sp is ");
+           print_address_numeric (sp, 1, gdb_stdout);
+           printf_filtered ("\n");
+           need_nl = 0;
          }
-      if (count)
-       puts_filtered ("\n");
-    }
-  else
-    {
-      /* We could get some information about saved registers by
-         calling get_saved_register on each register.  Which info goes
-         with which frame is necessarily lost, however, and I suspect
-         that the users don't care whether they get the info.  */
+       else if (!optimized && lval == lval_memory)
+         {
+           printf_filtered (" Previous frame's sp at ");
+           print_address_numeric (addr, 1, gdb_stdout);
+           printf_filtered ("\n");
+           need_nl = 0;
+         }
+       else if (!optimized && lval == lval_register)
+         {
+           printf_filtered (" Previous frame's sp in %s\n",
+                            REGISTER_NAME (realnum));
+           need_nl = 0;
+         }
+       /* else keep quiet.  */
+      }
+
+    count = 0;
+    numregs = NUM_REGS + NUM_PSEUDO_REGS;
+    for (i = 0; i < numregs; i++)
+      if (i != SP_REGNUM)
+       {
+         /* Find out the location of the saved register without
+             fetching the corresponding value.  */
+         frame_register_unwind (fi, i, &optimized, &lval, &addr, &realnum,
+                                NULL);
+         /* For moment, only display registers that were saved on the
+            stack.  */
+         if (!optimized && lval == lval_memory)
+           {
+             if (count == 0)
+               puts_filtered (" Saved registers:\n ");
+             else
+               puts_filtered (",");
+             wrap_here (" ");
+             printf_filtered (" %s at ", REGISTER_NAME (i));
+             print_address_numeric (addr, 1, gdb_stdout);
+             count++;
+           }
+       }
+    if (count || need_nl)
       puts_filtered ("\n");
-    }
+  }
 }
 
 #if 0
@@ -1066,7 +1083,7 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
           fi = get_prev_frame (fi))
        {
          QUIT;
-         ps = find_pc_psymtab (fi->pc);
+         ps = find_pc_psymtab (frame_address_in_block (fi));
          if (ps)
            PSYMTAB_TO_SYMTAB (ps);     /* Force syms to come in */
        }
@@ -1459,50 +1476,27 @@ args_plus_locals_info (char *ignore, int from_tty)
 }
 \f
 
-/* Select frame FI, and note that its stack level is LEVEL.
-   LEVEL may be -1 if an actual level number is not known.  */
+/* Select frame FI (or NULL - to invalidate the current frame).  */
 
 void
-select_frame (struct frame_info *fi, int level)
+select_frame (struct frame_info *fi)
 {
   register struct symtab *s;
 
   selected_frame = fi;
-  /* FIXME: cagney/2002-04-05: It can't be this easy (and looking at
-     the increasingly complex list of checkes, it wasn't)!  GDB is
-     dragging around, and constantly updating, the global variable
-     selected_frame_level.  Surely all that was needed was for the
-     level to be computed direct from the frame (by counting back to
-     the inner-most frame) or, as has been done here using a cached
-     value.  For moment, check that the expected and the actual level
-     are consistent.  If, after a few weeks, no one reports that this
-     assertion has failed, the global selected_frame_level and many
-     many parameters can all be deleted.  */
-  if (fi == NULL && level == -1)
-    /* Ok.  The target is clearing the selected frame as part of a
-       cache flush.  */
-    ;
-  else if (fi != NULL && fi->level == level)
-    /* Ok.  What you would expect.  Level is redundant.  */
-    ;
-  else if (fi != NULL && level == -1)
-    /* Ok.  See breakpoint.c.  The watchpoint code changes the
-       selected frame to the frame that contains the watchpoint and
-       then, later changes it back to the old value.  The -1 is used
-       as a marker so that the watchpoint code can easily detect that
-       things are not what they should be.  Why the watchpoint code
-       can't mindlessly save/restore the selected frame I don't know,
-       hopefully it can be simplified that way.  Hopefully the global
-       selected_frame can be replaced by a frame parameter, making
-       still more simplification possible.  */
-    ;
-  else
-    internal_error (__FILE__, __LINE__,
-                   "Conflicting frame levels fi->level=%d, level=%d",
-                   (fi ? fi->level : -1),
-                   level);
+  /* NOTE: cagney/2002-05-04: FI can be NULL.  This occures when the
+     frame is being invalidated.  */
   if (selected_frame_level_changed_hook)
-    selected_frame_level_changed_hook (level);
+    selected_frame_level_changed_hook (frame_relative_level (fi));
+
+  /* FIXME: kseitz/2002-08-28: It would be nice to call
+     selected_frame_level_changed_event right here, but due to limitations
+     in the current interfaces, we would end up flooding UIs with events
+     because select_frame is used extensively internally.
+
+     Once we have frame-parameterized frame (and frame-related) commands,
+     the event notification can be moved here, since this function will only
+     be called when the users selected frame is being changed. */
 
   /* Ensure that symbols for this frame are read in.  Also, determine the
      source language of this frame, and switch to it if desired.  */
@@ -1520,29 +1514,18 @@ select_frame (struct frame_info *fi, int level)
 }
 \f
 
-/* Select frame FI, noting that its stack level is LEVEL.  Also print
-   the stack frame and show the source if this is the tui version.  */
-void
-select_and_print_frame (struct frame_info *fi, int level)
+/* Select frame FI.  Also print the stack frame and show the source if
+   this is the tui version.  */
+static void
+select_and_print_frame (struct frame_info *fi)
 {
-  select_frame (fi, level);
+  select_frame (fi);
   if (fi)
     {
-      print_stack_frame (fi, level, 1);
+      print_stack_frame (fi, frame_relative_level (fi), 1);
     }
 }
 \f
-
-/* Store the selected frame and its level into *FRAMEP and *LEVELP.
-   If there is no selected frame, *FRAMEP is set to NULL.  */
-
-void
-record_selected_frame (CORE_ADDR *frameaddrp, int *levelp)
-{
-  *frameaddrp = selected_frame ? selected_frame->frame : 0;
-  *levelp = frame_relative_level (selected_frame);
-}
-
 /* Return the symbol-block in which the selected frame is executing.
    Can return zero under various legitimate circumstances.
 
@@ -1556,8 +1539,22 @@ get_selected_block (CORE_ADDR *addr_in_block)
   if (!target_has_stack)
     return 0;
 
+  /* NOTE: cagney/2002-11-28: Why go to all this effort to not create
+     a selected/current frame?  Perhaphs this function is called,
+     indirectly, by WFI in "infrun.c" where avoiding the creation of
+     an inner most frame is very important (it slows down single
+     step).  I suspect, though that this was true in the deep dark
+     past but is no longer the case.  A mindless look at all the
+     callers tends to support this theory.  I think we should be able
+     to assume that there is always a selcted frame.  */
+  /* gdb_assert (selected_frame != NULL); So, do you feel lucky? */
   if (!selected_frame)
-    return get_current_block (addr_in_block);
+    {
+      CORE_ADDR pc = read_pc ();
+      if (addr_in_block != NULL)
+       *addr_in_block = pc;
+      return block_for_pc (pc);
+    }
   return get_frame_block (selected_frame, addr_in_block);
 }
 
@@ -1618,29 +1615,17 @@ select_frame_command_wrapper (char *level_exp, int from_tty)
 static void
 select_frame_command (char *level_exp, int from_tty)
 {
-  register struct frame_info *frame, *frame1;
-  unsigned int level = 0;
+  struct frame_info *frame;
+  int level = frame_relative_level (selected_frame);
 
   if (!target_has_stack)
     error ("No stack.");
 
   frame = parse_frame_specification (level_exp);
 
-  /* Try to figure out what level this frame is.  But if there is
-     no current stack, don't error out -- let the user set one.  */
-  frame1 = 0;
-  if (get_current_frame ())
-    {
-      for (frame1 = get_prev_frame (0);
-          frame1 && frame1 != frame;
-          frame1 = get_prev_frame (frame1))
-       level++;
-    }
-
-  if (!frame1)
-    level = 0;
-
-  select_frame (frame, level);
+  select_frame (frame);
+  if (level != frame_relative_level (selected_frame))
+    selected_frame_level_changed_event (frame_relative_level (selected_frame));
 }
 
 /* The "frame" command.  With no arg, print selected frame briefly.
@@ -1685,7 +1670,8 @@ up_silently_base (char *count_exp)
   fi = find_relative_frame (selected_frame, &count1);
   if (count1 != 0 && count_exp == 0)
     error ("Initial frame selected; you cannot go up.");
-  select_frame (fi, frame_relative_level (selected_frame) + count - count1);
+  select_frame (fi);
+  selected_frame_level_changed_event (frame_relative_level (selected_frame));
 }
 
 static void
@@ -1730,7 +1716,8 @@ down_silently_base (char *count_exp)
       error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
     }
 
-  select_frame (frame, frame_relative_level (selected_frame) + count - count1);
+  select_frame (frame);
+  selected_frame_level_changed_event (frame_relative_level (selected_frame));
 }
 
 /* ARGSUSED */
@@ -1749,12 +1736,6 @@ down_command (char *count_exp, int from_tty)
 }
 \f
 void
-return_command_wrapper (char *retval_exp, int from_tty)
-{
-  return_command (retval_exp, from_tty);
-}
-
-static void
 return_command (char *retval_exp, int from_tty)
 {
   struct symbol *thisfun;
@@ -1766,7 +1747,7 @@ return_command (char *retval_exp, int from_tty)
   if (selected_frame == NULL)
     error ("No selected frame.");
   thisfun = get_frame_function (selected_frame);
-  selected_frame_addr = FRAME_FP (selected_frame);
+  selected_frame_addr = get_frame_base (selected_frame);
   selected_frame_pc = selected_frame->pc;
 
   /* Compute the return value (if any -- possibly getting errors here).  */
@@ -1828,7 +1809,7 @@ return_command (char *retval_exp, int from_tty)
   /* If we are at the end of a call dummy now, pop the dummy frame too.  */
 
   if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (),
-                               FRAME_FP (get_current_frame ())))
+                               get_frame_base (get_current_frame ())))
     POP_FRAME;
 
   /* If interactive, print the frame that is now current.  */
@@ -1897,7 +1878,7 @@ func_command (char *arg, int from_tty)
   if (!found)
     printf_filtered ("'%s' not within current stack frame.\n", arg);
   else if (fp != selected_frame)
-    select_and_print_frame (fp, level);
+    select_and_print_frame (fp);
 }
 
 /* Gets the language of the current frame.  */
This page took 0.033336 seconds and 4 git commands to generate.