HPUX gas testsuite fixes
[deliverable/binutils-gdb.git] / gdb / frame-unwind.c
index f17cda9c4b206e84c9920abaf849b83f528344a4..079a411c205575f93f2a0e632d325a90d98f4399 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for frame unwinder, for GDB, the GNU debugger.
 
-   Copyright (C) 2003-2014 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -24,9 +24,9 @@
 #include "inline-frame.h"
 #include "value.h"
 #include "regcache.h"
-#include "exceptions.h"
-#include "gdb_assert.h"
 #include "gdb_obstack.h"
+#include "target.h"
+#include "gdbarch.h"
 
 static struct gdbarch_data *frame_unwind_data;
 
@@ -65,7 +65,8 @@ void
 frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
                                const struct frame_unwind *unwinder)
 {
-  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table *table
+    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
   struct frame_unwind_table_entry *entry;
 
   /* Insert the new entry at the start of the list.  */
@@ -79,7 +80,8 @@ void
 frame_unwind_append_unwinder (struct gdbarch *gdbarch,
                              const struct frame_unwind *unwinder)
 {
-  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table *table
+    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
   struct frame_unwind_table_entry **ip;
 
   /* Find the end of the list and insert the new entry there.  */
@@ -88,47 +90,81 @@ frame_unwind_append_unwinder (struct gdbarch *gdbarch,
   (*ip)->unwinder = unwinder;
 }
 
-/* Iterate through sniffers for THIS_FRAME frame until one returns with an
-   unwinder implementation.  THIS_FRAME->UNWIND must be NULL, it will get set
-   by this function.  Possibly initialize THIS_CACHE.  */
+/* Call SNIFFER from UNWINDER.  If it succeeded set UNWINDER for
+   THIS_FRAME and return 1.  Otherwise the function keeps THIS_FRAME
+   unchanged and returns 0.  */
 
-void
-frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache)
+static int
+frame_unwind_try_unwinder (struct frame_info *this_frame, void **this_cache,
+                          const struct frame_unwind *unwinder)
 {
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
-  struct frame_unwind_table_entry *entry;
+  int res = 0;
 
-  for (entry = table->list; entry != NULL; entry = entry->next)
-    {
-      struct cleanup *old_cleanup;
-      volatile struct gdb_exception ex;
-      int res = 0;
+  frame_prepare_for_sniffer (this_frame, unwinder);
 
-      old_cleanup = frame_prepare_for_sniffer (this_frame, entry->unwinder);
+  try
+    {
+      res = unwinder->sniffer (unwinder, this_frame, this_cache);
+    }
+  catch (const gdb_exception &ex)
+    {
+      /* Catch all exceptions, caused by either interrupt or error.
+        Reset *THIS_CACHE.  */
+      *this_cache = NULL;
+      frame_cleanup_after_sniffer (this_frame);
 
-      TRY_CATCH (ex, RETURN_MASK_ERROR)
-       {
-         res = entry->unwinder->sniffer (entry->unwinder, this_frame,
-                                         this_cache);
-       }
-      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+      if (ex.error == NOT_AVAILABLE_ERROR)
        {
          /* This usually means that not even the PC is available,
             thus most unwinders aren't able to determine if they're
             the best fit.  Keep trying.  Fallback prologue unwinders
             should always accept the frame.  */
+         return 0;
        }
-      else if (ex.reason < 0)
-       throw_exception (ex);
-      else if (res)
-        {
-          discard_cleanups (old_cleanup);
-          return;
-        }
-
-      do_cleanups (old_cleanup);
+      throw;
     }
+
+  if (res)
+    return 1;
+  else
+    {
+      /* Don't set *THIS_CACHE to NULL here, because sniffer has to do
+        so.  */
+      frame_cleanup_after_sniffer (this_frame);
+      return 0;
+    }
+  gdb_assert_not_reached ("frame_unwind_try_unwinder");
+}
+
+/* Iterate through sniffers for THIS_FRAME frame until one returns with an
+   unwinder implementation.  THIS_FRAME->UNWIND must be NULL, it will get set
+   by this function.  Possibly initialize THIS_CACHE.  */
+
+void
+frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct frame_unwind_table *table
+    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table_entry *entry;
+  const struct frame_unwind *unwinder_from_target;
+
+  unwinder_from_target = target_get_unwinder ();
+  if (unwinder_from_target != NULL
+      && frame_unwind_try_unwinder (this_frame, this_cache,
+                                   unwinder_from_target))
+    return;
+
+  unwinder_from_target = target_get_tailcall_unwinder ();
+  if (unwinder_from_target != NULL
+      && frame_unwind_try_unwinder (this_frame, this_cache,
+                                   unwinder_from_target))
+    return;
+
+  for (entry = table->list; entry != NULL; entry = entry->next)
+    if (frame_unwind_try_unwinder (this_frame, this_cache, entry->unwinder))
+      return;
+
   internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed"));
 }
 
@@ -157,6 +193,26 @@ default_frame_unwind_stop_reason (struct frame_info *this_frame,
     return UNWIND_NO_REASON;
 }
 
+/* See frame-unwind.h.  */
+
+CORE_ADDR
+default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  int pc_regnum = gdbarch_pc_regnum (gdbarch);
+  CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum);
+  pc = gdbarch_addr_bits_remove (gdbarch, pc);
+  return pc;
+}
+
+/* See frame-unwind.h.  */
+
+CORE_ADDR
+default_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  int sp_regnum = gdbarch_sp_regnum (gdbarch);
+  return frame_unwind_register_unsigned (next_frame, sp_regnum);
+}
+
 /* Helper functions for value-based register unwinding.  These return
    a (possibly lazy) value of the appropriate type.  */
 
@@ -173,10 +229,11 @@ frame_unwind_got_optimized (struct frame_info *frame, int regnum)
      "<not saved>".  */
   val = allocate_value_lazy (type);
   set_value_lazy (val, 0);
-  set_value_optimized_out (val, 1);
+  mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (type));
   VALUE_LVAL (val) = lval_register;
   VALUE_REGNUM (val) = regnum;
-  VALUE_FRAME_ID (val) = get_frame_id (frame);
+  VALUE_NEXT_FRAME_ID (val)
+    = get_frame_id (get_next_frame_sentinel_okay (frame));
   return val;
 }
 
@@ -248,9 +305,6 @@ frame_unwind_got_address (struct frame_info *frame, int regnum,
   return reg_val;
 }
 
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_frame_unwind;
-
 void
 _initialize_frame_unwind (void)
 {
This page took 0.028821 seconds and 4 git commands to generate.