* Makefile.in (i386nbsd-tdep.o): Add $(arch_utils_h),
[deliverable/binutils-gdb.git] / gdb / stack.c
index 2fe6e420b0bb8da197c68da4efe5fccc1e818424..30ebc09dee70fba8ece1ae60770626d2f8e2d7f7 100644 (file)
@@ -119,7 +119,17 @@ struct frame_info *selected_frame;
    0 for innermost, 1 for its caller, ...
    or -1 for frame specified by address with no defined level.  */
 
-int selected_frame_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
@@ -388,6 +398,11 @@ print_frame_info_base (struct frame_info *fi, int level, int source, int args)
     print_frame (fi, level, source, args, sal);
 
   source_print = (source == SRC_LINE || source == SRC_AND_LOC);
+  if (sal.symtab)
+    {
+      current_source_symtab = sal.symtab;
+      current_source_line = sal.line;
+    }
 
   if (source_print && sal.symtab)
     {
@@ -400,10 +415,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
@@ -451,7 +463,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
@@ -470,7 +482,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))))
@@ -518,7 +530,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);
@@ -817,9 +829,10 @@ frame_info (char *addr_exp, int from_tty)
     }
   calling_frame_info = get_prev_frame (fi);
 
-  if (!addr_exp && selected_frame_level >= 0)
+  if (!addr_exp && frame_relative_level (selected_frame) >= 0)
     {
-      printf_filtered ("Stack level %d, frame at ", selected_frame_level);
+      printf_filtered ("Stack level %d, frame at ",
+                      frame_relative_level (selected_frame));
       print_address_numeric (fi->frame, 1, gdb_stdout);
       printf_filtered (":\n");
     }
@@ -918,39 +931,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
@@ -1055,7 +1113,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 */
        }
@@ -1238,7 +1296,7 @@ static void
 print_frame_local_vars (register struct frame_info *fi, register int num_tabs,
                        register struct ui_file *stream)
 {
-  register struct block *block = get_frame_block (fi);
+  register struct block *block = get_frame_block (fi, 0);
   register int values_printed = 0;
 
   if (block == 0)
@@ -1272,7 +1330,7 @@ print_frame_label_vars (register struct frame_info *fi, int this_level_only,
                        register struct ui_file *stream)
 {
   register struct blockvector *bl;
-  register struct block *block = get_frame_block (fi);
+  register struct block *block = get_frame_block (fi, 0);
   register int values_printed = 0;
   int index, have_default = 0;
   char *blocks_printed;
@@ -1448,18 +1506,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;
-  selected_frame_level = 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.  */
@@ -1477,41 +1544,34 @@ 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 = selected_frame_level;
-}
-
 /* Return the symbol-block in which the selected frame is executing.
-   Can return zero under various legitimate circumstances.  */
+   Can return zero under various legitimate circumstances.
+
+   If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the relevant
+   code address within the block returned.  We use this to decide
+   which macros are in scope.  */
 
 struct block *
-get_selected_block (void)
+get_selected_block (CORE_ADDR *addr_in_block)
 {
   if (!target_has_stack)
     return 0;
 
   if (!selected_frame)
-    return get_current_block ();
-  return get_frame_block (selected_frame);
+    return get_current_block (addr_in_block);
+  return get_frame_block (selected_frame, addr_in_block);
 }
 
 /* Find a frame a certain number of levels away from FRAME.
@@ -1571,29 +1631,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.
@@ -1604,7 +1652,8 @@ void
 frame_command (char *level_exp, int from_tty)
 {
   select_frame_command (level_exp, from_tty);
-  show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+  show_and_print_stack_frame (selected_frame,
+                             frame_relative_level (selected_frame), 1);
 }
 
 /* The XDB Compatibility command to print the current frame. */
@@ -1614,7 +1663,8 @@ current_frame_command (char *level_exp, int from_tty)
 {
   if (target_has_stack == 0 || selected_frame == 0)
     error ("No stack.");
-  print_only_stack_frame (selected_frame, selected_frame_level, 1);
+  print_only_stack_frame (selected_frame,
+                         frame_relative_level (selected_frame), 1);
 }
 
 /* Select the frame up one or COUNT stack levels
@@ -1636,7 +1686,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, selected_frame_level + count - count1);
+  select_frame (fi);
+  selected_frame_level_changed_event (frame_relative_level (selected_frame));
 }
 
 static void
@@ -1649,7 +1700,8 @@ static void
 up_command (char *count_exp, int from_tty)
 {
   up_silently_base (count_exp);
-  show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+  show_and_print_stack_frame (selected_frame,
+                             frame_relative_level (selected_frame), 1);
 }
 
 /* Select the frame down one or COUNT stack levels
@@ -1680,7 +1732,8 @@ down_silently_base (char *count_exp)
       error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
     }
 
-  select_frame (frame, selected_frame_level + count - count1);
+  select_frame (frame);
+  selected_frame_level_changed_event (frame_relative_level (selected_frame));
 }
 
 /* ARGSUSED */
@@ -1694,7 +1747,8 @@ static void
 down_command (char *count_exp, int from_tty)
 {
   down_silently_base (count_exp);
-  show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+  show_and_print_stack_frame (selected_frame,
+                             frame_relative_level (selected_frame), 1);
 }
 \f
 void
@@ -1846,7 +1900,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.029186 seconds and 4 git commands to generate.