]> 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 c82fa3dbe972010a30b27a3f4fea512e57258275..36f42cbcac39d5e5fb9cc7c4889f778ceb670e24 100644 (file)
@@ -1,6 +1,6 @@
 /* Python frame unwinder interface.
 
-   Copyright (C) 2015-2021 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 "observable.h"
 #include "python-internal.h"
 #include "regcache.h"
 #include "valprint.h"
+#include "user-regs.h"
 
-#define TRACE_PY_UNWIND(level, args...) if (pyuw_debug >= level)  \
-  { fprintf_unfiltered (gdb_stdlog, args); }
+/* Debugging of Python unwinders.  */
+
+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
 {
@@ -96,8 +117,6 @@ 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;
 
 /* Convert gdb.Value instance to inferior's pointer.  Return 1 on success,
@@ -114,7 +133,7 @@ pyuw_value_obj_to_pointer (PyObject *pyo_value, CORE_ADDR *addr)
       if ((value = value_object_to_value (pyo_value)) != NULL)
        {
          *addr = unpack_pointer (value_type (value),
-                                 value_contents (value));
+                                 value_contents (value).data ());
          rc = 1;
        }
     }
@@ -247,6 +266,26 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args)
       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;
@@ -424,6 +463,23 @@ pending_framepy_architecture (PyObject *self, PyObject *args)
   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
@@ -431,9 +487,7 @@ pyuw_this_id (struct frame_info *this_frame, void **cache_ptr,
              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: %s\n", __FUNCTION__,
-                       this_id->to_string ().c_str ());
+  pyuw_debug_printf ("frame_id: %s", this_id->to_string ().c_str ());
 }
 
 /* frame_unwind.prev_register.  */
@@ -442,12 +496,14 @@ static struct value *
 pyuw_prev_register (struct frame_info *this_frame, void **cache_ptr,
                    int regnum)
 {
+  PYUW_SCOPED_DEBUG_ENTER_EXIT;
+
   cached_frame_info *cached_frame = (cached_frame_info *) *cache_ptr;
   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->num)
@@ -463,14 +519,17 @@ static int
 pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
              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,
@@ -497,33 +556,56 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
     }
   gdbpy_ref<> pyo_execute (PyObject_GetAttrString (gdb_python_module,
                                                   "_execute_unwinders"));
-  if (pyo_execute == NULL)
+  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)
     {
       /* 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 *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 ();
+      (unwind_info_object *) pyo_unwind_info;
     int reg_count = unwind_info->saved_regs->size ();
 
     cached_frame
@@ -549,7 +631,8 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
        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_size);
+       memcpy (cached_frame->reg[i].data,
+               value_contents (value).data (), data_size);
       }
   }
 
@@ -562,7 +645,7 @@ 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++)
@@ -598,6 +681,7 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
       struct frame_unwind *unwinder
          = 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;
@@ -614,13 +698,13 @@ void _initialize_py_unwind ();
 void
 _initialize_py_unwind ()
 {
-  add_setshow_zuinteger_cmd
+  add_setshow_boolean_cmd
       ("py-unwind", class_maintenance, &pyuw_debug,
        _("Set Python unwinder debugging."),
        _("Show Python unwinder debugging."),
-       _("When non-zero, Python unwinder debugging is enabled."),
-       NULL,
+       _("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);
@@ -661,6 +745,8 @@ static PyMethodDef pending_frame_object_methods[] =
     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.036274 seconds and 4 git commands to generate.