aboutsummaryrefslogtreecommitdiff
path: root/gdb/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/block.c')
-rw-r--r--gdb/block.c208
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);
+}