summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/block.c86
-rw-r--r--gdb/block.h2
-rw-r--r--gdb/dwarf2read.c29
-rw-r--r--gdb/psymtab.c3
5 files changed, 91 insertions, 40 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4ad8c9604b7..9cab34ea646 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 38b64b33aff..15037300554 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 b4f92f3eb62..99c478832e8 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 fc1a864728d..1514e1393c0 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 814023e894a..e463fff0bc8 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;
}