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]

[patch] dwarf2read.c: compilation unit header reading cleanups


Hi.

This patch is built on
http://sourceware.org/ml/gdb-patches/2012-01/msg00171.html
and does a few things:

1) I didn't like having a function with "partial" in its name that
had nothing to do with partial symbols, so I renamed it.
2) Applies the same kind of error checkng that (the renamed)
partial_read_comp_unit_head does to the reading of type units.
3) Simplifies create_debug_types_hash_table, it was doing its own
manual reading of the type unit header, now it just calls
read_and_check_type_unit_head.
4) Removes "abfd" as a parameter from a few functions and instead
fetches it from section->asection->owner.
[This is useful for the fission work where the debug info can come
from non-objfile files.]

I will check this in in a few days if there are no objections.

Regression tested on amd64-linux with and without .debug_types.


2012-01-05  Doug Evans  <dje@google.com>

	* dwarf2read.c (read_and_check_comp_unit_head): Renamed from
	partial_read_comp_unit_head.  Replace "buffer", "buffer_size" and
	"abfd" args with "section".  All callers updated.
	Error checking code moved ...
	(error_check_comp_unit_head): ... here.  New function.
	(read_and_check_type_unit_head): Renamed from read_type_unit_head.
	Delete arg "abfd".  New arg "type_offset".  All callers updated.
	(create_debug_types_hash_table): Simplify by using
	read_and_check_type_unit_head.

--- /g3/gnu/sourceware/dwarf-cleanup/src/gdb/dwarf2read.c	2012-01-05 19:28:02.000000000 -0800
+++ ./dwarf2read.c	2012-01-05 19:31:36.000000000 -0800
@@ -1275,12 +1275,10 @@ static void find_file_and_directory (str
 static char *file_full_name (int file, struct line_header *lh,
 			     const char *comp_dir);
 
-static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header,
-					      gdb_byte *info_ptr,
-					      gdb_byte *buffer,
-					      unsigned int buffer_size,
-					      bfd *abfd,
-					      int is_debug_types_section);
+static gdb_byte *read_and_check_comp_unit_head
+  (struct comp_unit_head *header,
+   struct dwarf2_section_info *section, gdb_byte *info_ptr,
+   int is_debug_types_section);
 
 static void init_cu_die_reader (struct die_reader_specs *reader,
 				struct dwarf2_cu *cu);
@@ -2216,10 +2214,10 @@ dw2_get_file_names (struct objfile *objf
   struct cleanup *cleanups;
   struct die_info *comp_unit_die;
   struct dwarf2_section_info* sec;
-  gdb_byte *info_ptr, *buffer;
+  gdb_byte *info_ptr;
   int has_children, i;
   struct dwarf2_cu cu;
-  unsigned int bytes_read, buffer_size;
+  unsigned int bytes_read;
   struct die_reader_specs reader_specs;
   char *name, *comp_dir;
   void **slot;
@@ -2240,17 +2238,13 @@ dw2_get_file_names (struct objfile *objf
   else
     sec = &dwarf2_per_objfile->info;
   dwarf2_read_section (objfile, sec);
-  buffer_size = sec->size;
-  buffer = sec->buffer;
-  info_ptr = buffer + this_cu->offset;
-
-  info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
-					  buffer, buffer_size,
-					  abfd,
-					  this_cu->debug_types_section != NULL);
+  info_ptr = sec->buffer + this_cu->offset;
+
+  info_ptr = read_and_check_comp_unit_head (&cu.header, sec, info_ptr,
+					    this_cu->debug_types_section != NULL);
 
   /* Skip dummy compilation units.  */
-  if (info_ptr >= buffer + buffer_size
+  if (info_ptr >= (sec->buffer + sec->size)
       || peek_abbrev_code (abfd, info_ptr) == 0)
     {
       do_cleanups (cleanups);
@@ -2954,47 +2948,66 @@ read_comp_unit_head (struct comp_unit_he
   return info_ptr;
 }
 
-/* Read in a CU header and perform some basic error checking.  */
+/* Subroutine of read_and_check_comp_unit_head and
+   read_and_check_type_unit_head to simplify them.
+   Perform various error checking on the header.  */
 
-static gdb_byte *
-partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
-			     gdb_byte *buffer, unsigned int buffer_size,
-			     bfd *abfd, int is_debug_types_section)
+static void
+error_check_comp_unit_head (struct comp_unit_head *header,
+			    struct dwarf2_section_info *section)
 {
-  gdb_byte *beg_of_comp_unit = info_ptr;
-
-  header->offset = beg_of_comp_unit - buffer;
-
-  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
-
-  /* If we're reading a type unit, skip over the signature and
-     type_offset fields.  */
-  if (is_debug_types_section)
-    info_ptr += 8 /*signature*/ + header->offset_size;
-
-  header->first_die_offset = info_ptr - beg_of_comp_unit;
+  bfd *abfd = section->asection->owner;
+  const char *filename = bfd_get_filename (abfd);
 
   if (header->version != 2 && header->version != 3 && header->version != 4)
     error (_("Dwarf Error: wrong version in compilation unit header "
 	   "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
-	   bfd_get_filename (abfd));
+	   filename);
 
   if (header->abbrev_offset
       >= dwarf2_section_size (dwarf2_per_objfile->objfile,
 			      &dwarf2_per_objfile->abbrev))
     error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
 	   "(offset 0x%lx + 6) [in module %s]"),
-	   (long) header->abbrev_offset,
-	   (long) (beg_of_comp_unit - buffer),
-	   bfd_get_filename (abfd));
+	   (long) header->abbrev_offset, (long) header->offset,
+	   filename);
 
-  if (beg_of_comp_unit + header->length + header->initial_length_size
-      > buffer + buffer_size)
+  /* Cast to unsigned long to use 64-bit arithmetic when possible to
+     avoid potential 32-bit overflow.  */
+  if (((unsigned long) header->offset
+       + header->length + header->initial_length_size)
+      > section->size)
     error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
 	   "(offset 0x%lx + 0) [in module %s]"),
-	   (long) header->length,
-	   (long) (beg_of_comp_unit - buffer),
-	   bfd_get_filename (abfd));
+	   (long) header->length, (long) header->offset,
+	   filename);
+}
+
+/* Read in a CU/TU header and perform some basic error checking.
+   The contents of the header are stored in HEADER.
+   The result is a pointer to the start of the first DIE.  */
+
+static gdb_byte *
+read_and_check_comp_unit_head (struct comp_unit_head *header,
+			       struct dwarf2_section_info *section,
+			       gdb_byte *info_ptr,
+			       int is_debug_types_section)
+{
+  gdb_byte *beg_of_comp_unit = info_ptr;
+  bfd *abfd = section->asection->owner;
+
+  header->offset = beg_of_comp_unit - section->buffer;
+
+  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+
+  /* If we're reading a type unit, skip over the signature and
+     type_offset fields.  */
+  if (is_debug_types_section)
+    info_ptr += 8 /*signature*/ + header->offset_size;
+
+  header->first_die_offset = info_ptr - beg_of_comp_unit;
+
+  error_check_comp_unit_head (header, section);
 
   return info_ptr;
 }
@@ -3003,24 +3016,32 @@ partial_read_comp_unit_head (struct comp
    types_ptr.  The result is a pointer to one past the end of the header.  */
 
 static gdb_byte *
-read_type_comp_unit_head (struct comp_unit_head *cu_header,
-			  struct dwarf2_section_info *section,
-			  ULONGEST *signature,
-			  gdb_byte *types_ptr, bfd *abfd)
+read_and_check_type_unit_head (struct comp_unit_head *header,
+			       struct dwarf2_section_info *section,
+			       gdb_byte *info_ptr,
+			       ULONGEST *signature, unsigned int *type_offset)
 {
-  gdb_byte *initial_types_ptr = types_ptr;
+  gdb_byte *beg_of_comp_unit = info_ptr;
+  bfd *abfd = section->asection->owner;
+
+  header->offset = beg_of_comp_unit - section->buffer;
 
-  dwarf2_read_section (dwarf2_per_objfile->objfile, section);
-  cu_header->offset = types_ptr - section->buffer;
+  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
 
-  types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
+  /* If we're reading a type unit, skip over the signature and
+     type_offset fields.  */
+  if (signature != NULL)
+    *signature = read_8_bytes (abfd, info_ptr);
+  info_ptr += 8;
+  if (type_offset != NULL)
+    *type_offset = read_offset_1 (abfd, info_ptr, header->offset_size);
+  info_ptr += header->offset_size;
 
-  *signature = read_8_bytes (abfd, types_ptr);
-  types_ptr += 8;
-  types_ptr += cu_header->offset_size;
-  cu_header->first_die_offset = types_ptr - initial_types_ptr;
+  header->first_die_offset = info_ptr - beg_of_comp_unit;
 
-  return types_ptr;
+  error_check_comp_unit_head (header, section);
+
+  return info_ptr;
 }
 
 /* Allocate a new partial symtab for file named NAME and mark this new
@@ -3173,46 +3194,25 @@ create_debug_types_hash_table (struct ob
       while (info_ptr < end_ptr)
 	{
 	  unsigned int offset;
-	  unsigned int offset_size;
 	  unsigned int type_offset;
-	  unsigned int length, initial_length_size;
-	  unsigned short version;
 	  ULONGEST signature;
 	  struct signatured_type *type_sig;
 	  void **slot;
 	  gdb_byte *ptr = info_ptr;
+	  struct comp_unit_head header;
 
 	  offset = ptr - section->buffer;
 
 	  /* We need to read the type's signature in order to build the hash
-	     table, but we don't need to read anything else just yet.  */
+	     table, but we don't need anything else just yet.  */
 
-	  /* Sanity check to ensure entire cu is present.  */
-	  length = read_initial_length (objfile->obfd, ptr,
-					&initial_length_size);
-	  if (ptr + length + initial_length_size > end_ptr)
-	    {
-	      complaint (&symfile_complaints,
-			 _("debug type entry runs off end "
-			   "of `.debug_types' section, ignored"));
-	      break;
-	    }
-
-	  offset_size = initial_length_size == 4 ? 4 : 8;
-	  ptr += initial_length_size;
-	  version = bfd_get_16 (objfile->obfd, ptr);
-	  ptr += 2;
-	  ptr += offset_size; /* abbrev offset */
-	  ptr += 1; /* address size */
-	  signature = bfd_get_64 (objfile->obfd, ptr);
-	  ptr += 8;
-	  type_offset = read_offset_1 (objfile->obfd, ptr, offset_size);
-	  ptr += offset_size;
+	  ptr = read_and_check_type_unit_head (&header, section, ptr,
+					       &signature, &type_offset);
 
 	  /* Skip dummy type units.  */
 	  if (ptr >= end_ptr || peek_abbrev_code (objfile->obfd, ptr) == 0)
 	    {
-	      info_ptr = info_ptr + initial_length_size + length;
+	      info_ptr = info_ptr + header.initial_length_size + header.length;
 	      continue;
 	    }
 
@@ -3243,7 +3243,7 @@ create_debug_types_hash_table (struct ob
 	    fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature 0x%s\n",
 				offset, phex (signature, sizeof (signature)));
 
-	  info_ptr = info_ptr + initial_length_size + length;
+	  info_ptr = info_ptr + header.initial_length_size + header.length;
 	}
     }
 
@@ -3377,10 +3377,8 @@ process_psymtab_comp_unit (struct dwarf2
   init_one_comp_unit (&cu, this_cu);
   back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
 
-  info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
-					  buffer, buffer_size,
-					  abfd,
-					  is_debug_types_section);
+  info_ptr = read_and_check_comp_unit_head (&cu.header, section, info_ptr,
+					    is_debug_types_section);
 
   /* Skip dummy compilation units.  */
   if (info_ptr >= buffer + buffer_size
@@ -3606,11 +3604,12 @@ load_partial_comp_unit (struct dwarf2_pe
   int has_children;
   struct die_reader_specs reader_specs;
   int read_cu = 0;
+  struct dwarf2_section_info *section = &dwarf2_per_objfile->info;
 
   gdb_assert (! this_cu->debug_types_section);
 
-  gdb_assert (dwarf2_per_objfile->info.readin);
-  info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
+  gdb_assert (section->readin);
+  info_ptr = section->buffer + this_cu->offset;
 
   if (this_cu->cu == NULL)
     {
@@ -3622,14 +3621,11 @@ load_partial_comp_unit (struct dwarf2_pe
       /* If an error occurs while loading, release our storage.  */
       free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
 
-      info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
-					      dwarf2_per_objfile->info.buffer,
-					      dwarf2_per_objfile->info.size,
-					      abfd, 0);
+      info_ptr = read_and_check_comp_unit_head (&cu->header, section, info_ptr,
+						0);
 
       /* Skip dummy compilation units.  */
-      if (info_ptr >= (dwarf2_per_objfile->info.buffer
-		       + dwarf2_per_objfile->info.size)
+      if (info_ptr >= (section->buffer + section->size)
 	  || peek_abbrev_code (abfd, info_ptr) == 0)
 	{
 	  do_cleanups (free_cu_cleanup);
@@ -3662,7 +3658,7 @@ load_partial_comp_unit (struct dwarf2_pe
      If so, read the rest of the partial symbols from this comp unit.
      If not, there's no more debug_info for this comp unit.  */
   if (has_children)
-    load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu);
+    load_partial_dies (abfd, section->buffer, info_ptr, 0, cu);
 
   do_cleanups (free_abbrevs_cleanup);
 
@@ -14341,8 +14337,8 @@ read_signatured_type (struct signatured_
   /* If an error occurs while loading, release our storage.  */
   free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
 
-  types_ptr = read_type_comp_unit_head (&cu->header, section, &signature,
-					types_ptr, objfile->obfd);
+  types_ptr = read_and_check_type_unit_head (&cu->header, section, types_ptr,
+					     &signature, NULL);
   gdb_assert (signature == type_sig->signature);
 
   cu->die_hash


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