| Index: gdb/block.c
|
| diff --git a/gdb/block.c b/gdb/block.c
|
| index 57ab4c2024469bd2ecbef285750629369d4bb076..a0f82ece83790b3b68bd0e38cd1322b793928c19 100644
|
| --- a/gdb/block.c
|
| +++ b/gdb/block.c
|
| @@ -103,50 +103,28 @@ block_inlined_p (const struct block *bl)
|
| return BLOCK_FUNCTION (bl) != NULL && SYMBOL_INLINED (BLOCK_FUNCTION (bl));
|
| }
|
|
|
| -/* Return the blockvector immediately containing the innermost lexical
|
| - block containing the specified pc value and section, or 0 if there
|
| - is none. PBLOCK is a pointer to the block. If PBLOCK is NULL, we
|
| - don't pass this information back to the caller. */
|
| +/* A helper function that checks whether PC is in the blockvector BL.
|
| + It returns the containing block if there is one, or else NULL. */
|
|
|
| -struct blockvector *
|
| -blockvector_for_pc_sect (CORE_ADDR pc, struct obj_section *section,
|
| - struct block **pblock, struct symtab *symtab)
|
| +static struct block *
|
| +find_block_in_blockvector (struct blockvector *bl, CORE_ADDR pc)
|
| {
|
| struct block *b;
|
| int bot, top, half;
|
| - struct blockvector *bl;
|
| -
|
| - if (symtab == 0) /* if no symtab specified by caller */
|
| - {
|
| - /* First search all symtabs for one whose file contains our pc */
|
| - symtab = find_pc_sect_symtab (pc, section);
|
| - if (symtab == 0)
|
| - return 0;
|
| - }
|
| -
|
| - bl = BLOCKVECTOR (symtab);
|
| -
|
| - /* Then search that symtab for the smallest block that wins. */
|
|
|
| /* If we have an addrmap mapping code addresses to blocks, then use
|
| that. */
|
| if (BLOCKVECTOR_MAP (bl))
|
| - {
|
| - b = addrmap_find (BLOCKVECTOR_MAP (bl), pc);
|
| - if (b)
|
| - {
|
| - if (pblock)
|
| - *pblock = b;
|
| - return bl;
|
| - }
|
| - else
|
| - return 0;
|
| - }
|
| -
|
| + return addrmap_find (BLOCKVECTOR_MAP (bl), pc);
|
|
|
| /* Otherwise, use binary search to find the last block that starts
|
| - before PC. */
|
| - bot = 0;
|
| + before PC.
|
| + Note: GLOBAL_BLOCK is block 0, STATIC_BLOCK is block 1.
|
| + They both have the same START,END values.
|
| + Historically this code would choose STATIC_BLOCK over GLOBAL_BLOCK but the
|
| + fact that this choice was made was subtle, now we make it explicit. */
|
| + gdb_assert (BLOCKVECTOR_NBLOCKS (bl) >= 2);
|
| + bot = STATIC_BLOCK;
|
| top = BLOCKVECTOR_NBLOCKS (bl);
|
|
|
| while (top - bot > 1)
|
| @@ -161,18 +139,55 @@ blockvector_for_pc_sect (CORE_ADDR pc, struct obj_section *section,
|
|
|
| /* Now search backward for a block that ends after PC. */
|
|
|
| - while (bot >= 0)
|
| + while (bot >= STATIC_BLOCK)
|
| {
|
| b = BLOCKVECTOR_BLOCK (bl, bot);
|
| if (BLOCK_END (b) > pc)
|
| - {
|
| - if (pblock)
|
| - *pblock = b;
|
| - return bl;
|
| - }
|
| + return b;
|
| bot--;
|
| }
|
| - return 0;
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +/* Return the blockvector immediately containing the innermost lexical
|
| + block containing the specified pc value and section, or 0 if there
|
| + is none. PBLOCK is a pointer to the block. If PBLOCK is NULL, we
|
| + don't pass this information back to the caller. */
|
| +
|
| +struct blockvector *
|
| +blockvector_for_pc_sect (CORE_ADDR pc, struct obj_section *section,
|
| + struct block **pblock, struct symtab *symtab)
|
| +{
|
| + struct blockvector *bl;
|
| + struct block *b;
|
| +
|
| + if (symtab == 0) /* if no symtab specified by caller */
|
| + {
|
| + /* First search all symtabs for one whose file contains our pc */
|
| + symtab = find_pc_sect_symtab (pc, section);
|
| + if (symtab == 0)
|
| + return 0;
|
| + }
|
| +
|
| + bl = BLOCKVECTOR (symtab);
|
| +
|
| + /* Then search that symtab for the smallest block that wins. */
|
| + b = find_block_in_blockvector (bl, pc);
|
| + if (b == NULL)
|
| + return NULL;
|
| +
|
| + if (pblock)
|
| + *pblock = b;
|
| + return bl;
|
| +}
|
| +
|
| +/* Return true if the blockvector BV contains PC, false otherwise. */
|
| +
|
| +int
|
| +blockvector_contains_pc (struct blockvector *bv, CORE_ADDR pc)
|
| +{
|
| + return find_block_in_blockvector (bv, pc) != NULL;
|
| }
|
|
|
| /* Return call_site for specified PC in GDBARCH. PC must match exactly, it
|
| @@ -369,3 +384,311 @@ allocate_block (struct obstack *obstack)
|
|
|
| return bl;
|
| }
|
| +
|
| +/* Allocate a global block. */
|
| +
|
| +struct block *
|
| +allocate_global_block (struct obstack *obstack)
|
| +{
|
| + struct global_block *bl = OBSTACK_ZALLOC (obstack, struct global_block);
|
| +
|
| + return &bl->block;
|
| +}
|
| +
|
| +/* Set the symtab of the global block. */
|
| +
|
| +void
|
| +set_block_symtab (struct block *block, struct symtab *symtab)
|
| +{
|
| + struct global_block *gb;
|
| +
|
| + gdb_assert (BLOCK_SUPERBLOCK (block) == NULL);
|
| + gb = (struct global_block *) block;
|
| + gdb_assert (gb->symtab == NULL);
|
| + gb->symtab = symtab;
|
| +}
|
| +
|
| +/* Return the symtab of the global block. */
|
| +
|
| +static struct symtab *
|
| +get_block_symtab (const struct block *block)
|
| +{
|
| + struct global_block *gb;
|
| +
|
| + gdb_assert (BLOCK_SUPERBLOCK (block) == NULL);
|
| + gb = (struct global_block *) block;
|
| + gdb_assert (gb->symtab != NULL);
|
| + return gb->symtab;
|
| +}
|
| +
|
| +
|
| +
|
| +/* Initialize a block iterator, either to iterate over a single block,
|
| + or, for static and global blocks, all the included symtabs as
|
| + well. */
|
| +
|
| +static void
|
| +initialize_block_iterator (const struct block *block,
|
| + struct block_iterator *iter)
|
| +{
|
| + enum block_enum which;
|
| + struct symtab *symtab;
|
| +
|
| + iter->idx = -1;
|
| +
|
| + if (BLOCK_SUPERBLOCK (block) == NULL)
|
| + {
|
| + which = GLOBAL_BLOCK;
|
| + symtab = get_block_symtab (block);
|
| + }
|
| + else if (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL)
|
| + {
|
| + which = STATIC_BLOCK;
|
| + symtab = get_block_symtab (BLOCK_SUPERBLOCK (block));
|
| + }
|
| + else
|
| + {
|
| + iter->d.block = block;
|
| + /* A signal value meaning that we're iterating over a single
|
| + block. */
|
| + iter->which = FIRST_LOCAL_BLOCK;
|
| + return;
|
| + }
|
| +
|
| + /* If this is an included symtab, find the canonical includer and
|
| + use it instead. */
|
| + while (symtab->user != NULL)
|
| + symtab = symtab->user;
|
| +
|
| + /* Putting this check here simplifies the logic of the iterator
|
| + functions. If there are no included symtabs, we only need to
|
| + search a single block, so we might as well just do that
|
| + directly. */
|
| + if (symtab->includes == NULL)
|
| + {
|
| + iter->d.block = block;
|
| + /* A signal value meaning that we're iterating over a single
|
| + block. */
|
| + iter->which = FIRST_LOCAL_BLOCK;
|
| + }
|
| + else
|
| + {
|
| + iter->d.symtab = symtab;
|
| + iter->which = which;
|
| + }
|
| +}
|
| +
|
| +/* A helper function that finds the current symtab over whose static
|
| + or global block we should iterate. */
|
| +
|
| +static struct symtab *
|
| +find_iterator_symtab (struct block_iterator *iterator)
|
| +{
|
| + if (iterator->idx == -1)
|
| + return iterator->d.symtab;
|
| + return iterator->d.symtab->includes[iterator->idx];
|
| +}
|
| +
|
| +/* Perform a single step for a plain block iterator, iterating across
|
| + symbol tables as needed. Returns the next symbol, or NULL when
|
| + iteration is complete. */
|
| +
|
| +static struct symbol *
|
| +block_iterator_step (struct block_iterator *iterator, int first)
|
| +{
|
| + struct symbol *sym;
|
| +
|
| + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK);
|
| +
|
| + while (1)
|
| + {
|
| + if (first)
|
| + {
|
| + struct symtab *symtab = find_iterator_symtab (iterator);
|
| + const struct block *block;
|
| +
|
| + /* Iteration is complete. */
|
| + if (symtab == NULL)
|
| + return NULL;
|
| +
|
| + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which);
|
| + sym = dict_iterator_first (BLOCK_DICT (block), &iterator->dict_iter);
|
| + }
|
| + else
|
| + sym = dict_iterator_next (&iterator->dict_iter);
|
| +
|
| + if (sym != NULL)
|
| + return sym;
|
| +
|
| + /* We have finished iterating the appropriate block of one
|
| + symtab. Now advance to the next symtab and begin iteration
|
| + there. */
|
| + ++iterator->idx;
|
| + first = 1;
|
| + }
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iterator_first (const struct block *block,
|
| + struct block_iterator *iterator)
|
| +{
|
| + initialize_block_iterator (block, iterator);
|
| +
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iterator_first (block->dict, &iterator->dict_iter);
|
| +
|
| + return block_iterator_step (iterator, 1);
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iterator_next (struct block_iterator *iterator)
|
| +{
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iterator_next (&iterator->dict_iter);
|
| +
|
| + return block_iterator_step (iterator, 0);
|
| +}
|
| +
|
| +/* Perform a single step for a "name" block iterator, iterating across
|
| + symbol tables as needed. Returns the next symbol, or NULL when
|
| + iteration is complete. */
|
| +
|
| +static struct symbol *
|
| +block_iter_name_step (struct block_iterator *iterator, const char *name,
|
| + int first)
|
| +{
|
| + struct symbol *sym;
|
| +
|
| + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK);
|
| +
|
| + while (1)
|
| + {
|
| + if (first)
|
| + {
|
| + struct symtab *symtab = find_iterator_symtab (iterator);
|
| + const struct block *block;
|
| +
|
| + /* Iteration is complete. */
|
| + if (symtab == NULL)
|
| + return NULL;
|
| +
|
| + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which);
|
| + sym = dict_iter_name_first (BLOCK_DICT (block), name,
|
| + &iterator->dict_iter);
|
| + }
|
| + else
|
| + sym = dict_iter_name_next (name, &iterator->dict_iter);
|
| +
|
| + if (sym != NULL)
|
| + return sym;
|
| +
|
| + /* We have finished iterating the appropriate block of one
|
| + symtab. Now advance to the next symtab and begin iteration
|
| + there. */
|
| + ++iterator->idx;
|
| + first = 1;
|
| + }
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iter_name_first (const struct block *block,
|
| + const char *name,
|
| + struct block_iterator *iterator)
|
| +{
|
| + initialize_block_iterator (block, iterator);
|
| +
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iter_name_first (block->dict, name, &iterator->dict_iter);
|
| +
|
| + return block_iter_name_step (iterator, name, 1);
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iter_name_next (const char *name, struct block_iterator *iterator)
|
| +{
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iter_name_next (name, &iterator->dict_iter);
|
| +
|
| + return block_iter_name_step (iterator, name, 0);
|
| +}
|
| +
|
| +/* Perform a single step for a "match" block iterator, iterating
|
| + across symbol tables as needed. Returns the next symbol, or NULL
|
| + when iteration is complete. */
|
| +
|
| +static struct symbol *
|
| +block_iter_match_step (struct block_iterator *iterator,
|
| + const char *name,
|
| + symbol_compare_ftype *compare,
|
| + int first)
|
| +{
|
| + struct symbol *sym;
|
| +
|
| + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK);
|
| +
|
| + while (1)
|
| + {
|
| + if (first)
|
| + {
|
| + struct symtab *symtab = find_iterator_symtab (iterator);
|
| + const struct block *block;
|
| +
|
| + /* Iteration is complete. */
|
| + if (symtab == NULL)
|
| + return NULL;
|
| +
|
| + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which);
|
| + sym = dict_iter_match_first (BLOCK_DICT (block), name,
|
| + compare, &iterator->dict_iter);
|
| + }
|
| + else
|
| + sym = dict_iter_match_next (name, compare, &iterator->dict_iter);
|
| +
|
| + if (sym != NULL)
|
| + return sym;
|
| +
|
| + /* We have finished iterating the appropriate block of one
|
| + symtab. Now advance to the next symtab and begin iteration
|
| + there. */
|
| + ++iterator->idx;
|
| + first = 1;
|
| + }
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iter_match_first (const struct block *block,
|
| + const char *name,
|
| + symbol_compare_ftype *compare,
|
| + struct block_iterator *iterator)
|
| +{
|
| + initialize_block_iterator (block, iterator);
|
| +
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iter_match_first (block->dict, name, compare,
|
| + &iterator->dict_iter);
|
| +
|
| + return block_iter_match_step (iterator, name, compare, 1);
|
| +}
|
| +
|
| +/* See block.h. */
|
| +
|
| +struct symbol *
|
| +block_iter_match_next (const char *name,
|
| + symbol_compare_ftype *compare,
|
| + struct block_iterator *iterator)
|
| +{
|
| + if (iterator->which == FIRST_LOCAL_BLOCK)
|
| + return dict_iter_match_next (name, compare, &iterator->dict_iter);
|
| +
|
| + return block_iter_match_step (iterator, name, compare, 0);
|
| +}
|
|
|