Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] comdat types
@ 2009-06-20  0:04 Doug Evans
  2009-06-25 19:47 ` Tom Tromey
  0 siblings, 1 reply; 11+ messages in thread
From: Doug Evans @ 2009-06-20  0:04 UTC (permalink / raw)
  To: gdb-patches; +Cc: ccoutant

Hi.

This patch adds support for "comdat types" from dwarf4.
http://wiki.dwarfstd.org/index.php?title=COMDAT_Type_Sections

It requires http://sourceware.org/ml/gdb-patches/2009-06/msg00521.html.

There are no regressions on amd64 or i386 when not using -gdwarf-4.
There are a couple of failures with -gdwarf-4,
I need to revisit them with the latest gcc (the dwarf4 branch)
as they seem like gcc issues.
[specifically gdb.cp/classes.exp, and "info type foo" doesn't print the
source location though it should]

Storing each TU (type unit, a la CU for comp unit) in its own psymtab
may or may not be the right thing to do.  Psymtabs are eventually going
away, and doing it this way falls out naturally from the code so I
went with this for now.

Ok to check in?
[It's been painful continually updating this patch.
I'm kinda hoping for a relatively quick review,
though I understand this patch is not small.]

2009-06-19  Doug Evans  <dje@google.com>

	* dwarf2.h (enum dwarf_tag): Add DW_TAG_type_unit.
	(enum dwarf_form): Add DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(enum dwarf_attribute): Add DW_AT_signature, DW_AT_GNU_odr_signature.

	Add support for "comdat types" from DWARF4.
	* dwarf2read.c (dwarf2_per_objfile): New member types,
	signatured_types.
	(TYPES_SECTION): New macro.
	(dwarf2_per_cu_data): Change size of length field from 30 bits
	to 29 bits.  New member from_debug_types.
	(signatured_type): New struct.
	(struct attribute): New union member signatured_type.
	(DW_SIGNATURED_TYPE): New macro.
	(dwarf2_attr_no_follow): New function.
	(read_type_unit_scope): New function.
	(follow_die_ref_or_sig, follow_die_sig): New functions.
	(dwarf2_locate_sectoins): Handle .debug_types.
	(dwarf2_build_psymtabs): Read .debug_types.
	(read_type_comp_unit_head): New function.
	(hash_type_signature, eq_type_signature): New functions.
	(create_debug_types_hash_table): New function.
	(lookup_signatured_type): New function.
	(process_psymtab_comp_unit): Handle type units too.
	(process_type_comp_unit, build_type_psymtabs): New functions.
	(dwarf2_build_psymtabs_hard): Call build_type_psymtabs.
	(load_partial_comp_unit): Assert not called for a type unit.
	(skip_one_die): Handle DW_FORM_sig8.
	(queue_comp_unit): Don't call load_full_comp_unit here, or
	update read_in_chain.
	(psymtab_to_symtab_1): Call read_signatured_type_at_offset for
	type units, or load_full_comp_unit for comp units after
	queue_comp_unit returns.
	(load_full_comp_unit): Assert not called for type units.
	(load_full_comp_unit): Update read_in_chain here.
	(process_die): Handle DW_TAG_type_unit.
	(read_structure_type): Look for signatured types.
	(read_enumeration_type): Ditto.
	(init_cu_die_reader): Handle .debug_types.
	(read_comp_unit): Assert hash not computed yet.
	(read_die_and_children): Expand debugging printf to handle .debug_types.
	(read_partial_die): Handle DW_TAG_type_unit:
	(find_patial_die): Handle .debug_types.
	(read_attribute_value): Handle DW_FORM_sig8.
	(die_type): Call follow_die_ref_or_sig instead of follow_die_ref.
	(die_containing_type): Ditto.
	(dwarf_tag_name): Handle DW_TAG_type_unit.
	(dwarf_attr_name): Handle DW_AT_signature, DW_GNU_odr_signature.
	(dwarf_form_name): Handle DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(dump_die_shallow): Handlel DW_FORM_sig8.
	(maybe_queue_comp_unit): Change return type to int from void.
	All callers updated.
	(follow_die_ref): Handle .debug_types.
	(lookup_signatured_type_at_offset): New function.
	(read_signatured_type_at_offset): New function.
	(read_signatured_type): New function.

Index: ./include/elf/dwarf2.h
===================================================================
RCS file: /cvs/src/src/include/elf/dwarf2.h,v
retrieving revision 1.25
diff -u -p -r1.25 dwarf2.h
--- ./include/elf/dwarf2.h	24 Apr 2009 18:28:58 -0000	1.25
+++ ./include/elf/dwarf2.h	19 Jun 2009 23:48:31 -0000
@@ -190,6 +190,8 @@ enum dwarf_tag
     DW_TAG_imported_unit = 0x3d,
     DW_TAG_condition = 0x3f,
     DW_TAG_shared_type = 0x40,
+    /* DWARF 4.  */
+    DW_TAG_type_unit = 0x41,
     /* SGI/MIPS Extensions.  */
     DW_TAG_MIPS_loop = 0x4081,
     /* HP extensions.  See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz .  */
@@ -239,7 +241,12 @@ enum dwarf_form
     DW_FORM_ref4 = 0x13,
     DW_FORM_ref8 = 0x14,
     DW_FORM_ref_udata = 0x15,
-    DW_FORM_indirect = 0x16
+    DW_FORM_indirect = 0x16,
+    /* DWARF 4.  */
+    DW_FORM_sec_offset = 0x17,
+    DW_FORM_exprloc = 0x18,
+    DW_FORM_flag_present = 0x19,
+    DW_FORM_sig8 = 0x20
   };
 
 /* Attribute names and codes.  */
@@ -337,6 +344,8 @@ enum dwarf_attribute
     DW_AT_elemental     = 0x66,
     DW_AT_pure          = 0x67,
     DW_AT_recursive     = 0x68,
+    /* DWARF 4 values.  */
+    DW_AT_signature     = 0x69,
     /* SGI/MIPS extensions.  */
     DW_AT_MIPS_fde = 0x2001,
     DW_AT_MIPS_loop_begin = 0x2002,
@@ -372,6 +381,7 @@ enum dwarf_attribute
     DW_AT_body_begin = 0x2105,
     DW_AT_body_end   = 0x2106,
     DW_AT_GNU_vector = 0x2107,
+    DW_AT_GNU_odr_signature = 0x210f,
     /* VMS extensions.  */
     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
     /* UPC extension.  */
	
diff -u -p ../../dwarf-cleanup/src/gdb/dwarf2read.c ./gdb/dwarf2read.c
--- ../../dwarf-cleanup/src/gdb/dwarf2read.c	2009-06-18 19:07:07.000000000 -0700
+++ ./gdb/dwarf2read.c	2009-06-19 15:38:07.000000000 -0700
@@ -163,6 +163,7 @@ struct dwarf2_per_objfile
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info str;
   struct dwarf2_section_info ranges;
+  struct dwarf2_section_info types;
   struct dwarf2_section_info frame;
   struct dwarf2_section_info eh_frame;
 
@@ -177,6 +178,10 @@ struct dwarf2_per_objfile
      they can be freed later.  */
   struct dwarf2_per_cu_data *read_in_chain;
 
+  /* A table mapping .debug_types signatures to its signatured_type entry.
+     This is NULL if the .debug_types section hasn't been read in yet.  */
+  htab_t signatured_types;
+
   /* A flag indicating wether this objfile has a section loaded at a
      VMA of 0.  */
   int has_section_at_zero;
@@ -198,6 +203,7 @@ static struct dwarf2_per_objfile *dwarf2
 #define MACINFO_SECTION  "debug_macinfo"
 #define STR_SECTION      "debug_str"
 #define RANGES_SECTION   "debug_ranges"
+#define TYPES_SECTION    "debug_types"
 #define FRAME_SECTION    "debug_frame"
 #define EH_FRAME_SECTION "eh_frame"
 
@@ -339,13 +345,13 @@ struct dwarf2_cu
 
 struct dwarf2_per_cu_data
 {
-  /* The start offset and length of this compilation unit.  2**30-1
+  /* The start offset and length of this compilation unit.  2**29-1
      bytes should suffice to store the length of any compilation unit
      - if it doesn't, GDB will fall over anyway.
      NOTE: Unlike comp_unit_head.length, this length includes
      initial_length_size.  */
   unsigned int offset;
-  unsigned int length : 30;
+  unsigned int length : 29;
 
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
@@ -357,6 +363,10 @@ struct dwarf2_per_cu_data
      hash table and don't find it.  */
   unsigned int load_all_dies : 1;
 
+  /* Non-zero if this CU is from .debug_types.
+     Otherwise it's from .debug_info.  */
+  unsigned int from_debug_types : 1;
+
   /* Set iff currently read in.  */
   struct dwarf2_cu *cu;
 
@@ -372,6 +382,22 @@ struct dwarf2_per_cu_data
   struct partial_symtab *psymtab;
 };
 
+/* Entry in the signatured_types hash table.  */
+
+struct signatured_type
+{
+  ULONGEST signature;
+
+  /* Offset in .debug_types of the TU (type_unit) for this type.  */
+  unsigned int offset;
+
+  /* Offset in .debug_types of the type defined by this TU.  */
+  unsigned int type_offset;
+
+  /* The CU(/TU) of this type.  */
+  struct dwarf2_per_cu_data per_cu;
+};
+
 /* Struct used to pass misc. parameters to read_die_and_children, et. al.
    which are used for both .debug_info and .debug_types dies.
    All parameters here are unchanging for the life of the call.
@@ -540,6 +566,7 @@ struct attribute
 	unsigned long unsnd;
 	long int snd;
 	CORE_ADDR addr;
+	struct signatured_type *signatured_type;
       }
     u;
   };
@@ -589,6 +616,7 @@ struct function_range
 #define DW_BLOCK(attr)     ((attr)->u.blk)
 #define DW_SND(attr)       ((attr)->u.snd)
 #define DW_ADDR(attr)	   ((attr)->u.addr)
+#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type)
 
 /* Blocks are a bunch of untyped bytes. */
 struct dwarf_block
@@ -873,6 +901,10 @@ static void set_cu_language (unsigned in
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
 				      struct dwarf2_cu *);
 
+static struct attribute *dwarf2_attr_no_follow (struct die_info *,
+						unsigned int,
+						struct dwarf2_cu *);
+
 static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
                                struct dwarf2_cu *cu);
 
@@ -923,6 +955,8 @@ static char *typename_concat (struct obs
 
 static void read_file_scope (struct die_info *, struct dwarf2_cu *);
 
+static void read_type_unit_scope (struct die_info *, struct dwarf2_cu *);
+
 static void read_func_scope (struct die_info *, struct dwarf2_cu *);
 
 static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
@@ -1043,10 +1077,24 @@ static unsigned int dwarf2_get_ref_die_o
 
 static int dwarf2_get_attr_constant_value (struct attribute *, int);
 
+static struct die_info *follow_die_ref_or_sig (struct die_info *,
+					       struct attribute *,
+					       struct dwarf2_cu **);
+
 static struct die_info *follow_die_ref (struct die_info *,
 					struct attribute *,
 					struct dwarf2_cu **);
 
+static struct die_info *follow_die_sig (struct die_info *,
+					struct attribute *,
+					struct dwarf2_cu **);
+
+static void read_signatured_type_at_offset (struct objfile *objfile,
+					    unsigned int offset);
+
+static void read_signatured_type (struct objfile *,
+				  struct signatured_type *type_sig);
+
 /* memory allocation interface */
 
 static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
@@ -1214,6 +1262,11 @@ dwarf2_locate_sections (bfd *abfd, asect
       dwarf2_per_objfile->ranges.asection = sectp;
       dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, TYPES_SECTION))
+    {
+      dwarf2_per_objfile->types.asection = sectp;
+      dwarf2_per_objfile->types.size = bfd_get_section_size (sectp);
+    }
 
   if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
       && bfd_section_vma (abfd, sectp) == 0)
@@ -1413,6 +1466,7 @@ dwarf2_build_psymtabs (struct objfile *o
   dwarf2_read_section (objfile, &dwarf2_per_objfile->str);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->macinfo);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->loc);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->frame);
@@ -1551,6 +1605,29 @@ partial_read_comp_unit_head (struct comp
   return info_ptr;
 }
 
+/* Read in the types comp unit header information from .debug_types entry at
+   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,
+			  ULONGEST *signature,
+			  gdb_byte *types_ptr, bfd *abfd)
+{
+  unsigned int bytes_read;
+  gdb_byte *initial_types_ptr = types_ptr;
+
+  cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer;
+
+  types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
+
+  *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;
+
+  return types_ptr;
+}
+
 /* Allocate a new partial symtab for file named NAME and mark this new
    partial symtab as being an include of PST.  */
 
@@ -1610,9 +1687,137 @@ dwarf2_build_include_psymtabs (struct dw
   free_line_header (lh);
 }
 
-/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+static hashval_t
+hash_type_signature (const void *item)
+{
+  const struct signatured_type *type_sig = item;
+  /* This drops the top 32 bits of the signature, but is ok for a hash.  */
+  return type_sig->signature;
+}
+
+static int
+eq_type_signature (const void *item_lhs, const void *item_rhs)
+{
+  const struct signatured_type *lhs = item_lhs;
+  const struct signatured_type *rhs = item_rhs;
+  return lhs->signature == rhs->signature;
+}
+
+/* Create the hash table of all entries in the .debug_types section.
+   The result is zero if there is an error (e.g. missing .debug_types section),
+   otherwise non-zero.	*/
+
+static int
+create_debug_types_hash_table (struct objfile *objfile)
+{
+  gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer;
+  htab_t types_htab;
+
+  if (info_ptr == NULL)
+    {
+      dwarf2_per_objfile->signatured_types = NULL;
+      return 0;
+    }
+
+  types_htab = htab_create_alloc_ex (41,
+				     hash_type_signature,
+				     eq_type_signature,
+				     NULL,
+				     &objfile->objfile_obstack,
+				     hashtab_obstack_allocate,
+				     dummy_obstack_deallocate);
+
+  if (dwarf2_die_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
+    }
+
+  while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+    {
+      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;
+
+      offset = ptr - dwarf2_per_objfile->types.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.  */
+
+      /* Sanity check to ensure entire cu is present.  */
+      length = read_initial_length (objfile->obfd, ptr, &initial_length_size);
+      if (ptr + length + initial_length_size
+	  > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+	{
+	  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);
+
+      type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
+      memset (type_sig, 0, sizeof (*type_sig));
+      type_sig->signature = signature;
+      type_sig->offset = offset;
+      type_sig->type_offset = type_offset;
+
+      slot = htab_find_slot (types_htab, type_sig, INSERT);
+      gdb_assert (slot != NULL);
+      *slot = type_sig;
+
+      if (dwarf2_die_debug)
+	{
+	  fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature 0x%s\n",
+			      offset, phex (signature, sizeof (signature)));
+	}
+
+      info_ptr = info_ptr + initial_length_size + length;
+    }
+
+  dwarf2_per_objfile->signatured_types = types_htab;
+
+  return 1;
+}
+
+/* Lookup a signature based type.
+   Returns NULL if SIG is not present in the table.  */
+
+static struct signatured_type *
+lookup_signatured_type (struct objfile *objfile, ULONGEST sig)
+{
+  struct signatured_type find_entry, *entry;
+
+  if (dwarf2_per_objfile->signatured_types == NULL)
+    {
+      complaint (&symfile_complaints,
+		 _("missing `.debug_types' section for DW_FORM_sig8 die"));
+      return 0;
+    }
+
+  find_entry.signature = sig;
+  entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+  return entry;
+}
+
+/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard
+   to combine the common parts.
    Process a compilation unit for a psymtab.
-   BUFFER is a pointer to the beginning of the dwarf section buffer.
+   BUFFER is a pointer to the beginning of the dwarf section buffer,
+   either .debug_info or debug_types.
    INFO_PTR is a pointer to the start of the CU.
    Returns a pointer to the next CU.  */
 
@@ -1653,11 +1858,19 @@ process_psymtab_comp_unit (struct objfil
   make_cleanup (dwarf2_free_abbrev_table, &cu);
 
   /* Read the compilation unit die.  */
+  if (this_cu->from_debug_types)
+    info_ptr += 8 /*signature*/ + cu.header.offset_size;
   abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
   info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd,
 			       buffer, info_ptr, &cu);
 
-  if (comp_unit_die.tag == DW_TAG_partial_unit)
+  if (this_cu->from_debug_types)
+    {
+      /* ??? How come this is for .debug_types only?  */
+      this_cu->offset = cu.header.offset;
+      this_cu->length = cu.header.length + cu.header.initial_length_size;
+    }
+  else if (comp_unit_die.tag == DW_TAG_partial_unit)
     {
       info_ptr = (beg_of_comp_unit + cu.header.length
 		  + cu.header.initial_length_size);
@@ -1708,7 +1921,8 @@ process_psymtab_comp_unit (struct objfil
   this_cu->psymtab = pst;
 
   /* Possibly set the default values of LOWPC and HIGHPC from
-     `DW_AT_ranges'.  */
+     `DW_AT_ranges'.
+     ??? Is this valid for .debug_types?  */
   if (cu.has_ranges_offset)
     {
       if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc,
@@ -1764,12 +1978,18 @@ process_psymtab_comp_unit (struct objfil
   /* If there is already a psymtab or symtab for a file of this
      name, remove it. (If there is a symtab, more drastic things
      also happen.) This happens in VxWorks.  */
-  free_named_symtabs (pst->filename);
+  if (! this_cu->from_debug_types)
+    free_named_symtabs (pst->filename);
 
   info_ptr = (beg_of_comp_unit + cu.header.length
 	      + cu.header.initial_length_size);
 
-  if (comp_unit_die.has_stmt_list)
+  if (this_cu->from_debug_types)
+    {
+      /* ??? It's not clear we want to do anything with stmt lists here.
+	 Waiting to see what gcc ultimately does.  */
+    }
+  else if (comp_unit_die.has_stmt_list)
     {
       /* Get the list of files included in the current compilation unit,
 	 and build a psymtab for each of them.  */
@@ -1781,6 +2001,40 @@ process_psymtab_comp_unit (struct objfil
   return info_ptr;
 }
 
+/* Traversal function for htab_traverse_noresize.
+   Process one .debug_types comp-unit.	*/
+
+static int
+process_type_comp_unit (void **slot, void *info)
+{
+  struct signatured_type *entry = (struct signatured_type *) *slot;
+  struct objfile *objfile = (struct objfile *) info;
+  struct dwarf2_per_cu_data *this_cu;
+
+  this_cu = &entry->per_cu;
+  this_cu->from_debug_types = 1;
+
+  process_psymtab_comp_unit (objfile, this_cu,
+			     dwarf2_per_objfile->types.buffer,
+			     dwarf2_per_objfile->types.buffer + entry->offset,
+			     dwarf2_per_objfile->types.size);
+
+  return 1;
+}
+
+/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+   Build partial symbol tables for the .debug_types comp-units.  */
+
+static void
+build_type_psymtabs (struct objfile *objfile)
+{
+  if (! create_debug_types_hash_table (objfile))
+    return;
+
+  htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+			  process_type_comp_unit, objfile);
+}
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -1799,6 +2053,8 @@ dwarf2_build_psymtabs_hard (struct objfi
      read_in_chain.  Make sure to free them when we're done.  */
   back_to = make_cleanup (free_cached_comp_units, NULL);
 
+  build_type_psymtabs (objfile);
+
   create_all_comp_units (objfile);
 
   objfile->psymtabs_addrmap =
@@ -1852,6 +2108,8 @@ load_partial_comp_unit (struct dwarf2_pe
   unsigned int bytes_read;
   struct cleanup *back_to;
 
+  gdb_assert (! this_cu->from_debug_types);
+
   info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
   beg_of_comp_unit = info_ptr;
 
@@ -2592,6 +2850,7 @@ skip_one_die (gdb_byte *buffer, gdb_byte
 	  break;
 	case DW_FORM_data8:
 	case DW_FORM_ref8:
+	case DW_FORM_sig8:
 	  info_ptr += 8;
 	  break;
 	case DW_FORM_string:
@@ -2727,12 +2986,6 @@ queue_comp_unit (struct dwarf2_per_cu_da
     dwarf2_queue_tail->next = item;
 
   dwarf2_queue_tail = item;
-
-  /* Either PER_CU is the CU we want to process, or we're following a reference
-     pointing into PER_CU.  Either way, we need its DIEs now.  */
-  load_full_comp_unit (item->per_cu, objfile);
-  item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
-  dwarf2_per_objfile->read_in_chain = item->per_cu;
 }
 
 /* Process the queue.  */
@@ -2827,6 +3080,11 @@ psymtab_to_symtab_1 (struct partial_symt
 
   queue_comp_unit (per_cu, pst->objfile);
 
+  if (per_cu->from_debug_types)
+    read_signatured_type_at_offset (pst->objfile, per_cu->offset);
+  else
+    load_full_comp_unit (per_cu, pst->objfile);
+
   process_queue (pst->objfile);
 
   /* Age the cache, releasing compilation units that have not
@@ -2849,6 +3107,8 @@ load_full_comp_unit (struct dwarf2_per_c
   struct attribute *attr;
   CORE_ADDR baseaddr;
 
+  gdb_assert (! per_cu->from_debug_types);
+
   /* Set local variables from the partial symbol table info.  */
   offset = per_cu->offset;
 
@@ -2888,6 +3148,10 @@ load_full_comp_unit (struct dwarf2_per_c
   else
     set_cu_language (language_minimal, cu);
 
+  /* Link this CU into read_in_chain.  */
+  per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+  dwarf2_per_objfile->read_in_chain = per_cu;
+
   do_cleanups (back_to);
 
   /* We've successfully allocated this compilation unit.  Let our caller
@@ -2979,6 +3243,9 @@ process_die (struct die_info *die, struc
     case DW_TAG_compile_unit:
       read_file_scope (die, cu);
       break;
+    case DW_TAG_type_unit:
+      read_type_unit_scope (die, cu);
+      break;
     case DW_TAG_subprogram:
       read_func_scope (die, cu);
       break;
@@ -3222,6 +3489,91 @@ read_file_scope (struct die_info *die, s
   do_cleanups (back_to);
 }
 
+/* For TUs we want to skip the first top level sibling if it's not the
+   actual type being defined by this TU.  In this case the first top
+   level sibling is there to provide context only.  */
+
+static void
+read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+  CORE_ADDR lowpc;
+  struct attribute *attr;
+  char *name = NULL;
+  char *comp_dir = NULL;
+  struct die_info *child_die;
+  bfd *abfd = objfile->obfd;
+  struct line_header *line_header = 0;
+
+  /* start_symtab needs a low pc, but we don't really have one.
+     Do what read_file_scope would do in the absence of such info.  */
+  lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  /* Find the filename.  Do not use dwarf2_name here, since the filename
+     is not a source language identifier.  */
+  attr = dwarf2_attr (die, DW_AT_name, cu);
+  if (attr)
+    {
+      name = DW_STRING (attr);
+    }
+
+  attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
+  if (attr)
+    {
+      comp_dir = DW_STRING (attr);
+    }
+  else if (name != NULL && IS_ABSOLUTE_PATH (name))
+    {
+      comp_dir = ldirname (name);
+      if (comp_dir != NULL)
+	make_cleanup (xfree, comp_dir);
+    }
+
+  if (name == NULL)
+    name = "<unknown>";
+
+  attr = dwarf2_attr (die, DW_AT_language, cu);
+  if (attr)
+    {
+      set_cu_language (DW_UNSND (attr), cu);
+    }
+
+  /* This isn't technically needed today.  It is done for symmetry
+     with read_file_scope.  */
+  attr = dwarf2_attr (die, DW_AT_producer, cu);
+  if (attr) 
+    cu->producer = DW_STRING (attr);
+
+  /* We assume that we're processing GCC output. */
+  processing_gcc_compilation = 2;
+
+  processing_has_namespace_info = 0;
+
+  start_symtab (name, comp_dir, lowpc);
+  record_debugformat ("DWARF 2");
+  record_producer (cu->producer);
+
+  /* Process the dies in the type unit.  */
+  if (die->child == NULL)
+    {
+      dump_die_for_error (die);
+      error (_("Dwarf Error: Missing children for type unit [in module %s]"),
+	     bfd_get_filename (abfd));
+    }
+
+  child_die = die->child;
+
+  while (child_die && child_die->tag)
+    {
+      process_die (child_die, cu);
+
+      child_die = sibling_die (child_die);
+    }
+
+  do_cleanups (back_to);
+}
+
 static void
 add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
 		     struct dwarf2_cu *cu)
@@ -4414,6 +4766,22 @@ read_structure_type (struct die_info *di
   if (type)
     return type;
 
+  /* If the definition of this type lives in .debug_types, read that type.
+     Don't follow DW_AT_specification though, that will take us back up
+     the chain and we want to go down.  */
+  attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+  if (attr)
+    {
+      struct dwarf2_cu *type_cu = cu;
+      struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+      /* We could just recurse on read_structure_type, but we need to call
+	 get_die_type to ensure only one type for this DIE is created.
+	 This is important, for example, because for c++ classes we need
+	 TYPE_NAME set which is only done by new_symbol.  Blech.  */
+      type = read_type_die (type_die, type_cu);
+      return set_die_type (die, type, cu);
+    }
+
   type = alloc_type (objfile);
   INIT_CPLUS_SPECIFIC (type);
 
@@ -4628,6 +4996,18 @@ read_enumeration_type (struct die_info *
   struct attribute *attr;
   const char *name;
 
+  /* If the definition of this type lives in .debug_types, read that type.
+     Don't follow DW_AT_specification though, that will take us back up
+     the chain and we want to go down.  */
+  attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+  if (attr)
+    {
+      struct dwarf2_cu *type_cu = cu;
+      struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+      type = read_type_die (type_die, type_cu);
+      return set_die_type (die, type, cu);
+    }
+
   type = alloc_type (objfile);
 
   TYPE_CODE (type) = TYPE_CODE_ENUM;
@@ -5549,7 +5929,10 @@ init_cu_die_reader (struct die_reader_sp
 {
   reader->abfd = cu->objfile->obfd;
   reader->cu = cu;
-  reader->buffer = dwarf2_per_objfile->info.buffer;
+  if (cu->per_cu->from_debug_types)
+    reader->buffer = dwarf2_per_objfile->types.buffer;
+  else
+    reader->buffer = dwarf2_per_objfile->info.buffer;
 }
 
 /* Read a whole compilation unit into a linked list of dies.  */
@@ -5559,6 +5942,7 @@ read_comp_unit (gdb_byte *info_ptr, stru
 {
   struct die_reader_specs reader_specs;
 
+  gdb_assert (cu->die_hash == NULL);
   cu->die_hash
     = htab_create_alloc_ex (cu->header.length / 12,
 			    die_hash,
@@ -5587,7 +5971,14 @@ read_die_and_children (const struct die_
 
   if (dwarf2_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog, "Read die from .debug_info:\n");
+      fprintf_unfiltered (gdb_stdlog,
+			  "\nRead die from %s of %s:\n",
+			  reader->buffer == dwarf2_per_objfile->info.buffer
+			  ? ".debug_info"
+			  : reader->buffer == dwarf2_per_objfile->types.buffer
+			  ? ".debug_types"
+			  : "unknown section",
+			  reader->abfd->filename);
       dump_die (result, dwarf2_die_debug);
     }
 
@@ -6157,6 +6548,7 @@ read_partial_die (struct partial_die_inf
 	  switch (part_die->tag)
 	    {
 	    case DW_TAG_compile_unit:
+	    case DW_TAG_type_unit:
 	      /* Compilation units have a DW_AT_name that is a filename, not
 		 a source language identifier.  */
 	    case DW_TAG_enumeration_type:
@@ -6319,7 +6711,10 @@ find_partial_die_in_comp_unit (unsigned 
   return lookup_die;
 }
 
-/* Find a partial DIE at OFFSET, which may or may not be in CU.  */
+/* Find a partial DIE at OFFSET, which may or may not be in CU,
+   except in the case of .debug_types DIEs which do not reference
+   outside their CU (they do however referencing other types via
+   DW_FORM_sig8).  */
 
 static struct partial_die_info *
 find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
@@ -6327,6 +6722,14 @@ find_partial_die (unsigned int offset, s
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
 
+  if (cu->per_cu->from_debug_types)
+    {
+      pd = find_partial_die_in_comp_unit (offset, cu);
+      if (pd != NULL)
+	return pd;
+      goto NotFound;
+    }
+
   if (offset_in_cu_p (&cu->header, offset))
     {
       pd = find_partial_die_in_comp_unit (offset, cu);
@@ -6380,6 +6783,8 @@ find_partial_die (unsigned int offset, s
       pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
     }
 
+ NotFound:
+
   if (pd == NULL)
     internal_error (__FILE__, __LINE__,
 		    _("could not find partial DIE 0x%x in cache [from module %s]\n"),
@@ -6533,6 +6938,14 @@ read_attribute_value (struct attribute *
       DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
+    case DW_FORM_sig8:
+      /* Convert the signature to something we can record in DW_UNSND
+	 for later lookup.
+         NOTE: This is NULL if the type wasn't found.  */
+      DW_SIGNATURED_TYPE (attr) =
+	lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr));
+      info_ptr += 8;
+      break;
     case DW_FORM_ref_udata:
       DW_ADDR (attr) = (cu->header.offset
 			+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
@@ -6995,6 +7408,27 @@ dwarf2_attr (struct die_info *die, unsig
   return NULL;
 }
 
+/* Return the named attribute or NULL if not there,
+   but do not follow DW_AT_specification, etc.
+   This is for use in contexts where we're reading .debug_types dies.
+   Following DW_AT_specification, DW_AT_abstract_origin will take us
+   back up the chain, and we want to go down.  */
+
+static struct attribute *
+dwarf2_attr_no_follow (struct die_info *die, unsigned int name,
+		       struct dwarf2_cu *cu)
+{
+  unsigned int i;
+
+  for (i = 0; i < die->num_attrs; ++i)
+    {
+      if (die->attrs[i].name == name)
+	return &die->attrs[i];
+    }
+
+  return NULL;
+}
+
 /* Return non-zero iff the attribute NAME is defined for the given DIE,
    and holds a non-zero value.  This function should only be used for
    DW_FORM_flag attributes.  */
@@ -8125,8 +8559,8 @@ die_type (struct die_info *die, struct d
       /* A missing DW_AT_type represents a void type.  */
       return builtin_type (gdbarch)->builtin_void;
     }
-  else
-    type_die = follow_die_ref (die, type_attr, &cu);
+
+  type_die = follow_die_ref_or_sig (die, type_attr, &cu);
 
   type = tag_type_to_type (type_die, cu);
   if (!type)
@@ -8151,7 +8585,7 @@ die_containing_type (struct die_info *di
   type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
   if (type_attr)
     {
-      type_die = follow_die_ref (die, type_attr, &cu);
+      type_die = follow_die_ref_or_sig (die, type_attr, &cu);
       type = tag_type_to_type (type_die, cu);
     }
   if (!type)
@@ -8589,6 +9023,8 @@ dwarf_tag_name (unsigned tag)
       return "DW_TAG_condition";
     case DW_TAG_shared_type:
       return "DW_TAG_shared_type";
+    case DW_TAG_type_unit:
+      return "DW_TAG_type_unit";
     case DW_TAG_MIPS_loop:
       return "DW_TAG_MIPS_loop";
     case DW_TAG_HP_array_descriptor:
@@ -8804,6 +9240,9 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_pure";
     case DW_AT_recursive:
       return "DW_AT_recursive";
+    /* DWARF 4 values.  */
+    case DW_AT_signature:
+      return "DW_AT_signature";
     /* SGI/MIPS extensions.  */
 #ifdef MIPS /* collides with DW_AT_HP_block_index */
     case DW_AT_MIPS_fde:
@@ -8875,6 +9314,8 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_body_end";
     case DW_AT_GNU_vector:
       return "DW_AT_GNU_vector";
+    case DW_AT_GNU_odr_signature:
+      return "DW_AT_GNU_odr_signature";
     /* VMS extensions.  */
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
@@ -8942,6 +9383,14 @@ dwarf_form_name (unsigned form)
       return "DW_FORM_ref_udata";
     case DW_FORM_indirect:
       return "DW_FORM_indirect";
+    case DW_FORM_sec_offset:
+      return "DW_FORM_sec_offset";
+    case DW_FORM_exprloc:
+      return "DW_FORM_exprloc";
+    case DW_FORM_flag_present:
+      return "DW_FORM_flag_present";
+    case DW_FORM_sig8:
+      return "DW_FORM_sig8";
     case GDB_FORM_cached_string:
       return "GDB_FORM_cached_string";
     default:
@@ -9487,6 +9936,13 @@ dump_die_shallow (struct ui_file *f, int
 	case DW_FORM_sdata:
 	  fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i]));
 	  break;
+	case DW_FORM_sig8:
+	  if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
+	    fprintf_unfiltered (f, "signatured type, offset: 0x%x",
+				DW_SIGNATURED_TYPE (&die->attrs[i])->offset);
+	  else
+	    fprintf_unfiltered (f, "signatured type, offset: unknown");
+	  break;
 	case DW_FORM_string:
 	case DW_FORM_strp:
 	case GDB_FORM_cached_string:
@@ -9624,9 +10080,11 @@ dwarf2_get_attr_constant_value (struct a
 }
 
 /* THIS_CU has a reference to PER_CU.  If necessary, load the new compilation
-   unit and add it to our queue.  */
+   unit and add it to our queue.
+   The result is non-zero if PER_CU was queued, otherwise the result is zero
+   meaning either PER_CU is already queued or it is already loaded.  */
 
-static void
+static int
 maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
 		       struct dwarf2_per_cu_data *per_cu)
 {
@@ -9636,18 +10094,48 @@ maybe_queue_comp_unit (struct dwarf2_cu 
 
   /* If it's already on the queue, we have nothing to do.  */
   if (per_cu->queued)
-    return;
+    return 0;
 
   /* If the compilation unit is already loaded, just mark it as
      used.  */
   if (per_cu->cu != NULL)
     {
       per_cu->cu->last_used = 0;
-      return;
+      return 0;
     }
 
   /* Add it to the queue.  */
   queue_comp_unit (per_cu, this_cu->objfile);
+
+  return 1;
+}
+
+/* Follow reference or signature attribute ATTR of SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
+
+static struct die_info *
+follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
+		       struct dwarf2_cu **ref_cu)
+{
+  struct die_info *die;
+
+  if (is_ref_attr (attr))
+    {
+      die = follow_die_ref (src_die, attr, ref_cu);
+    }
+  else if (attr->form == DW_FORM_sig8)
+    {
+      die = follow_die_sig (src_die, attr, ref_cu);
+    }
+  else
+    {
+      dump_die_for_error (src_die);
+      error (_("Dwarf Error: Expected reference attribute [in module %s]"),
+	     (*ref_cu)->objfile->name);
+    }
+
+  return die;
 }
 
 /* Follow reference attribute ATTR of SRC_DIE.
@@ -9663,15 +10151,27 @@ follow_die_ref (struct die_info *src_die
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
 
+  gdb_assert (cu->per_cu != NULL);
+
   offset = dwarf2_get_ref_die_offset (attr);
 
-  if (! offset_in_cu_p (&cu->header, offset))
+  if (cu->per_cu->from_debug_types)
+    {
+      /* .debug_types CUs cannot reference anything outside their CU.
+	 If they need to, they have to reference a signatured type via
+	 DW_FORM_sig8.  */
+      if (! offset_in_cu_p (&cu->header, offset))
+	goto NotFound;
+      target_cu = cu;
+    }
+  else if (! offset_in_cu_p (&cu->header, offset))
     {
       struct dwarf2_per_cu_data *per_cu;
       per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
-      maybe_queue_comp_unit (cu, per_cu);
+      if (maybe_queue_comp_unit (cu, per_cu))
+	load_full_comp_unit (per_cu, cu->objfile);
 
       target_cu = per_cu->cu;
     }
@@ -9684,9 +10184,164 @@ follow_die_ref (struct die_info *src_die
   if (die)
     return die;
 
-  error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
-	 "at 0x%lx [in module %s]"),
-	 (long) offset, (long) src_die->offset, cu->objfile->name);
+ NotFound:
+
+  error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
+	 "at 0x%x [in module %s]"),
+	 offset, src_die->offset, cu->objfile->name);
+}
+
+/* Follow the signature attribute ATTR in SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
+
+static struct die_info *
+follow_die_sig (struct die_info *src_die, struct attribute *attr,
+		struct dwarf2_cu **ref_cu)
+{
+  struct objfile *objfile = (*ref_cu)->objfile;
+  struct die_info temp_die;
+  struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
+  struct dwarf2_cu *sig_cu;
+  struct die_info *die;
+
+  /* sig_type will be NULL if the signatured type is missing from
+     the debug info.  */
+  if (sig_type == NULL)
+    error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
+	     "at 0x%x [in module %s]"),
+	   src_die->offset, objfile->name);
+
+  /* If necessary, add it to the queue and load its DIEs.  */
+
+  if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
+    read_signatured_type (objfile, sig_type);
+
+  gdb_assert (sig_type->per_cu.cu != NULL);
+
+  sig_cu = sig_type->per_cu.cu;
+  temp_die.offset = sig_cu->header.offset + sig_type->type_offset;
+  die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset);
+  if (die)
+    {
+      *ref_cu = sig_cu;
+      return die;
+    }
+
+  error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE "
+	 "at 0x%x [in module %s]"),
+	 sig_type->type_offset, src_die->offset, objfile->name);
+}
+
+/* Given an offset of a signatured type, return its signatured_type.  */
+
+static struct signatured_type *
+lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset)
+{
+  gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset;
+  unsigned int length, initial_length_size;
+  unsigned int sig_offset;
+  struct signatured_type find_entry, *type_sig;
+
+  length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size);
+  sig_offset = (initial_length_size
+		+ 2 /*version*/
+		+ (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/
+		+ 1 /*address_size*/);
+  find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset);
+  type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+
+  /* This is only used to lookup previously recorded types.
+     If we didn't find it, it's our bug.  */
+  gdb_assert (type_sig != NULL);
+  gdb_assert (offset == type_sig->offset);
+
+  return type_sig;
+}
+
+/* Read in signatured type at OFFSET and build its CU and die(s).  */
+
+static void
+read_signatured_type_at_offset (struct objfile *objfile,
+				unsigned int offset)
+{
+  struct signatured_type *type_sig;
+
+  /* We have the section offset, but we need the signature to do the
+     hash table lookup.	 */
+  type_sig = lookup_signatured_type_at_offset (objfile, offset);
+
+  gdb_assert (type_sig->per_cu.cu == NULL);
+
+  read_signatured_type (objfile, type_sig);
+
+  gdb_assert (type_sig->per_cu.cu != NULL);
+}
+
+/* Read in a signatured type and build its CU and DIEs.  */
+
+static void
+read_signatured_type (struct objfile *objfile,
+		      struct signatured_type *type_sig)
+{
+  gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+  struct die_reader_specs reader_specs;
+  struct dwarf2_cu *cu;
+  ULONGEST signature;
+  struct cleanup *back_to, *free_cu_cleanup;
+  struct attribute *attr;
+
+  gdb_assert (type_sig->per_cu.cu == NULL);
+
+  cu = xmalloc (sizeof (struct dwarf2_cu));
+  memset (cu, 0, sizeof (struct dwarf2_cu));
+  obstack_init (&cu->comp_unit_obstack);
+  cu->objfile = objfile;
+  type_sig->per_cu.cu = cu;
+  cu->per_cu = &type_sig->per_cu;
+
+  /* If an error occurs while loading, release our storage.  */
+  free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+
+  types_ptr = read_type_comp_unit_head (&cu->header, &signature,
+					types_ptr, objfile->obfd);
+  gdb_assert (signature == type_sig->signature);
+
+  cu->die_hash
+    = htab_create_alloc_ex (cu->header.length / 12,
+			    die_hash,
+			    die_eq,
+			    NULL,
+			    &cu->comp_unit_obstack,
+			    hashtab_obstack_allocate,
+			    dummy_obstack_deallocate);
+
+  dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+  back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+  init_cu_die_reader (&reader_specs, cu);
+
+  cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr,
+				    NULL /*parent*/);
+
+  /* We try not to read any attributes in this function, because not
+     all objfiles needed for references have been loaded yet, and symbol
+     table processing isn't initialized.  But we have to set the CU language,
+     or we won't be able to build types correctly.  */
+  attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
+  if (attr)
+    set_cu_language (DW_UNSND (attr), cu);
+  else
+    set_cu_language (language_minimal, cu);
+
+  do_cleanups (back_to);
+
+  /* We've successfully allocated this compilation unit.  Let our caller
+     clean it up when finished with it.	 */
+  discard_cleanups (free_cu_cleanup);
+
+  type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+  dwarf2_per_objfile->read_in_chain = &type_sig->per_cu;
 }
 
 /* Decode simple location descriptions.
@@ -10622,8 +11277,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_p
     }
 }
 
-/* Locate the compilation unit from CU's objfile which contains the
-   DIE at OFFSET.  Raises an error on failure.  */
+/* Locate the .debug_info compilation unit from CU's objfile which contains
+   the DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
 dwarf2_find_containing_comp_unit (unsigned int offset,


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-20  0:04 [RFA] comdat types Doug Evans
@ 2009-06-25 19:47 ` Tom Tromey
  2009-06-25 20:28   ` Doug Evans
  2009-06-26  0:01   ` Cary Coutant
  0 siblings, 2 replies; 11+ messages in thread
From: Tom Tromey @ 2009-06-25 19:47 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches, ccoutant

>>>>> "Doug" == Doug Evans <dje@google.com> writes:

Doug> This patch adds support for "comdat types" from dwarf4.
Doug> http://wiki.dwarfstd.org/index.php?title=COMDAT_Type_Sections

I am a fan of this.

I'm curious about one thing on this page, and I thought I'd take the
opportunity to ask.  DW_TAG_type_unit may have a DW_AT_language child.
But, the language is not mentioned in the suggested method for
computing a type's signature.  This seems strange to me: either the
language matters (in which case, it seems like it ought to be in the
signature); or the language does not matter, in which case, why
mention it?

Doug> I need to revisit them with the latest gcc (the dwarf4 branch)
Doug> as they seem like gcc issues.
Doug> [specifically gdb.cp/classes.exp, and "info type foo" doesn't print the
Doug> source location though it should]

Yeah; my view is that since this patch can't hurt anything, if the gcc
changes require gdb changes in turn, it won't matter.

Doug> Ok to check in?

I read through it.  Unfortunately, I don't think I am enough of a
dwarf2read.c expert to approve this.  So, I would appreciate it if
someone more expert could claim it.  Alternatively, if nobody has time
to do this, and they say so, I will learn more and take it on.

One concern I have is whether there is any chance that the
specification will change between now and when DWARF-4 is published.

I do have a few nits.

Doug> +  types_htab = htab_create_alloc_ex (41,
Doug> +				     hash_type_signature,
Doug> +				     eq_type_signature,
Doug> +				     NULL,
Doug> +				     &objfile->objfile_obstack,
Doug> +				     hashtab_obstack_allocate,
Doug> +				     dummy_obstack_deallocate);

This is just a side note -- I've seen a few hash tables allocated on
obstacks.  Doesn't resizing the table waste memory?

Too bad we don't have allocation pools instead of obstacks.  I suppose
in this specific case we could use the objfile data machinery to
deallocate hash tables.

Doug> +  if (dwarf2_die_debug)
Doug> +    {
Doug> +      fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
Doug> +    }

Over-bracing.  There's a fair amount of this in the patch.

Doug> +  if (this_cu->from_debug_types)
Doug> +    {
Doug> +      /* ??? How come this is for .debug_types only?  */
Doug> +      this_cu->offset = cu.header.offset;
Doug> +      this_cu->length = cu.header.length + cu.header.initial_length_size;

Daniel has asked before for "no new FIXMEs".  You can't escape this by
spelling it "???" :-)

Seriously, I think this is a valid concern and I would like some
definitive resolution to the various "???" comments.

Doug> + NotFound:

Should be "not_found".  There's a couple of these.

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-25 19:47 ` Tom Tromey
@ 2009-06-25 20:28   ` Doug Evans
  2009-06-25 20:49     ` Tom Tromey
  2009-06-26  1:33     ` Daniel Jacobowitz
  2009-06-26  0:01   ` Cary Coutant
  1 sibling, 2 replies; 11+ messages in thread
From: Doug Evans @ 2009-06-25 20:28 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, ccoutant

On Thu, Jun 25, 2009 at 12:46 PM, Tom Tromey<tromey@redhat.com> wrote:
> I'm curious about one thing on this page, and I thought I'd take the
> opportunity to ask.  DW_TAG_type_unit may have a DW_AT_language child.
> But, the language is not mentioned in the suggested method for
> computing a type's signature.  This seems strange to me: either the
> language matters (in which case, it seems like it ought to be in the
> signature); or the language does not matter, in which case, why
> mention it?

I'll leave this for Cary.

> One concern I have is whether there is any chance that the
> specification will change between now and when DWARF-4 is published.

Cary?

> I do have a few nits.
>
> Doug> +  types_htab = htab_create_alloc_ex (41,
> Doug> +                              hash_type_signature,
> Doug> +                              eq_type_signature,
> Doug> +                              NULL,
> Doug> +                              &objfile->objfile_obstack,
> Doug> +                              hashtab_obstack_allocate,
> Doug> +                              dummy_obstack_deallocate);
>
> This is just a side note -- I've seen a few hash tables allocated on
> obstacks.  Doesn't resizing the table waste memory?

IIRC I use the noresize traversal routine.
It's not ideal, no.

> Too bad we don't have allocation pools instead of obstacks.  I suppose
> in this specific case we could use the objfile data machinery to
> deallocate hash tables.

If that's ok, I'll do that.

> Doug> +  if (dwarf2_die_debug)
> Doug> +    {
> Doug> +      fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
> Doug> +    }
>
> Over-bracing.  There's a fair amount of this in the patch.

One of the style rules I'm less fond of (and see others are too from
scans of gdb, is this a rule or a guideline?).
[I'm reminded of Pirates of the Caribbean, "They're more like
guidelines anyway." :-)]
But ok.

> Doug> +  if (this_cu->from_debug_types)
> Doug> +    {
> Doug> +      /* ??? How come this is for .debug_types only?  */
> Doug> +      this_cu->offset = cu.header.offset;
> Doug> +      this_cu->length = cu.header.length + cu.header.initial_length_size;
>
> Daniel has asked before for "no new FIXMEs".  You can't escape this by
> spelling it "???" :-)

Well, that one was an oversight (these patches drag on and my eyes
tend to glaze over ...).
While as a general rule I don't disagree, it's kinda odd to see others
add new functionality with open issues.

> Seriously, I think this is a valid concern and I would like some
> definitive resolution to the various "???" comments.
>
> Doug> + NotFound:
>
> Should be "not_found".  There's a couple of these.

fwiw I like StudlyCaps for labels:  How many labels should there be in
one's code?
--> As absolutely few as possible.
Same with StudlyCaps. :-)
There are existing uses of StudlyCaps for labels (albeit isolated to
one file) so I went with that.
But ok.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-25 20:28   ` Doug Evans
@ 2009-06-25 20:49     ` Tom Tromey
  2009-07-15  1:13       ` Doug Evans
  2009-06-26  1:33     ` Daniel Jacobowitz
  1 sibling, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2009-06-25 20:49 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches, ccoutant

>>>>> "Doug" == Doug Evans <dje@google.com> writes:

Tom> Too bad we don't have allocation pools instead of obstacks.  I suppose
Tom> in this specific case we could use the objfile data machinery to
Tom> deallocate hash tables.

Doug> If that's ok, I'll do that.

Sorry, I wasn't clear.  This particular thing was just a drive-by
complaint on my part.  I don't think you need to make any change to
your patch.

Tom> Over-bracing.  There's a fair amount of this in the patch.

Doug> One of the style rules I'm less fond of (and see others are too from
Doug> scans of gdb, is this a rule or a guideline?).
Doug> [I'm reminded of Pirates of the Caribbean, "They're more like
Doug> guidelines anyway." :-)]
Doug> But ok.

Yeah, I tend to treat this one as a rule.

Doug> Well, that one was an oversight (these patches drag on and my eyes
Doug> tend to glaze over ...).
Doug> While as a general rule I don't disagree, it's kinda odd to see others
Doug> add new functionality with open issues.

I'm sorry.  I try to be reasonably consistent when reviewing, but I'm
probably not.  It is fair to call me on that when it happens.

Perhaps it was wrong of me to drag in the general rule (which, as we
were discussing on irc, has various corner cases and ambiguities) when
something specific would serve better.

The comments in question:

+  if (this_cu->from_debug_types)
+    {
+      /* ??? How come this is for .debug_types only?  */
+      this_cu->offset = cu.header.offset;
+      this_cu->length = cu.header.length + cu.header.initial_length_size;
+    }

   /* Possibly set the default values of LOWPC and HIGHPC from
-     `DW_AT_ranges'.  */
+     `DW_AT_ranges'.
+     ??? Is this valid for .debug_types?  */
   if (cu.has_ranges_offset)
     {

+  if (this_cu->from_debug_types)
+    {
+      /* ??? It's not clear we want to do anything with stmt lists here.
+	 Waiting to see what gcc ultimately does.  */
+    }


It seems to me that the first one is (IIUC) a question about the
implementation of dwarf2read.c itself.  So, can it answered and
rephrased as a note?

The second seems like a question about the spec.

The third one, I'm less sure.  Perhaps just removing the "???" part is
appropriate.

Doug> fwiw I like StudlyCaps for labels:  How many labels should there be in
Doug> one's code?
Doug> --> As absolutely few as possible.
Doug> Same with StudlyCaps. :-)

:-)

StudlyCaps just look weird to me in GNU code.  And the many gotos in
gdb largely follow the GNUish naming convention, though I see some
counterexamples in Ada:

ada-typeprint.c:	goto Huh;
ada-exp.y:      goto BadEncoding;
ada-exp.y:              goto TryAfterRenaming;

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-25 19:47 ` Tom Tromey
  2009-06-25 20:28   ` Doug Evans
@ 2009-06-26  0:01   ` Cary Coutant
  2009-06-26  0:54     ` Doug Evans
  1 sibling, 1 reply; 11+ messages in thread
From: Cary Coutant @ 2009-06-26  0:01 UTC (permalink / raw)
  To: tromey; +Cc: Doug Evans, gdb-patches

> I'm curious about one thing on this page, and I thought I'd take the
> opportunity to ask.  DW_TAG_type_unit may have a DW_AT_language child.
> But, the language is not mentioned in the suggested method for
> computing a type's signature.  This seems strange to me: either the
> language matters (in which case, it seems like it ought to be in the
> signature); or the language does not matter, in which case, why
> mention it?

DW_AT_language was a late addition, and if I recall correctly, it was
at Doug's request because there were still some places in gdb where
the language mattered. It's an attribute of the type_unit (just like
it is of the compile_unit), not of the type itself, so it's not
involved in computing the type signature. Theoretically, if two type
definitions from different languages generate the same signature,
they're still the same type, and should be merged together. On the
other hand, if the language really does matter to gdb, maybe they
shouldn't be merged. I'm not sure it's likely enough to matter much,
although I think it would be desirable for a C type and the same type
in C++ to have the same signature. I had the impression that the
dependence on language was a wart, and that ideally, it really
shouldn't be necessary, so the language attribute is there only as
helpful extra information.

> One concern I have is whether there is any chance that the
> specification will change between now and when DWARF-4 is published.

The DWARF proposal (after a long drawn-out process to finalize the
details of the signature computation) is final, and is being
incorporated into the next draft specification. The editor has
promised me that the new DW_TAG and DW_AT codes are cast in stone.
DWARF-4 is closed to new issues now, and I think the chances of any
changes are virtually nil.

-cary


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-26  0:01   ` Cary Coutant
@ 2009-06-26  0:54     ` Doug Evans
  0 siblings, 0 replies; 11+ messages in thread
From: Doug Evans @ 2009-06-26  0:54 UTC (permalink / raw)
  To: Cary Coutant; +Cc: tromey, gdb-patches

On Thu, Jun 25, 2009 at 5:01 PM, Cary Coutant<ccoutant@google.com> wrote:
>> I'm curious about one thing on this page, and I thought I'd take the
>> opportunity to ask.  DW_TAG_type_unit may have a DW_AT_language child.
>> But, the language is not mentioned in the suggested method for
>> computing a type's signature.  This seems strange to me: either the
>> language matters (in which case, it seems like it ought to be in the
>> signature); or the language does not matter, in which case, why
>> mention it?
>
> DW_AT_language was a late addition, and if I recall correctly, it was
> at Doug's request because there were still some places in gdb where
> the language mattered. It's an attribute of the type_unit (just like
> it is of the compile_unit), not of the type itself, so it's not
> involved in computing the type signature. Theoretically, if two type
> definitions from different languages generate the same signature,
> they're still the same type, and should be merged together. On the
> other hand, if the language really does matter to gdb, maybe they
> shouldn't be merged. I'm not sure it's likely enough to matter much,
> although I think it would be desirable for a C type and the same type
> in C++ to have the same signature. I had the impression that the
> dependence on language was a wart, and that ideally, it really
> shouldn't be necessary, so the language attribute is there only as
> helpful extra information.

I looked back, and apparently it there's by request of the dwarf committee.
Since it's there I made use of it, but that can change of course.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-25 20:28   ` Doug Evans
  2009-06-25 20:49     ` Tom Tromey
@ 2009-06-26  1:33     ` Daniel Jacobowitz
  1 sibling, 0 replies; 11+ messages in thread
From: Daniel Jacobowitz @ 2009-06-26  1:33 UTC (permalink / raw)
  To: Doug Evans; +Cc: tromey, gdb-patches, ccoutant

On Thu, Jun 25, 2009 at 01:28:02PM -0700, Doug Evans wrote:
> > Doug> +  types_htab = htab_create_alloc_ex (41,
> > Doug> +                              hash_type_signature,
> > Doug> +                              eq_type_signature,
> > Doug> +                              NULL,
> > Doug> +                              &objfile->objfile_obstack,
> > Doug> +                              hashtab_obstack_allocate,
> > Doug> +                              dummy_obstack_deallocate);
> >
> > This is just a side note -- I've seen a few hash tables allocated on
> > obstacks.  Doesn't resizing the table waste memory?
> 
> IIRC I use the noresize traversal routine.
> It's not ideal, no.

FWIW, 3 of the other 4 hash tables are on the compilation unit
obstack, which is temporary.  The exception is type_hash which I found
to be performance-sensitive (both time and space) and have a pretty
good initial size estimate.  Obstacks are a big win for that sort of
thing.

This one probably fills the same niche, but doesn't have an initial
estimate.  So I'm not sure what I think about keeping it on the
obstack.  If the contents can go on the obstack instead, that's
probably enough.

> > Doug> +  if (this_cu->from_debug_types)
> > Doug> +    {
> > Doug> +      /* ??? How come this is for .debug_types only?  */
> > Doug> +      this_cu->offset = cu.header.offset;
> > Doug> +      this_cu->length = cu.header.length + cu.header.initial_length_size;
> >
> > Daniel has asked before for "no new FIXMEs".  You can't escape this by
> > spelling it "???" :-)
> 
> Well, that one was an oversight (these patches drag on and my eyes
> tend to glaze over ...).
> While as a general rule I don't disagree, it's kinda odd to see others
> add new functionality with open issues.

Yes, we're (me included) not totally consistent on this - but it's a
sure way to get reviewers to chew on you, as you know :-)

As a general extension to the general rule, "FIXME: Foo doesn't work"
makes me happier than "FIXME: What about foo?".  I particularly don't
like FIXMEs with questions in them; we should know what works and
what doesn't.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-06-25 20:49     ` Tom Tromey
@ 2009-07-15  1:13       ` Doug Evans
  2009-07-15 19:28         ` Tom Tromey
  0 siblings, 1 reply; 11+ messages in thread
From: Doug Evans @ 2009-07-15  1:13 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

How about this?

It addresses the issues raised here:
http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html

This patch requires:
http://sourceware.org/ml/gdb-patches/2009-06/msg00521.html
which is unchanged (modulo the requested formatting change),
and was approved here:
http://sourceware.org/ml/gdb-patches/2009-06/msg00657.html

[-- Attachment #2: gdb-090714-dwarf2read-sig8-2.patch.txt --]
[-- Type: text/plain, Size: 41153 bytes --]

2009-06-19  Doug Evans  <dje@google.com>

	* dwarf2.h (enum dwarf_tag): Add DW_TAG_type_unit.
	(enum dwarf_form): Add DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(enum dwarf_attribute): Add DW_AT_signature, DW_AT_GNU_odr_signature.

	Add support for "comdat types" from DWARF4.
	* dwarf2read.c (dwarf2_per_objfile): New member types,
	signatured_types.
	(TYPES_SECTION): New macro.
	(dwarf2_per_cu_data): Change size of length field from 30 bits
	to 29 bits.  New member from_debug_types.
	(signatured_type): New struct.
	(struct attribute): New union member signatured_type.
	(DW_SIGNATURED_TYPE): New macro.
	(dwarf2_attr_no_follow): New function.
	(read_type_unit_scope): New function.
	(follow_die_ref_or_sig, follow_die_sig): New functions.
	(dwarf2_locate_sectoins): Handle .debug_types.
	(dwarf2_build_psymtabs): Read .debug_types.
	(read_type_comp_unit_head): New function.
	(hash_type_signature, eq_type_signature): New functions.
	(create_debug_types_hash_table): New function.
	(lookup_signatured_type): New function.
	(process_psymtab_comp_unit): Handle type units too.
	(process_type_comp_unit, build_type_psymtabs): New functions.
	(dwarf2_build_psymtabs_hard): Call build_type_psymtabs.
	(load_partial_comp_unit): Assert not called for a type unit.
	(skip_one_die): Handle DW_FORM_sig8.
	(queue_comp_unit): Don't call load_full_comp_unit here, or
	update read_in_chain.
	(psymtab_to_symtab_1): Call read_signatured_type_at_offset for
	type units, or load_full_comp_unit for comp units after
	queue_comp_unit returns.
	(load_full_comp_unit): Assert not called for type units.
	(load_full_comp_unit): Update read_in_chain here.
	(process_die): Handle DW_TAG_type_unit.
	(read_structure_type): Look for signatured types.
	(read_enumeration_type): Ditto.
	(init_cu_die_reader): Handle .debug_types.
	(read_comp_unit): Assert hash not computed yet.
	(read_die_and_children): Expand debugging printf to handle .debug_types.
	(read_partial_die): Handle DW_TAG_type_unit:
	(find_patial_die): Handle .debug_types.
	(read_attribute_value): Handle DW_FORM_sig8.
	(die_type): Call follow_die_ref_or_sig instead of follow_die_ref.
	(die_containing_type): Ditto.
	(dwarf_tag_name): Handle DW_TAG_type_unit.
	(dwarf_attr_name): Handle DW_AT_signature, DW_GNU_odr_signature.
	(dwarf_form_name): Handle DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(dump_die_shallow): Handlel DW_FORM_sig8.
	(maybe_queue_comp_unit): Change return type to int from void.
	All callers updated.
	(follow_die_ref): Handle .debug_types.
	(lookup_signatured_type_at_offset): New function.
	(read_signatured_type_at_offset): New function.
	(read_signatured_type): New function.


diff -u -p -r1.2 dwarf2.h
--- dwarf2.h	9 Jul 2009 21:01:15 -0000	1.2
+++ dwarf2.h	14 Jul 2009 23:22:35 -0000
@@ -194,6 +194,8 @@ enum dwarf_tag
     DW_TAG_imported_unit = 0x3d,
     DW_TAG_condition = 0x3f,
     DW_TAG_shared_type = 0x40,
+    /* DWARF 4.  */
+    DW_TAG_type_unit = 0x41,
 
     DW_TAG_lo_user = 0x4080,
     DW_TAG_hi_user = 0xffff,
@@ -244,7 +246,12 @@ enum dwarf_form
     DW_FORM_ref4 = 0x13,
     DW_FORM_ref8 = 0x14,
     DW_FORM_ref_udata = 0x15,
-    DW_FORM_indirect = 0x16
+    DW_FORM_indirect = 0x16,
+    /* DWARF 4.  */
+    DW_FORM_sec_offset = 0x17,
+    DW_FORM_exprloc = 0x18,
+    DW_FORM_flag_present = 0x19,
+    DW_FORM_sig8 = 0x20
   };
 
 /* Attribute names and codes.  */
@@ -342,6 +349,8 @@ enum dwarf_attribute
     DW_AT_elemental     = 0x66,
     DW_AT_pure          = 0x67,
     DW_AT_recursive     = 0x68,
+    /* DWARF 4 values.  */
+    DW_AT_signature     = 0x69,
 
     DW_AT_lo_user = 0x2000,	/* Implementation-defined range start.  */
     DW_AT_hi_user = 0x3ff0,	/* Implementation-defined range end.  */
@@ -381,6 +390,7 @@ enum dwarf_attribute
     DW_AT_body_begin = 0x2105,
     DW_AT_body_end   = 0x2106,
     DW_AT_GNU_vector = 0x2107,
+    DW_AT_GNU_odr_signature = 0x210f,
     /* VMS extensions.  */
     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
     /* UPC extension.  */

diff -u -p ../../dwarf-cleanup/src/gdb/dwarf2read.c ./gdb/dwarf2read.c
--- ../../../dwarf-cleanup/src/gdb/dwarf2read.c	2009-07-14 14:36:55.000000000 -0700
+++ ./dwarf2read.c	2009-07-14 16:19:30.000000000 -0700
@@ -164,6 +164,7 @@ struct dwarf2_per_objfile
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info str;
   struct dwarf2_section_info ranges;
+  struct dwarf2_section_info types;
   struct dwarf2_section_info frame;
   struct dwarf2_section_info eh_frame;
 
@@ -178,6 +179,10 @@ struct dwarf2_per_objfile
      they can be freed later.  */
   struct dwarf2_per_cu_data *read_in_chain;
 
+  /* A table mapping .debug_types signatures to its signatured_type entry.
+     This is NULL if the .debug_types section hasn't been read in yet.  */
+  htab_t signatured_types;
+
   /* A flag indicating wether this objfile has a section loaded at a
      VMA of 0.  */
   int has_section_at_zero;
@@ -199,6 +204,7 @@ static struct dwarf2_per_objfile *dwarf2
 #define MACINFO_SECTION  "debug_macinfo"
 #define STR_SECTION      "debug_str"
 #define RANGES_SECTION   "debug_ranges"
+#define TYPES_SECTION    "debug_types"
 #define FRAME_SECTION    "debug_frame"
 #define EH_FRAME_SECTION "eh_frame"
 
@@ -340,13 +346,13 @@ struct dwarf2_cu
 
 struct dwarf2_per_cu_data
 {
-  /* The start offset and length of this compilation unit.  2**30-1
+  /* The start offset and length of this compilation unit.  2**29-1
      bytes should suffice to store the length of any compilation unit
      - if it doesn't, GDB will fall over anyway.
      NOTE: Unlike comp_unit_head.length, this length includes
      initial_length_size.  */
   unsigned int offset;
-  unsigned int length : 30;
+  unsigned int length : 29;
 
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
@@ -358,6 +364,10 @@ struct dwarf2_per_cu_data
      hash table and don't find it.  */
   unsigned int load_all_dies : 1;
 
+  /* Non-zero if this CU is from .debug_types.
+     Otherwise it's from .debug_info.  */
+  unsigned int from_debug_types : 1;
+
   /* Set iff currently read in.  */
   struct dwarf2_cu *cu;
 
@@ -373,6 +383,22 @@ struct dwarf2_per_cu_data
   struct partial_symtab *psymtab;
 };
 
+/* Entry in the signatured_types hash table.  */
+
+struct signatured_type
+{
+  ULONGEST signature;
+
+  /* Offset in .debug_types of the TU (type_unit) for this type.  */
+  unsigned int offset;
+
+  /* Offset in .debug_types of the type defined by this TU.  */
+  unsigned int type_offset;
+
+  /* The CU(/TU) of this type.  */
+  struct dwarf2_per_cu_data per_cu;
+};
+
 /* Struct used to pass misc. parameters to read_die_and_children, et. al.
    which are used for both .debug_info and .debug_types dies.
    All parameters here are unchanging for the life of the call.
@@ -541,6 +567,7 @@ struct attribute
 	unsigned long unsnd;
 	long int snd;
 	CORE_ADDR addr;
+	struct signatured_type *signatured_type;
       }
     u;
   };
@@ -590,6 +617,7 @@ struct function_range
 #define DW_BLOCK(attr)     ((attr)->u.blk)
 #define DW_SND(attr)       ((attr)->u.snd)
 #define DW_ADDR(attr)	   ((attr)->u.addr)
+#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type)
 
 /* Blocks are a bunch of untyped bytes. */
 struct dwarf_block
@@ -874,6 +902,10 @@ static void set_cu_language (unsigned in
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
 				      struct dwarf2_cu *);
 
+static struct attribute *dwarf2_attr_no_follow (struct die_info *,
+						unsigned int,
+						struct dwarf2_cu *);
+
 static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
                                struct dwarf2_cu *cu);
 
@@ -924,6 +956,8 @@ static char *typename_concat (struct obs
 
 static void read_file_scope (struct die_info *, struct dwarf2_cu *);
 
+static void read_type_unit_scope (struct die_info *, struct dwarf2_cu *);
+
 static void read_func_scope (struct die_info *, struct dwarf2_cu *);
 
 static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
@@ -1046,10 +1080,24 @@ static unsigned int dwarf2_get_ref_die_o
 
 static int dwarf2_get_attr_constant_value (struct attribute *, int);
 
+static struct die_info *follow_die_ref_or_sig (struct die_info *,
+					       struct attribute *,
+					       struct dwarf2_cu **);
+
 static struct die_info *follow_die_ref (struct die_info *,
 					struct attribute *,
 					struct dwarf2_cu **);
 
+static struct die_info *follow_die_sig (struct die_info *,
+					struct attribute *,
+					struct dwarf2_cu **);
+
+static void read_signatured_type_at_offset (struct objfile *objfile,
+					    unsigned int offset);
+
+static void read_signatured_type (struct objfile *,
+				  struct signatured_type *type_sig);
+
 /* memory allocation interface */
 
 static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
@@ -1217,6 +1265,11 @@ dwarf2_locate_sections (bfd *abfd, asect
       dwarf2_per_objfile->ranges.asection = sectp;
       dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, TYPES_SECTION))
+    {
+      dwarf2_per_objfile->types.asection = sectp;
+      dwarf2_per_objfile->types.size = bfd_get_section_size (sectp);
+    }
 
   if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
       && bfd_section_vma (abfd, sectp) == 0)
@@ -1416,6 +1469,7 @@ dwarf2_build_psymtabs (struct objfile *o
   dwarf2_read_section (objfile, &dwarf2_per_objfile->str);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->macinfo);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->loc);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame);
   dwarf2_read_section (objfile, &dwarf2_per_objfile->frame);
@@ -1554,6 +1608,29 @@ partial_read_comp_unit_head (struct comp
   return info_ptr;
 }
 
+/* Read in the types comp unit header information from .debug_types entry at
+   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,
+			  ULONGEST *signature,
+			  gdb_byte *types_ptr, bfd *abfd)
+{
+  unsigned int bytes_read;
+  gdb_byte *initial_types_ptr = types_ptr;
+
+  cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer;
+
+  types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
+
+  *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;
+
+  return types_ptr;
+}
+
 /* Allocate a new partial symtab for file named NAME and mark this new
    partial symtab as being an include of PST.  */
 
@@ -1613,9 +1690,133 @@ dwarf2_build_include_psymtabs (struct dw
   free_line_header (lh);
 }
 
-/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+static hashval_t
+hash_type_signature (const void *item)
+{
+  const struct signatured_type *type_sig = item;
+  /* This drops the top 32 bits of the signature, but is ok for a hash.  */
+  return type_sig->signature;
+}
+
+static int
+eq_type_signature (const void *item_lhs, const void *item_rhs)
+{
+  const struct signatured_type *lhs = item_lhs;
+  const struct signatured_type *rhs = item_rhs;
+  return lhs->signature == rhs->signature;
+}
+
+/* Create the hash table of all entries in the .debug_types section.
+   The result is zero if there is an error (e.g. missing .debug_types section),
+   otherwise non-zero.	*/
+
+static int
+create_debug_types_hash_table (struct objfile *objfile)
+{
+  gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer;
+  htab_t types_htab;
+
+  if (info_ptr == NULL)
+    {
+      dwarf2_per_objfile->signatured_types = NULL;
+      return 0;
+    }
+
+  types_htab = htab_create_alloc_ex (41,
+				     hash_type_signature,
+				     eq_type_signature,
+				     NULL,
+				     &objfile->objfile_obstack,
+				     hashtab_obstack_allocate,
+				     dummy_obstack_deallocate);
+
+  if (dwarf2_die_debug)
+    fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
+
+  while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+    {
+      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;
+
+      offset = ptr - dwarf2_per_objfile->types.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.  */
+
+      /* Sanity check to ensure entire cu is present.  */
+      length = read_initial_length (objfile->obfd, ptr, &initial_length_size);
+      if (ptr + length + initial_length_size
+	  > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+	{
+	  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);
+
+      type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
+      memset (type_sig, 0, sizeof (*type_sig));
+      type_sig->signature = signature;
+      type_sig->offset = offset;
+      type_sig->type_offset = type_offset;
+
+      slot = htab_find_slot (types_htab, type_sig, INSERT);
+      gdb_assert (slot != NULL);
+      *slot = type_sig;
+
+      if (dwarf2_die_debug)
+	fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature 0x%s\n",
+			    offset, phex (signature, sizeof (signature)));
+
+      info_ptr = info_ptr + initial_length_size + length;
+    }
+
+  dwarf2_per_objfile->signatured_types = types_htab;
+
+  return 1;
+}
+
+/* Lookup a signature based type.
+   Returns NULL if SIG is not present in the table.  */
+
+static struct signatured_type *
+lookup_signatured_type (struct objfile *objfile, ULONGEST sig)
+{
+  struct signatured_type find_entry, *entry;
+
+  if (dwarf2_per_objfile->signatured_types == NULL)
+    {
+      complaint (&symfile_complaints,
+		 _("missing `.debug_types' section for DW_FORM_sig8 die"));
+      return 0;
+    }
+
+  find_entry.signature = sig;
+  entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+  return entry;
+}
+
+/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard
+   to combine the common parts.
    Process a compilation unit for a psymtab.
-   BUFFER is a pointer to the beginning of the dwarf section buffer.
+   BUFFER is a pointer to the beginning of the dwarf section buffer,
+   either .debug_info or debug_types.
    INFO_PTR is a pointer to the start of the CU.
    Returns a pointer to the next CU.  */
 
@@ -1656,11 +1857,19 @@ process_psymtab_comp_unit (struct objfil
   make_cleanup (dwarf2_free_abbrev_table, &cu);
 
   /* Read the compilation unit die.  */
+  if (this_cu->from_debug_types)
+    info_ptr += 8 /*signature*/ + cu.header.offset_size;
   abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
   info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd,
 			       buffer, info_ptr, &cu);
 
-  if (comp_unit_die.tag == DW_TAG_partial_unit)
+  if (this_cu->from_debug_types)
+    {
+      /* offset,length haven't been set yet for type units.  */
+      this_cu->offset = cu.header.offset;
+      this_cu->length = cu.header.length + cu.header.initial_length_size;
+    }
+  else if (comp_unit_die.tag == DW_TAG_partial_unit)
     {
       info_ptr = (beg_of_comp_unit + cu.header.length
 		  + cu.header.initial_length_size);
@@ -1767,12 +1976,18 @@ process_psymtab_comp_unit (struct objfil
   /* If there is already a psymtab or symtab for a file of this
      name, remove it. (If there is a symtab, more drastic things
      also happen.) This happens in VxWorks.  */
-  free_named_symtabs (pst->filename);
+  if (! this_cu->from_debug_types)
+    free_named_symtabs (pst->filename);
 
   info_ptr = (beg_of_comp_unit + cu.header.length
 	      + cu.header.initial_length_size);
 
-  if (comp_unit_die.has_stmt_list)
+  if (this_cu->from_debug_types)
+    {
+      /* It's not clear we want to do anything with stmt lists here.
+	 Waiting to see what gcc ultimately does.  */
+    }
+  else if (comp_unit_die.has_stmt_list)
     {
       /* Get the list of files included in the current compilation unit,
 	 and build a psymtab for each of them.  */
@@ -1784,6 +1999,40 @@ process_psymtab_comp_unit (struct objfil
   return info_ptr;
 }
 
+/* Traversal function for htab_traverse_noresize.
+   Process one .debug_types comp-unit.	*/
+
+static int
+process_type_comp_unit (void **slot, void *info)
+{
+  struct signatured_type *entry = (struct signatured_type *) *slot;
+  struct objfile *objfile = (struct objfile *) info;
+  struct dwarf2_per_cu_data *this_cu;
+
+  this_cu = &entry->per_cu;
+  this_cu->from_debug_types = 1;
+
+  process_psymtab_comp_unit (objfile, this_cu,
+			     dwarf2_per_objfile->types.buffer,
+			     dwarf2_per_objfile->types.buffer + entry->offset,
+			     dwarf2_per_objfile->types.size);
+
+  return 1;
+}
+
+/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+   Build partial symbol tables for the .debug_types comp-units.  */
+
+static void
+build_type_psymtabs (struct objfile *objfile)
+{
+  if (! create_debug_types_hash_table (objfile))
+    return;
+
+  htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+			  process_type_comp_unit, objfile);
+}
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -1802,6 +2051,8 @@ dwarf2_build_psymtabs_hard (struct objfi
      read_in_chain.  Make sure to free them when we're done.  */
   back_to = make_cleanup (free_cached_comp_units, NULL);
 
+  build_type_psymtabs (objfile);
+
   create_all_comp_units (objfile);
 
   objfile->psymtabs_addrmap =
@@ -1855,6 +2106,8 @@ load_partial_comp_unit (struct dwarf2_pe
   unsigned int bytes_read;
   struct cleanup *back_to;
 
+  gdb_assert (! this_cu->from_debug_types);
+
   info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
   beg_of_comp_unit = info_ptr;
 
@@ -2595,6 +2848,7 @@ skip_one_die (gdb_byte *buffer, gdb_byte
 	  break;
 	case DW_FORM_data8:
 	case DW_FORM_ref8:
+	case DW_FORM_sig8:
 	  info_ptr += 8;
 	  break;
 	case DW_FORM_string:
@@ -2730,12 +2984,6 @@ queue_comp_unit (struct dwarf2_per_cu_da
     dwarf2_queue_tail->next = item;
 
   dwarf2_queue_tail = item;
-
-  /* Either PER_CU is the CU we want to process, or we're following a reference
-     pointing into PER_CU.  Either way, we need its DIEs now.  */
-  load_full_comp_unit (item->per_cu, objfile);
-  item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
-  dwarf2_per_objfile->read_in_chain = item->per_cu;
 }
 
 /* Process the queue.  */
@@ -2830,6 +3078,11 @@ psymtab_to_symtab_1 (struct partial_symt
 
   queue_comp_unit (per_cu, pst->objfile);
 
+  if (per_cu->from_debug_types)
+    read_signatured_type_at_offset (pst->objfile, per_cu->offset);
+  else
+    load_full_comp_unit (per_cu, pst->objfile);
+
   process_queue (pst->objfile);
 
   /* Age the cache, releasing compilation units that have not
@@ -2852,6 +3105,8 @@ load_full_comp_unit (struct dwarf2_per_c
   struct attribute *attr;
   CORE_ADDR baseaddr;
 
+  gdb_assert (! per_cu->from_debug_types);
+
   /* Set local variables from the partial symbol table info.  */
   offset = per_cu->offset;
 
@@ -2891,6 +3146,10 @@ load_full_comp_unit (struct dwarf2_per_c
   else
     set_cu_language (language_minimal, cu);
 
+  /* Link this CU into read_in_chain.  */
+  per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+  dwarf2_per_objfile->read_in_chain = per_cu;
+
   do_cleanups (back_to);
 
   /* We've successfully allocated this compilation unit.  Let our caller
@@ -2982,6 +3241,9 @@ process_die (struct die_info *die, struc
     case DW_TAG_compile_unit:
       read_file_scope (die, cu);
       break;
+    case DW_TAG_type_unit:
+      read_type_unit_scope (die, cu);
+      break;
     case DW_TAG_subprogram:
     case DW_TAG_inlined_subroutine:
       read_func_scope (die, cu);
@@ -3303,6 +3565,85 @@ read_file_scope (struct die_info *die, s
   do_cleanups (back_to);
 }
 
+/* For TUs we want to skip the first top level sibling if it's not the
+   actual type being defined by this TU.  In this case the first top
+   level sibling is there to provide context only.  */
+
+static void
+read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+  CORE_ADDR lowpc;
+  struct attribute *attr;
+  char *name = NULL;
+  char *comp_dir = NULL;
+  struct die_info *child_die;
+  bfd *abfd = objfile->obfd;
+  struct line_header *line_header = 0;
+
+  /* start_symtab needs a low pc, but we don't really have one.
+     Do what read_file_scope would do in the absence of such info.  */
+  lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  /* Find the filename.  Do not use dwarf2_name here, since the filename
+     is not a source language identifier.  */
+  attr = dwarf2_attr (die, DW_AT_name, cu);
+  if (attr)
+    name = DW_STRING (attr);
+
+  attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
+  if (attr)
+    comp_dir = DW_STRING (attr);
+  else if (name != NULL && IS_ABSOLUTE_PATH (name))
+    {
+      comp_dir = ldirname (name);
+      if (comp_dir != NULL)
+	make_cleanup (xfree, comp_dir);
+    }
+
+  if (name == NULL)
+    name = "<unknown>";
+
+  attr = dwarf2_attr (die, DW_AT_language, cu);
+  if (attr)
+    set_cu_language (DW_UNSND (attr), cu);
+
+  /* This isn't technically needed today.  It is done for symmetry
+     with read_file_scope.  */
+  attr = dwarf2_attr (die, DW_AT_producer, cu);
+  if (attr) 
+    cu->producer = DW_STRING (attr);
+
+  /* We assume that we're processing GCC output. */
+  processing_gcc_compilation = 2;
+
+  processing_has_namespace_info = 0;
+
+  start_symtab (name, comp_dir, lowpc);
+  record_debugformat ("DWARF 2");
+  record_producer (cu->producer);
+
+  /* Process the dies in the type unit.  */
+  if (die->child == NULL)
+    {
+      dump_die_for_error (die);
+      error (_("Dwarf Error: Missing children for type unit [in module %s]"),
+	     bfd_get_filename (abfd));
+    }
+
+  child_die = die->child;
+
+  while (child_die && child_die->tag)
+    {
+      process_die (child_die, cu);
+
+      child_die = sibling_die (child_die);
+    }
+
+  do_cleanups (back_to);
+}
+
 static void
 add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
 		     struct dwarf2_cu *cu)
@@ -4532,6 +4873,22 @@ read_structure_type (struct die_info *di
   if (type)
     return type;
 
+  /* If the definition of this type lives in .debug_types, read that type.
+     Don't follow DW_AT_specification though, that will take us back up
+     the chain and we want to go down.  */
+  attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+  if (attr)
+    {
+      struct dwarf2_cu *type_cu = cu;
+      struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+      /* We could just recurse on read_structure_type, but we need to call
+	 get_die_type to ensure only one type for this DIE is created.
+	 This is important, for example, because for c++ classes we need
+	 TYPE_NAME set which is only done by new_symbol.  Blech.  */
+      type = read_type_die (type_die, type_cu);
+      return set_die_type (die, type, cu);
+    }
+
   type = alloc_type (objfile);
   INIT_CPLUS_SPECIFIC (type);
 
@@ -4746,6 +5103,18 @@ read_enumeration_type (struct die_info *
   struct attribute *attr;
   const char *name;
 
+  /* If the definition of this type lives in .debug_types, read that type.
+     Don't follow DW_AT_specification though, that will take us back up
+     the chain and we want to go down.  */
+  attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+  if (attr)
+    {
+      struct dwarf2_cu *type_cu = cu;
+      struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+      type = read_type_die (type_die, type_cu);
+      return set_die_type (die, type, cu);
+    }
+
   type = alloc_type (objfile);
 
   TYPE_CODE (type) = TYPE_CODE_ENUM;
@@ -5665,7 +6034,10 @@ init_cu_die_reader (struct die_reader_sp
 {
   reader->abfd = cu->objfile->obfd;
   reader->cu = cu;
-  reader->buffer = dwarf2_per_objfile->info.buffer;
+  if (cu->per_cu->from_debug_types)
+    reader->buffer = dwarf2_per_objfile->types.buffer;
+  else
+    reader->buffer = dwarf2_per_objfile->info.buffer;
 }
 
 /* Read a whole compilation unit into a linked list of dies.  */
@@ -5675,6 +6047,7 @@ read_comp_unit (gdb_byte *info_ptr, stru
 {
   struct die_reader_specs reader_specs;
 
+  gdb_assert (cu->die_hash == NULL);
   cu->die_hash
     = htab_create_alloc_ex (cu->header.length / 12,
 			    die_hash,
@@ -5703,7 +6076,14 @@ read_die_and_children (const struct die_
 
   if (dwarf2_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog, "Read die from .debug_info:\n");
+      fprintf_unfiltered (gdb_stdlog,
+			  "\nRead die from %s of %s:\n",
+			  reader->buffer == dwarf2_per_objfile->info.buffer
+			  ? ".debug_info"
+			  : reader->buffer == dwarf2_per_objfile->types.buffer
+			  ? ".debug_types"
+			  : "unknown section",
+			  reader->abfd->filename);
       dump_die (result, dwarf2_die_debug);
     }
 
@@ -5735,9 +6115,7 @@ read_die_and_children_1 (const struct di
   store_in_ref_table (die, reader->cu);
 
   if (has_children)
-    {
-      die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die);
-    }
+    die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die);
   else
     {
       die->child = NULL;
@@ -5813,11 +6191,10 @@ read_full_die (const struct die_reader_s
 
   abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
   if (!abbrev)
-    {
-      error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
-	     abbrev_number,
-	     bfd_get_filename (abfd));
-    }
+    error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
+	   abbrev_number,
+	   bfd_get_filename (abfd));
+
   die = dwarf_alloc_die (cu, abbrev->num_attrs);
   die->offset = offset;
   die->tag = abbrev->tag;
@@ -6273,6 +6650,7 @@ read_partial_die (struct partial_die_inf
 	  switch (part_die->tag)
 	    {
 	    case DW_TAG_compile_unit:
+	    case DW_TAG_type_unit:
 	      /* Compilation units have a DW_AT_name that is a filename, not
 		 a source language identifier.  */
 	    case DW_TAG_enumeration_type:
@@ -6435,7 +6813,10 @@ find_partial_die_in_comp_unit (unsigned 
   return lookup_die;
 }
 
-/* Find a partial DIE at OFFSET, which may or may not be in CU.  */
+/* Find a partial DIE at OFFSET, which may or may not be in CU,
+   except in the case of .debug_types DIEs which do not reference
+   outside their CU (they do however referencing other types via
+   DW_FORM_sig8).  */
 
 static struct partial_die_info *
 find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
@@ -6443,6 +6824,14 @@ find_partial_die (unsigned int offset, s
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
 
+  if (cu->per_cu->from_debug_types)
+    {
+      pd = find_partial_die_in_comp_unit (offset, cu);
+      if (pd != NULL)
+	return pd;
+      goto not_found;
+    }
+
   if (offset_in_cu_p (&cu->header, offset))
     {
       pd = find_partial_die_in_comp_unit (offset, cu);
@@ -6496,6 +6885,8 @@ find_partial_die (unsigned int offset, s
       pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
     }
 
+ not_found:
+
   if (pd == NULL)
     internal_error (__FILE__, __LINE__,
 		    _("could not find partial DIE 0x%x in cache [from module %s]\n"),
@@ -6649,6 +7040,14 @@ read_attribute_value (struct attribute *
       DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
+    case DW_FORM_sig8:
+      /* Convert the signature to something we can record in DW_UNSND
+	 for later lookup.
+         NOTE: This is NULL if the type wasn't found.  */
+      DW_SIGNATURED_TYPE (attr) =
+	lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr));
+      info_ptr += 8;
+      break;
     case DW_FORM_ref_udata:
       DW_ADDR (attr) = (cu->header.offset
 			+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
@@ -7111,6 +7510,25 @@ dwarf2_attr (struct die_info *die, unsig
   return NULL;
 }
 
+/* Return the named attribute or NULL if not there,
+   but do not follow DW_AT_specification, etc.
+   This is for use in contexts where we're reading .debug_types dies.
+   Following DW_AT_specification, DW_AT_abstract_origin will take us
+   back up the chain, and we want to go down.  */
+
+static struct attribute *
+dwarf2_attr_no_follow (struct die_info *die, unsigned int name,
+		       struct dwarf2_cu *cu)
+{
+  unsigned int i;
+
+  for (i = 0; i < die->num_attrs; ++i)
+    if (die->attrs[i].name == name)
+      return &die->attrs[i];
+
+  return NULL;
+}
+
 /* Return non-zero iff the attribute NAME is defined for the given DIE,
    and holds a non-zero value.  This function should only be used for
    DW_FORM_flag attributes.  */
@@ -8266,8 +8684,8 @@ die_type (struct die_info *die, struct d
       /* A missing DW_AT_type represents a void type.  */
       return objfile_type (cu->objfile)->builtin_void;
     }
-  else
-    type_die = follow_die_ref (die, type_attr, &cu);
+
+  type_die = follow_die_ref_or_sig (die, type_attr, &cu);
 
   type = tag_type_to_type (type_die, cu);
   if (!type)
@@ -8292,7 +8710,7 @@ die_containing_type (struct die_info *di
   type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
   if (type_attr)
     {
-      type_die = follow_die_ref (die, type_attr, &cu);
+      type_die = follow_die_ref_or_sig (die, type_attr, &cu);
       type = tag_type_to_type (type_die, cu);
     }
   if (!type)
@@ -8731,6 +9149,8 @@ dwarf_tag_name (unsigned tag)
       return "DW_TAG_condition";
     case DW_TAG_shared_type:
       return "DW_TAG_shared_type";
+    case DW_TAG_type_unit:
+      return "DW_TAG_type_unit";
     case DW_TAG_MIPS_loop:
       return "DW_TAG_MIPS_loop";
     case DW_TAG_HP_array_descriptor:
@@ -8946,6 +9366,9 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_pure";
     case DW_AT_recursive:
       return "DW_AT_recursive";
+    /* DWARF 4 values.  */
+    case DW_AT_signature:
+      return "DW_AT_signature";
     /* SGI/MIPS extensions.  */
 #ifdef MIPS /* collides with DW_AT_HP_block_index */
     case DW_AT_MIPS_fde:
@@ -9017,6 +9440,8 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_body_end";
     case DW_AT_GNU_vector:
       return "DW_AT_GNU_vector";
+    case DW_AT_GNU_odr_signature:
+      return "DW_AT_GNU_odr_signature";
     /* VMS extensions.  */
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
@@ -9084,6 +9509,14 @@ dwarf_form_name (unsigned form)
       return "DW_FORM_ref_udata";
     case DW_FORM_indirect:
       return "DW_FORM_indirect";
+    case DW_FORM_sec_offset:
+      return "DW_FORM_sec_offset";
+    case DW_FORM_exprloc:
+      return "DW_FORM_exprloc";
+    case DW_FORM_flag_present:
+      return "DW_FORM_flag_present";
+    case DW_FORM_sig8:
+      return "DW_FORM_sig8";
     case GDB_FORM_cached_string:
       return "GDB_FORM_cached_string";
     default:
@@ -9629,6 +10062,13 @@ dump_die_shallow (struct ui_file *f, int
 	case DW_FORM_sdata:
 	  fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i]));
 	  break;
+	case DW_FORM_sig8:
+	  if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
+	    fprintf_unfiltered (f, "signatured type, offset: 0x%x",
+				DW_SIGNATURED_TYPE (&die->attrs[i])->offset);
+	  else
+	    fprintf_unfiltered (f, "signatured type, offset: unknown");
+	  break;
 	case DW_FORM_string:
 	case DW_FORM_strp:
 	case GDB_FORM_cached_string:
@@ -9766,9 +10206,11 @@ dwarf2_get_attr_constant_value (struct a
 }
 
 /* THIS_CU has a reference to PER_CU.  If necessary, load the new compilation
-   unit and add it to our queue.  */
+   unit and add it to our queue.
+   The result is non-zero if PER_CU was queued, otherwise the result is zero
+   meaning either PER_CU is already queued or it is already loaded.  */
 
-static void
+static int
 maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
 		       struct dwarf2_per_cu_data *per_cu)
 {
@@ -9778,18 +10220,44 @@ maybe_queue_comp_unit (struct dwarf2_cu 
 
   /* If it's already on the queue, we have nothing to do.  */
   if (per_cu->queued)
-    return;
+    return 0;
 
   /* If the compilation unit is already loaded, just mark it as
      used.  */
   if (per_cu->cu != NULL)
     {
       per_cu->cu->last_used = 0;
-      return;
+      return 0;
     }
 
   /* Add it to the queue.  */
   queue_comp_unit (per_cu, this_cu->objfile);
+
+  return 1;
+}
+
+/* Follow reference or signature attribute ATTR of SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
+
+static struct die_info *
+follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
+		       struct dwarf2_cu **ref_cu)
+{
+  struct die_info *die;
+
+  if (is_ref_attr (attr))
+    die = follow_die_ref (src_die, attr, ref_cu);
+  else if (attr->form == DW_FORM_sig8)
+    die = follow_die_sig (src_die, attr, ref_cu);
+  else
+    {
+      dump_die_for_error (src_die);
+      error (_("Dwarf Error: Expected reference attribute [in module %s]"),
+	     (*ref_cu)->objfile->name);
+    }
+
+  return die;
 }
 
 /* Follow reference attribute ATTR of SRC_DIE.
@@ -9805,15 +10273,27 @@ follow_die_ref (struct die_info *src_die
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
 
+  gdb_assert (cu->per_cu != NULL);
+
   offset = dwarf2_get_ref_die_offset (attr);
 
-  if (! offset_in_cu_p (&cu->header, offset))
+  if (cu->per_cu->from_debug_types)
+    {
+      /* .debug_types CUs cannot reference anything outside their CU.
+	 If they need to, they have to reference a signatured type via
+	 DW_FORM_sig8.  */
+      if (! offset_in_cu_p (&cu->header, offset))
+	goto not_found;
+      target_cu = cu;
+    }
+  else if (! offset_in_cu_p (&cu->header, offset))
     {
       struct dwarf2_per_cu_data *per_cu;
       per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
-      maybe_queue_comp_unit (cu, per_cu);
+      if (maybe_queue_comp_unit (cu, per_cu))
+	load_full_comp_unit (per_cu, cu->objfile);
 
       target_cu = per_cu->cu;
     }
@@ -9826,9 +10306,164 @@ follow_die_ref (struct die_info *src_die
   if (die)
     return die;
 
-  error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
-	 "at 0x%lx [in module %s]"),
-	 (long) offset, (long) src_die->offset, cu->objfile->name);
+ not_found:
+
+  error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
+	 "at 0x%x [in module %s]"),
+	 offset, src_die->offset, cu->objfile->name);
+}
+
+/* Follow the signature attribute ATTR in SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
+
+static struct die_info *
+follow_die_sig (struct die_info *src_die, struct attribute *attr,
+		struct dwarf2_cu **ref_cu)
+{
+  struct objfile *objfile = (*ref_cu)->objfile;
+  struct die_info temp_die;
+  struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
+  struct dwarf2_cu *sig_cu;
+  struct die_info *die;
+
+  /* sig_type will be NULL if the signatured type is missing from
+     the debug info.  */
+  if (sig_type == NULL)
+    error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
+	     "at 0x%x [in module %s]"),
+	   src_die->offset, objfile->name);
+
+  /* If necessary, add it to the queue and load its DIEs.  */
+
+  if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
+    read_signatured_type (objfile, sig_type);
+
+  gdb_assert (sig_type->per_cu.cu != NULL);
+
+  sig_cu = sig_type->per_cu.cu;
+  temp_die.offset = sig_cu->header.offset + sig_type->type_offset;
+  die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset);
+  if (die)
+    {
+      *ref_cu = sig_cu;
+      return die;
+    }
+
+  error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE "
+	 "at 0x%x [in module %s]"),
+	 sig_type->type_offset, src_die->offset, objfile->name);
+}
+
+/* Given an offset of a signatured type, return its signatured_type.  */
+
+static struct signatured_type *
+lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset)
+{
+  gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset;
+  unsigned int length, initial_length_size;
+  unsigned int sig_offset;
+  struct signatured_type find_entry, *type_sig;
+
+  length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size);
+  sig_offset = (initial_length_size
+		+ 2 /*version*/
+		+ (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/
+		+ 1 /*address_size*/);
+  find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset);
+  type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+
+  /* This is only used to lookup previously recorded types.
+     If we didn't find it, it's our bug.  */
+  gdb_assert (type_sig != NULL);
+  gdb_assert (offset == type_sig->offset);
+
+  return type_sig;
+}
+
+/* Read in signatured type at OFFSET and build its CU and die(s).  */
+
+static void
+read_signatured_type_at_offset (struct objfile *objfile,
+				unsigned int offset)
+{
+  struct signatured_type *type_sig;
+
+  /* We have the section offset, but we need the signature to do the
+     hash table lookup.	 */
+  type_sig = lookup_signatured_type_at_offset (objfile, offset);
+
+  gdb_assert (type_sig->per_cu.cu == NULL);
+
+  read_signatured_type (objfile, type_sig);
+
+  gdb_assert (type_sig->per_cu.cu != NULL);
+}
+
+/* Read in a signatured type and build its CU and DIEs.  */
+
+static void
+read_signatured_type (struct objfile *objfile,
+		      struct signatured_type *type_sig)
+{
+  gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+  struct die_reader_specs reader_specs;
+  struct dwarf2_cu *cu;
+  ULONGEST signature;
+  struct cleanup *back_to, *free_cu_cleanup;
+  struct attribute *attr;
+
+  gdb_assert (type_sig->per_cu.cu == NULL);
+
+  cu = xmalloc (sizeof (struct dwarf2_cu));
+  memset (cu, 0, sizeof (struct dwarf2_cu));
+  obstack_init (&cu->comp_unit_obstack);
+  cu->objfile = objfile;
+  type_sig->per_cu.cu = cu;
+  cu->per_cu = &type_sig->per_cu;
+
+  /* If an error occurs while loading, release our storage.  */
+  free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+
+  types_ptr = read_type_comp_unit_head (&cu->header, &signature,
+					types_ptr, objfile->obfd);
+  gdb_assert (signature == type_sig->signature);
+
+  cu->die_hash
+    = htab_create_alloc_ex (cu->header.length / 12,
+			    die_hash,
+			    die_eq,
+			    NULL,
+			    &cu->comp_unit_obstack,
+			    hashtab_obstack_allocate,
+			    dummy_obstack_deallocate);
+
+  dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+  back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+  init_cu_die_reader (&reader_specs, cu);
+
+  cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr,
+				    NULL /*parent*/);
+
+  /* We try not to read any attributes in this function, because not
+     all objfiles needed for references have been loaded yet, and symbol
+     table processing isn't initialized.  But we have to set the CU language,
+     or we won't be able to build types correctly.  */
+  attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
+  if (attr)
+    set_cu_language (DW_UNSND (attr), cu);
+  else
+    set_cu_language (language_minimal, cu);
+
+  do_cleanups (back_to);
+
+  /* We've successfully allocated this compilation unit.  Let our caller
+     clean it up when finished with it.	 */
+  discard_cleanups (free_cu_cleanup);
+
+  type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+  dwarf2_per_objfile->read_in_chain = &type_sig->per_cu;
 }
 
 /* Decode simple location descriptions.
@@ -10764,8 +11399,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_p
     }
 }
 
-/* Locate the compilation unit from CU's objfile which contains the
-   DIE at OFFSET.  Raises an error on failure.  */
+/* Locate the .debug_info compilation unit from CU's objfile which contains
+   the DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
 dwarf2_find_containing_comp_unit (unsigned int offset,

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-07-15  1:13       ` Doug Evans
@ 2009-07-15 19:28         ` Tom Tromey
  2009-07-16  1:25           ` Doug Evans
  2009-07-21  0:10           ` Cary Coutant
  0 siblings, 2 replies; 11+ messages in thread
From: Tom Tromey @ 2009-07-15 19:28 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

>>>>> "Doug" == Doug Evans <dje@google.com> writes:

Doug> How about this?
Doug> It addresses the issues raised here:
Doug> http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html

Now that you are a global maintainer (congratulations!) I think you
ought to self-approve it.  There has been plenty of time for comments.

BTW, what is the status of the GCC patch?

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-07-15 19:28         ` Tom Tromey
@ 2009-07-16  1:25           ` Doug Evans
  2009-07-21  0:10           ` Cary Coutant
  1 sibling, 0 replies; 11+ messages in thread
From: Doug Evans @ 2009-07-16  1:25 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, Jul 15, 2009 at 11:57 AM, Tom Tromey<tromey@redhat.com> wrote:
>>>>>> "Doug" == Doug Evans <dje@google.com> writes:
>
> Doug> How about this?
> Doug> It addresses the issues raised here:
> Doug> http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html
>
> Now that you are a global maintainer (congratulations!) I think you
> ought to self-approve it.  There has been plenty of time for comments.

Cool. :-)

> BTW, what is the status of the GCC patch?

I don't know if it's changed, but I'll get an update from Cary.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] comdat types
  2009-07-15 19:28         ` Tom Tromey
  2009-07-16  1:25           ` Doug Evans
@ 2009-07-21  0:10           ` Cary Coutant
  1 sibling, 0 replies; 11+ messages in thread
From: Cary Coutant @ 2009-07-21  0:10 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Doug Evans, gdb-patches

> BTW, what is the status of the GCC patch?

I have one bug that I need to fix on the dwarf4 branch in gcc, then I
need to do another merge from trunk and fix any breakage that causes.
After that, the branch should be ready to merge into the trunk. I hope
to have that bug fixed this week.

-cary


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-07-20 21:36 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-20  0:04 [RFA] comdat types Doug Evans
2009-06-25 19:47 ` Tom Tromey
2009-06-25 20:28   ` Doug Evans
2009-06-25 20:49     ` Tom Tromey
2009-07-15  1:13       ` Doug Evans
2009-07-15 19:28         ` Tom Tromey
2009-07-16  1:25           ` Doug Evans
2009-07-21  0:10           ` Cary Coutant
2009-06-26  1:33     ` Daniel Jacobowitz
2009-06-26  0:01   ` Cary Coutant
2009-06-26  0:54     ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox