diff options
Diffstat (limited to 'gdb/block.h')
-rw-r--r-- | gdb/block.h | 130 |
1 files changed, 96 insertions, 34 deletions
diff --git a/gdb/block.h b/gdb/block.h index ae676c4..76fa203 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -1,6 +1,6 @@ /* Code dealing with blocks for GDB. - Copyright (C) 2003-2024 Free Software Foundation, Inc. + Copyright (C) 2003-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -17,11 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef BLOCK_H -#define BLOCK_H +#ifndef GDB_BLOCK_H +#define GDB_BLOCK_H #include "dictionary.h" #include "gdbsupport/array-view.h" +#include "gdbsupport/next-iterator.h" /* Opaque declarations. */ @@ -177,27 +178,31 @@ struct block : public allocate_on_obstack<block> bool is_contiguous () const { return this->ranges ().size () <= 1; } - /* Return the "entry PC" of this block. + /* Return the entry-pc of this block. - The entry PC is the lowest (start) address for the block when all addresses - within the block are contiguous. If non-contiguous, then use the start - address for the first range in the block. + If the entry PC has been set to a specific value then this is + returned. Otherwise, the default_entry_pc() address is returned. */ - At the moment, this almost matches what DWARF specifies as the entry - pc. (The missing bit is support for DW_AT_entry_pc which should be - preferred over range data and the low_pc.) + CORE_ADDR entry_pc () const + { + return default_entry_pc () + m_entry_pc_offset; + } - Once support for DW_AT_entry_pc is added, I expect that an entry_pc - field will be added to one of these data structures. Once that's done, - the entry_pc field can be set from the dwarf reader (and other readers - too). ENTRY_PC can then be redefined to be less DWARF-centric. */ + /* Set this block's entry-pc to ADDR, which must lie between start() and + end(). The entry-pc is stored as the signed offset from the + default_entry_pc() address. - CORE_ADDR entry_pc () const + Note that block sub-ranges can be out of order, as such the offset of + the entry-pc might be negative. */ + + void set_entry_pc (CORE_ADDR addr) { - if (this->is_contiguous ()) - return this->start (); - else - return this->ranges ()[0].start (); + CORE_ADDR start = default_entry_pc (); + + gdb_assert (addr >= this->start () && addr < this->end ()); + gdb_assert (start >= this->start () && start < this->end ()); + + m_entry_pc_offset = addr - start; } /* Return the objfile of this block. */ @@ -227,7 +232,7 @@ struct block : public allocate_on_obstack<block> /* This returns the using directives list associated with this block, if any. */ - struct using_direct *get_using () const; + next_range<using_direct> get_using () const; /* Set this block's using member to USING; if needed, allocate memory via OBSTACK. (It won't make a copy of USING, however, so @@ -264,25 +269,26 @@ struct block : public allocate_on_obstack<block> return sup->is_global_block (); } - /* Return the static block associated with block. */ + /* Return the global block associated with block. */ - const struct block *global_block () const; + const struct global_block *global_block () const; /* Return true if this block is a global block. */ bool is_global_block () const { return superblock () == nullptr; } + /* Return this block as a global_block. This block must be a global + block. */ + struct global_block *as_global_block (); + const struct global_block *as_global_block () const; + /* Return the function block for this block. Returns nullptr if there is no enclosing function, i.e., if this block is a static or global block. */ const struct block *function_block () const; - /* Set the compunit of this block, which must be a global block. */ - - void set_compunit_symtab (struct compunit_symtab *); - /* Return a property to evaluate the static link associated to this block. @@ -307,6 +313,26 @@ struct block : public allocate_on_obstack<block> private: + /* Return the default entry-pc of this block. The default is the address + we use if the debug information hasn't specifically set a different + entry-pc value. This is the lowest address for the block when all + addresses within the block are contiguous. If non-contiguous, then + use the start address for the first range in the block. + + This almost matches what DWARF specifies as the entry pc, except that + the final case, using the first address of the first range, is a GDB + extension. However, the DWARF reader sets the specific entry-pc + wherever possible, so this non-standard fallback case is only used as + a last resort. */ + + CORE_ADDR default_entry_pc () const + { + if (this->is_contiguous ()) + return this->start (); + else + return this->ranges ()[0].start (); + } + /* If the namespace_info is NULL, allocate it via OBSTACK and initialize its members to zero. */ void initialize_namespace (struct obstack *obstack); @@ -343,16 +369,49 @@ private: startaddr and endaddr above. */ struct blockranges *m_ranges = nullptr; + + /* The offset of the actual entry-pc value from the default entry-pc + value. If space was no object then we'd store an actual address along + with a flag to indicate if the address has been set or not. But we'd + like to keep the size of block low, so we'd like to use a single + member variable. + + We would also like to avoid using 0 as a special address; some targets + do allow for accesses to address 0. + + So instead we store the offset of the defined entry-pc from the + default entry-pc. See default_entry_pc() for the definition of the + default entry-pc. See entry_pc() for how this offset is used. */ + + LONGEST m_entry_pc_offset = 0; }; /* The global block is singled out so that we can provide a back-link - to the compunit symtab. */ + to the compunit. */ struct global_block : public block { - /* This holds a pointer to the compunit symtab holding this block. */ + /* Set the compunit of this global block. + + The compunit must not have been set previously. */ + void set_compunit (compunit_symtab *cu) + { + gdb_assert (m_compunit == nullptr); + m_compunit = cu; + } + + /* Return the compunit of this global block. - struct compunit_symtab *compunit_symtab = nullptr; + The compunit must have been set previously. */ + compunit_symtab *compunit () const + { + gdb_assert (m_compunit != nullptr); + return m_compunit; + } + +private: + /* This holds a pointer to the compunit holding this block. */ + compunit_symtab *m_compunit = nullptr; }; struct blockvector @@ -394,12 +453,15 @@ struct blockvector { return m_num_blocks; } /* Return the global block of this blockvector. */ - struct block *global_block () - { return this->block (GLOBAL_BLOCK); } + struct global_block *global_block () + { return static_cast<struct global_block *> (this->block (GLOBAL_BLOCK)); } /* Const version of the above. */ - const struct block *global_block () const - { return this->block (GLOBAL_BLOCK); } + const struct global_block *global_block () const + { + return static_cast<const struct global_block *> + (this->block (GLOBAL_BLOCK)); + } /* Return the static block of this blockvector. */ struct block *static_block () @@ -592,4 +654,4 @@ extern struct symbol *block_find_symbol (const struct block *block, struct blockranges *make_blockranges (struct objfile *objfile, const std::vector<blockrange> &rangevec); -#endif /* BLOCK_H */ +#endif /* GDB_BLOCK_H */ |