From d3561c0b6975dee7e5dc277481b8c152044252da Mon Sep 17 00:00:00 2001 From: Jan Vrany Date: Thu, 21 Nov 2024 12:31:20 +0000 Subject: [PATCH] gdb/python: add subblocks property to gdb.Block This commit adds new propery "subblocks" to gdb.Block objects. This allows Python to traverse block tree starting with global block. Reviewed-By: Eli Zaretskii --- gdb/NEWS | 3 +++ gdb/doc/python.texi | 5 +++++ gdb/python/py-block.c | 30 +++++++++++++++++++++++++++ gdb/testsuite/gdb.python/py-block.exp | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/gdb/NEWS b/gdb/NEWS index 046daad0eae..c9e0439645f 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -83,6 +83,9 @@ ** The 'qualified' argument to gdb.Breakpoint constructor will no longer accept non-bool types. + ** Added gdb.Block.subblocks. Returns a list of blocks contained in that + block. + * Debugger Adapter Protocol changes ** The "scopes" request will now return a scope holding global diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index cc455483166..290e9fea62f 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -6040,6 +6040,11 @@ The block containing this block. If this parent block does not exist, this attribute holds @code{None}. This attribute is not writable. @end defvar +@defvar Block.subblocks +A list of blocks nested in this block. If there are no blocks nested, +this attribute holds an empty list. This attribute is not writable. +@end defvar + @defvar Block.global_block The global block associated with this block. This attribute is not writable. diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c index aeb9acb7260..1c5eab44b3a 100644 --- a/gdb/python/py-block.c +++ b/gdb/python/py-block.c @@ -149,6 +149,34 @@ blpy_get_superblock (PyObject *self, void *closure) Py_RETURN_NONE; } +static PyObject * +blpy_get_subblocks (PyObject *self, void *closure) +{ + const struct block *block; + + BLPY_REQUIRE_VALID (self, block); + + gdbpy_ref<> list (PyList_New (0)); + if (list == nullptr) + return nullptr; + + compunit_symtab *cu = block->global_block ()->compunit (); + + for (const struct block *each : cu->blockvector ()->blocks ()) + { + if (each->superblock () == block) + { + gdbpy_ref<> item (block_to_block_object (each, cu->objfile ())); + + if (item.get () == nullptr + || PyList_Append (list.get (), item.get ()) == -1) + return nullptr; + } + } + + return list.release (); +} + /* Return the global block associated to this block. */ static PyObject * @@ -529,6 +557,8 @@ static gdb_PyGetSetDef block_object_getset[] = { "Whether this block is a static block.", NULL }, { "is_global", blpy_is_global, NULL, "Whether this block is a global block.", NULL }, + { "subblocks", blpy_get_subblocks, nullptr, + "List of blocks contained in this block.", nullptr }, { NULL } /* Sentinel */ }; diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp index 0e6851ddf8b..20f21711126 100644 --- a/gdb/testsuite/gdb.python/py-block.exp +++ b/gdb/testsuite/gdb.python/py-block.exp @@ -61,6 +61,10 @@ gdb_py_test_silent_cmd "python sblock = block.static_block" \ "Get block, static_block" 1 gdb_test "python print (gblock.is_global)" "True" "is the global block" gdb_test "python print (sblock.is_static)" "True" "is the static block" +gdb_test "python print (len(gblock.subblocks) > 0)" "True" \ + "global block contains at least one block" +gdb_test "python print (sblock in gblock.subblocks)" "True" \ + "global block contains at static block" # Move up superblock(s) until we reach function block_func. gdb_test_no_output "python block = block.superblock" "get superblock" -- 2.47.3