]> Git Repo - binutils.git/blobdiff - gdb/python/py-unwind.c
gdb: remove COMPUNIT_PRODUCER macro, add getter/setter
[binutils.git] / gdb / python / py-unwind.c
index 690412a0ecb5da908f7e74eae8c76b33825b9f39..36f42cbcac39d5e5fb9cc7c4889f778ceb670e24 100644 (file)
@@ -1,6 +1,6 @@
 /* Python frame unwinder interface.
 
-   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   Copyright (C) 2015-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "defs.h"
 #include "arch-utils.h"
 #include "frame-unwind.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include "gdbcmd.h"
 #include "language.h"
-#include "observer.h"
+#include "observable.h"
 #include "python-internal.h"
 #include "regcache.h"
 #include "valprint.h"
 #include "user-regs.h"
-#include "py-ref.h"
 
-#define TRACE_PY_UNWIND(level, args...) if (pyuw_debug >= level)  \
-  { fprintf_unfiltered (gdb_stdlog, args); }
+/* Debugging of Python unwinders.  */
 
-typedef struct
+static bool pyuw_debug;
+
+/* Implementation of "show debug py-unwind".  */
+
+static void
+show_pyuw_debug (struct ui_file *file, int from_tty,
+                struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Python unwinder debugging is %s.\n"), value);
+}
+
+/* Print a "py-unwind" debug statement.  */
+
+#define pyuw_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (pyuw_debug, "py-unwind", fmt, ##__VA_ARGS__)
+
+/* Print "py-unwind" enter/exit debug statements.  */
+
+#define PYUW_SCOPED_DEBUG_ENTER_EXIT \
+  scoped_debug_enter_exit (pyuw_debug, "py-unwind")
+
+struct pending_frame_object
 {
   PyObject_HEAD
 
@@ -42,21 +61,26 @@ typedef struct
 
   /* Its architecture, passed by the sniffer caller.  */
   struct gdbarch *gdbarch;
-} pending_frame_object;
+};
 
 /* Saved registers array item.  */
 
-typedef struct
+struct saved_reg
 {
+  saved_reg (int n, gdbpy_ref<> &&v)
+    : number (n),
+      value (std::move (v))
+  {
+  }
+
   int number;
-  PyObject *value;
-} saved_reg;
-DEF_VEC_O (saved_reg);
+  gdbpy_ref<> value;
+};
 
 /* The data we keep for the PyUnwindInfo: pending_frame, saved registers
    and frame ID.  */
 
-typedef struct
+struct unwind_info_object
 {
   PyObject_HEAD
 
@@ -67,22 +91,13 @@ typedef struct
   struct frame_id frame_id;
 
   /* Saved registers array.  */
-  VEC (saved_reg) *saved_regs;
-} unwind_info_object;
+  std::vector<saved_reg> *saved_regs;
+};
 
 /* The data we keep for a frame we can unwind: frame ID and an array of
    (register_number, register_value) pairs.  */
 
-struct reg_info
-{
-  /* Register number.  */
-  int number;
-
-  /* Register data bytes pointer.  */
-  gdb_byte data[MAX_REGISTER_SIZE];
-};
-
-typedef struct
+struct cached_frame_info
 {
   /* Frame ID.  */
   struct frame_id frame_id;
@@ -93,8 +108,8 @@ typedef struct
   /* Length of the `reg' array below.  */
   int reg_count;
 
-  struct reg_info reg[];
-} cached_frame_info;
+  cached_reg_t reg[];
+};
 
 extern PyTypeObject pending_frame_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pending_frame_object");
@@ -102,41 +117,8 @@ extern PyTypeObject pending_frame_object_type
 extern PyTypeObject unwind_info_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("unwind_info_object");
 
-static unsigned int pyuw_debug = 0;
-
 static struct gdbarch_data *pyuw_gdbarch_data;
 
-/* Parses register id, which can be either a number or a name.
-   Returns 1 on success, 0 otherwise.  */
-
-static int
-pyuw_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id,
-                        int *reg_num)
-{
-  if (pyo_reg_id == NULL)
-    return 0;
-  if (gdbpy_is_string (pyo_reg_id))
-    {
-      gdb::unique_xmalloc_ptr<char> reg_name (gdbpy_obj_to_string (pyo_reg_id));
-
-      if (reg_name == NULL)
-        return 0;
-      *reg_num = user_reg_map_name_to_regnum (gdbarch, reg_name.get (),
-                                              strlen (reg_name.get ()));
-      return *reg_num >= 0;
-    }
-  else if (PyInt_Check (pyo_reg_id))
-    {
-      long value;
-      if (gdb_py_int_as_long (pyo_reg_id, &value) && (int) value == value)
-        {
-          *reg_num = (int) value;
-          return user_reg_map_regnum_to_name (gdbarch, *reg_num) != NULL;
-        }
-    }
-  return 0;
-}
-
 /* Convert gdb.Value instance to inferior's pointer.  Return 1 on success,
    0 on failure.  */
 
@@ -146,20 +128,19 @@ pyuw_value_obj_to_pointer (PyObject *pyo_value, CORE_ADDR *addr)
   int rc = 0;
   struct value *value;
 
-  TRY
+  try
     {
       if ((value = value_object_to_value (pyo_value)) != NULL)
-        {
-          *addr = unpack_pointer (value_type (value),
-                                  value_contents (value));
-          rc = 1;
-        }
+       {
+         *addr = unpack_pointer (value_type (value),
+                                 value_contents (value).data ());
+         rc = 1;
+       }
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       gdbpy_convert_exception (except);
     }
-  END_CATCH
   return rc;
 }
 
@@ -171,23 +152,23 @@ pyuw_value_obj_to_pointer (PyObject *pyo_value, CORE_ADDR *addr)
 
 static int
 pyuw_object_attribute_to_pointer (PyObject *pyo, const char *attr_name,
-                                  CORE_ADDR *addr)
+                                 CORE_ADDR *addr)
 {
   int rc = 0;
 
   if (PyObject_HasAttrString (pyo, attr_name))
     {
-      gdbpy_ref pyo_value (PyObject_GetAttrString (pyo, attr_name));
+      gdbpy_ref<> pyo_value (PyObject_GetAttrString (pyo, attr_name));
 
       if (pyo_value != NULL && pyo_value != Py_None)
-        {
-          rc = pyuw_value_obj_to_pointer (pyo_value.get (), addr);
-          if (!rc)
-            PyErr_Format (
-                PyExc_ValueError,
-                _("The value of the '%s' attribute is not a pointer."),
-                attr_name);
-        }
+       {
+         rc = pyuw_value_obj_to_pointer (pyo_value.get (), addr);
+         if (!rc)
+           PyErr_Format (
+               PyExc_ValueError,
+               _("The value of the '%s' attribute is not a pointer."),
+               attr_name);
+       }
     }
   return rc;
 }
@@ -198,49 +179,41 @@ pyuw_object_attribute_to_pointer (PyObject *pyo, const char *attr_name,
 static PyObject *
 unwind_infopy_str (PyObject *self)
 {
-  struct ui_file *strfile = mem_fileopen ();
   unwind_info_object *unwind_info = (unwind_info_object *) self;
-  PyObject *result;
+  string_file stb;
 
-  fprintf_unfiltered (strfile, "Frame ID: ");
-  fprint_frame_id (strfile, unwind_info->frame_id);
+  stb.printf ("Frame ID: %s", unwind_info->frame_id.to_string ().c_str ());
   {
-    char *sep = "";
-    int i;
+    const char *sep = "";
     struct value_print_options opts;
-    saved_reg *reg;
 
     get_user_print_options (&opts);
-    fprintf_unfiltered (strfile, "\nSaved registers: (");
-    for (i = 0; VEC_iterate (saved_reg, unwind_info->saved_regs, i, reg); i++)
+    stb.printf ("\nSaved registers: (");
+    for (const saved_reg &reg : *unwind_info->saved_regs)
       {
-        struct value *value = value_object_to_value (reg->value);
-
-        fprintf_unfiltered (strfile, "%s(%d, ", sep, reg->number);
-        if (value != NULL)
-          {
-            TRY
-              {
-                value_print (value, strfile, &opts);
-                fprintf_unfiltered (strfile, ")");
-              }
-            CATCH (except, RETURN_MASK_ALL)
-              {
-                GDB_PY_HANDLE_EXCEPTION (except);
-              }
-            END_CATCH
-          }
-        else
-          fprintf_unfiltered (strfile, "<BAD>)");
-        sep = ", ";
+       struct value *value = value_object_to_value (reg.value.get ());
+
+       stb.printf ("%s(%d, ", sep, reg.number);
+       if (value != NULL)
+         {
+           try
+             {
+               value_print (value, &stb, &opts);
+               stb.puts (")");
+             }
+           catch (const gdb_exception &except)
+             {
+               GDB_PY_HANDLE_EXCEPTION (except);
+             }
+         }
+       else
+         stb.puts ("<BAD>)");
+       sep = ", ";
       }
-    fprintf_unfiltered (strfile, ")");
+    stb.puts (")");
   }
 
-  std::string s = ui_file_as_string (strfile);
-  result = PyString_FromString (s.c_str ());
-  ui_file_delete (strfile);
-  return result;
+  return PyString_FromString (stb.c_str ());
 }
 
 /* Create UnwindInfo instance for given PendingFrame and frame ID.
@@ -248,7 +221,7 @@ unwind_infopy_str (PyObject *self)
 
 static PyObject *
 pyuw_create_unwind_info (PyObject *pyo_pending_frame,
-                         struct frame_id frame_id)
+                        struct frame_id frame_id)
 {
   unwind_info_object *unwind_info
       = PyObject_New (unwind_info_object, &unwind_info_object_type);
@@ -256,13 +229,13 @@ pyuw_create_unwind_info (PyObject *pyo_pending_frame,
   if (((pending_frame_object *) pyo_pending_frame)->frame_info == NULL)
     {
       PyErr_SetString (PyExc_ValueError,
-                       "Attempting to use stale PendingFrame");
+                      "Attempting to use stale PendingFrame");
       return NULL;
     }
   unwind_info->frame_id = frame_id;
   Py_INCREF (pyo_pending_frame);
   unwind_info->pending_frame = pyo_pending_frame;
-  unwind_info->saved_regs = VEC_alloc (saved_reg, 4);
+  unwind_info->saved_regs = new std::vector<saved_reg>;
   return (PyObject *) unwind_info;
 }
 
@@ -282,17 +255,37 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args)
   if (pending_frame->frame_info == NULL)
     {
       PyErr_SetString (PyExc_ValueError,
-                       "UnwindInfo instance refers to a stale PendingFrame");
+                      "UnwindInfo instance refers to a stale PendingFrame");
       return NULL;
     }
   if (!PyArg_UnpackTuple (args, "previous_frame_register", 2, 2,
-                          &pyo_reg_id, &pyo_reg_value))
+                         &pyo_reg_id, &pyo_reg_value))
     return NULL;
-  if (!pyuw_parse_register_id (pending_frame->gdbarch, pyo_reg_id, &regnum))
+  if (!gdbpy_parse_register_id (pending_frame->gdbarch, pyo_reg_id, &regnum))
     {
       PyErr_SetString (PyExc_ValueError, "Bad register");
       return NULL;
     }
+
+  /* If REGNUM identifies a user register then *maybe* we can convert this
+     to a real (i.e. non-user) register.  The maybe qualifier is because we
+     don't know what user registers each target might add, however, the
+     following logic should work for the usual style of user registers,
+     where the read function just forwards the register read on to some
+     other register with no adjusting the value.  */
+  if (regnum >= gdbarch_num_cooked_regs (pending_frame->gdbarch))
+    {
+      struct value *user_reg_value
+       = value_of_user_reg (regnum, pending_frame->frame_info);
+      if (VALUE_LVAL (user_reg_value) == lval_register)
+       regnum = VALUE_REGNUM (user_reg_value);
+      if (regnum >= gdbarch_num_cooked_regs (pending_frame->gdbarch))
+       {
+         PyErr_SetString (PyExc_ValueError, "Bad register");
+         return NULL;
+       }
+    }
+
   {
     struct value *value;
     size_t data_size;
@@ -300,40 +293,35 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args)
     if (pyo_reg_value == NULL
       || (value = value_object_to_value (pyo_reg_value)) == NULL)
       {
-        PyErr_SetString (PyExc_ValueError, "Bad register value");
-        return NULL;
+       PyErr_SetString (PyExc_ValueError, "Bad register value");
+       return NULL;
       }
     data_size = register_size (pending_frame->gdbarch, regnum);
     if (data_size != TYPE_LENGTH (value_type (value)))
       {
-        PyErr_Format (
-            PyExc_ValueError,
-            "The value of the register returned by the Python "
-            "sniffer has unexpected size: %u instead of %u.",
-            (unsigned) TYPE_LENGTH (value_type (value)),
-            (unsigned) data_size);
-        return NULL;
+       PyErr_Format (
+           PyExc_ValueError,
+           "The value of the register returned by the Python "
+           "sniffer has unexpected size: %u instead of %u.",
+           (unsigned) TYPE_LENGTH (value_type (value)),
+           (unsigned) data_size);
+       return NULL;
       }
   }
   {
-    int i;
-    saved_reg *reg;
-
-    for (i = 0; VEC_iterate (saved_reg, unwind_info->saved_regs, i, reg); i++)
+    gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
+    bool found = false;
+    for (saved_reg &reg : *unwind_info->saved_regs)
       {
-        if (regnum == reg->number)
-          {
-            Py_DECREF (reg->value);
-            break;
-          }
+       if (regnum == reg.number)
+         {
+           found = true;
+           reg.value = std::move (new_value);
+           break;
+         }
       }
-    if (reg == NULL)
-      {
-        reg = VEC_safe_push (saved_reg, unwind_info->saved_regs, NULL);
-        reg->number = regnum;
-      }
-    Py_INCREF (pyo_reg_value);
-    reg->value = pyo_reg_value;
+    if (!found)
+      unwind_info->saved_regs->emplace_back (regnum, std::move (new_value));
   }
   Py_RETURN_NONE;
 }
@@ -344,13 +332,9 @@ static void
 unwind_infopy_dealloc (PyObject *self)
 {
   unwind_info_object *unwind_info = (unwind_info_object *) self;
-  int i;
-  saved_reg *reg;
 
   Py_XDECREF (unwind_info->pending_frame);
-  for (i = 0; VEC_iterate (saved_reg, unwind_info->saved_regs, i, reg); i++)
-      Py_DECREF (reg->value);
-  VEC_free (saved_reg, unwind_info->saved_regs);
+  delete unwind_info->saved_regs;
   Py_TYPE (self)->tp_free (self);
 }
 
@@ -366,16 +350,15 @@ pending_framepy_str (PyObject *self)
 
   if (frame == NULL)
     return PyString_FromString ("Stale PendingFrame instance");
-  TRY
+  try
     {
       sp_str = core_addr_to_string_nz (get_frame_sp (frame));
       pc_str = core_addr_to_string_nz (get_frame_pc (frame));
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       GDB_PY_HANDLE_EXCEPTION (except);
     }
-  END_CATCH
 
   return PyString_FromFormat ("SP=%s,PC=%s", sp_str, pc_str);
 }
@@ -394,18 +377,18 @@ pending_framepy_read_register (PyObject *self, PyObject *args)
   if (pending_frame->frame_info == NULL)
     {
       PyErr_SetString (PyExc_ValueError,
-                       "Attempting to read register from stale PendingFrame");
+                      "Attempting to read register from stale PendingFrame");
       return NULL;
     }
   if (!PyArg_UnpackTuple (args, "read_register", 1, 1, &pyo_reg_id))
     return NULL;
-  if (!pyuw_parse_register_id (pending_frame->gdbarch, pyo_reg_id, &regnum))
+  if (!gdbpy_parse_register_id (pending_frame->gdbarch, pyo_reg_id, &regnum))
     {
       PyErr_SetString (PyExc_ValueError, "Bad register");
       return NULL;
     }
 
-  TRY
+  try
     {
       /* Fetch the value associated with a register, whether it's
         a real register or a so called "user" register, like "pc",
@@ -414,15 +397,14 @@ pending_framepy_read_register (PyObject *self, PyObject *args)
         handle the user register case.  */
       val = value_of_register (regnum, pending_frame->frame_info);
       if (val == NULL)
-        PyErr_Format (PyExc_ValueError,
-                      "Cannot read register %d from frame.",
-                      regnum);
+       PyErr_Format (PyExc_ValueError,
+                     "Cannot read register %d from frame.",
+                     regnum);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       GDB_PY_HANDLE_EXCEPTION (except);
     }
-  END_CATCH
 
   return val == NULL ? NULL : value_to_value_object (val);
 }
@@ -443,7 +425,7 @@ pending_framepy_create_unwind_info (PyObject *self, PyObject *args)
   if (!pyuw_object_attribute_to_pointer (pyo_frame_id, "sp", &sp))
     {
       PyErr_SetString (PyExc_ValueError,
-                       _("frame_id should have 'sp' attribute."));
+                      _("frame_id should have 'sp' attribute."));
       return NULL;
     }
 
@@ -462,40 +444,70 @@ pending_framepy_create_unwind_info (PyObject *self, PyObject *args)
     return pyuw_create_unwind_info (self, frame_id_build (sp, pc));
   else
     return pyuw_create_unwind_info (self,
-                                    frame_id_build_special (sp, pc, special));
+                                   frame_id_build_special (sp, pc, special));
+}
+
+/* Implementation of PendingFrame.architecture (self) -> gdb.Architecture.  */
+
+static PyObject *
+pending_framepy_architecture (PyObject *self, PyObject *args)
+{
+  pending_frame_object *pending_frame = (pending_frame_object *) self;
+
+  if (pending_frame->frame_info == NULL)
+    {
+      PyErr_SetString (PyExc_ValueError,
+                      "Attempting to read register from stale PendingFrame");
+      return NULL;
+    }
+  return gdbarch_to_arch_object (pending_frame->gdbarch);
+}
+
+/* Implementation of PendingFrame.level (self) -> Integer.  */
+
+static PyObject *
+pending_framepy_level (PyObject *self, PyObject *args)
+{
+  pending_frame_object *pending_frame = (pending_frame_object *) self;
+
+  if (pending_frame->frame_info == NULL)
+    {
+      PyErr_SetString (PyExc_ValueError,
+                      "Attempting to read stack level from stale PendingFrame");
+      return NULL;
+    }
+  int level = frame_relative_level (pending_frame->frame_info);
+  return gdb_py_object_from_longest (level).release ();
 }
 
 /* frame_unwind.this_id method.  */
 
 static void
 pyuw_this_id (struct frame_info *this_frame, void **cache_ptr,
-              struct frame_id *this_id)
+             struct frame_id *this_id)
 {
   *this_id = ((cached_frame_info *) *cache_ptr)->frame_id;
-  if (pyuw_debug >= 1)
-    {
-      fprintf_unfiltered (gdb_stdlog, "%s: frame_id: ", __FUNCTION__);
-      fprint_frame_id (gdb_stdlog, *this_id);
-      fprintf_unfiltered (gdb_stdlog, "\n");
-    }
+  pyuw_debug_printf ("frame_id: %s", this_id->to_string ().c_str ());
 }
 
 /* frame_unwind.prev_register.  */
 
 static struct value *
 pyuw_prev_register (struct frame_info *this_frame, void **cache_ptr,
-                    int regnum)
+                   int regnum)
 {
+  PYUW_SCOPED_DEBUG_ENTER_EXIT;
+
   cached_frame_info *cached_frame = (cached_frame_info *) *cache_ptr;
-  struct reg_info *reg_info = cached_frame->reg;
-  struct reg_info *reg_info_end = reg_info + cached_frame->reg_count;
+  cached_reg_t *reg_info = cached_frame->reg;
+  cached_reg_t *reg_info_end = reg_info + cached_frame->reg_count;
 
-  TRACE_PY_UNWIND (1, "%s (frame=%p,...,reg=%d)\n", __FUNCTION__, this_frame,
-                   regnum);
+  pyuw_debug_printf ("frame=%d, reg=%d",
+                    frame_relative_level (this_frame), regnum);
   for (; reg_info < reg_info_end; ++reg_info)
     {
-      if (regnum == reg_info->number)
-        return frame_unwind_got_bytes (this_frame, regnum, reg_info->data);
+      if (regnum == reg_info->num)
+       return frame_unwind_got_bytes (this_frame, regnum, reg_info->data);
     }
 
   return frame_unwind_got_optimized (this_frame, regnum);
@@ -505,21 +517,24 @@ pyuw_prev_register (struct frame_info *this_frame, void **cache_ptr,
 
 static int
 pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
-              void **cache_ptr)
+             void **cache_ptr)
 {
+  PYUW_SCOPED_DEBUG_ENTER_EXIT;
+
   struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data);
   cached_frame_info *cached_frame;
 
-  gdbpy_enter enter_py (gdbarch, current_language);
+  gdbpy_enter enter_py (gdbarch);
 
-  TRACE_PY_UNWIND (3, "%s (SP=%s, PC=%s)\n", __FUNCTION__,
-                   paddress (gdbarch, get_frame_sp (this_frame)),
-                   paddress (gdbarch, get_frame_pc (this_frame)));
+  pyuw_debug_printf ("frame=%d, sp=%s, pc=%s",
+                    frame_relative_level (this_frame),
+                    paddress (gdbarch, get_frame_sp (this_frame)),
+                    paddress (gdbarch, get_frame_pc (this_frame)));
 
   /* Create PendingFrame instance to pass to sniffers.  */
   pending_frame_object *pfo = PyObject_New (pending_frame_object,
                                            &pending_frame_object_type);
-  gdbpy_ref pyo_pending_frame ((PyObject *) pfo);
+  gdbpy_ref<> pyo_pending_frame ((PyObject *) pfo);
   if (pyo_pending_frame == NULL)
     {
       gdbpy_print_stack ();
@@ -531,44 +546,67 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
 
   /* Run unwinders.  */
   if (gdb_python_module == NULL
-      || ! PyObject_HasAttrString (gdb_python_module, "execute_unwinders"))
+      || ! PyObject_HasAttrString (gdb_python_module, "_execute_unwinders"))
     {
       PyErr_SetString (PyExc_NameError,
-                       "Installation error: gdb.execute_unwinders function "
-                       "is missing");
+                      "Installation error: gdb._execute_unwinders function "
+                      "is missing");
       gdbpy_print_stack ();
       return 0;
     }
-  gdbpy_ref pyo_execute (PyObject_GetAttrString (gdb_python_module,
-                                                "execute_unwinders"));
-  if (pyo_execute == NULL)
+  gdbpy_ref<> pyo_execute (PyObject_GetAttrString (gdb_python_module,
+                                                  "_execute_unwinders"));
+  if (pyo_execute == nullptr)
     {
       gdbpy_print_stack ();
       return 0;
     }
 
-  gdbpy_ref pyo_unwind_info
+  /* A (gdb.UnwindInfo, str) tuple, or None.  */
+  gdbpy_ref<> pyo_execute_ret
     (PyObject_CallFunctionObjArgs (pyo_execute.get (),
                                   pyo_pending_frame.get (), NULL));
-  if (pyo_unwind_info == NULL)
+  if (pyo_execute_ret == nullptr)
     {
-      gdbpy_print_stack ();
+      /* If the unwinder is cancelled due to a Ctrl-C, then propagate
+        the Ctrl-C as a GDB exception instead of swallowing it.  */
+      gdbpy_print_stack_or_quit ();
       return 0;
     }
-  if (pyo_unwind_info == Py_None)
+  if (pyo_execute_ret == Py_None)
     return 0;
 
+  /* Verify the return value of _execute_unwinders is a tuple of size 2.  */
+  gdb_assert (PyTuple_Check (pyo_execute_ret.get ()));
+  gdb_assert (PyTuple_GET_SIZE (pyo_execute_ret.get ()) == 2);
+
+  if (pyuw_debug)
+    {
+      PyObject *pyo_unwinder_name = PyTuple_GET_ITEM (pyo_execute_ret.get (), 1);
+      gdb::unique_xmalloc_ptr<char> name
+       = python_string_to_host_string (pyo_unwinder_name);
+
+      /* This could happen if the user passed something else than a string
+        as the unwinder's name.  */
+      if (name == nullptr)
+       {
+         gdbpy_print_stack ();
+         name = make_unique_xstrdup ("<failed to get unwinder name>");
+       }
+
+      pyuw_debug_printf ("frame claimed by unwinder %s", name.get ());
+    }
+
   /* Received UnwindInfo, cache data.  */
-  if (PyObject_IsInstance (pyo_unwind_info.get (),
-                           (PyObject *) &unwind_info_object_type) <= 0)
+  PyObject *pyo_unwind_info = PyTuple_GET_ITEM (pyo_execute_ret.get (), 0);
+  if (PyObject_IsInstance (pyo_unwind_info,
+                          (PyObject *) &unwind_info_object_type) <= 0)
     error (_("A Unwinder should return gdb.UnwindInfo instance."));
 
   {
     unwind_info_object *unwind_info =
-      (unwind_info_object *) pyo_unwind_info.get ();
-    int reg_count = VEC_length (saved_reg, unwind_info->saved_regs);
-    saved_reg *reg;
-    int i;
+      (unwind_info_object *) pyo_unwind_info;
+    int reg_count = unwind_info->saved_regs->size ();
 
     cached_frame
       = ((cached_frame_info *)
@@ -579,19 +617,22 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
     cached_frame->reg_count = reg_count;
 
     /* Populate registers array.  */
-    for (i = 0; VEC_iterate (saved_reg, unwind_info->saved_regs, i, reg); i++)
+    for (int i = 0; i < unwind_info->saved_regs->size (); ++i)
       {
-        struct value *value = value_object_to_value (reg->value);
-        size_t data_size = register_size (gdbarch, reg->number);
+       saved_reg *reg = &(*unwind_info->saved_regs)[i];
 
-        cached_frame->reg[i].number = reg->number;
+       struct value *value = value_object_to_value (reg->value.get ());
+       size_t data_size = register_size (gdbarch, reg->number);
 
-        /* `value' validation was done before, just assert.  */
-        gdb_assert (value != NULL);
-        gdb_assert (data_size == TYPE_LENGTH (value_type (value)));
-        gdb_assert (data_size <= MAX_REGISTER_SIZE);
+       cached_frame->reg[i].num = reg->number;
 
-        memcpy (cached_frame->reg[i].data, value_contents (value), data_size);
+       /* `value' validation was done before, just assert.  */
+       gdb_assert (value != NULL);
+       gdb_assert (data_size == TYPE_LENGTH (value_type (value)));
+
+       cached_frame->reg[i].data = (gdb_byte *) xmalloc (data_size);
+       memcpy (cached_frame->reg[i].data,
+               value_contents (value).data (), data_size);
       }
   }
 
@@ -604,7 +645,12 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
 static void
 pyuw_dealloc_cache (struct frame_info *this_frame, void *cache)
 {
-  TRACE_PY_UNWIND (3, "%s: enter", __FUNCTION__);
+  PYUW_SCOPED_DEBUG_ENTER_EXIT;
+  cached_frame_info *cached_frame = (cached_frame_info *) cache;
+
+  for (int i = 0; i < cached_frame->reg_count; i++)
+    xfree (cached_frame->reg[i].data);
+
   xfree (cache);
 }
 
@@ -633,8 +679,9 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
   if (!data->unwinder_registered)
     {
       struct frame_unwind *unwinder
-          = GDBARCH_OBSTACK_ZALLOC (newarch, struct frame_unwind);
+         = GDBARCH_OBSTACK_ZALLOC (newarch, struct frame_unwind);
 
+      unwinder->name = "python";
       unwinder->type = NORMAL_FRAME;
       unwinder->stop_reason = default_frame_unwind_stop_reason;
       unwinder->this_id = pyuw_this_id;
@@ -647,29 +694,35 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
     }
 }
 
+void _initialize_py_unwind ();
+void
+_initialize_py_unwind ()
+{
+  add_setshow_boolean_cmd
+      ("py-unwind", class_maintenance, &pyuw_debug,
+       _("Set Python unwinder debugging."),
+       _("Show Python unwinder debugging."),
+       _("When on, Python unwinder debugging is enabled."),
+       NULL,
+       show_pyuw_debug,
+       &setdebuglist, &showdebuglist);
+  pyuw_gdbarch_data
+    = gdbarch_data_register_post_init (pyuw_gdbarch_data_init);
+}
+
 /* Initialize unwind machinery.  */
 
 int
 gdbpy_initialize_unwind (void)
 {
-  int rc;
-  add_setshow_zuinteger_cmd
-      ("py-unwind", class_maintenance, &pyuw_debug,
-        _("Set Python unwinder debugging."),
-        _("Show Python unwinder debugging."),
-        _("When non-zero, Python unwinder debugging is enabled."),
-        NULL,
-        NULL,
-        &setdebuglist, &showdebuglist);
-  pyuw_gdbarch_data
-      = gdbarch_data_register_post_init (pyuw_gdbarch_data_init);
-  observer_attach_architecture_changed (pyuw_on_new_gdbarch);
+  gdb::observers::architecture_changed.attach (pyuw_on_new_gdbarch,
+                                              "py-unwind");
 
   if (PyType_Ready (&pending_frame_object_type) < 0)
     return -1;
-  rc = gdb_pymodule_addobject (gdb_module, "PendingFrame",
-      (PyObject *) &pending_frame_object_type);
-  if (rc)
+  int rc = gdb_pymodule_addobject (gdb_module, "PendingFrame",
+                                  (PyObject *) &pending_frame_object_type);
+  if (rc != 0)
     return rc;
 
   if (PyType_Ready (&unwind_info_object_type) < 0)
@@ -688,6 +741,12 @@ static PyMethodDef pending_frame_object_methods[] =
     "create_unwind_info (FRAME_ID) -> gdb.UnwindInfo\n"
     "Construct UnwindInfo for this PendingFrame, using FRAME_ID\n"
     "to identify it." },
+  { "architecture",
+    pending_framepy_architecture, METH_NOARGS,
+    "architecture () -> gdb.Architecture\n"
+    "The architecture for this PendingFrame." },
+  { "level", pending_framepy_level, METH_NOARGS,
+    "The stack level of this frame." },
   {NULL}  /* Sentinel */
 };
 
This page took 0.05512 seconds and 4 git commands to generate.