From patchwork Fri Mar 10 14:55:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 66218 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8A1DE3857838 for ; Fri, 10 Mar 2023 14:56:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8A1DE3857838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1678460215; bh=TWrN7LJLgeufwKNewsReFmDEJCfjWZBLG6O+hIvM0n0=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=fTVHePdUwRC2VN5IsAaaYDSwNXgDsARtED5aIRiHLHL9kIlRjD1xm9vBiPap/gLvx 8gt/ggaQlWDhSjy+frX5nUdHFuPvO1/D9uCfzxgoFx7sexa8gbJNv+anJKj63vHIx/ L0DCFrni3mSIDW0BliBaMfhMZuqvvIRBus27D6Ds= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 23FC83858C1F for ; Fri, 10 Mar 2023 14:56:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 23FC83858C1F Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-341-hkXyAFhuMqi75n3dzgqC7Q-1; Fri, 10 Mar 2023 09:55:59 -0500 X-MC-Unique: hkXyAFhuMqi75n3dzgqC7Q-1 Received: by mail-wm1-f72.google.com with SMTP id c7-20020a7bc847000000b003e00be23a70so3975861wml.2 for ; Fri, 10 Mar 2023 06:55:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678460158; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TWrN7LJLgeufwKNewsReFmDEJCfjWZBLG6O+hIvM0n0=; b=jXFwXQx4wPTqWfXxPUR1BWHb+OGw7d5UnXFZ3qD1ASMUer1e6X8NrJdKNnRDFcz/Ae b9RZVnDYOrAQzY4R6Tgv5FO7BoOE5PHfem9P8Om4AmEU/pF/yrhtEgJdUQ69Tf+T+CCH ZeQSQ6vA+oBtIpZoZr0lq5YU6ufTvmwhCQd1EQKv/Ekr7/g9UG/3wZlj72yytsXkpTtl bIisoQeJloE4J0aw2vU23JKzpX8h4QZePcjXsM2ncrR8ZX4qRez1EjkjWIjbsbvQzBaa 47x/r0MpfLdgHddT48XlKDW3AncUUUWHhWNEKRCKHvOi9unN4ypk/wfsblbx+zqBblqB jNCg== X-Gm-Message-State: AO0yUKUSG/CDKe/mWu87FO/5FtGvxG/SKTiTD38pDWpDVRo9XY/rL3NA l5qysjbpbNrgXBCa6A5zNV1zPskky5pWjqOmqqstd3T8n4VFpqGKG6EwTZ2hcik1j6KK2xM7qBA XD1hhSC2t/yvmVmIeCHe44GCIjruUsqLdYkzK52YS3jsFAw3CFOPeDugGBeSFMAe/Hc2uqE4M98 DQeL6URA== X-Received: by 2002:a5d:670f:0:b0:2ca:a36e:3441 with SMTP id o15-20020a5d670f000000b002caa36e3441mr17049913wru.15.1678460158213; Fri, 10 Mar 2023 06:55:58 -0800 (PST) X-Google-Smtp-Source: AK7set9bb5ASKz2NuWSuDl7NPJY0ej9QP5+g65ZCMLF/6mLNgOPvOYX/2TUiLgKrfeCIdFdoNROZMw== X-Received: by 2002:a5d:670f:0:b0:2ca:a36e:3441 with SMTP id o15-20020a5d670f000000b002caa36e3441mr17049902wru.15.1678460157878; Fri, 10 Mar 2023 06:55:57 -0800 (PST) Received: from localhost (95.72.115.87.dyn.plus.net. [87.115.72.95]) by smtp.gmail.com with ESMTPSA id c12-20020a5d4ccc000000b002c4084d3472sm7867wrt.58.2023.03.10.06.55.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Mar 2023 06:55:57 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH 06/10] gdb/python: add __repr__ for PendingFrame and UnwindInfo Date: Fri, 10 Mar 2023 14:55:23 +0000 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" 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))" \ + "" + +# 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))" \ + "" + +# 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)" \ + "" + +# 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)" \ + "" + # 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