diff options
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/block.c | 86 | ||||
-rw-r--r-- | gdb/block.h | 2 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 29 | ||||
-rw-r--r-- | gdb/psymtab.c | 3 |
5 files changed, 91 insertions, 40 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4ad8c96..9cab34e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2012-05-18 Tom Tromey <tromey@redhat.com> + + * psymtab.c (find_pc_sect_symtab_from_partial): Return the symtab + directly corresponding to the found psymtab. + * dwarf2read.c (recursively_find_pc_sect_symtab): New function. + (dw2_find_pc_sect_symtab): Use it. + * block.h (blockvector_contains_pc): Declare. + * block.c (find_block_in_blockvector): New function. + (blockvector_for_pc_sect): Use it. + (blockvector_contains_pc): New function. + 2012-05-18 Maciej W. Rozycki <macro@codesourcery.com> * mips-tdep.h (mips_write_pc): New prototype. diff --git a/gdb/block.c b/gdb/block.c index 38b64b3..1503730 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -103,46 +103,19 @@ 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. */ @@ -165,14 +138,51 @@ blockvector_for_pc_sect (CORE_ADDR pc, struct obj_section *section, { 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 diff --git a/gdb/block.h b/gdb/block.h index b4f92f3..99c4788 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -152,6 +152,8 @@ extern struct blockvector *blockvector_for_pc_sect (CORE_ADDR, struct block **, struct symtab *); +extern int blockvector_contains_pc (struct blockvector *bv, CORE_ADDR pc); + extern struct call_site *call_site_for_pc (struct gdbarch *gdbarch, CORE_ADDR pc); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index fc1a864..1514e13 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -2992,6 +2992,30 @@ dw2_expand_symtabs_matching } } +/* A helper for dw2_find_pc_sect_symtab which finds the most specific + symtab. */ + +static struct symtab * +recursively_find_pc_sect_symtab (struct symtab *symtab, CORE_ADDR pc) +{ + int i; + + if (BLOCKVECTOR (symtab) != NULL + && blockvector_contains_pc (BLOCKVECTOR (symtab), pc)) + return symtab; + + for (i = 0; symtab->includes[i]; ++i) + { + struct symtab *s; + + s = recursively_find_pc_sect_symtab (s, pc); + if (s != NULL) + return s; + } + + return NULL; +} + static struct symtab * dw2_find_pc_sect_symtab (struct objfile *objfile, struct minimal_symbol *msymbol, @@ -3000,6 +3024,7 @@ dw2_find_pc_sect_symtab (struct objfile *objfile, int warn_if_readin) { struct dwarf2_per_cu_data *data; + struct symtab *result; dw2_setup (objfile); @@ -3014,7 +3039,9 @@ dw2_find_pc_sect_symtab (struct objfile *objfile, warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"), paddress (get_objfile_arch (objfile), pc)); - return dw2_instantiate_symtab (data); + result = recursively_find_pc_sect_symtab (dw2_instantiate_symtab (data), pc); + gdb_assert (result != NULL); + return result; } static void diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 814023e..e463fff 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -397,7 +397,8 @@ find_pc_sect_symtab_from_partial (struct objfile *objfile, warning (_("\ (Internal error: pc %s in read in psymtab, but not in symtab.)\n"), paddress (get_objfile_arch (ps->objfile), pc)); - return psymtab_to_symtab (ps); + psymtab_to_symtab (ps); + return ps->symtab; } return NULL; } |