]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: add block ordering predicate for ordering blocks in 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 commit adds blockvector::block_less_than() predicate that defines
required ordering of blocks within blockvector.

It orders blocks so that blocks with lower start address come before
blocks with higher start address.  If two blocks start at the same
address, enclosing (larger) block should come before nested (smaller)
block.

This ordering is depended upon in find_block_in_blockvector(). Although
its comment did not say so, find_block_in_blockvector() is called from
blockvector_for_pc_sect() which is explicit about it. While at it, I
changed the comment of find_block_in_blockvector() to say so explicitly
too.

As Andrew pointed out, buildsym.c sorts block slightly differently,
taking only the start address into account.  The comment there says
blocks with same start address should not be reordered as they are in
correct order already and that order is needed.  It is unclear to me
if buildsym.c arranges blocks starting at the same address in required
order before sorting them or this happens "by chance".  I did modify
buildsym_compunit::make_blockvector() to assert blocks are properly
ordered and running testsuite did not show any regressions.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/block.c
gdb/block.h

index 55a1d767dd9b760190b5ce2430c76d381fab9e7b..02e6d0e4be2bab2c1b3750a2f396e4bc97b7bc5d 100644 (file)
@@ -119,7 +119,8 @@ block::inlined_p () const
 }
 
 /* A helper function that checks whether PC is in the blockvector BL.
-   It returns the containing block if there is one, or else NULL.  */
+   It returns the innermost lexical block containing the specified pc 
+   if there is one, or else NULL.  */
 
 static const struct block *
 find_block_in_blockvector (const struct blockvector *bl, CORE_ADDR pc)
@@ -811,9 +812,33 @@ make_blockranges (struct objfile *objfile,
 
 /* See block.h.  */
 
+bool
+blockvector::block_less_than (const struct block *b1, const struct block *b2)
+{
+  /* Blocks with lower start address must come before blocks with higher start
+     address.  If two blocks start at the same address,  enclosing block 
+     should come before nested blocks.  Function find_block_in_blockvector() 
+     depends on this ordering, allowing it to use binary search to find 
+     inner-most block for given address.  */
+  CORE_ADDR start1 = b1->start ();
+  CORE_ADDR start2 = b2->start ();
+
+  if (start1 != start2)
+    return start1 < start2;
+
+  return (b1->end () > b2->end ());
+}
+
+/* See block.h.  */
+
 void
 blockvector::append_block (struct block *block)
 {
+  gdb_assert ((num_blocks () == GLOBAL_BLOCK && block->is_global_block ())
+             || (num_blocks () == STATIC_BLOCK && block->is_static_block ())
+             || (num_blocks () >= FIRST_LOCAL_BLOCK
+                 && !block_less_than (block, m_blocks.back ())));
+
   m_blocks.push_back (block);
 }
 
index 0d914d82d9e0cf29ac164bdb7f2942c02323d610..61070619ca7daa7b3310a9c5cd8d6ca86c044ada 100644 (file)
@@ -490,6 +490,10 @@ struct blockvector
   void set_map (addrmap_fixed *map)
   { m_map = map; }
 
+  /* Block comparison function.  Returns true if B1 must be ordered before 
+     B2 in a blockvector, false otherwise.  */
+  static bool block_less_than (const struct block *b1, const struct block *b2);
+
   /* 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);