stack: fix gdb.dwarf2/dw2-undefined-ret-addr.exp regression
[binutils-gdb.git] / gdb / stack.c
index e2b4dac1c0b00ff3d4ab54c65796f0a871b25509..706dd51f58cc1707ccb291087c8ddb6940cf59e3 100644 (file)
@@ -1,6 +1,6 @@
 /* Print and select stack frames for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -51,6 +51,7 @@
 #include "safe-ctype.h"
 #include "symfile.h"
 #include "extension.h"
+#include "observer.h"
 
 /* The possible choices of "set print frame-arguments", and the value
    of this setting.  */
@@ -141,6 +142,24 @@ frame_show_address (struct frame_info *frame,
   return get_frame_pc (frame) != sal.pc;
 }
 
+/* See frame.h.  */
+
+void
+print_stack_frame_to_uiout (struct ui_out *uiout, struct frame_info *frame,
+                           int print_level, enum print_what print_what,
+                           int set_current_sal)
+{
+  struct cleanup *old_chain;
+
+  old_chain = make_cleanup_restore_current_uiout ();
+
+  current_uiout = uiout;
+
+  print_stack_frame (frame, print_level, print_what, set_current_sal);
+
+  do_cleanups (old_chain);
+}
+
 /* Show or print a stack frame FRAME briefly.  The output is formatted
    according to PRINT_LEVEL and PRINT_WHAT printing the frame's
    relative level, function name, argument list, and file name and
@@ -310,8 +329,6 @@ void
 read_frame_local (struct symbol *sym, struct frame_info *frame,
                  struct frame_arg *argp)
 {
-  struct value *val = NULL;
-
   argp->sym = sym;
   argp->val = NULL;
   argp->error = NULL;
@@ -1103,7 +1120,8 @@ find_frame_funname (struct frame_info *frame, char **funname,
        }
       else
        {
-         *funname = xstrdup (SYMBOL_PRINT_NAME (func));
+         const char *print_name = SYMBOL_PRINT_NAME (func);
+
          *funlang = SYMBOL_LANGUAGE (func);
          if (funcp)
            *funcp = func;
@@ -1114,14 +1132,17 @@ find_frame_funname (struct frame_info *frame, char **funname,
                 stored in the symbol table, but we stored a version
                 with DMGL_PARAMS turned on, and here we don't want to
                 display parameters.  So remove the parameters.  */
-             char *func_only = cp_remove_params (*funname);
+             char *func_only = cp_remove_params (print_name);
 
              if (func_only)
-               {
-                 xfree (*funname);
-                 *funname = func_only;
-               }
+               *funname = func_only;
            }
+
+         /* If we didn't hit the C++ case above, set *funname here.
+            This approach is taken to avoid having to install a
+            cleanup in case cp_remove_params can throw.  */
+         if (*funname == NULL)
+           *funname = xstrdup (print_name);
        }
     }
   else
@@ -1273,15 +1294,13 @@ print_frame (struct frame_info *frame, int print_level,
 }
 \f
 
-/* Read a frame specification in whatever the appropriate format is
-   from FRAME_EXP.  Call error(), printing MESSAGE, if the
-   specification is in any way invalid (so this function never returns
-   NULL).  When SEPECTED_P is non-NULL set its target to indicate that
-   the default selected frame was used.  */
+/* Read a frame specification in whatever the appropriate format is from
+   FRAME_EXP.  Call error() if the specification is in any way invalid (so
+   this function never returns NULL).  When SELECTED_FRAME_P is non-NULL
+   set its target to indicate that the default selected frame was used.  */
 
 static struct frame_info *
-parse_frame_specification (const char *frame_exp, const char *message,
-                          int *selected_frame_p)
+parse_frame_specification (const char *frame_exp, int *selected_frame_p)
 {
   int numargs;
   struct value *args[4];
@@ -1330,7 +1349,7 @@ parse_frame_specification (const char *frame_exp, const char *message,
     {
       if (selected_frame_p != NULL)
        (*selected_frame_p) = 1;
-      return get_selected_frame (message);
+      return get_selected_frame (_("No stack."));
     }
 
   /* None of the remaining use the selected frame.  */
@@ -1425,7 +1444,7 @@ frame_info (char *addr_exp, int from_tty)
   CORE_ADDR caller_pc = 0;
   int caller_pc_p = 0;
 
-  fi = parse_frame_specification (addr_exp, "No stack.", &selected_frame_p);
+  fi = parse_frame_specification (addr_exp, &selected_frame_p);
   gdbarch = get_frame_arch (fi);
 
   /* Name of the value returned by get_frame_pc().  Per comments, "pc"
@@ -1511,27 +1530,32 @@ frame_info (char *addr_exp, int from_tty)
   wrap_here ("    ");
   printf_filtered ("saved %s = ", pc_regname);
 
-  TRY
-    {
-      caller_pc = frame_unwind_caller_pc (fi);
-      caller_pc_p = 1;
-    }
-  CATCH (ex, RETURN_MASK_ERROR)
+  if (!frame_id_p (frame_unwind_caller_id (fi)))
+    val_print_not_saved (gdb_stdout);
+  else
     {
-      switch (ex.error)
+      TRY
        {
-       case NOT_AVAILABLE_ERROR:
-         val_print_unavailable (gdb_stdout);
-         break;
-       case OPTIMIZED_OUT_ERROR:
-         val_print_not_saved (gdb_stdout);
-         break;
-       default:
-         fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
-         break;
+         caller_pc = frame_unwind_caller_pc (fi);
+         caller_pc_p = 1;
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         switch (ex.error)
+           {
+           case NOT_AVAILABLE_ERROR:
+             val_print_unavailable (gdb_stdout);
+             break;
+           case OPTIMIZED_OUT_ERROR:
+             val_print_not_saved (gdb_stdout);
+             break;
+           default:
+             fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+             break;
+           }
        }
+      END_CATCH
     }
-  END_CATCH
 
   if (caller_pc_p)
     fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout);
@@ -2084,6 +2108,7 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs,
   struct print_variable_and_value_data cb_data;
   const struct block *block;
   CORE_ADDR pc;
+  struct gdb_exception except = exception_none;
 
   if (!get_frame_pc_if_available (frame, &pc))
     {
@@ -2104,9 +2129,27 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs,
   cb_data.stream = stream;
   cb_data.values_printed = 0;
 
-  iterate_over_block_local_vars (block,
-                                do_print_variable_and_value,
-                                &cb_data);
+  /* Temporarily change the selected frame to the given FRAME.
+     This allows routines that rely on the selected frame instead
+     of being given a frame as parameter to use the correct frame.  */
+  select_frame (frame);
+
+  TRY
+    {
+      iterate_over_block_local_vars (block,
+                                    do_print_variable_and_value,
+                                    &cb_data);
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      except = ex;
+    }
+  END_CATCH
+
+  /* Restore the selected frame, and then rethrow if there was a problem.  */
+  select_frame (frame_find_by_id (cb_data.frame_id));
+  if (except.reason < 0)
+    throw_exception (except);
 
   /* do_print_variable_and_value invalidates FRAME.  */
   frame = NULL;
@@ -2278,7 +2321,11 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr)
 void
 select_frame_command (char *level_exp, int from_tty)
 {
-  select_frame (parse_frame_specification (level_exp, "No stack.", NULL));
+  struct frame_info *prev_frame = get_selected_frame_if_set ();
+
+  select_frame (parse_frame_specification (level_exp, NULL));
+  if (get_selected_frame_if_set () != prev_frame)
+    observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
 
 /* The "frame" command.  With no argument, print the selected frame
@@ -2288,8 +2335,13 @@ select_frame_command (char *level_exp, int from_tty)
 static void
 frame_command (char *level_exp, int from_tty)
 {
-  select_frame_command (level_exp, from_tty);
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
+  struct frame_info *prev_frame = get_selected_frame_if_set ();
+
+  select_frame (parse_frame_specification (level_exp, NULL));
+  if (get_selected_frame_if_set () != prev_frame)
+    observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
+  else
+    print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
 }
 
 /* Select the frame up one or COUNT_EXP stack levels from the
@@ -2320,7 +2372,7 @@ static void
 up_command (char *count_exp, int from_tty)
 {
   up_silently_base (count_exp);
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
+  observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
 
 /* Select the frame down one or COUNT_EXP stack levels from the previously
@@ -2359,9 +2411,8 @@ static void
 down_command (char *count_exp, int from_tty)
 {
   down_silently_base (count_exp);
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
+  observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
-\f
 
 void
 return_command (char *retval_exp, int from_tty)
@@ -2592,10 +2643,11 @@ a command file or a user-defined command."));
 
   add_com_alias ("f", "frame", class_stack, 1);
 
-  add_com ("select-frame", class_stack, select_frame_command, _("\
+  add_com_suppress_notification ("select-frame", class_stack, select_frame_command, _("\
 Select a stack frame without printing anything.\n\
 An argument specifies the frame to select.\n\
-It can be a stack frame number or the address of the frame.\n"));
+It can be a stack frame number or the address of the frame.\n"),
+                &cli_suppress_notification.user_selected_context);
 
   add_com ("backtrace", class_stack, backtrace_command, _("\
 Print backtrace of all stack frames, or innermost COUNT frames.\n\