]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: use std::vector<> to hold on blocks in struct blockvector
authorJan Vrany <jan.vrany@labware.com>
Thu, 23 Oct 2025 11:01:34 +0000 (12:01 +0100)
committerJan Vrany <jan.vrany@labware.com>
Thu, 23 Oct 2025 11:01:34 +0000 (12:01 +0100)
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 <tom@tromey.com>
gdb/block.c
gdb/block.h
gdb/buildsym.c
gdb/buildsym.h
gdb/jit.c
gdb/mdebugread.c
gdb/symtab.c
gdb/symtab.h

index 42ace7c60cfa5d7ae8cf7d138c78c0141648c9bc..55a1d767dd9b760190b5ce2430c76d381fab9e7b 100644 (file)
@@ -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.  */
index 8a3ea822d04c61d7e2b875ae7ecc96b9c06598f0..0d914d82d9e0cf29ac164bdb7f2942c02323d610 100644 (file)
@@ -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<struct block *> blocks ()
   {
-    return gdb::array_view<struct block *> (m_blocks, m_num_blocks);
+    return gdb::array_view<struct block *> (m_blocks.data (),
+                                           m_blocks.size ());
   }
 
   /* Const version of the above.  */
   gdb::array_view<const struct block *const> blocks () const
   {
-    const struct block **blocks = (const struct block **) m_blocks;
-    return gdb::array_view<const struct block *const> (blocks, m_num_blocks);
+    const struct block **blocks = (const struct block **) m_blocks.data ();
+    return gdb::array_view<const struct block *const> (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<struct block *> m_blocks;
 };
 
 extern const struct blockvector *blockvector_for_pc (CORE_ADDR,
index af3f5f792fc6964633dd56ffb5256adf01a8f3b8..ce671716b45f85bad417179c9e5432166a19377c 100644 (file)
@@ -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<struct blockvector>
 buildsym_compunit::make_blockvector ()
 {
   struct pending_block *next;
-  struct blockvector *blockvector;
+  std::unique_ptr<struct blockvector> 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<struct blockvector> (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> 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;
index 5d4b582349a46ac66156bedd4e71781ee7583234..b568b15fad07a116bf50dbfbd60e893663f21a6b 100644 (file)
@@ -349,7 +349,7 @@ private:
                                       CORE_ADDR start, CORE_ADDR end,
                                       int is_global, int expandable);
 
-  struct blockvector *make_blockvector ();
+  std::unique_ptr<blockvector> make_blockvector ();
 
   void watch_main_source_file_lossage ();
 
index ca817e85c71375fe1bcafc5fe3d0f717db071344..ac5bf397345ab5d92dd43df16ad39116ab4f060b 100644 (file)
--- 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<blockvector> (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
index 19d7a3d3e0c62ac9c93c546b912721802ec49c8a..4927d44eb2653228a247b95e9e61c419fbf2dc99 100644 (file)
@@ -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<compunit_symtab> (objfile, name);
   struct symtab *symtab;
-  struct blockvector *bv;
+  std::unique_ptr<struct blockvector> 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<struct blockvector> (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
index 4e96503586ecc7369bf2232e90dae5d1f488bf61..fd08ca7f15ec11b5b45fc1731e5bf48c10914a40 100644 (file)
@@ -424,6 +424,16 @@ compunit_symtab::find_call_site (CORE_ADDR pc) const
 
 /* See symtab.h.  */
 
+void
+compunit_symtab::set_blockvector
+  (std::unique_ptr<struct blockvector> 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)
 {
index 3248e585badd9d3caf9ea1c48261e052deff3a07..616119d50fba16c5ccd871a55469a85b4b3522d1 100644 (file)
@@ -1895,19 +1895,17 @@ struct compunit_symtab : intrusive_list_node<compunit_symtab>
 
   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<struct blockvector> blockvector);
+  
   bool locations_valid () const
   {
     return m_locations_valid;
@@ -1994,7 +1992,7 @@ struct compunit_symtab : intrusive_list_node<compunit_symtab>
 
   /* 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<struct blockvector> 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