From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH 06/10] gdb/python: add __repr__ for PendingFrame and UnwindInfo
Date: Fri, 10 Mar 2023 14:55:23 +0000 [thread overview]
Message-ID: <c18da4b59561e137b92cb00912670a808493cdfb.1678460067.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1678460067.git.aburgess@redhat.com>
Having a useful __repr__ method can make debugging Python code that
little bit easier. This commit adds __repr__ for gdb.PendingFrame and
gdb.UnwindInfo classes, along with some tests.
---
gdb/python/py-unwind.c | 67 +++++++++++++++++++++++++-
gdb/testsuite/gdb.python/py-unwind.exp | 19 ++++++++
gdb/testsuite/gdb.python/py-unwind.py | 16 +++++-
3 files changed, 99 insertions(+), 3 deletions(-)
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 5ed3ff37e64..1e94c243163 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -229,6 +229,38 @@ unwind_infopy_str (PyObject *self)
return PyUnicode_FromString (stb.c_str ());
}
+/* Implement UnwindInfo.__repr__(). */
+
+static PyObject *
+unwind_infopy_repr (PyObject *self)
+{
+ unwind_info_object *unwind_info = (unwind_info_object *) self;
+ pending_frame_object *pending_frame
+ = (pending_frame_object *) (unwind_info->pending_frame);
+ frame_info_ptr frame = pending_frame->frame_info;
+
+ if (frame == nullptr)
+ return PyUnicode_FromFormat ("<%s for an invalid frame>",
+ Py_TYPE (self)->tp_name);
+
+ std::string saved_reg_names;
+ struct gdbarch *gdbarch = pending_frame->gdbarch;
+
+ for (const saved_reg ® : *unwind_info->saved_regs)
+ {
+ const char *name = gdbarch_register_name (gdbarch, reg.number);
+ if (saved_reg_names.empty ())
+ saved_reg_names = name;
+ else
+ saved_reg_names = (saved_reg_names + ", ") + name;
+ }
+
+ return PyUnicode_FromFormat ("<%s frame #%d, saved_regs=(%s)>",
+ Py_TYPE (self)->tp_name,
+ frame_relative_level (frame),
+ saved_reg_names.c_str ());
+}
+
/* Create UnwindInfo instance for given PendingFrame and frame ID.
Sets Python error and returns NULL on error.
@@ -372,6 +404,37 @@ pending_framepy_str (PyObject *self)
return PyUnicode_FromFormat ("SP=%s,PC=%s", sp_str, pc_str);
}
+/* Implement PendingFrame.__repr__(). */
+
+static PyObject *
+pending_framepy_repr (PyObject *self)
+{
+ pending_frame_object *pending_frame = (pending_frame_object *) self;
+ frame_info_ptr frame = pending_frame->frame_info;
+
+ if (frame == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ const char *sp_str = nullptr;
+ const char *pc_str = nullptr;
+
+ try
+ {
+ sp_str = core_addr_to_string_nz (get_frame_sp (frame));
+ pc_str = core_addr_to_string_nz (get_frame_pc (frame));
+ }
+ catch (const gdb_exception &except)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+
+ return PyUnicode_FromFormat ("<%s level=%d, sp=%s, pc=%s>",
+ Py_TYPE (self)->tp_name,
+ frame_relative_level (frame),
+ sp_str,
+ pc_str);
+}
+
/* Implementation of gdb.PendingFrame.read_register (self, reg) -> gdb.Value.
Returns the value of register REG as gdb.Value instance. */
@@ -974,7 +1037,7 @@ PyTypeObject pending_frame_object_type =
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
- 0, /* tp_repr */
+ pending_framepy_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
@@ -1024,7 +1087,7 @@ PyTypeObject unwind_info_object_type =
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
- 0, /* tp_repr */
+ unwind_infopy_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
diff --git a/gdb/testsuite/gdb.python/py-unwind.exp b/gdb/testsuite/gdb.python/py-unwind.exp
index f670da5a7cd..7e6ac9a8623 100644
--- a/gdb/testsuite/gdb.python/py-unwind.exp
+++ b/gdb/testsuite/gdb.python/py-unwind.exp
@@ -152,6 +152,25 @@ check_for_broken_backtrace "backtrace to capture a PendingFrame object"
# Check the captured PendingFrame is not valid.
gdb_test "python print(captured_pending_frame.is_valid())" "False"
+# Check the __repr__ of an invalid PendingFrame.
+gdb_test "python print(repr(captured_pending_frame))" \
+ "<gdb.PendingFrame \\(invalid\\)>"
+
+# Check the __repr__ of an UnwindInfo for an invalid PendingFrame.
+gdb_test "python print(captured_unwind_info)"
+gdb_test "python print(repr(captured_unwind_info))" \
+ "<gdb.UnwindInfo for an invalid frame>"
+
+# Check the repr of a PendingFrame that was copied (as a string) at a
+# time the PendingFrame was valid.
+gdb_test "python print(captured_pending_frame_repr)" \
+ "<gdb.PendingFrame level=0, sp=$hex, pc=$hex>"
+
+# Check the repr of an UnwindInfo that was copied (as a string) at a
+# time the UnwindInfo was valid.
+gdb_test "python print(captured_unwind_info_repr)" \
+ "<gdb.UnwindInfo frame #0, saved_regs=\\(rip, rbp, rsp\\)>"
+
# Call methods on the captured gdb.PendingFrame and check we see the
# expected error.
gdb_test_no_output "python pf = captured_pending_frame"
diff --git a/gdb/testsuite/gdb.python/py-unwind.py b/gdb/testsuite/gdb.python/py-unwind.py
index 8e3c1f398bc..f8f04b7f514 100644
--- a/gdb/testsuite/gdb.python/py-unwind.py
+++ b/gdb/testsuite/gdb.python/py-unwind.py
@@ -133,8 +133,11 @@ class TestUnwinder(Unwinder):
global_test_unwinder = TestUnwinder()
gdb.unwinder.register_unwinder(None, global_test_unwinder, True)
-# This is filled in by the simple_unwinder class.
+# These are filled in by the simple_unwinder class.
captured_pending_frame = None
+captured_pending_frame_repr = None
+captured_unwind_info = None
+captured_unwind_info_repr = None
class simple_unwinder(Unwinder):
@@ -143,11 +146,22 @@ class simple_unwinder(Unwinder):
def __call__(self, pending_frame):
global captured_pending_frame
+ global captured_pending_frame_repr
+ global captured_unwind_info
+ global captured_unwind_info_repr
assert pending_frame.is_valid()
if captured_pending_frame is None:
captured_pending_frame = pending_frame
+ captured_pending_frame_repr = repr(pending_frame)
+ fid = FrameId(gdb.Value(0x123), gdb.Value(0x456))
+ uw = pending_frame.create_unwind_info(fid)
+ uw.add_saved_register("rip", gdb.Value(0x123))
+ uw.add_saved_register("rbp", gdb.Value(0x456))
+ uw.add_saved_register("rsp", gdb.Value(0x789))
+ captured_unwind_info = uw
+ captured_unwind_info_repr = repr(uw)
return None
--
2.25.4
next prev parent reply other threads:[~2023-03-10 14:56 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-10 14:55 [PATCH 00/10] Improvements & Cleanup For Python Unwinder API Andrew Burgess
2023-03-10 14:55 ` [PATCH 01/10] gdb/doc: spring clean the Python unwinders documentation Andrew Burgess
2023-03-10 15:24 ` Eli Zaretskii
2023-03-14 9:27 ` Andrew Burgess
2023-03-14 12:56 ` Eli Zaretskii
2023-03-16 14:30 ` Andrew Burgess
2023-03-10 14:55 ` [PATCH 02/10] gdb/python: make the gdb.unwinder.Unwinder class more robust Andrew Burgess
2023-03-10 15:32 ` Eli Zaretskii
2023-03-14 10:06 ` Andrew Burgess
2023-03-14 12:57 ` Eli Zaretskii
2023-03-31 2:15 ` Simon Marchi
2023-04-03 10:02 ` Andrew Burgess
2023-03-10 14:55 ` [PATCH 03/10] gdb/python: remove unneeded nullptr check in frapy_block Andrew Burgess
2023-03-10 14:55 ` [PATCH 04/10] gdb/python: add PENDING_FRAMEPY_REQUIRE_VALID macro in py-unwind.c Andrew Burgess
2023-03-10 14:55 ` [PATCH 05/10] gdb/python: add some additional methods to gdb.PendingFrame Andrew Burgess
2023-03-10 15:42 ` Eli Zaretskii
2023-03-14 10:18 ` Andrew Burgess
2023-03-14 12:59 ` Eli Zaretskii
2023-03-16 14:28 ` Andrew Burgess
2023-03-16 14:46 ` Eli Zaretskii
2023-03-16 17:26 ` Andrew Burgess
2023-03-16 19:54 ` Eli Zaretskii
2023-03-10 14:55 ` Andrew Burgess [this message]
2023-03-10 14:55 ` [PATCH 07/10] gdb/python: remove Py_TPFLAGS_BASETYPE from gdb.UnwindInfo Andrew Burgess
2023-03-10 14:55 ` [PATCH 08/10] gdb: have value_as_address call unpack_pointer Andrew Burgess
2023-03-10 15:28 ` Tom Tromey
2023-03-10 22:08 ` Andrew Burgess
2023-03-10 14:55 ` [PATCH 09/10] gdb/python: Allow gdb.UnwindInfo to be created with non gdb.Value args Andrew Burgess
2023-03-10 15:34 ` Tom Tromey
2023-03-10 22:16 ` Andrew Burgess
2023-03-11 14:47 ` Tom Tromey
2023-03-10 15:38 ` Eli Zaretskii
2023-03-10 14:55 ` [PATCH 10/10] gdb/python: Add new gdb.unwinder.FrameId class Andrew Burgess
2023-03-10 15:36 ` Eli Zaretskii
2023-03-14 10:58 ` Andrew Burgess
2023-03-14 13:00 ` Eli Zaretskii
2023-03-29 16:27 ` [PATCH 00/10] Improvements & Cleanup For Python Unwinder API Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c18da4b59561e137b92cb00912670a808493cdfb.1678460067.git.aburgess@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).