* [PATCH] gdb/python: print name of unwinder that claimed frame in debug message
@ 2021-05-10 15:49 Simon Marchi
2021-05-10 16:45 ` Andrew Burgess
0 siblings, 1 reply; 6+ messages in thread
From: Simon Marchi @ 2021-05-10 15:49 UTC (permalink / raw)
To: gdb-patches
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
---
gdb/python/lib/gdb/__init__.py | 14 ++++++++++----
gdb/python/py-unwind.c | 32 ++++++++++++++++++++++++++------
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index d748b3a5827e..f2f38b32af96 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -90,27 +90,33 @@ def _execute_unwinders(pending_frame):
Arguments:
pending_frame: gdb.PendingFrame instance.
+
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 unwinder in objfile.frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
for unwinder in current_progspace().frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
for unwinder in frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
return None
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 7c195eb539da..7c8b73c2e680 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -524,27 +524,48 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
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);
+ const char *name;
+
+ /* We never enforce that the name is a string, so check the type just
+ in case somebody passed something else. */
+ if (PyUnicode_Check (pyo_unwinder_name))
+ name = PyUnicode_AsUTF8 (pyo_unwinder_name);
+ else
+ name = "<unwinder name is not a string>";
+
+ pyuw_debug_printf ("frame claimed by unwinder %s", name);
+ }
+
/* 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
@@ -575,7 +596,6 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
}
*cache_ptr = cached_frame;
- pyuw_debug_printf ("frame claimed");
return 1;
}
--
2.30.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] gdb/python: print name of unwinder that claimed frame in debug message
2021-05-10 15:49 [PATCH] gdb/python: print name of unwinder that claimed frame in debug message Simon Marchi
@ 2021-05-10 16:45 ` Andrew Burgess
2021-05-10 16:53 ` Simon Marchi
0 siblings, 1 reply; 6+ messages in thread
From: Andrew Burgess @ 2021-05-10 16:45 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
* Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> [2021-05-10 11:49:31 -0400]:
> 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
> ---
> gdb/python/lib/gdb/__init__.py | 14 ++++++++++----
> gdb/python/py-unwind.c | 32 ++++++++++++++++++++++++++------
> 2 files changed, 36 insertions(+), 10 deletions(-)
>
> diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
> index d748b3a5827e..f2f38b32af96 100644
> --- a/gdb/python/lib/gdb/__init__.py
> +++ b/gdb/python/lib/gdb/__init__.py
> @@ -90,27 +90,33 @@ def _execute_unwinders(pending_frame):
>
> Arguments:
> pending_frame: gdb.PendingFrame instance.
> +
> 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 unwinder in objfile.frame_unwinders:
> if unwinder.enabled:
> unwind_info = unwinder(pending_frame)
> if unwind_info is not None:
> - return unwind_info
> + return (unwind_info, unwinder.name)
>
> for unwinder in current_progspace().frame_unwinders:
> if unwinder.enabled:
> unwind_info = unwinder(pending_frame)
> if unwind_info is not None:
> - return unwind_info
> + return (unwind_info, unwinder.name)
>
> for unwinder in frame_unwinders:
> if unwinder.enabled:
> unwind_info = unwinder(pending_frame)
> if unwind_info is not None:
> - return unwind_info
> + return (unwind_info, unwinder.name)
>
> return None
>
> diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
> index 7c195eb539da..7c8b73c2e680 100644
> --- a/gdb/python/py-unwind.c
> +++ b/gdb/python/py-unwind.c
> @@ -524,27 +524,48 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
> 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);
Maybe being a little paranoid, but I wonder if we should avoid
asserting on the interface between GDB and Python code? In theory I
guess a user could modify the Python code in some incompatible way.
Perhaps a check and error (...) call would be better?
Otherwise, this looks good to me.
Thanks,
Andrew
> +
> + if (pyuw_debug)
> + {
> + PyObject *pyo_unwinder_name = PyTuple_GET_ITEM (pyo_execute_ret.get (), 1);
> + const char *name;
> +
> + /* We never enforce that the name is a string, so check the type just
> + in case somebody passed something else. */
> + if (PyUnicode_Check (pyo_unwinder_name))
> + name = PyUnicode_AsUTF8 (pyo_unwinder_name);
> + else
> + name = "<unwinder name is not a string>";
> +
> + pyuw_debug_printf ("frame claimed by unwinder %s", name);
> + }
> +
> /* 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
> @@ -575,7 +596,6 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
> }
>
> *cache_ptr = cached_frame;
> - pyuw_debug_printf ("frame claimed");
> return 1;
> }
>
> --
> 2.30.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] gdb/python: print name of unwinder that claimed frame in debug message
2021-05-10 16:45 ` Andrew Burgess
@ 2021-05-10 16:53 ` Simon Marchi
2021-05-10 17:00 ` Simon Marchi
0 siblings, 1 reply; 6+ messages in thread
From: Simon Marchi @ 2021-05-10 16:53 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
On 2021-05-10 12:45 p.m., Andrew Burgess wrote:
> Maybe being a little paranoid, but I wonder if we should avoid
> asserting on the interface between GDB and Python code? In theory I
> guess a user could modify the Python code in some incompatible way.
> Perhaps a check and error (...) call would be better?
I thought about this, and in my opinion the GDB Python code is
"internal" code as much as the C code. If a user modifies the Python
code we ship, then they modify GDB, it's their problem. To me, it's the
same as if they modified the C source code, rebuilt GDB, and the
complained about an assertion failure that would happen as a result of
their change.
> Otherwise, this looks good to me.
Thanks, I'll push it as-is.
Simon
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] gdb/python: print name of unwinder that claimed frame in debug message
2021-05-10 16:53 ` Simon Marchi
@ 2021-05-10 17:00 ` Simon Marchi
2021-05-10 17:23 ` [PATCH v2] " Simon Marchi
0 siblings, 1 reply; 6+ messages in thread
From: Simon Marchi @ 2021-05-10 17:00 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
On 2021-05-10 12:53 p.m., Simon Marchi via Gdb-patches wrote:
> On 2021-05-10 12:45 p.m., Andrew Burgess wrote:
>> Maybe being a little paranoid, but I wonder if we should avoid
>> asserting on the interface between GDB and Python code? In theory I
>> guess a user could modify the Python code in some incompatible way.
>> Perhaps a check and error (...) call would be better?
>
> I thought about this, and in my opinion the GDB Python code is
> "internal" code as much as the C code. If a user modifies the Python
> code we ship, then they modify GDB, it's their problem. To me, it's the
> same as if they modified the C source code, rebuilt GDB, and the
> complained about an assertion failure that would happen as a result of
> their change.
>
>> Otherwise, this looks good to me.
>
> Thanks, I'll push it as-is.
Actually, I thought about testing it with Python 2 (we still support
Python 2 right?) and it doesn't build. I'll address that and send a new
version.
Simon
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] gdb/python: print name of unwinder that claimed frame in debug message
2021-05-10 17:00 ` Simon Marchi
@ 2021-05-10 17:23 ` Simon Marchi
2021-06-22 18:47 ` Simon Marchi
0 siblings, 1 reply; 6+ messages in thread
From: Simon Marchi @ 2021-05-10 17:23 UTC (permalink / raw)
To: gdb-patches
New in v2:
- use python_string_to_host_string to get C string from Python string.
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
---
gdb/ChangeLog | 7 +++++++
gdb/python/lib/gdb/__init__.py | 14 +++++++++----
gdb/python/py-unwind.c | 36 +++++++++++++++++++++++++++-------
3 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 52d5faac8a9d..067cb6378b9f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2021-05-10 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-05-10 Simon Marchi <simon.marchi@polymtl.ca>
* nat/linux-waitpid.c (status_to_str): Show signal name.
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index d748b3a5827e..f2f38b32af96 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -90,27 +90,33 @@ def _execute_unwinders(pending_frame):
Arguments:
pending_frame: gdb.PendingFrame instance.
+
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 unwinder in objfile.frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
for unwinder in current_progspace().frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
for unwinder in frame_unwinders:
if unwinder.enabled:
unwind_info = unwinder(pending_frame)
if unwind_info is not None:
- return unwind_info
+ return (unwind_info, unwinder.name)
return None
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 7c195eb539da..0a997e35072a 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -518,33 +518,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
@@ -575,7 +598,6 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
}
*cache_ptr = cached_frame;
- pyuw_debug_printf ("frame claimed");
return 1;
}
--
2.30.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] gdb/python: print name of unwinder that claimed frame in debug message
2021-05-10 17:23 ` [PATCH v2] " Simon Marchi
@ 2021-06-22 18:47 ` Simon Marchi
0 siblings, 0 replies; 6+ messages in thread
From: Simon Marchi @ 2021-06-22 18:47 UTC (permalink / raw)
To: gdb-patches
On 2021-05-10 1:23 p.m., Simon Marchi wrote:
> New in v2:
>
> - use python_string_to_host_string to get C string from Python string.
>
> 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.
I pushed this.
Simon
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-06-22 18:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-10 15:49 [PATCH] gdb/python: print name of unwinder that claimed frame in debug message Simon Marchi
2021-05-10 16:45 ` Andrew Burgess
2021-05-10 16:53 ` Simon Marchi
2021-05-10 17:00 ` Simon Marchi
2021-05-10 17:23 ` [PATCH v2] " Simon Marchi
2021-06-22 18:47 ` Simon Marchi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).