diff options
Diffstat (limited to 'gdb/block.c')
-rw-r--r-- | gdb/block.c | 208 |
1 files changed, 157 insertions, 51 deletions
diff --git a/gdb/block.c b/gdb/block.c index 511689c..1866c0f 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -1,6 +1,6 @@ /* Block-related functions for the GNU debugger, GDB. - Copyright (C) 2003-2024 Free Software Foundation, Inc. + Copyright (C) 2003-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -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 @@ -41,13 +43,10 @@ struct block_namespace_info : public allocate_on_obstack<block_namespace_info> struct objfile * block::objfile () const { - const struct global_block *global_block; - if (function () != nullptr) return function ()->objfile (); - global_block = (struct global_block *) this->global_block (); - return global_block->compunit_symtab->objfile (); + return this->global_block ()->compunit ()->objfile (); } /* See block. */ @@ -227,7 +226,7 @@ call_site_for_pc (struct gdbarch *gdbarch, CORE_ADDR pc) if (cs == nullptr) { - struct bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc); + bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc); /* DW_TAG_gnu_call_site will be missing just if GCC could not determine the call target. */ @@ -323,13 +322,13 @@ block::set_scope (const char *scope, struct obstack *obstack) /* See block.h. */ -struct using_direct * +next_range<using_direct> block::get_using () const { if (m_namespace_info == nullptr) - return nullptr; + return {}; else - return m_namespace_info->using_decl; + return next_range<using_direct> (m_namespace_info->using_decl); } /* See block.h. */ @@ -364,7 +363,7 @@ block::static_block () const /* See block.h. */ -const struct block * +const struct global_block * block::global_block () const { const block *block = this; @@ -372,33 +371,40 @@ block::global_block () const while (block->superblock () != NULL) block = block->superblock (); - return block; + return block->as_global_block (); } /* See block.h. */ -const struct block * -block::function_block () const +struct global_block * +block::as_global_block () { - const block *block = this; + gdb_assert (this->is_global_block ()); - while (block != nullptr && block->function () == nullptr) - block = block->superblock (); + return static_cast<struct global_block *>(this); +} - return block; +/* See block.h. */ + +const struct global_block * +block::as_global_block () const +{ + gdb_assert (this->is_global_block ()); + + return static_cast<const struct global_block *>(this); } /* See block.h. */ -void -block::set_compunit_symtab (struct compunit_symtab *cu) +const struct block * +block::function_block () const { - struct global_block *gb; + const block *block = this; - gdb_assert (superblock () == NULL); - gb = (struct global_block *) this; - gdb_assert (gb->compunit_symtab == NULL); - gb->compunit_symtab = cu; + while (block != nullptr && block->function () == nullptr) + block = block->superblock (); + + return block; } /* See block.h. */ @@ -416,21 +422,6 @@ block::static_link () const return (struct dynamic_prop *) objfile_lookup_static_link (objfile, this); } -/* Return the compunit of the global block. */ - -static struct compunit_symtab * -get_block_compunit_symtab (const struct block *block) -{ - struct global_block *gb; - - gdb_assert (block->superblock () == NULL); - gb = (struct global_block *) block; - gdb_assert (gb->compunit_symtab != NULL); - return gb->compunit_symtab; -} - - - /* Initialize a block iterator, either to iterate over a single block, or, for static and global blocks, all the included symtabs as well. */ @@ -438,33 +429,29 @@ get_block_compunit_symtab (const struct block *block) static void initialize_block_iterator (const struct block *block, struct block_iterator *iter, - const lookup_name_info *name = nullptr) + const lookup_name_info *name) { enum block_enum which; - struct compunit_symtab *cu; iter->idx = -1; iter->name = name; - if (block->superblock () == NULL) - { - which = GLOBAL_BLOCK; - cu = get_block_compunit_symtab (block); - } - else if (block->superblock ()->superblock () == NULL) - { - which = STATIC_BLOCK; - cu = get_block_compunit_symtab (block->superblock ()); - } + if (block->is_global_block ()) + which = GLOBAL_BLOCK; + else if (block->is_static_block ()) + which = STATIC_BLOCK; else { iter->d.block = block; + /* A signal value meaning that we're iterating over a single block. */ iter->which = FIRST_LOCAL_BLOCK; return; } + compunit_symtab *cu = block->global_block ()->compunit (); + /* If this is an included symtab, find the canonical includer and use it instead. */ while (cu->user != NULL) @@ -834,3 +821,122 @@ 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 ())); + } + } +} + + + +INIT_GDB_FILE (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); +} |