From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 115178 invoked by alias); 2 Aug 2019 23:11:31 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 115171 invoked by uid 89); 2 Aug 2019 23:11:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.2 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-yw1-f74.google.com Received: from mail-yw1-f74.google.com (HELO mail-yw1-f74.google.com) (209.85.161.74) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 02 Aug 2019 23:11:29 +0000 Received: by mail-yw1-f74.google.com with SMTP id i63so56778376ywc.1 for ; Fri, 02 Aug 2019 16:11:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=0EvSnzYz6YCh1g/NyPbSsdSSnRF2V0GaIoaycG/ltv8=; b=Uc4wQ0v9GFiwbXd4BxH1tacv6qI/WZiJwnYelqHNfJTeCu60YexiRychEz+IbxNZiI zDN3W1mQJVSelpnilJapgLMHb0FwBRMs20WZ8EgFPe3TwHojGUpdox3Q/CJnEEIR7C27 oNPv9uB268mT8+zQ2vQFXRxYbQuD9kiPvNwKtjb6cE7BwoXFfEfD3b/hcUgL7UaRVZI8 eGF7tosmPOanjK4ShNzWmrpd2JndO6A8BdEAr8ufMEKwgrS7zMhiyYdGyUSmEVO4WNbR 9LkdH/wR9hepKi11giI3q1He/Hj1uk2pe/SCJOrYDjFbmRwhaQPsHDNP7IMts15e53iV nQIg== Date: Fri, 02 Aug 2019 23:11:00 -0000 In-Reply-To: <87y30bit95.fsf@tromey.com> Message-Id: <20190802231125.240974-1-cbiesinger@google.com> Mime-Version: 1.0 References: <87y30bit95.fsf@tromey.com> Subject: [PATCH v2] Add block['var'] accessor From: "Christian Biesinger via gdb-patches" Reply-To: Christian Biesinger To: gdb-patches@sourceware.org Cc: Christian Biesinger Content-Type: text/plain; charset="UTF-8" X-SW-Source: 2019-08/txt/msg00057.txt.bz2 Sorry about the coding style. Both issues should be fixed now. Currently we support iteration on blocks; this patch extends that to make subscript access work as well. gdb/ChangeLog: 2019-08-01 Christian Biesinger * NEWS: Mention dictionary access on blocks. * python/py-block.c (blpy_getitem): New function. (block_object_as_mapping): New struct. (block_object_type): Use new struct for tp_as_mapping field. gdb/doc/ChangeLog: 2019-08-01 Christian Biesinger * python.texi (Blocks In Python): Document dictionary access on blocks. gdb/testsuite/ChangeLog: 2019-08-01 Christian Biesinger * gdb.python/py-block.exp: Test dictionary access on blocks. --- gdb/NEWS | 3 ++ gdb/doc/python.texi | 7 ++++- gdb/python/py-block.c | 45 ++++++++++++++++++++++++++- gdb/testsuite/gdb.python/py-block.exp | 5 +++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 3c3351e2c4..2db86c2ae7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -47,6 +47,9 @@ ** gdb.Objfile has new methods 'lookup_global_symbol' and 'lookup_static_symbol' to lookup a symbol from this objfile only. + ** gdb.Block now supports the dictionary syntax for accessing symbols in + this block (e.g. block['local_variable']). + * New commands | [COMMAND] | SHELL_COMMAND diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 3fdccd5e43..832283dede 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -4722,7 +4722,12 @@ A @code{gdb.Block} is iterable. The iterator returns the symbols should not assume that a specific block object will always contain a given symbol, since changes in @value{GDBN} features and infrastructure may cause symbols move across blocks in a symbol -table. +table. You can also use Python's @dfn{dictionary syntax} to access +variables in this block, e.g.: + +@smallexample +symbol = some_block['variable'] # symbol is of type gdb.Symbol +@end smallexample The following block-related functions are available in the @code{gdb} module: diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c index 90140ebc34..4dc47ff169 100644 --- a/gdb/python/py-block.c +++ b/gdb/python/py-block.c @@ -224,6 +224,43 @@ blpy_is_static (PyObject *self, void *closure) Py_RETURN_FALSE; } +/* Given a string, returns the gdb.Symbol representing that symbol in this + block. If such a symbol does not exist, returns NULL with a Python + exception. */ + +static PyObject * +blpy_getitem (PyObject *self, PyObject *key) +{ + const struct block *block; + + BLPY_REQUIRE_VALID (self, block); + + gdb::unique_xmalloc_ptr name = python_string_to_host_string (key); + if (name == nullptr) + return nullptr; + + lookup_name_info lookup_name (name.get(), symbol_name_match_type::FULL); + + /* We use ALL_BLOCK_SYMBOLS_WITH_NAME instead of block_lookup_symbol so + that we can look up symbols irrespective of the domain, matching the + iterator. It would be confusing if the iterator returns symbols you + can't find via getitem. */ + struct block_iterator iter; + struct symbol *sym = nullptr; + ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym) + { + /* Just stop at the first match */ + break; + } + + if (sym == nullptr) + { + PyErr_SetObject (PyExc_KeyError, key); + return nullptr; + } + return symbol_to_symbol_object (sym); +} + static void blpy_dealloc (PyObject *obj) { @@ -440,6 +477,12 @@ static gdb_PyGetSetDef block_object_getset[] = { { NULL } /* Sentinel */ }; +static PyMappingMethods block_object_as_mapping = { + NULL, + blpy_getitem, + NULL +}; + PyTypeObject block_object_type = { PyVarObject_HEAD_INIT (NULL, 0) "gdb.Block", /*tp_name*/ @@ -453,7 +496,7 @@ PyTypeObject block_object_type = { 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ + &block_object_as_mapping, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp index 20d3968c04..6be1abe7ae 100644 --- a/gdb/testsuite/gdb.python/py-block.exp +++ b/gdb/testsuite/gdb.python/py-block.exp @@ -43,6 +43,11 @@ gdb_test "python print (block)" "" "check block not No gdb_test "python print (block.function)" "None" "first anonymous block" gdb_test "python print (block.start)" "${decimal}" "check start not None" gdb_test "python print (block.end)" "${decimal}" "check end not None" +gdb_test "python print (block\['f'\].name == 'f')" "True" "check variable access" +gdb_test "python print (block\['nonexistent'\])" ".*KeyError: 'nonexistent'.*" \ + "check nonexistent variable" +gdb_test "python print (block\[42\])" ".*TypeError: Expected a string.*" \ + "check non-string key" # Test global/static blocks gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 -- 2.22.0.770.g0f2c4a37fd-goog