From 45b3bfcc906830d4feed35dbd0e2203f1886ead7 Mon Sep 17 00:00:00 2001 From: Jan Vrany Date: Thu, 23 Oct 2025 12:01:34 +0100 Subject: [PATCH] gdb: add block ordering predicate for ordering blocks in blockvector 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 --- gdb/block.c | 27 ++++++++++++++++++++++++++- gdb/block.h | 4 ++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gdb/block.c b/gdb/block.c index 55a1d767dd9..02e6d0e4be2 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -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); } diff --git a/gdb/block.h b/gdb/block.h index 0d914d82d9e..61070619ca7 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -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); -- 2.47.3