diff options
author | Andrew Burgess <aburgess@redhat.com> | 2024-07-18 11:16:13 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2024-08-28 10:30:31 +0100 |
commit | be85cdf4159c1f130778959d3ddff7c44f5eacde (patch) | |
tree | 0cc2cd556f9cc005a180dba1a62fba27c02ed498 /gdb/block.c | |
parent | 56260065c80caf67b57ec612b85bb978e06dad2d (diff) | |
download | gdb-be85cdf4159c1f130778959d3ddff7c44f5eacde.zip gdb-be85cdf4159c1f130778959d3ddff7c44f5eacde.tar.gz gdb-be85cdf4159c1f130778959d3ddff7c44f5eacde.tar.bz2 |
gdb: add 'maint info blocks' command
While reviewing a patch I wanted to understand which blocks existed at
a given address.
The 'maint print symbols' command does provide some of this
information, but that command displays all blocks within a given
symtab. If I want to know which blocks are at a given address I have
to figure that out for myself based on the output of 'maint print
symbols' ... and I'm too lazy for that!
So this command lists just those blocks at a given address, along with
information about the blocks type. This new command doesn't list the
symbols within each block, for that my expectation is that you'd cross
reference the output with that of 'maint print symbols'.
The new command format is:
maintenance info blocks
maintenance info blocks ADDRESS
This lists the blocks at ADDRESS, or at the current $pc if ADDRESS is
not given. Blocks are listed starting at the global block, then the
static block, and then the progressively narrower scoped blocks.
For each block we list the internal block pointer (which allows easy
cross referencing with 'maint print symbols'), the inferior address
range, along with other useful information.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Diffstat (limited to 'gdb/block.c')
-rw-r--r-- | gdb/block.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/gdb/block.c b/gdb/block.c index d4baaae..6f60877 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -25,6 +25,8 @@ #include "addrmap.h" #include "gdbtypes.h" #include "objfiles.h" +#include "cli/cli-cmds.h" +#include "inferior.h" /* This is used by struct block to store namespace-related info for C++ files, namely using declarations and the current namespace in @@ -819,3 +821,124 @@ make_blockranges (struct objfile *objfile, return blr; } +/* Implement 'maint info blocks' command. If passed an argument then + print a list of all blocks at the given address. With no arguments + then list all blocks at the current address of the current inferior. */ + +static void +maintenance_info_blocks (const char *arg, int from_tty) +{ + CORE_ADDR address; + + /* With no argument use the program counter of the current thread. If + there is an argument then use this as the address to examine. */ + if (arg == nullptr) + { + if (inferior_ptid == null_ptid) + error (_("no inferior thread")); + + struct regcache *regcache = get_thread_regcache (inferior_thread ()); + address = regcache_read_pc (regcache); + } + else + address = parse_and_eval_address (arg); + + /* Find the inner most block for ADDRESS. */ + const struct block *cur_block = block_for_pc (address); + if (cur_block == nullptr) + { + gdb_printf (_("No blocks at %s\n"), core_addr_to_string_nz (address)); + return; + } + + gdb_printf (_("Blocks at %s:\n"), core_addr_to_string_nz (address)); + + const struct objfile *toplevel_objfile = cur_block->objfile (); + if (toplevel_objfile != nullptr) + gdb_printf (_(" from objfile: [(objfile *) %s] %s\n"), + host_address_to_string (toplevel_objfile), + objfile_name (toplevel_objfile)); + + gdb_printf ("\n"); + + /* List the blocks backwards; global block (widest scope) first, down to + the smallest scoped block last. To do this we need to build the list + of blocks starting from the inner block, then print that list + backwards. */ + std::vector<const struct block *> blocks; + while (cur_block != nullptr) + { + blocks.emplace_back (cur_block); + cur_block = cur_block->superblock (); + } + + for (auto it = blocks.rbegin (); it != blocks.rend (); ++it) + { + cur_block = *it; + + gdb_assert (cur_block->objfile () == toplevel_objfile); + + gdb_printf (_("[(block *) %s] %s..%s\n"), + host_address_to_string (cur_block), + core_addr_to_string_nz (cur_block->start ()), + core_addr_to_string_nz (cur_block->end ())); + gdb_printf (_(" entry pc: %s\n"), + core_addr_to_string_nz (cur_block->entry_pc ())); + + if (cur_block->is_static_block ()) + gdb_printf (_(" is static block\n")); + + if (cur_block->is_global_block ()) + gdb_printf (_(" is global block\n")); + + if (cur_block->function () != nullptr) + { + if (cur_block->inlined_p ()) + gdb_printf (_(" inline function: %s\n"), + cur_block->function ()->print_name ()); + else + gdb_printf (_(" function: %s\n"), + cur_block->function ()->print_name ()); + } + + if (cur_block->scope () != nullptr + && *cur_block->scope () != '\0') + gdb_printf (_(" scope: %s\n"), cur_block->scope ()); + + if (int symbol_count = mdict_size (cur_block->multidict ()); + symbol_count > 0) + gdb_printf (_(" symbol count: %d\n"), symbol_count); + + if (cur_block->is_contiguous ()) + gdb_printf (_(" is contiguous\n")); + else + { + gdb_printf (_(" address ranges:\n")); + for (const blockrange &rng : cur_block->ranges ()) + gdb_printf (_(" %s..%s\n"), + core_addr_to_string_nz (rng.start ()), + core_addr_to_string_nz (rng.end ())); + } + } +} + + + +void _initialize_block (); +void +_initialize_block () +{ + add_cmd ("blocks", class_maintenance, maintenance_info_blocks, + _("\ +Display block information for current thread.\n\ +\n\ +Usage:\n\ +\n\ + maintenance info blocks [ADDRESS]\n\ +\n\ +With no ADDRESS show all blocks at the current address, starting with the\n\ +global block and working down to the inner most block.\n\ +\n\ +When ADDRESS is given, list the blocks at ADDRESS."), + &maintenanceinfolist); +} |