gdb/python: print name of unwinder that claimed frame in debug message

If we have multiple registered unwinders, this will helps identify which
unwinder was chosen and make it easier to track down potential problems.
Unwinders have a mandatory name argument, which we can use in the
message.

First, make gdb._execute_unwinders return a tuple containing the name,
in addition to the UnwindInfo.  Then, make pyuw_sniffer include the name
in the debug message.

I moved the debug message earlier.  I think it's good to print it as
early as possible, so that we see it in case an assert is hit in the
loop below, for example.

gdb/ChangeLog:

	* python/lib/gdb/__init__.py (_execute_unwinders): Return tuple
	with name of chosen unwinder.
	* python/py-unwind.c (pyuw_sniffer): Print name of chosen
	unwinder in debug message.

Change-Id: Id603545b44a97df2a39dd1872fe1f38ad5059f03
This commit is contained in:
Simon Marchi 2021-06-22 14:16:01 -04:00
parent 80d1206d7f
commit 4e317a765b
3 changed files with 46 additions and 11 deletions

View file

@ -1,3 +1,10 @@
2021-06-22 Simon Marchi <simon.marchi@polymtl.ca>
* python/lib/gdb/__init__.py (_execute_unwinders): Return tuple
with name of chosen unwinder.
* python/py-unwind.c (pyuw_sniffer): Print name of chosen
unwinder in debug message.
2021-06-22 Andreas Schwab <schwab@suse.de> 2021-06-22 Andreas Schwab <schwab@suse.de>
PR symtab/27999 PR symtab/27999

View file

@ -90,27 +90,33 @@ def _execute_unwinders(pending_frame):
Arguments: Arguments:
pending_frame: gdb.PendingFrame instance. pending_frame: gdb.PendingFrame instance.
Returns: Returns:
gdb.UnwindInfo instance or None. Tuple with:
[0] gdb.UnwindInfo instance
[1] Name of unwinder that claimed the frame (type `str`)
or None, if no unwinder has claimed the frame.
""" """
for objfile in objfiles(): for objfile in objfiles():
for unwinder in objfile.frame_unwinders: for unwinder in objfile.frame_unwinders:
if unwinder.enabled: if unwinder.enabled:
unwind_info = unwinder(pending_frame) unwind_info = unwinder(pending_frame)
if unwind_info is not None: if unwind_info is not None:
return unwind_info return (unwind_info, unwinder.name)
for unwinder in current_progspace().frame_unwinders: for unwinder in current_progspace().frame_unwinders:
if unwinder.enabled: if unwinder.enabled:
unwind_info = unwinder(pending_frame) unwind_info = unwinder(pending_frame)
if unwind_info is not None: if unwind_info is not None:
return unwind_info return (unwind_info, unwinder.name)
for unwinder in frame_unwinders: for unwinder in frame_unwinders:
if unwinder.enabled: if unwinder.enabled:
unwind_info = unwinder(pending_frame) unwind_info = unwinder(pending_frame)
if unwind_info is not None: if unwind_info is not None:
return unwind_info return (unwind_info, unwinder.name)
return None return None

View file

@ -556,33 +556,56 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
} }
gdbpy_ref<> pyo_execute (PyObject_GetAttrString (gdb_python_module, gdbpy_ref<> pyo_execute (PyObject_GetAttrString (gdb_python_module,
"_execute_unwinders")); "_execute_unwinders"));
if (pyo_execute == NULL) if (pyo_execute == nullptr)
{ {
gdbpy_print_stack (); gdbpy_print_stack ();
return 0; return 0;
} }
gdbpy_ref<> pyo_unwind_info /* A (gdb.UnwindInfo, str) tuple, or None. */
gdbpy_ref<> pyo_execute_ret
(PyObject_CallFunctionObjArgs (pyo_execute.get (), (PyObject_CallFunctionObjArgs (pyo_execute.get (),
pyo_pending_frame.get (), NULL)); 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 /* If the unwinder is cancelled due to a Ctrl-C, then propagate
the Ctrl-C as a GDB exception instead of swallowing it. */ the Ctrl-C as a GDB exception instead of swallowing it. */
gdbpy_print_stack_or_quit (); gdbpy_print_stack_or_quit ();
return 0; return 0;
} }
if (pyo_unwind_info == Py_None) if (pyo_execute_ret == Py_None)
return 0; 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. */ /* 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) (PyObject *) &unwind_info_object_type) <= 0)
error (_("A Unwinder should return gdb.UnwindInfo instance.")); error (_("A Unwinder should return gdb.UnwindInfo instance."));
{ {
unwind_info_object *unwind_info = 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 (); int reg_count = unwind_info->saved_regs->size ();
cached_frame cached_frame
@ -613,7 +636,6 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
} }
*cache_ptr = cached_frame; *cache_ptr = cached_frame;
pyuw_debug_printf ("frame claimed");
return 1; return 1;
} }