From: Jan Vrany Date: Thu, 23 Oct 2025 11:01:34 +0000 (+0100) Subject: gdb: use std::vector<> to hold on blocks in struct blockvector X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2bccd1858432b759c495369b8414881a7f89b12;p=thirdparty%2Fbinutils-gdb.git gdb: use std::vector<> to hold on blocks in struct blockvector This patch changes blockvector to be allocated on the heap (using 'new') and changes internal implementation to use std::vector<> rather than flexible array to add blocks to existing blockvector. This is needed for lazy CU expansion and for Python API to build objfiles, compunits and symtabs dynamically (similarly to JIT reader API). The downside is higher memory consumption. The size of std::vector is 24 bytes (GCC 14) compared to 8 bytes used currently to store the number of blocks (m_num_blocks). Stopping gdb at its main(), followed by "maint expand-symtabs" results in 4593 compunit symtabs so in this case the overhead is 16*4593 = 73488 bytes which I hope is acceptable. While at it, add blockvector::append_block() to add more block at the end of block vector. This is currently used only in mdebugread.c. Approved-By: Tom Tromey --- diff --git a/gdb/block.c b/gdb/block.c index 42ace7c60cf..55a1d767dd9 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -809,6 +809,14 @@ make_blockranges (struct objfile *objfile, return blr; } +/* See block.h. */ + +void +blockvector::append_block (struct block *block) +{ + m_blocks.push_back (block); +} + /* 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. */ diff --git a/gdb/block.h b/gdb/block.h index 8a3ea822d04..0d914d82d9e 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -420,41 +420,44 @@ private: struct blockvector { + explicit blockvector (int nblocks) + : m_blocks (nblocks, nullptr) + {} + /* Return a view on the blocks of this blockvector. */ gdb::array_view blocks () { - return gdb::array_view (m_blocks, m_num_blocks); + return gdb::array_view (m_blocks.data (), + m_blocks.size ()); } /* Const version of the above. */ gdb::array_view blocks () const { - const struct block **blocks = (const struct block **) m_blocks; - return gdb::array_view (blocks, m_num_blocks); + const struct block **blocks = (const struct block **) m_blocks.data (); + return gdb::array_view (blocks, + m_blocks.size ()); } /* Return the block at index I. */ struct block *block (size_t i) - { return this->blocks ()[i]; } + { return m_blocks[i]; } /* Const version of the above. */ const struct block *block (size_t i) const - { return this->blocks ()[i]; } + { return m_blocks[i]; } /* Set the block at index I. */ void set_block (int i, struct block *block) { m_blocks[i] = block; } - /* Set the number of blocks of this blockvector. - - The storage of blocks is done using a flexible array member, so the number - of blocks set here must agree with what was effectively allocated. */ + /* Set the number of blocks of this blockvector. */ void set_num_blocks (int num_blocks) - { m_num_blocks = num_blocks; } + { m_blocks.resize (num_blocks, nullptr); } /* Return the number of blocks in this blockvector. */ int num_blocks () const - { return m_num_blocks; } + { return m_blocks.size (); } /* Return the global block of this blockvector. */ struct global_block *global_block () @@ -487,17 +490,18 @@ struct blockvector void set_map (addrmap_fixed *map) { m_map = map; } + /* Append BLOCK at the end of blockvector. The caller has to make sure that + blocks are appended in correct order. */ + void append_block (struct block *block); + private: /* An address map mapping addresses to blocks in this blockvector. This pointer is zero if the blocks' start and end addresses are enough. */ - addrmap_fixed *m_map; - - /* Number of blocks in the list. */ - int m_num_blocks; + addrmap_fixed *m_map = nullptr; /* The blocks themselves. */ - struct block *m_blocks[1]; + std::vector m_blocks; }; extern const struct blockvector *blockvector_for_pc (CORE_ADDR, diff --git a/gdb/buildsym.c b/gdb/buildsym.c index af3f5f792fc..ce671716b45 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -409,11 +409,11 @@ buildsym_compunit::record_block_range (struct block *block, m_pending_addrmap.set_empty (start, end_inclusive, block); } -struct blockvector * +std::unique_ptr buildsym_compunit::make_blockvector () { struct pending_block *next; - struct blockvector *blockvector; + std::unique_ptr blockvector; int i; /* Count the length of the list of blocks. */ @@ -422,10 +422,7 @@ buildsym_compunit::make_blockvector () { } - blockvector = (struct blockvector *) - obstack_alloc (&m_objfile->objfile_obstack, - (sizeof (struct blockvector) - + (i - 1) * sizeof (struct block *))); + blockvector = std::make_unique (i); /* Copy the blocks into the blockvector. This is done in reverse order, which happens to put the blocks into the proper order @@ -831,7 +828,7 @@ buildsym_compunit::end_compunit_symtab_with_blockvector (struct block *static_block, int expandable) { struct compunit_symtab *cu = m_compunit_symtab; - struct blockvector *blockvector; + std::unique_ptr blockvector; struct subfile *subfile; CORE_ADDR end_addr; @@ -930,7 +927,6 @@ buildsym_compunit::end_compunit_symtab_with_blockvector /* Similarly for the producer. */ cu->set_producer (m_producer); - cu->set_blockvector (blockvector); blockvector->global_block ()->set_compunit (cu); cu->set_macro_table (release_macros ()); @@ -962,6 +958,8 @@ buildsym_compunit::end_compunit_symtab_with_blockvector } } + cu->set_blockvector (std::move (blockvector)); + add_compunit_symtab_to_objfile (std::move (m_owned_compunit_symtab)); return cu; diff --git a/gdb/buildsym.h b/gdb/buildsym.h index 5d4b582349a..b568b15fad0 100644 --- a/gdb/buildsym.h +++ b/gdb/buildsym.h @@ -349,7 +349,7 @@ private: CORE_ADDR start, CORE_ADDR end, int is_global, int expandable); - struct blockvector *make_blockvector (); + std::unique_ptr make_blockvector (); void watch_main_source_file_lossage (); diff --git a/gdb/jit.c b/gdb/jit.c index ca817e85c71..ac5bf397345 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -517,9 +517,7 @@ jit_symtab_close_impl (struct gdb_symbol_callbacks *cb, static void finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) { - size_t blockvector_size; CORE_ADDR begin, end; - struct blockvector *bv; int actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks; @@ -554,18 +552,12 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) filetab->set_linetable (new_table); } - blockvector_size = (sizeof (struct blockvector) - + (actual_nblocks - 1) * sizeof (struct block *)); - bv = (struct blockvector *) obstack_alloc (&objfile->objfile_obstack, - blockvector_size); - cust->set_blockvector (bv); - + auto bv = std::make_unique (actual_nblocks); + /* At the end of this function, (begin, end) will contain the PC range this entire blockvector spans. */ - bv->set_map (nullptr); begin = stab->blocks.front ().begin; end = stab->blocks.front ().end; - bv->set_num_blocks (actual_nblocks); /* First run over all the gdb_block objects, creating a real block object for each. Simultaneously, keep setting the real_block @@ -649,6 +641,9 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) gdb_block_iter.real_block->set_superblock (bv->static_block ()); } } + + /* Move just built blockvector over to CUST. */ + cust->set_blockvector (std::move (bv)); } /* Called when closing a gdb_objfile. Converts OBJ to a proper diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c index 19d7a3d3e0c..4927d44eb26 100644 --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@ -315,8 +315,6 @@ static struct compunit_symtab *new_symtab (const char *, int, struct objfile *); static struct linetable *new_linetable (int); -static struct blockvector *new_bvect (int); - static struct type *parse_type (int, union aux_ext *, unsigned int, int *, int, const char *); @@ -331,8 +329,6 @@ static legacy_psymtab *new_psymtab (const char *, psymtab_storage *, static void mdebug_expand_psymtab (legacy_psymtab *pst, struct objfile *objfile); -static void add_block (struct block *, struct symtab *); - static void add_symbol (struct symbol *, struct symtab *, struct block *); static int add_line (struct linetable *, int, CORE_ADDR, int); @@ -878,7 +874,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, b->set_start (sh->value); b->set_end (sh->value); b->set_superblock (top_stack->cur_block); - add_block (b, top_stack->cur_st); + top_stack->cur_st->compunit ()->blockvector ()->append_block (b); /* Not if we only have partial info. */ if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil) @@ -1206,7 +1202,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, b->set_start (sh->value + top_stack->procadr); b->set_superblock (top_stack->cur_block); top_stack->cur_block = b; - add_block (b, top_stack->cur_st); + top_stack->cur_st->compunit ()->blockvector ()->append_block (b); break; case stEnd: /* end (of anything) */ @@ -3669,27 +3665,6 @@ add_symbol (struct symbol *s, struct symtab *symtab, struct block *b) mdict_add_symbol (b->multidict (), s); } -/* Add a new block B to a symtab S. */ - -static void -add_block (struct block *b, struct symtab *s) -{ - /* Cast away "const", but that's ok because we're building the - symtab and blockvector here. */ - struct blockvector *bv - = (struct blockvector *) s->compunit ()->blockvector (); - - bv = (struct blockvector *) xrealloc ((void *) bv, - (sizeof (struct blockvector) - + bv->num_blocks () - * sizeof (struct block))); - if (bv != s->compunit ()->blockvector ()) - s->compunit ()->set_blockvector (bv); - - bv->set_block (bv->num_blocks (), b); - bv->set_num_blocks (bv->num_blocks () + 1); -} - /* Add a new linenumber entry (LINENO,ADR) to a linevector LT. MIPS' linenumber encoding might need more than one byte to describe it, LAST is used to detect these continuation lines. @@ -3800,7 +3775,7 @@ new_symtab (const char *name, int maxlines, struct objfile *objfile) { auto cusymtab = std::make_unique (objfile, name); struct symtab *symtab; - struct blockvector *bv; + std::unique_ptr bv; enum language lang; struct compunit_symtab *cust @@ -3811,11 +3786,11 @@ new_symtab (const char *name, int maxlines, struct objfile *objfile) lang = cust->language (); /* All symtabs must have at least two blocks. */ - bv = new_bvect (2); + bv = std::make_unique (2); bv->set_block (GLOBAL_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, lang)); bv->set_block (STATIC_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, lang)); bv->static_block ()->set_superblock (bv->global_block ()); - cust->set_blockvector (bv); + cust->set_blockvector (std::move(bv)); cust->set_debugformat ("ECOFF"); return cust; @@ -3879,21 +3854,6 @@ shrink_linetable (struct linetable *lt) * sizeof (lt->item)))); } -/* Allocate and zero a new blockvector of NBLOCKS blocks. */ - -static struct blockvector * -new_bvect (int nblocks) -{ - struct blockvector *bv; - int size; - - size = sizeof (struct blockvector) + nblocks * sizeof (struct block *); - bv = (struct blockvector *) xzalloc (size); - bv->set_num_blocks (nblocks); - - return bv; -} - /* Allocate and zero a new block of language LANGUAGE, and set its BLOCK_MULTIDICT. If function is non-zero, assume the block is associated to a function, and make sure that the symbols are stored diff --git a/gdb/symtab.c b/gdb/symtab.c index 4e96503586e..fd08ca7f15e 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -424,6 +424,16 @@ compunit_symtab::find_call_site (CORE_ADDR pc) const /* See symtab.h. */ +void +compunit_symtab::set_blockvector + (std::unique_ptr blockvector) +{ + gdb_assert (m_blockvector == nullptr); + m_blockvector = std::move (blockvector); +} + +/* See symtab.h. */ + void compunit_symtab::set_call_site_htab (call_site_htab_t &&call_site_htab) { diff --git a/gdb/symtab.h b/gdb/symtab.h index 3248e585bad..616119d50fb 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1895,19 +1895,17 @@ struct compunit_symtab : intrusive_list_node struct blockvector *blockvector () { - return m_blockvector; + return m_blockvector.get (); } const struct blockvector *blockvector () const { - return m_blockvector; - } - - void set_blockvector (struct blockvector *blockvector) - { - m_blockvector = blockvector; + return m_blockvector.get (); } + /* Set m_blockvector. */ + void set_blockvector (std::unique_ptr blockvector); + bool locations_valid () const { return m_locations_valid; @@ -1994,7 +1992,7 @@ struct compunit_symtab : intrusive_list_node /* List of all symbol scope blocks for this symtab. It is shared among all symtabs in a given compilation unit. */ - struct blockvector *m_blockvector = nullptr; + std::unique_ptr m_blockvector; /* Symtab has been compiled with both optimizations and debug info so that GDB may stop skipping prologues as variables locations are valid already