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]

SEGV in dwarf2read.c -- gdb-7.2


I ran into a SEGV in in gdb-7.2 in dwarf_expr_eval() (actually one of the
functions it calls) which is called from dwarf2_evaluate_loc_desc_full().
This was caused by the per_cu->cu==NULL.

The circumstances which triggered this SEGV is printing a huge structure
(four or five pages of output) followed by a backtrace.  While printing
the struct, dwarf2_fetch_die_location_block() is called multiple times,
which calls age_cached_comp_units() which removes CU data from the cache.
When doing the backtrace, location descriptions are referenced and eventually
a NULL per_cu->cu is dereferenced.

I created the attached patch fixes the problem in gdb-7.2 by adding a new
function dwarf2_read_comp_unit_if_needed() which reloads the CU data and
adds it to the cache.  I also modified dwarf2_per_cu_addr_size() and
dwarf2_per_cu_addr_size() to use this function rather than read the CU
header into a temporary.

When I tried to apply this to the head, I discovered that these functions
had been refactored adding a function per_cu_header_read_in() which read
in the CU header into a temporary.

I can rework the patch to exclude the conflicting changes, but this raises
a question:  Is there a reason to read the CU header into a temporary data
area rather than reload it using load_full_comp_unit() which will add it to
the CU cache?

I noticed that a TRY_CATCH was added to dwarf2_evaluate_loc_desc_full()
which would catch this SEGV, but (it seems to me, incorrectly) indicate that
debug data was not available.

--
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077
diff -u gdb/dwarf2loc.c /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.c
--- gdb/dwarf2loc.c	Fri Oct 28 11:43:19 2011
+++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.c	Fri Oct 28 11:03:40 2011
@@ -919,6 +919,7 @@
   ctx->get_tls_address = dwarf_expr_tls_address;
   ctx->dwarf_call = dwarf_expr_dwarf_call;
 
+  dwarf2_read_comp_unit_if_needed (per_cu);
   dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
     {
diff -u gdb/dwarf2loc.h /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.h
--- gdb/dwarf2loc.h	Wed Nov 17 17:23:58 2010
+++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.h	Fri Oct 28 11:03:05 2011
@@ -33,6 +33,10 @@
    returned.  */
 struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu);
 
+/* Read in CU if needed.  */
+
+void dwarf2_read_comp_unit_if_needed (struct dwarf2_per_cu_data *per_cu);
+
 /* Return the address size given in the compilation unit header for CU.  */
 CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu);
 
diff -u gdb/dwarf2read.c /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2read.c
--- gdb/dwarf2read.c	Fri Oct 28 11:43:19 2011
+++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2read.c	Fri Oct 28 11:11:58 2011
@@ -12116,48 +12116,34 @@
   return objfile;
 }
 
-/* Return the address size given in the compilation unit header for CU.  */
+/* Read in CU if needed.  */
 
-CORE_ADDR
-dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
+void
+dwarf2_read_comp_unit_if_needed (struct dwarf2_per_cu_data *per_cu)
 {
-  if (per_cu->cu)
-    return per_cu->cu->header.addr_size;
-  else
+  if (!per_cu->cu)
     {
-      /* If the CU is not currently read in, we re-read its header.  */
       struct objfile *objfile = per_cu->psymtab->objfile;
-      struct dwarf2_per_objfile *per_objfile
-	= objfile_data (objfile, dwarf2_objfile_data_key);
-      gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset;
-      struct comp_unit_head cu_header;
-
-      memset (&cu_header, 0, sizeof cu_header);
-      read_comp_unit_head (&cu_header, info_ptr, objfile->obfd);
-      return cu_header.addr_size;
+      load_full_comp_unit (per_cu, objfile);
     }
 }
 
+/* Return the address size given in the compilation unit header for CU.  */
+
+CORE_ADDR
+dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
+{
+  dwarf2_read_comp_unit_if_needed (per_cu);
+  return per_cu->cu->header.addr_size;
+}
+
 /* Return the offset size given in the compilation unit header for CU.  */
 
 int
 dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu)
 {
-  if (per_cu->cu)
-    return per_cu->cu->header.offset_size;
-  else
-    {
-      /* If the CU is not currently read in, we re-read its header.  */
-      struct objfile *objfile = per_cu->psymtab->objfile;
-      struct dwarf2_per_objfile *per_objfile
-	= objfile_data (objfile, dwarf2_objfile_data_key);
-      gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset;
-      struct comp_unit_head cu_header;
-
-      memset (&cu_header, 0, sizeof cu_header);
-      read_comp_unit_head (&cu_header, info_ptr, objfile->obfd);
-      return cu_header.offset_size;
-    }
+  dwarf2_read_comp_unit_if_needed (per_cu);
+  return per_cu->cu->header.offset_size;
 }
 
 /* Return the text offset of the CU.  The returned offset comes from

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