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]

[commit] Record range information for DWARF compilation units without any


This is Debian bug #513816.  The symptom is that when debugging a
Linux kernel, we attribute most of the text section as belonging to
the first source file - even in the addrmap, which exists to solve
this problem.

We have debug info that looks like this:

  Compilation unit with no PC information
    Function in .text
    Function in .init.text

Because the CU does not have DW_AT_ranges, we fall back to putting its
low and high bounds in the addrmap; not useful when those bounds are
computed in GDB as the union of all contained functions.  We should
only do that for CUs with explicit bounds, DW_AT_high_pc and
DW_AT_low_pc.

This patch causes us to add each function to the addrmap as a
reference to the current psymtab, fixing the bug.

It does waste a bit of memory.  Functions are laid out as
"function; padding; function; padding; function" and the padding gets
an entry with value NULL in the addrmap.  I have a patch to
coalesce entries in this case, but I decided against including
it; the patch adds 1MB in addrmap usage for the Linux kernel, of which
only 220K is padding.  And the coalescing patch violates the abstract
definition of the addrmap type.  I think the usage is acceptable,
for a binary with 40MB debug info already.

Tested on x86_64-linux and checked in.

-- 
Daniel Jacobowitz
CodeSourcery

2009-02-07  Daniel Jacobowitz  <dan@codesourcery.com>

	* dwarf2read.c (dwarf2_build_psymtabs_hard): Move lowpc and highpc
	inside the loop.  Only call addrmap_set_empty if the compilation unit
	had DW_AT_high_pc and DW_AT_low_pc.  Update call to
	scan_partial_symbols.
	(scan_partial_symbols): Take NEED_PC argument and pass it along with
	LOWPC and HIGHPC.
	(add_partial_namespace): Take NEED_PC argument and pass it through.
	(add_partial_subprogram): Take NEED_PC argument.  Update the addrmap
	if necessary.

---
 gdb/dwarf2read.c |   59 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 38 insertions(+), 21 deletions(-)

Index: src/gdb/dwarf2read.c
===================================================================
--- src.orig/gdb/dwarf2read.c	2009-02-07 13:25:47.000000000 -0500
+++ src/gdb/dwarf2read.c	2009-02-07 13:26:31.000000000 -0500
@@ -763,7 +763,7 @@ static void dwarf2_build_psymtabs_hard (
 
 static void scan_partial_symbols (struct partial_die_info *,
 				  CORE_ADDR *, CORE_ADDR *,
-				  struct dwarf2_cu *);
+				  int, struct dwarf2_cu *);
 
 static void add_partial_symbol (struct partial_die_info *,
 				struct dwarf2_cu *);
@@ -772,14 +772,14 @@ static int pdi_needs_namespace (enum dwa
 
 static void add_partial_namespace (struct partial_die_info *pdi,
 				   CORE_ADDR *lowpc, CORE_ADDR *highpc,
-				   struct dwarf2_cu *cu);
+				   int need_pc, struct dwarf2_cu *cu);
 
 static void add_partial_enumeration (struct partial_die_info *enum_pdi,
 				     struct dwarf2_cu *cu);
 
 static void add_partial_subprogram (struct partial_die_info *pdi,
 				    CORE_ADDR *lowpc, CORE_ADDR *highpc,
-				    struct dwarf2_cu *cu);
+				    int need_pc, struct dwarf2_cu *cu);
 
 static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
                                      gdb_byte *info_ptr,
@@ -1486,7 +1486,7 @@ dwarf2_build_psymtabs_hard (struct objfi
   struct partial_die_info comp_unit_die;
   struct partial_symtab *pst;
   struct cleanup *back_to;
-  CORE_ADDR lowpc, highpc, baseaddr;
+  CORE_ADDR baseaddr;
 
   info_ptr = dwarf2_per_objfile->info_buffer;
 
@@ -1607,6 +1607,13 @@ dwarf2_build_psymtabs_hard (struct objfi
 				  &comp_unit_die.highpc, &cu, pst))
 	    comp_unit_die.has_pc_info = 1;
 	}
+      else if (comp_unit_die.has_pc_info
+	       && comp_unit_die.lowpc < comp_unit_die.highpc)
+	/* Store the contiguous range if it is not empty; it can be empty for
+	   CUs with no code.  */
+	addrmap_set_empty (objfile->psymtabs_addrmap,
+			   comp_unit_die.lowpc + baseaddr,
+			   comp_unit_die.highpc + baseaddr - 1, pst);
 
       /* Check if comp unit has_children.
          If so, read the rest of the partial symbols from this comp unit.
@@ -1614,13 +1621,15 @@ dwarf2_build_psymtabs_hard (struct objfi
       if (comp_unit_die.has_children)
 	{
 	  struct partial_die_info *first_die;
+	  CORE_ADDR lowpc, highpc;
 
 	  lowpc = ((CORE_ADDR) -1);
 	  highpc = ((CORE_ADDR) 0);
 
 	  first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
 
-	  scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
+	  scan_partial_symbols (first_die, &lowpc, &highpc,
+				! comp_unit_die.has_pc_info, &cu);
 
 	  /* If we didn't find a lowpc, set it to highpc to avoid
 	     complaints from `maint check'.  */
@@ -1638,12 +1647,6 @@ dwarf2_build_psymtabs_hard (struct objfi
       pst->textlow = comp_unit_die.lowpc + baseaddr;
       pst->texthigh = comp_unit_die.highpc + baseaddr;
 
-      /* Store the contiguous range; `DW_AT_ranges' range is stored above.  The
-         range can be also empty for CUs with no code.  */
-      if (!cu.has_ranges_offset && pst->textlow < pst->texthigh)
-	addrmap_set_empty (objfile->psymtabs_addrmap, pst->textlow,
-			   pst->texthigh - 1, pst);
-
       pst->n_global_syms = objfile->global_psymbols.next -
 	(objfile->global_psymbols.list + pst->globals_offset);
       pst->n_static_syms = objfile->static_psymbols.next -
@@ -1788,13 +1791,16 @@ create_all_comp_units (struct objfile *o
   dwarf2_per_objfile->n_comp_units = n_comp_units;
 }
 
-/* Process all loaded DIEs for compilation unit CU, starting at FIRST_DIE.
-   Also set *LOWPC and *HIGHPC to the lowest and highest PC values found
-   in CU.  */
+/* Process all loaded DIEs for compilation unit CU, starting at
+   FIRST_DIE.  The caller should pass NEED_PC == 1 if the compilation
+   unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
+   DW_AT_ranges).  If NEED_PC is set, then this function will set
+   *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
+   and record the covered ranges in the addrmap.  */
 
 static void
 scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
-		      CORE_ADDR *highpc, struct dwarf2_cu *cu)
+		      CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
@@ -1820,7 +1826,7 @@ scan_partial_symbols (struct partial_die
 	  switch (pdi->tag)
 	    {
 	    case DW_TAG_subprogram:
-	      add_partial_subprogram (pdi, lowpc, highpc, cu);
+	      add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
 	      break;
 	    case DW_TAG_variable:
 	    case DW_TAG_typedef:
@@ -1849,7 +1855,7 @@ scan_partial_symbols (struct partial_die
 	      add_partial_symbol (pdi, cu);
 	      break;
 	    case DW_TAG_namespace:
-	      add_partial_namespace (pdi, lowpc, highpc, cu);
+	      add_partial_namespace (pdi, lowpc, highpc, need_pc, cu);
 	      break;
 	    default:
 	      break;
@@ -2156,7 +2162,7 @@ pdi_needs_namespace (enum dwarf_tag tag)
 static void
 add_partial_namespace (struct partial_die_info *pdi,
 		       CORE_ADDR *lowpc, CORE_ADDR *highpc,
-		       struct dwarf2_cu *cu)
+		       int need_pc, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
 
@@ -2167,7 +2173,7 @@ add_partial_namespace (struct partial_di
   /* Now scan partial symbols in that namespace.  */
 
   if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
+    scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
 }
 
 /* Read a partial die corresponding to a subprogram and create a partial
@@ -2183,7 +2189,7 @@ add_partial_namespace (struct partial_di
 static void
 add_partial_subprogram (struct partial_die_info *pdi,
 			CORE_ADDR *lowpc, CORE_ADDR *highpc,
-			struct dwarf2_cu *cu)
+			int need_pc, struct dwarf2_cu *cu)
 {
   if (pdi->tag == DW_TAG_subprogram)
     {
@@ -2193,6 +2199,17 @@ add_partial_subprogram (struct partial_d
             *lowpc = pdi->lowpc;
           if (pdi->highpc > *highpc)
             *highpc = pdi->highpc;
+	  if (need_pc)
+	    {
+	      CORE_ADDR baseaddr;
+	      struct objfile *objfile = cu->objfile;
+
+	      baseaddr = ANOFFSET (objfile->section_offsets,
+				   SECT_OFF_TEXT (objfile));
+	      addrmap_set_empty (objfile->psymtabs_addrmap,
+				 pdi->lowpc, pdi->highpc - 1,
+				 cu->per_cu->psymtab);
+	    }
           if (!pdi->is_declaration)
             add_partial_symbol (pdi, cu);
         }
@@ -2209,7 +2226,7 @@ add_partial_subprogram (struct partial_d
 	  fixup_partial_die (pdi, cu);
 	  if (pdi->tag == DW_TAG_subprogram
 	      || pdi->tag == DW_TAG_lexical_block)
-	    add_partial_subprogram (pdi, lowpc, highpc, cu);
+	    add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
 	  pdi = pdi->die_sibling;
 	}
     }


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