From patchwork Fri Aug 29 23:32:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Smundak X-Patchwork-Id: 2597 Received: (qmail 3177 invoked by alias); 29 Aug 2014 23:32:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 3167 invoked by uid 89); 29 Aug 2014 23:32:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f43.google.com Received: from mail-pa0-f43.google.com (HELO mail-pa0-f43.google.com) (209.85.220.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 29 Aug 2014 23:32:35 +0000 Received: by mail-pa0-f43.google.com with SMTP id et14so7518060pad.30 for ; Fri, 29 Aug 2014 16:32:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type; bh=VxkHqaJhwheGhTLD9g3Cr0AAruOH9pvyneZrYu9Kg7k=; b=BXTGbF2gc7P+/i8zCX61f9xOuM4wA0B7ZCGn/X5TpYg3IjO/H9iyqONRlsqpneTbc3 t0dLukvr9Np5wCLfYRXv48nwTYUdONpP6UnesmWGWXjyzChkoJvw1/VrQI2mqb31oyMX fzJtV8t6Pt7XdpmUPu7AhG52jLNiWeMROzJHCS0eXFqU/AhKYR27WBiB7aXKmNVwsWPP 3keKHWNCuyKJZwXqeG2M5sk0MTYLKb9yenXwCxvUdMsHORa/uPCInhCsfR6Sc6kbUZ4N ZJGk6YgFAgVjqEQaJwITWoLcd+4jH+X81X7sbfZou37TRqXvOrQFOwe+joAYIw8ZrHT/ wzvA== X-Gm-Message-State: ALoCoQnkggbGRCJMhQDWgYwfW70NT7OLZEZ9BJOiiNtyde8SbD6dB+EvzZ4VazPEsmvMP5291J60 X-Received: by 10.68.161.197 with SMTP id xu5mr19880592pbb.160.1409355153881; Fri, 29 Aug 2014 16:32:33 -0700 (PDT) Received: from sasha2.mtv.corp.google.com ([2620:0:1000:3002:3dcf:4667:f1fe:9216]) by mx.google.com with ESMTPSA id db4sm1545132pdb.74.2014.08.29.16.32.32 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Aug 2014 16:32:32 -0700 (PDT) Message-ID: <54010D8F.7090607@google.com> Date: Fri, 29 Aug 2014 16:32:31 -0700 From: Sasha Smundak User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.0 MIME-Version: 1.0 To: Doug Evans CC: gdb-patches Subject: Re: [PATCH] Add Frame.read_register to Python API References: <83oay128ca.fsf@gnu.org> <87ioo7uuqm.fsf@fleche.redhat.com> <21494.15883.93664.480097@ruffy2.mtv.corp.google.com> <21503.26406.286858.300183@ruffy2.mtv.corp.google.com> In-Reply-To: <21503.26406.286858.300183@ruffy2.mtv.corp.google.com> Thanks. Here it is again: The ability to read registers is needed to use Frame Filter API to display the frames created by JIT compilers. gdb/ChangeLog: 2014-08-29 Sasha Smundak * python/py-frame.c (frapy_read_register): New function. gdb/doc/ChangeLog 2014-08-26 Sasha Smundak * python.texi (Frames in Python): Add read_register description. gdb/testsuite/ChangeLog: 2014-08-26 Sasha Smundak * gdb.python/py-frame.exp: Test Frame.read_register. diff --git a/gdb/NEWS b/gdb/NEWS index d603cf7..46c6a87 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.8 +* Python Scripting + You can now access frame registers from Python scripts. + * On resume, GDB now always passes the signal the program had stopped for to the thread the signal was sent to, even if the user changed threads before resuming. Previously GDB would often (but not diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 4688783..3cb6bf8 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -3589,6 +3589,13 @@ Return the frame's symtab and line object. @xref{Symbol Tables In Python}. @end defun +@defun Frame.read_register (register) +Return the value of @var{register} in this frame. The @var{register} +argument must be a string (e.g., @code{'sp'} or @code{'rax'}). +Returns a @code{Gdb.Value} object. Throws an exception if @var{register} +does not exist. +@end defun + @defun Frame.read_var (variable @r{[}, block@r{]}) Return the value of @var{variable} in this frame. If the optional argument @var{block} is provided, search for the variable from that diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 120e147..859d115 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -28,6 +28,7 @@ #include "python-internal.h" #include "symfile.h" #include "objfiles.h" +#include "user-regs.h" typedef struct { PyObject_HEAD @@ -235,6 +236,40 @@ frapy_pc (PyObject *self, PyObject *args) return gdb_py_long_from_ulongest (pc); } +/* Implementation of gdb.Frame.read_register (self, register) -> gdb.Value. + Returns the value of a register in this frame. */ + +static PyObject * +frapy_read_register (PyObject *self, PyObject *args) +{ + volatile struct gdb_exception except; + const char *regnum_str; + struct value *val = NULL; + + if (!PyArg_ParseTuple (args, "s", ®num_str)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct frame_info *frame; + int regnum; + + FRAPY_REQUIRE_VALID (self, frame); + + regnum = user_reg_map_name_to_regnum (get_frame_arch (frame), + regnum_str, + strlen (regnum_str)); + if (regnum >= 0) + val = value_of_register (regnum, frame); + + if (val == NULL) + PyErr_SetString (PyExc_ValueError, _("Unknown register.")); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return val == NULL ? NULL : value_to_value_object (val); +} + /* Implementation of gdb.Frame.block (self) -> gdb.Block. Returns the frame's code block. */ @@ -674,6 +709,9 @@ Return the reason why it's not possible to find frames older than this." }, { "pc", frapy_pc, METH_NOARGS, "pc () -> Long.\n\ Return the frame's resume address." }, + { "read_register", frapy_read_register, METH_VARARGS, + "read_register (register_name) -> gdb.Value\n\ +Return the value of the register in the frame." }, { "block", frapy_block, METH_NOARGS, "block () -> gdb.Block.\n\ Return the frame's code block." }, diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp index 3517824..e47f340 100644 --- a/gdb/testsuite/gdb.python/py-frame.exp +++ b/gdb/testsuite/gdb.python/py-frame.exp @@ -94,3 +94,20 @@ gdb_test "python print ('result = %s' % f0.read_var ('variable_which_surely_does gdb_test "python print ('result = %s' % f0.read_var ('a'))" " = 1" "test Frame.read_var - success" gdb_test "python print ('result = %s' % (gdb.selected_frame () == f1))" " = True" "test gdb.selected_frame" + +# Can read SP register. +gdb_test "python print ('result = %s' % (gdb.selected_frame ().read_register ('sp') == gdb.parse_and_eval ('\$sp')))" \ + " = True" \ + "test Frame.read_register(sp)" + +# PC value obtained via read_register is as expected. +gdb_test "python print ('result = %s' % (f0.read_register('pc') == f0.pc()))" \ + " = True" \ + "test Frame.read_register(pc)" + +# On x86-64, PC is in $rip register. +if {[istarget x86_64-*]} { + gdb_test "python print ('result = %s' % (f0.read_register('pc') == f0.read_register('rip')))" \ + " = True" \ + "test Frame.read_register(rip)" +}