From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id AKpfI+fr0GDhRAAAWB0awg (envelope-from ) for ; Mon, 21 Jun 2021 15:43:35 -0400 Received: by simark.ca (Postfix, from userid 112) id 8E30D1F1F2; Mon, 21 Jun 2021 15:43:35 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RDNS_DYNAMIC,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 14E3D1E54D for ; Mon, 21 Jun 2021 15:43:34 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D0099387743F for ; Mon, 21 Jun 2021 19:43:33 +0000 (GMT) Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by sourceware.org (Postfix) with ESMTPS id D411D393C86B for ; Mon, 21 Jun 2021 19:42:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D411D393C86B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x442.google.com with SMTP id y7so20866420wrh.7 for ; Mon, 21 Jun 2021 12:42:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=2XMUzIs4fxiw6x9iY8qJaK9T1mTupVQfGf7oEu3Fn5U=; b=fYlR2grh1VGPT9ZYyNhgHG0e+EhJGxRXJLxAqNgJ45oa1n+mG7iYTg2+0dGatSv3xk NvfalKAfrK8MBgApZoz1vFFkEubyi0RADhhze6W4WMUZJZrHHAI0hpwdDy0CY3abVBFy SDq2doGJN+v1rVvxvI+GLwMekYS5SNTAoouX7tILTwdTtOnEtBpOjtUZG6zvmXgMVJO/ ZcPO3RE1q07cIrm9RDaLFvzfYmMM/I1lx7rs6D825a27TSRBgcFmDbe1ypt0qFcmrGSV A3sKRCswREoj/CPMxCHgh7aMCiQE+3NXOPqrsTPHn9V2v4KNC8GgIhHZ7tIATjuKNW16 RMMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=2XMUzIs4fxiw6x9iY8qJaK9T1mTupVQfGf7oEu3Fn5U=; b=IgO7lT9ruDVgCru+TLlly0Bj0Oh61t1l84x5+eJ9WyVfT02+7M8V+rK1ONisDtAmbp 2EJ34jLwBnuSZX3vTtBhFFkdVSca6NtcZYAatimZnll11Ku+gG857A/IJvicKGDT+jcJ aLR1DHgBfesQ7L6s769rgvCiJqloJKs1xgzy4ThWIadJ9WZHXghzE/O3zCuG/SlhzUcJ pyDmNpw6kr4sEKSB+qB5Zn5YCfMwuOZuT+nKWyPd3Wr12CFs6Ogg2kqOS3XwBGfMHXNg 84sup9F4P/F7W11xrlUwwx2Gf6nVndKLR2q484khgoGnTaEpRujMrjhOlF55CMNl07Xy TpbQ== X-Gm-Message-State: AOAM530DURvU1wFQ3uzr3hvdlGNddbWHHgDzqFTQVv6zbgl6+JHPH/zG zqMBB5mcfN6yDUS79nC+Momkd2GflBYyrsg0 X-Google-Smtp-Source: ABdhPJxlPjRAjzwBEnVJtGPdKj80uWmpIfQQehIIA77pOm9oGQ6KYbxoIC86RqbltNuz12gLa8f2Eg== X-Received: by 2002:a5d:6c62:: with SMTP id r2mr17999wrz.407.1624304568807; Mon, 21 Jun 2021 12:42:48 -0700 (PDT) Received: from localhost (host86-140-92-85.range86-140.btcentralplus.com. [86.140.92.85]) by smtp.gmail.com with ESMTPSA id r3sm3728wmq.8.2021.06.21.12.42.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Jun 2021 12:42:48 -0700 (PDT) Date: Mon, 21 Jun 2021 20:42:47 +0100 From: Andrew Burgess To: gdb-patches@sourceware.org Subject: Re: [PATCH 3/5] gdb/python: add PendingFrame.level and Frame.level methods Message-ID: <20210621194247.GH2568@embecosm.com> References: <5d6ac8c94e5c473d533d945ba9759af2d8ae57a6.1622321523.git.andrew.burgess@embecosm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5d6ac8c94e5c473d533d945ba9759af2d8ae57a6.1622321523.git.andrew.burgess@embecosm.com> X-Operating-System: Linux/5.8.18-100.fc31.x86_64 (x86_64) X-Uptime: 20:42:35 up 5 days, 3:34, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] 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: , Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" I've pushed this patch now. Thanks, Andrew * Andrew Burgess [2021-05-29 21:57:12 +0100]: > Add new methods to the PendingFrame and Frame classes to obtain the > stack frame level for each object. > > The use of 'level' as the method name is consistent with the existing > attribute RecordFunctionSegment.level (though this is an attribute > rather than a method). > > For Frame/PendingFrame I went with methods as these classes currently > only use methods, including for simple data like architecture, so I > want to be consistent with this interface. > > gdb/ChangeLog: > > * python/py-frame.c (frapy_level): New function. > (frame_object_methods): Register 'level' method. > * python/py-unwind.c (pending_framepy_level): New function. > (pending_frame_object_methods): Register 'level' method. > > gdb/doc/ChangeLog: > > * python.texi (Unwinding Frames in Python): Mention > PendingFrame.level. > (Frames In Python): Mention Frame.level. > > gdb/testsuite/ChangeLog: > > * gdb.python/py-frame.exp: Add Frame.level tests. > * gdb.python/py-pending-frame-level.c: New file. > * gdb.python/py-pending-frame-level.exp: New file. > * gdb.python/py-pending-frame-level.py: New file. > --- > gdb/ChangeLog | 7 ++ > gdb/doc/ChangeLog | 6 ++ > gdb/doc/python.texi | 9 +++ > gdb/python/py-frame.c | 23 +++++++ > gdb/python/py-unwind.c | 19 ++++++ > gdb/testsuite/ChangeLog | 7 ++ > gdb/testsuite/gdb.python/py-frame.exp | 11 ++++ > .../gdb.python/py-pending-frame-level.c | 49 ++++++++++++++ > .../gdb.python/py-pending-frame-level.exp | 65 +++++++++++++++++++ > .../gdb.python/py-pending-frame-level.py | 55 ++++++++++++++++ > 10 files changed, 251 insertions(+) > create mode 100644 gdb/testsuite/gdb.python/py-pending-frame-level.c > create mode 100644 gdb/testsuite/gdb.python/py-pending-frame-level.exp > create mode 100644 gdb/testsuite/gdb.python/py-pending-frame-level.py > > diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi > index 23e6ac666ff..b7e16351a5d 100644 > --- a/gdb/doc/python.texi > +++ b/gdb/doc/python.texi > @@ -2605,6 +2605,11 @@ > the particular frame being unwound. > @end defun > > +@defun PendingFrame.level () > +Return an integer, the stack frame level for this frame. > +@xref{Frames, ,Stack Frames}. > +@end defun > + > @subheading Unwinder Output: UnwindInfo > > Use @code{PendingFrame.create_unwind_info} method described above to > @@ -4813,6 +4818,10 @@ > Stack}. > @end defun > > +@defun Frame.level () > +Return an integer, the stack frame level for this frame. @xref{Frames, ,Stack Frames}. > +@end defun > + > @node Blocks In Python > @subsubsection Accessing blocks from Python > > diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c > index c8eab5291ea..4f218c40367 100644 > --- a/gdb/python/py-frame.c > +++ b/gdb/python/py-frame.c > @@ -577,6 +577,27 @@ frapy_select (PyObject *self, PyObject *args) > Py_RETURN_NONE; > } > > +/* The stack frame level for this frame. */ > + > +static PyObject * > +frapy_level (PyObject *self, PyObject *args) > +{ > + struct frame_info *fi; > + > + try > + { > + FRAPY_REQUIRE_VALID (self, fi); > + > + return gdb_py_object_from_int (frame_relative_level (fi)).release (); > + } > + catch (const gdb_exception &except) > + { > + GDB_PY_HANDLE_EXCEPTION (except); > + } > + > + Py_RETURN_NONE; > +} > + > /* Implementation of gdb.newest_frame () -> gdb.Frame. > Returns the newest frame object. */ > > @@ -748,6 +769,8 @@ Return the frame's symtab and line." }, > Return the value of the variable in this frame." }, > { "select", frapy_select, METH_NOARGS, > "Select this frame as the user's current frame." }, > + { "level", frapy_level, METH_NOARGS, > + "The stack level of this frame." }, > {NULL} /* Sentinel */ > }; > > diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c > index d6e2f85dbc1..ff1a7e922a7 100644 > --- a/gdb/python/py-unwind.c > +++ b/gdb/python/py-unwind.c > @@ -463,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_int (level).release (); > +} > + > /* frame_unwind.this_id method. */ > > static void > @@ -704,6 +721,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 */ > }; > > diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp > index a6a5c0de726..05c7fb00dfd 100644 > --- a/gdb/testsuite/gdb.python/py-frame.exp > +++ b/gdb/testsuite/gdb.python/py-frame.exp > @@ -70,6 +70,17 @@ gdb_test "up" ".*" "" > > gdb_py_test_silent_cmd "python f1 = gdb.selected_frame ()" "get second frame" 0 > gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0 > +gdb_py_test_silent_cmd "python f2 = f1.older ()" "get last frame" 0 > + > +# Check the Frame.level method. > +gdb_test "python print ('bframe.level = %d' % bframe.level ())" \ > + "bframe\\.level = 0" > +gdb_test "python print ('f0.level = %d' % f0.level ())" \ > + "f0\\.level = 0" > +gdb_test "python print ('f1.level = %d' % f1.level ())" \ > + "f1\\.level = 1" > +gdb_test "python print ('f2.level = %d' % f2.level ())" \ > + "f2\\.level = 2" > > gdb_test "python print (f1 == gdb.newest_frame())" False \ > "selected frame -vs- newest frame" > diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.c b/gdb/testsuite/gdb.python/py-pending-frame-level.c > new file mode 100644 > index 00000000000..5e5495c1d71 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.c > @@ -0,0 +1,49 @@ > +/* This test program is part of GDB, the GNU debugger. > + > + Copyright 2021 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +volatile int global_var; > + > +void __attribute__ ((noinline)) > +f0 (void) > +{ > + ++global_var; /* Break here. */ > +} > + > +void __attribute__ ((noinline)) > +f1 (void) > +{ > + f0 (); > +} > + > +void __attribute__ ((noinline)) > +f2 (void) > +{ > + f1 (); > +} > + > +void __attribute__ ((noinline)) > +f3 (void) > +{ > + f2 (); > +} > + > +int > +main (void) > +{ > + f3 (); > + return 0; > +} > diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.exp b/gdb/testsuite/gdb.python/py-pending-frame-level.exp > new file mode 100644 > index 00000000000..1aadcaeacae > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.exp > @@ -0,0 +1,65 @@ > +# Copyright (C) 2021 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see . > + > +# Test gdb.PendingFrame.level method. > + > +load_lib gdb-python.exp > + > +standard_testfile > + > +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { > + return -1 > +} > + > +# Skip all tests if Python scripting is not enabled. > +if { [skip_python_tests] } { continue } > + > +if ![runto_main] then { > + fail "can't run to main" > + return 0 > +} > + > +set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py] > + > +gdb_breakpoint [gdb_get_line_number "Break here"] > +gdb_continue_to_breakpoint "stop at test breakpoint" > + > +# An initial look at the stack to ensure it is correct. > +gdb_test_sequence "bt" "Initial backtrace" { > + "\\r\\n#0 \[^\r\n\]* f0 \\(\\) at " > + "\\r\\n#1 \[^\r\n\]* f1 \\(\\) at " > + "\\r\\n#2 \[^\r\n\]* f2 \\(\\) at " > + "\\r\\n#3 \[^\r\n\]* f3 \\(\\) at " > + "\\r\\n#4 \[^\r\n\]* main \\(\\) at " > +} > + > +# Load the script containing the unwinder. > +gdb_test_no_output "source ${pyfile}"\ > + "import python scripts" > + > +# Now look at the stack again, we should see output from the Python > +# unwinder mixed in. > +gdb_test_sequence "bt" "Backtrace with extra Python output" { > + "Func f0, Level 0" > + "Func f1, Level 1" > + "\\r\\n#0 \[^\r\n\]* f0 \\(\\) at " > + "\\r\\n#1 \[^\r\n\]* f1 \\(\\) at " > + "Func f2, Level 2" > + "\\r\\n#2 \[^\r\n\]* f2 \\(\\) at " > + "Func f3, Level 3" > + "\\r\\n#3 \[^\r\n\]* f3 \\(\\) at " > + "Func main, Level 4" > + "\\r\\n#4 \[^\r\n\]* main \\(\\) at " > +} > diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.py b/gdb/testsuite/gdb.python/py-pending-frame-level.py > new file mode 100644 > index 00000000000..182edcdc0df > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.py > @@ -0,0 +1,55 @@ > +# Copyright (C) 2021 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see . > + > +import gdb > +from gdb.unwinder import Unwinder > + > + > +class FrameId(object): > + def __init__(self, sp, pc): > + self._sp = sp > + self._pc = pc > + > + @property > + def sp(self): > + return self._sp > + > + @property > + def pc(self): > + return self._pc > + > + > +class TestUnwinder(Unwinder): > + def __init__(self): > + Unwinder.__init__(self, "show level") > + > + def __call__(self, pending_frame): > + pc_desc = pending_frame.architecture().registers().find("pc") > + pc = pending_frame.read_register(pc_desc) > + > + block = gdb.block_for_pc(int(pc)) > + if block == None: > + return None > + func = block.function > + if func == None: > + return None > + > + print("Func %s, Level %d" % (str(func), pending_frame.level())) > + > + # This unwinder never claims any frames. > + return None > + > + > +gdb.unwinder.register_unwinder(None, TestUnwinder(), True) > -- > 2.25.4 >