This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: psymtab expansion fix


I'm checking this in.

Testing Jason's comdat debuginfo change (origin/jason/comdat-debug in
the gcc git mirror) found a bug in the recent imported-unit changes.

With the modified GCC, we can see a CU which includes another CU; and
the included CU holds a function definition (not just declaration).

In this situation, find_pc_sect_symtab_from_partial will return the
outermost including CU -- but this CU's blockvector does not actually
contain the relevant PC.

This patch fixes the problem by changing the implementations of this
method to return the appropriate symtab instead, namely, the one whose
blockvector includes the PC.

Regression tested on x86-64 Fedora 16 with both the system GCC and the
modified one.

Tom

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.

Index: block.c
===================================================================
RCS file: /cvs/src/src/gdb/block.c,v
retrieving revision 1.30
diff -u -r1.30 block.c
--- block.c	10 May 2012 20:04:00 -0000	1.30
+++ block.c	18 May 2012 14:22:06 -0000
@@ -103,46 +103,19 @@
   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 @@
     {
       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
Index: block.h
===================================================================
RCS file: /cvs/src/src/gdb/block.h,v
retrieving revision 1.29
diff -u -r1.29 block.h
--- block.h	10 May 2012 20:04:00 -0000	1.29
+++ block.h	18 May 2012 14:22:06 -0000
@@ -152,6 +152,8 @@
 						    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);
 
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.651
diff -u -r1.651 dwarf2read.c
--- dwarf2read.c	16 May 2012 22:10:48 -0000	1.651
+++ dwarf2read.c	18 May 2012 14:22:08 -0000
@@ -2992,6 +2992,30 @@
     }
 }
 
+/* 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 @@
 			 int warn_if_readin)
 {
   struct dwarf2_per_cu_data *data;
+  struct symtab *result;
 
   dw2_setup (objfile);
 
@@ -3014,7 +3039,9 @@
     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
Index: psymtab.c
===================================================================
RCS file: /cvs/src/src/gdb/psymtab.c,v
retrieving revision 1.45
diff -u -r1.45 psymtab.c
--- psymtab.c	10 May 2012 19:54:45 -0000	1.45
+++ psymtab.c	18 May 2012 14:22:08 -0000
@@ -397,7 +397,8 @@
 	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;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]