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


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

[RFC] Support for comdat-based dwarf debug info reduction for types.


Hi.  Here is my current patch to support comdat-based dwarf debug info
reduction for types.

http://wiki.dwarfstd.org/index.php?title=COMDAT_Type_Sections

I'm hoping someone can find some to give me a review.
The patch can't go in today as the corresponding GCC support isn't
in the main trunk yet.

This patch is incomplete in that the proposal has moved the ODR signature
from the CU header to an attribute.
This is a trivial change, relative to the entire patch.

2008-11-05  Doug Evans  <dje@google.com>

	* include/elf/dwarf2.h (dwarf_tag): New enum DW_TAG_type_unit.
	(dwarf_form): New enums DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(dwarf_attribute): New enum DW_AT_signature.

	* gdb/dwarf2read.c (dwarf2_per_objfile): New members types_size,
	types_buffer, signatured_types.
	(dwarf_types_section): New static global.
	(TYPES_SECTION): New macro.
	(dwarf2_per_cu_data): Change length member to 29 bits from 30 bits.
	New member from_debug_types.
	(signatured_type): New struct.
	(die_reader_params): New struct.
	(TYPES_CU_HAS_ODR_SIGNATURE, CU_VERSION_MASK): New macros.
	(attribute): New member u.signatured_type.
	(DW_SIGNATURED_TYPE): New macro.
	(dwarf2_has_info): Initialize dwarf_types_section.
	(dwarf2_locate_sections): Handle TYPES_SECTION.
	(dwarf2_resize_section): Ditto.
	(dwarf2_build_psymtabs): Handle dwarf_types_section if present.
	(partial_read_comp_unit_head): New arg `buffer'.  All callers updated.
	Mask off flag bits from version before validating version number.
	(read_type_comp_unit_head): New function.
	(hash_type_signature, eq_type_signature, create_debug_types_hash_table,
	process_type_comp_unit, build_type_psymtabs): New functions.
	(dwarf2_build_psymtabs_hard): Call build_type_psymtabs.
	Call read_partial_die_1 instead of read_partial_die.
	(load_comp_unit): Assert not called for .debug_types CUs.
	(skip_children): New arg `buffer'.  All callers updated.
	(skip_one_die): New arg `buffer'.  All callers updated.
	Handle DW_FORM_sig8.
	(locate_pdi_sibling): New arg `buffer'.  All callers updated.
	(queue_comp_unit): Don't load CU or update read_in_chain here.
	(psymtab_to_symtab_1): Load CU here.  Watch for .debug_types CUs.
	(load_full_comp_unit): Assert not called for .debug_types CUs.
	Update read_in_chain.
	(process_die): Handle DW_TAG_type_unit.
	(read_type_unit_scope): New function.
	(read_structure_type): Watch for DW_AT_signature.
	(read_enumation_type): Watch for DW_AT_signature.
	(init_cu_die_reader): New function.
	(read_comp_unit): Call it.  Remove `abfd' arg.  All callers updated.
	(read_die_and_children): Change `cu' arg to `reader' and make first
	parameter.  Remove `abfd' arg.  All callers updated.
	(read_die_and_children_1, read_die_and_siblings, read_full_die): Ditto.
	(load_partial_dies): New arg `buffer'.  All callers updated.
	Call read_partial_die_1 instead of read_partial_die.
	(read_partial_die_1): New function, implements previous
	read_partial_die with new `buffer' argument.
	(read_partial_die): Rewrite as wrapper around read_partial_die_1.
	(find_partial_die): Handle .debug_types CUs.
	(read_attribute_value): Handle DW_FORM_sig8.
	(read_8_bytes): Fix result type.
	(dwarf2_attr_no_follow): New function.
	(die_type,die_containing_type): Handle DW_FORM_sig8.
	(dwarf_tag_name): Handle DW_TAG_type_unit.
	(dwarf_attr_name): Handle DW_AT_signature.
	(dwarf_form_name): Handle DW_FORM_sec_offset, DW_FORM_exprloc,
	DW_FORM_flag_present, DW_FORM_sig8.
	(dump_die_shallow): Handle DW_FORM_sig8.
	(is_ref_attr): New function.
	(dwarf2_get_ref_die_offset): Simplify.
	(maybe_queue_comp_unit): Return int indicating CU was queued.
	All callers updated.
	(follow_die_ref_or_sig): New function.
	(follow_die_ref): Handle .debug_types CUs.
	(follow_die_sig, lookup_signatured_type_at_offset,
	read_signatured_type_at_offset, read_signatured_type,
	lookup_signatured_type): New functions.

diff --git a/include/elf/dwarf2.h b/include/elf/dwarf2.h
index f8d010b..89e2977 100644
--- a/include/elf/dwarf2.h
+++ b/include/elf/dwarf2.h
@@ -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,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ba863fe..ab6e47d 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -164,6 +164,7 @@ struct dwarf2_per_objfile
   unsigned int macinfo_size;
   unsigned int str_size;
   unsigned int ranges_size;
+  unsigned int types_size;
   unsigned int frame_size;
   unsigned int eh_frame_size;
 
@@ -174,6 +175,7 @@ struct dwarf2_per_objfile
   gdb_byte *str_buffer;
   gdb_byte *macinfo_buffer;
   gdb_byte *ranges_buffer;
+  gdb_byte *types_buffer;
   gdb_byte *loc_buffer;
 
   /* A list of all the compilation units.  This is used to locate
@@ -187,6 +189,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;
@@ -203,6 +209,7 @@ static asection *dwarf_loc_section;
 static asection *dwarf_macinfo_section;
 static asection *dwarf_str_section;
 static asection *dwarf_ranges_section;
+static asection *dwarf_types_section;
 asection *dwarf_frame_section;
 asection *dwarf_eh_frame_section;
 
@@ -220,6 +227,7 @@ asection *dwarf_eh_frame_section;
 #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"
 
@@ -361,13 +369,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.  */
@@ -379,6 +387,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;
 
@@ -394,6 +406,47 @@ 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;
+};
+
+/* Encoded in version field of a .debug_types CU,
+   indicates odr_signature field is present.  */
+#define TYPES_CU_HAS_ODR_SIGNATURE 0x8000
+/* Mask of bits used by version number in the CU header version field.  */
+#define CU_VERSION_MASK 0x7fff
+
+/* 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.
+   This struct exists so we can add params without having to add more
+   parameters to functions that already take a lot of parameters.  */
+
+struct die_reader_params
+{
+  /* The bfd of this objfile.  */
+  bfd* abfd;
+
+  /* The CU of the DIE we are parsing.  */
+  struct dwarf2_cu *cu;
+
+  /* Pointer to start of section buffer.
+     This is either the start of .debug_info or .debug_types.  */
+  const gdb_byte *buffer;
+};
+
 /* The line number information for a compilation unit (found in the
    .debug_line section) begins with a "statement program header",
    which contains the following information.  */
@@ -488,7 +541,7 @@ struct partial_die_info
     CORE_ADDR lowpc;
     CORE_ADDR highpc;
 
-    /* Pointer into the info_buffer pointing at the target of
+    /* Pointer into the info_buffer (or types_buffer) pointing at the target of
        DW_AT_sibling, if any.  */
     gdb_byte *sibling;
 
@@ -534,6 +587,7 @@ struct attribute
 	unsigned long unsnd;
 	long int snd;
 	CORE_ADDR addr;
+	struct signatured_type *signatured_type;
       }
     u;
   };
@@ -550,7 +604,7 @@ struct die_info
     /* Abbrev number */
     unsigned int abbrev;
 
-    /* Offset in .debug_info section */
+    /* Offset in .debug_info or .debug_types section.  */
     unsigned int offset;
 
     /* The dies in a compilation unit form an n-ary tree.  PARENT
@@ -583,6 +637,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
@@ -751,6 +806,10 @@ static void dwarf2_build_include_psymtabs (struct dwarf2_cu *,
                                            struct partial_die_info *,
                                            struct partial_symtab *);
 
+static int create_debug_types_hash_table (struct objfile *objfile);
+
+static void build_type_psymtabs (struct objfile *);
+
 static void dwarf2_build_psymtabs_hard (struct objfile *, int);
 
 static void scan_partial_symbols (struct partial_die_info *,
@@ -774,7 +833,7 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
 				    struct dwarf2_cu *cu);
 
 static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
-                                     gdb_byte *info_ptr,
+				     gdb_byte *buffer, gdb_byte *info_ptr,
                                      bfd *abfd,
                                      struct dwarf2_cu *cu);
 
@@ -794,8 +853,15 @@ static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *,
 static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
 						 struct dwarf2_cu *);
 
-static struct partial_die_info *load_partial_dies (bfd *, gdb_byte *, int,
-						   struct dwarf2_cu *);
+static struct partial_die_info *load_partial_dies (bfd *,
+						   gdb_byte *, gdb_byte *,
+						   int, struct dwarf2_cu *);
+
+static gdb_byte *read_partial_die_1 (struct partial_die_info *,
+				     struct abbrev_info *abbrev,
+				     unsigned int, bfd *,
+				     gdb_byte *, gdb_byte *,
+				     struct dwarf2_cu *);
 
 static gdb_byte *read_partial_die (struct partial_die_info *,
                                    struct abbrev_info *abbrev, unsigned int,
@@ -807,9 +873,6 @@ static struct partial_die_info *find_partial_die (unsigned int,
 static void fixup_partial_die (struct partial_die_info *,
 			       struct dwarf2_cu *);
 
-static gdb_byte *read_full_die (struct die_info **, bfd *, gdb_byte *,
-                                struct dwarf2_cu *, int *);
-
 static gdb_byte *read_attribute (struct attribute *, struct attr_abbrev *,
                                  bfd *, gdb_byte *, struct dwarf2_cu *);
 
@@ -824,7 +887,7 @@ static unsigned int read_2_bytes (bfd *, gdb_byte *);
 
 static unsigned int read_4_bytes (bfd *, gdb_byte *);
 
-static unsigned long read_8_bytes (bfd *, gdb_byte *);
+static ULONGEST read_8_bytes (bfd *, gdb_byte *);
 
 static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
 			       unsigned int *);
@@ -859,6 +922,10 @@ static void set_cu_language (unsigned int, struct dwarf2_cu *);
 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);
 
@@ -909,6 +976,8 @@ static char *typename_concat (struct obstack *,
 
 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 *);
@@ -958,23 +1027,27 @@ static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
 static enum dwarf_array_dim_ordering read_array_order (struct die_info *, 
 						       struct dwarf2_cu *);
 
-static struct die_info *read_comp_unit (gdb_byte *, bfd *, struct dwarf2_cu *);
+static struct die_info *read_comp_unit (gdb_byte *, struct dwarf2_cu *);
 
-static struct die_info *read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
-						 struct dwarf2_cu *,
+static struct die_info *read_die_and_children_1 (const struct die_reader_params *reader,
+						 gdb_byte *info_ptr,
 						 gdb_byte **new_info_ptr,
 						 struct die_info *parent);
 
-static struct die_info *read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
-					       struct dwarf2_cu *,
+static struct die_info *read_die_and_children (const struct die_reader_params *reader,
+					       gdb_byte *info_ptr,
 					       gdb_byte **new_info_ptr,
 					       struct die_info *parent);
 
-static struct die_info *read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
-					       struct dwarf2_cu *,
+static struct die_info *read_die_and_siblings (const struct die_reader_params *reader,
+					       gdb_byte *info_ptr,
 					       gdb_byte **new_info_ptr,
 					       struct die_info *parent);
 
+static gdb_byte *read_full_die (const struct die_reader_params *reader,
+				struct die_info **, gdb_byte *,
+				int *);
+
 static void process_die (struct die_info *, struct dwarf2_cu *);
 
 static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
@@ -1014,14 +1087,36 @@ static void dump_die_1 (struct ui_file *, int level, int max_level,
 static void store_in_ref_table (struct die_info *,
 				struct dwarf2_cu *);
 
+static int is_ref_attr (struct attribute *);
+
 static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
 
 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 struct signatured_type * lookup_signatured_type_at_offset
+  (struct objfile *objfile, unsigned int offset);
+
+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);
+
+static struct signatured_type *lookup_signatured_type (struct objfile *,
+						       ULONGEST sig);
+
 /* memory allocation interface */
 
 static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
@@ -1048,8 +1143,9 @@ static void dwarf2_symbol_mark_computed (struct attribute *attr,
 					 struct symbol *sym,
 					 struct dwarf2_cu *cu);
 
-static gdb_byte *skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
-                               struct dwarf2_cu *cu);
+static gdb_byte *skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
+			       struct abbrev_info *abbrev,
+			       struct dwarf2_cu *cu);
 
 static void free_stack_comp_unit (void *);
 
@@ -1112,8 +1208,9 @@ dwarf2_has_info (struct objfile *objfile)
   dwarf_frame_section = 0;
   dwarf_eh_frame_section = 0;
   dwarf_ranges_section = 0;
+  dwarf_types_section = 0;
   dwarf_loc_section = 0;
-  
+
   bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
   return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
 }
@@ -1196,7 +1293,12 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr)
       dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp);
       dwarf_ranges_section = sectp;
     }
-  
+  else if (section_is_p (sectp, TYPES_SECTION))
+    {
+      dwarf2_per_objfile->types_size = bfd_get_section_size (sectp);
+      dwarf_types_section = sectp;
+    }
+
   if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
       && bfd_section_vma (abfd, sectp) == 0)
     dwarf2_per_objfile->has_section_at_zero = 1;
@@ -1230,6 +1332,8 @@ dwarf2_resize_section (asection *sectp, bfd_size_type new_size)
     dwarf2_per_objfile->eh_frame_size = new_size;
   else if (section_is_p (sectp, RANGES_SECTION))
     dwarf2_per_objfile->ranges_size = new_size;
+  else if (section_is_p (sectp, TYPES_SECTION))
+    dwarf2_per_objfile->types_size = new_size;
   else
     internal_error (__FILE__, __LINE__,
 		    _("dwarf2_resize_section: missing section_is_p check: %s"),
@@ -1267,6 +1371,11 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
   else
     dwarf2_per_objfile->ranges_buffer = NULL;
 
+  if (dwarf_types_section)
+    dwarf2_per_objfile->types_buffer = dwarf2_read_section (objfile, dwarf_types_section);
+  else
+    dwarf2_per_objfile->types_buffer = NULL;
+
   if (dwarf_loc_section)
     dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
   else
@@ -1375,35 +1484,66 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
 
 static gdb_byte *
 partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
+			     gdb_byte *buffer, unsigned int buffer_size,
 			     bfd *abfd)
 {
   gdb_byte *beg_of_comp_unit = info_ptr;
+  unsigned short version;
 
   info_ptr = read_comp_unit_head (header, info_ptr, abfd);
 
-  if (header->version != 2 && header->version != 3)
+  version = header->version & CU_VERSION_MASK;
+  if (version != 2 && version != 3)
     error (_("Dwarf Error: wrong version in compilation unit header "
-	   "(is %d, should be %d) [in module %s]"), header->version,
+	   "(is %d, should be %d) [in module %s]"), version,
 	   2, bfd_get_filename (abfd));
 
   if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size)
     error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
 	   "(offset 0x%lx + 6) [in module %s]"),
 	   (long) header->abbrev_offset,
-	   (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+	   (long) (beg_of_comp_unit - buffer),
 	   bfd_get_filename (abfd));
 
   if (beg_of_comp_unit + header->length + header->initial_length_size
-      > dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
+      > buffer + buffer_size)
     error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
 	   "(offset 0x%lx + 0) [in module %s]"),
 	   (long) header->length,
-	   (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+	   (long) (beg_of_comp_unit - buffer),
 	   bfd_get_filename (abfd));
 
   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;
+  if ((cu_header->version & TYPES_CU_HAS_ODR_SIGNATURE) != 0)
+    {
+      /* ODR signature ignored */
+      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.  */
 
@@ -1463,6 +1603,270 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
   free_line_header (lh);
 }
 
+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;
+      if ((version & TYPES_CU_HAS_ODR_SIGNATURE) != 0)
+	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;
+}
+
+/* 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;
+  bfd *abfd = objfile->obfd;
+  gdb_byte *info_ptr = dwarf2_per_objfile->types_buffer + entry->offset;
+  gdb_byte *beg_of_comp_unit = info_ptr;
+  struct cleanup *back_to_inner;
+  struct dwarf2_cu cu;
+  struct abbrev_info *abbrev;
+  unsigned int bytes_read;
+  struct dwarf2_per_cu_data *this_cu;
+  CORE_ADDR lowpc, highpc, baseaddr;
+  struct partial_die_info comp_unit_die;
+  struct partial_symtab *pst;
+
+  this_cu = &entry->per_cu;
+  this_cu->from_debug_types = 1;
+
+  memset (&cu, 0, sizeof (cu));
+
+  obstack_init (&cu.comp_unit_obstack);
+
+  back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
+
+  cu.objfile = objfile;
+  info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
+					  dwarf2_per_objfile->types_buffer,
+					  dwarf2_per_objfile->types_size,
+					  abfd);
+
+  /* Complete the cu_header */
+  cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->types_buffer;
+  cu.header.first_die_offset = info_ptr - beg_of_comp_unit;
+
+  cu.list_in_scope = &file_symbols;
+
+  /* Read the abbrevs for this compilation unit into a table */
+  dwarf2_read_abbrevs (abfd, &cu);
+  make_cleanup (dwarf2_free_abbrev_table, &cu);
+
+  /* Read the compilation unit die */
+  info_ptr += (8
+	       + ((cu.header.version & TYPES_CU_HAS_ODR_SIGNATURE) ? 8 : 0)
+	       + cu.header.offset_size);
+  abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
+  info_ptr = read_partial_die_1 (&comp_unit_die, abbrev, bytes_read, abfd,
+				 dwarf2_per_objfile->types_buffer, info_ptr,
+				 &cu);
+
+  this_cu->offset = cu.header.offset;
+  this_cu->length = cu.header.length + cu.header.initial_length_size;
+
+  /* Set the language we're debugging */
+  set_cu_language (comp_unit_die.language, &cu);
+
+  /* Allocate a new partial symbol table structure */
+  pst = start_psymtab_common (objfile, objfile->section_offsets,
+			      comp_unit_die.name ? comp_unit_die.name : "",
+			      /* TEXTLOW and TEXTHIGH are set below.  */
+			      0,
+			      objfile->global_psymbols.next,
+			      objfile->static_psymbols.next);
+
+  if (comp_unit_die.dirname)
+    pst->dirname = obsavestring (comp_unit_die.dirname,
+				 strlen (comp_unit_die.dirname),
+				 &objfile->objfile_obstack);
+
+  pst->read_symtab_private = (char *) this_cu;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  /* Store the function that reads in the rest of the symbol table */
+  pst->read_symtab = dwarf2_psymtab_to_symtab;
+
+  /* If this compilation unit was already read in, free the
+     cached copy in order to read it in again.	This is
+     necessary because we skipped some symbols when we first
+     read in the compilation unit (see load_partial_dies).
+     This problem could be avoided, but the benefit is
+     unclear.  */
+  if (this_cu->cu != NULL)
+    free_one_cached_comp_unit (this_cu->cu);
+
+  cu.per_cu = this_cu;
+
+  /* Note that this is a pointer to our stack frame, being
+     added to a global data structure.	It will be cleaned up
+     in free_stack_comp_unit when we finish with this
+     compilation unit.	*/
+  this_cu->cu = &cu;
+
+  this_cu->psymtab = pst;
+
+  /* Check if comp unit has_children.
+     If so, read the rest of the partial symbols from this comp unit.
+     If not, there's no more debug_info for this comp unit. */
+  if (comp_unit_die.has_children)
+    {
+      struct partial_die_info *first_die;
+
+      lowpc = ((CORE_ADDR) -1);
+      highpc = ((CORE_ADDR) 0);
+
+      first_die = load_partial_dies (abfd,
+				     dwarf2_per_objfile->types_buffer,
+				     info_ptr, 1, &cu);
+
+      scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
+
+      /* If we didn't find a lowpc, set it to highpc to avoid
+	 complaints from `maint check'.	 */
+      if (lowpc == ((CORE_ADDR) -1))
+	lowpc = highpc;
+
+      /* If the compilation unit didn't have an explicit address range,
+	 then use the information extracted from its child dies.  */
+      if (! comp_unit_die.has_pc_info)
+	{
+	  comp_unit_die.lowpc = lowpc;
+	  comp_unit_die.highpc = highpc;
+	}
+    }
+  pst->textlow = comp_unit_die.lowpc + baseaddr;
+  pst->texthigh = comp_unit_die.highpc + baseaddr;
+
+  pst->n_global_syms = objfile->global_psymbols.next -
+    (objfile->global_psymbols.list + pst->globals_offset);
+  pst->n_static_syms = objfile->static_psymbols.next -
+    (objfile->static_psymbols.list + pst->statics_offset);
+  sort_pst_symbols (pst);
+
+  do_cleanups (back_to_inner);
+
+  return 1;
+}
+
+/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+   Build partial symbol tables for the .debug_types comp-units.
+   FIXME: A lot of duplicated code from dwarf2_build_psymtabs_hard.
+*/
+
+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.  */
@@ -1486,6 +1890,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
      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 = addrmap_create_mutable
@@ -1522,7 +1928,10 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
       back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
 
       cu.objfile = objfile;
-      info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd);
+      info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
+					      dwarf2_per_objfile->info_buffer,
+					      dwarf2_per_objfile->info_size,
+					      abfd);
 
       /* Complete the cu_header */
       cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
@@ -1538,8 +1947,11 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 
       /* Read the compilation unit die */
       abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
-      info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
-				   abfd, info_ptr, &cu);
+      /* This doesn't call read_partial_die because the cu->per_cu backlink
+	 hasn't been set yet.  */
+      info_ptr = read_partial_die_1 (&comp_unit_die, abbrev, bytes_read, abfd,
+				     dwarf2_per_objfile->info_buffer, info_ptr,
+				     &cu);
 
       if (comp_unit_die.tag == DW_TAG_partial_unit)
 	{
@@ -1610,7 +2022,9 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 	  lowpc = ((CORE_ADDR) -1);
 	  highpc = ((CORE_ADDR) 0);
 
-	  first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
+	  first_die = load_partial_dies (abfd,
+					 dwarf2_per_objfile->info_buffer,
+					 info_ptr, 1, &cu);
 
 	  scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
 
@@ -1679,6 +2093,8 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile)
   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;
 
@@ -1688,7 +2104,10 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile)
   obstack_init (&cu->comp_unit_obstack);
 
   cu->objfile = objfile;
-  info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd);
+  info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
+					  dwarf2_per_objfile->info_buffer,
+					  dwarf2_per_objfile->info_size,
+					  abfd);
 
   /* Complete the cu_header.  */
   cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
@@ -1715,15 +2134,12 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile)
      If so, read the rest of the partial symbols from this comp unit.
      If not, there's no more debug_info for this comp unit. */
   if (comp_unit_die.has_children)
-    load_partial_dies (abfd, info_ptr, 0, cu);
+    load_partial_dies (abfd, dwarf2_per_objfile->info_buffer, info_ptr, 0, cu);
 
   do_cleanups (back_to);
 }
 
-/* Create a list of all compilation units in OBJFILE.  We do this only
-   if an inter-comp-unit reference is found; presumably if there is one,
-   there will be many, and one will occur early in the .debug_info section.
-   So there's no point in building this list incrementally.  */
+/* Create a list of all compilation units in OBJFILE.  */
 
 static void
 create_all_comp_units (struct objfile *objfile)
@@ -2320,7 +2736,7 @@ peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
    DIE.  Any children of the skipped DIEs will also be skipped.  */
 
 static gdb_byte *
-skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu)
+skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu)
 {
   struct abbrev_info *abbrev;
   unsigned int bytes_read;
@@ -2331,7 +2747,7 @@ skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu)
       if (abbrev == NULL)
 	return info_ptr + bytes_read;
       else
-	info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+	info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
     }
 }
 
@@ -2342,8 +2758,8 @@ skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu)
    children.  */
 
 static gdb_byte *
-skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
-	      struct dwarf2_cu *cu)
+skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
+	      struct abbrev_info *abbrev, struct dwarf2_cu *cu)
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -2360,8 +2776,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
 	  if (attr.form == DW_FORM_ref_addr)
 	    complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
 	  else
-	    return dwarf2_per_objfile->info_buffer
-	      + dwarf2_get_ref_die_offset (&attr);
+	    return buffer + dwarf2_get_ref_die_offset (&attr);
 	}
 
       /* If it isn't DW_AT_sibling, skip this attribute.  */
@@ -2388,6 +2803,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
 	  break;
 	case DW_FORM_data8:
 	case DW_FORM_ref8:
+	case DW_FORM_sig8:
 	  info_ptr += 8;
 	  break;
 	case DW_FORM_string:
@@ -2430,7 +2846,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
     }
 
   if (abbrev->has_children)
-    return skip_children (info_ptr, cu);
+    return skip_children (buffer, info_ptr, cu);
   else
     return info_ptr;
 }
@@ -2439,7 +2855,8 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
    the next DIE after ORIG_PDI.  */
 
 static gdb_byte *
-locate_pdi_sibling (struct partial_die_info *orig_pdi, gdb_byte *info_ptr,
+locate_pdi_sibling (struct partial_die_info *orig_pdi,
+		    gdb_byte *buffer, gdb_byte *info_ptr,
 		    bfd *abfd, struct dwarf2_cu *cu)
 {
   /* Do we know the sibling already?  */
@@ -2454,7 +2871,7 @@ locate_pdi_sibling (struct partial_die_info *orig_pdi, gdb_byte *info_ptr,
 
   /* Skip the children the long way.  */
 
-  return skip_children (info_ptr, cu);
+  return skip_children (buffer, info_ptr, cu);
 }
 
 /* Expand this partial symbol table into a full symbol table.  */
@@ -2508,12 +2925,6 @@ queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
     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.  */
@@ -2608,6 +3019,11 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
 
   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
@@ -2617,7 +3033,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   do_cleanups (back_to);
 }
 
-/* Load the DIEs associated with PST and PER_CU into memory.  */
+/* Load the DIEs associated with PER_CU into memory.  */
 
 static struct dwarf2_cu *
 load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
@@ -2630,6 +3046,8 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
   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;
 
@@ -2638,6 +3056,9 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
   cu = xmalloc (sizeof (struct dwarf2_cu));
   memset (cu, 0, sizeof (struct dwarf2_cu));
 
+  /* We use this obstack for block values in dwarf_alloc_block.  */
+  obstack_init (&cu->comp_unit_obstack);
+
   /* If an error occurs while loading, release our storage.  */
   free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
 
@@ -2651,15 +3072,13 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
   back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
 
   cu->header.offset = offset;
+  /* FIXME: Set cu->header.first_die_offset?  */
 
   cu->per_cu = per_cu;
   per_cu->cu = cu;
   cu->type_hash = per_cu->type_hash;
 
-  /* We use this obstack for block values in dwarf_alloc_block.  */
-  obstack_init (&cu->comp_unit_obstack);
-
-  cu->dies = read_comp_unit (info_ptr, abfd, cu);
+  cu->dies = read_comp_unit (info_ptr, cu);
 
   /* We try not to read any attributes in this function, because not
      all objfiles needed for references have been loaded yet, and symbol
@@ -2677,6 +3096,9 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
      clean it up when finished with it.  */
   discard_cleanups (free_cu_cleanup);
 
+  per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+  dwarf2_per_objfile->read_in_chain = per_cu;
+
   return cu;
 }
 
@@ -2764,6 +3186,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     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;
@@ -3003,6 +3428,91 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   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)
@@ -4096,8 +4606,31 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   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);
+    }
+
+  if (dwarf2_die_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "\nReading structure type.\n");
+      dump_die (die, dwarf2_die_debug);
+    }
+
   type = alloc_type (objfile);
   INIT_CPLUS_SPECIFIC (type);
+
   name = dwarf2_name (die, cu);
   if (name != NULL)
     {
@@ -4309,6 +4842,18 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   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;
@@ -5202,11 +5747,28 @@ die_eq (const void *item_lhs, const void *item_rhs)
   return die_lhs->offset == die_rhs->offset;
 }
 
+/* Initialize a die_reader_params struct from a dwarf2_cu struct.  */
+
+static void
+init_cu_die_reader (struct die_reader_params *reader,
+		    struct dwarf2_cu *cu)
+{
+  reader->abfd = cu->objfile->obfd;
+  reader->cu = cu;
+  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.  */
 
 static struct die_info *
-read_comp_unit (gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
+read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu)
 {
+  struct die_reader_params reader_specs;
+
+  gdb_assert (cu->die_hash == NULL);
   cu->die_hash
     = htab_create_alloc_ex (cu->header.length / 12,
 			    die_hash,
@@ -5216,24 +5778,33 @@ read_comp_unit (gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
 			    hashtab_obstack_allocate,
 			    dummy_obstack_deallocate);
 
-  return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
+  init_cu_die_reader (&reader_specs, cu);
+
+  return read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL);
 }
 
 /* Main entry point for reading a DIE and all children.
    Read the DIE and dump it if requested.  */
 
 static struct die_info *
-read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
-		       struct dwarf2_cu *cu,
+read_die_and_children (const struct die_reader_params *reader,
+		       gdb_byte *info_ptr,
 		       gdb_byte **new_info_ptr,
 		       struct die_info *parent)
 {
-  struct die_info *result = read_die_and_children_1 (info_ptr, abfd, cu,
+  struct die_info *result = read_die_and_children_1 (reader, info_ptr,
 						     new_info_ptr, parent);
 
   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);
     }
 
@@ -5247,8 +5818,8 @@ read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
    is the parent of the die in question.  */
 
 static struct die_info *
-read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
-			 struct dwarf2_cu *cu,
+read_die_and_children_1 (const struct die_reader_params *reader,
+			 gdb_byte *info_ptr,
 			 gdb_byte **new_info_ptr,
 			 struct die_info *parent)
 {
@@ -5256,18 +5827,17 @@ read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
   gdb_byte *cur_ptr;
   int has_children;
 
-  cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
+  cur_ptr = read_full_die (reader, &die, info_ptr, &has_children);
   if (die == NULL)
     {
       *new_info_ptr = cur_ptr;
       return NULL;
     }
-  store_in_ref_table (die, cu);
+  store_in_ref_table (die, reader->cu);
 
   if (has_children)
     {
-      die->child = read_die_and_siblings (cur_ptr, abfd, cu,
-					  new_info_ptr, die);
+      die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die);
     }
   else
     {
@@ -5277,6 +5847,7 @@ read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
 
   die->sibling = NULL;
   die->parent = parent;
+
   return die;
 }
 
@@ -5285,8 +5856,8 @@ read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
    in read_die_and_children.  */
 
 static struct die_info *
-read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
-		       struct dwarf2_cu *cu,
+read_die_and_siblings (const struct die_reader_params *reader,
+		       gdb_byte *info_ptr,
 		       gdb_byte **new_info_ptr,
 		       struct die_info *parent)
 {
@@ -5299,7 +5870,7 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
   while (1)
     {
       struct die_info *die
-	= read_die_and_children_1 (cur_ptr, abfd, cu, &cur_ptr, parent);
+	= read_die_and_children_1 (reader, cur_ptr, &cur_ptr, parent);
 
       if (die == NULL)
 	{
@@ -5316,6 +5887,55 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
     }
 }
 
+/* Read the die from the .debug_info section buffer.  Set DIEP to
+   point to a newly allocated die with its information, except for its
+   child, sibling, and parent fields.  Set HAS_CHILDREN to tell
+   whether the die has children or not.  */
+
+static gdb_byte *
+read_full_die (const struct die_reader_params *reader,
+	       struct die_info **diep, gdb_byte *info_ptr,
+	       int *has_children)
+{
+  unsigned int abbrev_number, bytes_read, i, offset;
+  struct abbrev_info *abbrev;
+  struct die_info *die;
+  struct dwarf2_cu *cu = reader->cu;
+  bfd *abfd = reader->abfd;
+
+  offset = info_ptr - reader->buffer;
+  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+  info_ptr += bytes_read;
+  if (!abbrev_number)
+    {
+      *diep = NULL;
+      *has_children = 0;
+      return info_ptr;
+    }
+
+  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));
+    }
+  die = dwarf_alloc_die (cu, abbrev->num_attrs);
+  die->offset = offset;
+  die->tag = abbrev->tag;
+  die->abbrev = abbrev_number;
+
+  die->num_attrs = abbrev->num_attrs;
+
+  for (i = 0; i < abbrev->num_attrs; ++i)
+    info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
+			       abfd, info_ptr, cu);
+
+  *diep = die;
+  *has_children = abbrev->has_children;
+  return info_ptr;
+}
+
 /* Decompress a section that was compressed using zlib.  Store the
    decompressed buffer, and its size, in OUTBUF and OUTSIZE.  */
 
@@ -5617,8 +6237,8 @@ is_type_tag_for_partial (int tag)
 /* Load all DIEs that are interesting for partial symbols into memory.  */
 
 static struct partial_die_info *
-load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
-		   struct dwarf2_cu *cu)
+load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
+		   int building_psymtab, struct dwarf2_cu *cu)
 {
   struct partial_die_info *part_die;
   struct partial_die_info *parent_die, *last_die, *first_die = NULL;
@@ -5683,12 +6303,12 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
 	  && abbrev->tag != DW_TAG_member)
 	{
 	  /* Otherwise we skip to the next sibling, if any.  */
-	  info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+	  info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
 	  continue;
 	}
 
-      info_ptr = read_partial_die (part_die, abbrev, bytes_read,
-				   abfd, info_ptr, cu);
+      info_ptr = read_partial_die_1 (part_die, abbrev, bytes_read,
+				     abfd, buffer, info_ptr, cu);
 
       /* This two-pass algorithm for processing partial symbols has a
 	 high cost in cache pressure.  Thus, handle some simple cases
@@ -5718,7 +6338,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
 				 VAR_DOMAIN, LOC_TYPEDEF,
 				 &cu->objfile->static_psymbols,
 				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
-	  info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+	  info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
 	  continue;
 	}
 
@@ -5743,7 +6363,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
 				 : &cu->objfile->static_psymbols,
 				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
 
-	  info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+	  info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
 	  continue;
 	}
 
@@ -5827,7 +6447,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
 	}
 
       /* Otherwise we skip to the next sibling, if any.  */
-      info_ptr = locate_pdi_sibling (last_die, info_ptr, abfd, cu);
+      info_ptr = locate_pdi_sibling (last_die, buffer, info_ptr, abfd, cu);
 
       /* Back to the top, do it again.  */
     }
@@ -5836,10 +6456,11 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
 /* Read a minimal amount of information into the minimal die structure.  */
 
 static gdb_byte *
-read_partial_die (struct partial_die_info *part_die,
-		  struct abbrev_info *abbrev,
-		  unsigned int abbrev_len, bfd *abfd,
-		  gdb_byte *info_ptr, struct dwarf2_cu *cu)
+read_partial_die_1 (struct partial_die_info *part_die,
+		    struct abbrev_info *abbrev,
+		    unsigned int abbrev_len, bfd *abfd,
+		    gdb_byte *buffer, gdb_byte *info_ptr,
+		    struct dwarf2_cu *cu)
 {
   unsigned int bytes_read, i;
   struct attribute attr;
@@ -5857,7 +6478,7 @@ read_partial_die (struct partial_die_info *part_die,
 
   memset (part_die, 0, sizeof (struct partial_die_info));
 
-  part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer;
+  part_die->offset = info_ptr - buffer;
 
   info_ptr += abbrev_len;
 
@@ -5876,7 +6497,6 @@ read_partial_die (struct partial_die_info *part_die,
       switch (attr.name)
 	{
 	case DW_AT_name:
-
 	  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
 	  if (part_die->name == NULL)
 	    part_die->name = DW_STRING (&attr);
@@ -5957,7 +6577,7 @@ read_partial_die (struct partial_die_info *part_die,
 	  if (attr.form == DW_FORM_ref_addr)
 	    complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
 	  else
-	    part_die->sibling = dwarf2_per_objfile->info_buffer
+	    part_die->sibling = buffer
 	      + dwarf2_get_ref_die_offset (&attr);
 	  break;
         case DW_AT_stmt_list:
@@ -6015,6 +6635,22 @@ read_partial_die (struct partial_die_info *part_die,
   return info_ptr;
 }
 
+/* Read a minimal amount of information from .debug_info into the
+   minimal die structure.  */
+
+static gdb_byte *
+read_partial_die (struct partial_die_info *part_die,
+		  struct abbrev_info *abbrev,
+		  unsigned int abbrev_len, bfd *abfd,
+		  gdb_byte *info_ptr,
+		  struct dwarf2_cu *cu)
+{
+  gdb_assert (! cu->per_cu->from_debug_types);
+
+  return read_partial_die_1 (part_die, abbrev, abbrev_len, abfd,
+			     dwarf2_per_objfile->info_buffer, info_ptr, cu);
+}
+
 /* Find a cached partial DIE at OFFSET in CU.  */
 
 static struct partial_die_info *
@@ -6029,7 +6665,9 @@ find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu)
   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 (except when referencing other types via DW_FORM_sig8).  */
 
 static struct partial_die_info *
 find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
@@ -6037,6 +6675,16 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
   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;
+      /* Creating unnecessary diffs in a patch for a prototype
+	 isn't worth it.  */
+      goto NotFound;
+    }
+
   if (offset_in_cu_p (&cu->header, offset))
     {
       pd = find_partial_die_in_comp_unit (offset, cu);
@@ -6081,12 +6729,16 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
 				   per_cu->cu->objfile->obfd, info_ptr,
 				   per_cu->cu);
       if (comp_unit_die.has_children)
-	load_partial_dies (per_cu->cu->objfile->obfd, info_ptr, 0, per_cu->cu);
+	load_partial_dies (per_cu->cu->objfile->obfd,
+			   dwarf2_per_objfile->info_buffer, info_ptr,
+			   0, per_cu->cu);
       do_cleanups (back_to);
 
       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"),
@@ -6136,52 +6788,6 @@ fixup_partial_die (struct partial_die_info *part_die,
     guess_structure_name (part_die, cu);
 }
 
-/* Read the die from the .debug_info section buffer.  Set DIEP to
-   point to a newly allocated die with its information, except for its
-   child, sibling, and parent fields.  Set HAS_CHILDREN to tell
-   whether the die has children or not.  */
-
-static gdb_byte *
-read_full_die (struct die_info **diep, bfd *abfd, gdb_byte *info_ptr,
-	       struct dwarf2_cu *cu, int *has_children)
-{
-  unsigned int abbrev_number, bytes_read, i, offset;
-  struct abbrev_info *abbrev;
-  struct die_info *die;
-
-  offset = info_ptr - dwarf2_per_objfile->info_buffer;
-  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-  info_ptr += bytes_read;
-  if (!abbrev_number)
-    {
-      *diep = NULL;
-      *has_children = 0;
-      return info_ptr;
-    }
-
-  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));
-    }
-  die = dwarf_alloc_die (cu, abbrev->num_attrs);
-  die->offset = offset;
-  die->tag = abbrev->tag;
-  die->abbrev = abbrev_number;
-
-  die->num_attrs = abbrev->num_attrs;
-
-  for (i = 0; i < abbrev->num_attrs; ++i)
-    info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
-			       abfd, info_ptr, cu);
-
-  *diep = die;
-  *has_children = abbrev->has_children;
-  return info_ptr;
-}
-
 /* Read an attribute value described by an attribute form.  */
 
 static gdb_byte *
@@ -6286,6 +6892,14 @@ read_attribute_value (struct attribute *attr, unsigned form,
       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.  */
+      DW_SIGNATURED_TYPE (attr) =
+	lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr));
+      /* FIXME: flag error if not found */
+      info_ptr += 8;
+      break;
     case DW_FORM_ref_udata:
       DW_ADDR (attr) = (cu->header.offset
 			+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
@@ -6370,7 +6984,7 @@ read_4_signed_bytes (bfd *abfd, gdb_byte *buf)
   return bfd_get_signed_32 (abfd, buf);
 }
 
-static unsigned long
+static ULONGEST
 read_8_bytes (bfd *abfd, gdb_byte *buf)
 {
   return bfd_get_64 (abfd, buf);
@@ -6747,6 +7361,24 @@ dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
   return NULL;
 }
 
+/* Return the named attribute or NULL if not there,
+   but do not follow DW_AT_specification, etc.  */
+
+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.  */
@@ -7852,8 +8484,8 @@ die_type (struct die_info *die, struct dwarf2_cu *cu)
       /* 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)
@@ -7878,9 +8510,10 @@ die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
   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)
     {
       if (type_die)
@@ -8277,6 +8910,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:
@@ -8492,6 +9127,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:
@@ -8630,6 +9268,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";
     default:
       return "DW_FORM_<unknown>";
     }
@@ -9173,6 +9819,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 	case DW_FORM_sdata:
 	  fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i]));
 	  break;
+	case DW_FORM_sig8:
+	  fprintf_unfiltered (f, "signatured type, offset: 0x%lx",
+			      DW_UNSND (&die->attrs[i]));
+	  break;
 	case DW_FORM_string:
 	case DW_FORM_strp:
 	  fprintf_unfiltered (f, "string: \"%s\"",
@@ -9257,11 +9907,9 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
   *slot = die;
 }
 
-static unsigned int
-dwarf2_get_ref_die_offset (struct attribute *attr)
+static int
+is_ref_attr (struct attribute *attr)
 {
-  unsigned int result = 0;
-
   switch (attr->form)
     {
     case DW_FORM_ref_addr:
@@ -9270,14 +9918,22 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
     case DW_FORM_ref4:
     case DW_FORM_ref8:
     case DW_FORM_ref_udata:
-      result = DW_ADDR (attr);
-      break;
+      return 1;
     default:
-      complaint (&symfile_complaints,
-		 _("unsupported die ref attribute form: '%s'"),
-		 dwarf_form_name (attr->form));
+      return 0;
     }
-  return result;
+}
+
+static unsigned int
+dwarf2_get_ref_die_offset (struct attribute *attr)
+{
+  if (is_ref_attr (attr))
+    return DW_ADDR (attr);
+
+  complaint (&symfile_complaints,
+	     _("unsupported die ref attribute form: '%s'"),
+	     dwarf_form_name (attr->form));
+  return 0;
 }
 
 /* Return the constant value held by the given attribute.  Return -1
@@ -9303,9 +9959,11 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
 }
 
 /* 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)
 {
@@ -9315,20 +9973,52 @@ maybe_queue_comp_unit (struct dwarf2_cu *this_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;
 }
 
+/* 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;
+}
+
+/* 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 (struct die_info *src_die, struct attribute *attr,
 		struct dwarf2_cu **ref_cu)
@@ -9338,15 +10028,31 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
   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))
+	{
+	  /* Creating unnecessary diffs in a patch for a prototype
+	     isn't worth it.  */
+	  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;
     }
@@ -9359,9 +10065,176 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
   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;
+
+  /* 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.
+   Returns NULL if type is not found.  */
+
+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);
+
+  gdb_assert (type_sig != NULL);
+  gdb_assert (offset == type_sig->offset);
+
+  return type_sig;
+}
+
+/* Read in a signatured type 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_params 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;
+}
+
+/* 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;
 }
 
 /* Decode simple location descriptions.
@@ -10175,8 +11048,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
     }
 }
 
-/* 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,
@@ -10460,9 +11333,6 @@ get_die_type (struct die_info *die, struct dwarf2_cu *cu)
     return NULL;
 }
 
-/* Set the mark field in CU and in every other compilation unit in the
-   cache that we must keep because we are keeping CU.  */
-
 /* Add a dependence relationship from CU to REF_PER_CU.  */
 
 static void
@@ -10502,6 +11372,9 @@ dwarf2_mark_helper (void **slot, void *data)
   return 1;
 }
 
+/* Set the mark field in CU and in every other compilation unit in the
+   cache that we must keep because we are keeping CU.  */
+
 static void
 dwarf2_mark (struct dwarf2_cu *cu)
 {


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