8faa3f8
--- valgrind-3.7.0/memcheck/tests/Makefile.am	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/memcheck/tests/Makefile.am	(revision 12491)
8faa3f8
@@ -76,6 +76,7 @@ EXTRA_DIST = \
8faa3f8
 	deep_templates.stdout.exp deep_templates.stderr.exp \
8faa3f8
 	describe-block.stderr.exp describe-block.vgtest \
8faa3f8
 	doublefree.stderr.exp doublefree.vgtest \
8faa3f8
+	dw4.vgtest dw4.stderr.exp dw4.stdout.exp \
8faa3f8
 	err_disable1.vgtest err_disable1.stderr.exp \
8faa3f8
 	err_disable2.vgtest err_disable2.stderr.exp \
8faa3f8
 	err_disable3.vgtest err_disable3.stderr.exp \
8faa3f8
@@ -281,6 +282,9 @@ check_PROGRAMS = \
8faa3f8
 	wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \
8faa3f8
 	writev1
8faa3f8
 
8faa3f8
+if DWARF4
8faa3f8
+check_PROGRAMS += dw4
8faa3f8
+endif
8faa3f8
 
8faa3f8
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
8faa3f8
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
8faa3f8
@@ -299,6 +303,8 @@ endif
8faa3f8
 deep_templates_SOURCES	= deep_templates.cpp
8faa3f8
 deep_templates_CXXFLAGS	= $(AM_CFLAGS) -O -gstabs
8faa3f8
 
8faa3f8
+dw4_CFLAGS		= $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section
8faa3f8
+
8faa3f8
 err_disable3_LDADD 	= -lpthread
8faa3f8
 err_disable4_LDADD 	= -lpthread
8faa3f8
 
8faa3f8
--- valgrind-3.7.0/memcheck/tests/dw4.c	(revision 0)
8faa3f8
+++ valgrind-3.7.0/memcheck/tests/dw4.c	(revision 12491)
8faa3f8
@@ -0,0 +1,54 @@
8faa3f8
+
8faa3f8
+/* Check of variable location identification when using .debug_types.  */
8faa3f8
+
8faa3f8
+/* Relevant compile flags are:
8faa3f8
+
8faa3f8
+   -Wall -g -I$prefix/include/valgrind -gdwarf-4 -fdebug-types-section
8faa3f8
+
8faa3f8
+   eg -Wall -g -I`pwd`/Inst/include/valgrind -gdwarf-4 -fdebug-types-section
8faa3f8
+*/
8faa3f8
+
8faa3f8
+#include <stdio.h>
8faa3f8
+#include <stdlib.h>
8faa3f8
+#include <assert.h>
8faa3f8
+#include "memcheck/memcheck.h"
8faa3f8
+
8faa3f8
+/* Cause memcheck to complain about the address "a" and so to print
8faa3f8
+   its best guess as to what "a" actually is.  a must be
8faa3f8
+   addressible. */
8faa3f8
+
8faa3f8
+void croak ( void* aV )
8faa3f8
+{
8faa3f8
+  char* a = (char*)aV;
8faa3f8
+  char* undefp = malloc(1);
8faa3f8
+  char saved = *a;
8faa3f8
+  assert(undefp);
8faa3f8
+  *a = *undefp;
8faa3f8
+  VALGRIND_CHECK_MEM_IS_DEFINED(a, 1);
8faa3f8
+  *a = saved;
8faa3f8
+  free(undefp);
8faa3f8
+}
8faa3f8
+
8faa3f8
+struct s1
8faa3f8
+{
8faa3f8
+  char c;
8faa3f8
+  short s;
8faa3f8
+  int i;
8faa3f8
+  long l;
8faa3f8
+  float f;
8faa3f8
+  double d;
8faa3f8
+};
8faa3f8
+
8faa3f8
+struct s1 S2[30];
8faa3f8
+
8faa3f8
+int main ( void )
8faa3f8
+{
8faa3f8
+  struct s1 local;
8faa3f8
+  struct s1* onheap = malloc(sizeof (struct s1));
8faa3f8
+  assert(onheap);
8faa3f8
+  croak(&onheap->i);
8faa3f8
+
8faa3f8
+  croak( &S2[0].i );
8faa3f8
+  croak( &local.i );
8faa3f8
+  return 0;
8faa3f8
+}
8faa3f8
--- valgrind-3.7.0/memcheck/tests/dw4.stderr.exp	(revision 0)
8faa3f8
+++ valgrind-3.7.0/memcheck/tests/dw4.stderr.exp	(revision 12491)
8faa3f8
@@ -0,0 +1,19 @@
8faa3f8
+Uninitialised byte(s) found during client check request
8faa3f8
+   at 0x........: croak (dw4.c:27)
8faa3f8
+   by 0x........: main (dw4.c:49)
8faa3f8
+ Address 0x........ is 4 bytes inside a block of size 32 alloc'd
8faa3f8
+   at 0x........: malloc (vg_replace_malloc.c:...)
8faa3f8
+   by 0x........: main (dw4.c:47)
8faa3f8
+
8faa3f8
+Uninitialised byte(s) found during client check request
8faa3f8
+   at 0x........: croak (dw4.c:27)
8faa3f8
+   by 0x........: main (dw4.c:51)
8faa3f8
+ Location 0x........ is 0 bytes inside S2[0].i,
8faa3f8
+ a global variable declared at dw4.c:42
8faa3f8
+
8faa3f8
+Uninitialised byte(s) found during client check request
8faa3f8
+   at 0x........: croak (dw4.c:27)
8faa3f8
+   by 0x........: main (dw4.c:52)
8faa3f8
+ Location 0x........ is 0 bytes inside local.i,
8faa3f8
+ declared at dw4.c:46, in frame #1 of thread 1
8faa3f8
+
8faa3f8
--- valgrind-3.7.0/memcheck/tests/dw4.vgtest	(revision 0)
8faa3f8
+++ valgrind-3.7.0/memcheck/tests/dw4.vgtest	(revision 12491)
8faa3f8
@@ -0,0 +1,2 @@
8faa3f8
+prog: dw4
8faa3f8
+vgopts: --read-var-info=yes -q
8faa3f8
--- valgrind-3.7.0/configure.in	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/configure.in	(revision 12491)
8faa3f8
@@ -1453,6 +1453,26 @@ AC_MSG_RESULT([no])
8faa3f8
 CFLAGS=$safe_CFLAGS
8faa3f8
 
8faa3f8
 
8faa3f8
+# does this compiler support -gdwarf-4 -fdebug-types-section ?
8faa3f8
+
8faa3f8
+AC_MSG_CHECKING([if gcc accepts -gdwarf-4 -fdebug-types-section])
8faa3f8
+
8faa3f8
+safe_CFLAGS=$CFLAGS
8faa3f8
+CFLAGS="-gdwarf-4 -fdebug-types-section"
8faa3f8
+
8faa3f8
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
8faa3f8
+  return 0;
8faa3f8
+]])], [
8faa3f8
+ac_have_dwarf4=yes
8faa3f8
+AC_MSG_RESULT([yes])
8faa3f8
+], [
8faa3f8
+ac_have_dwarf4=no
8faa3f8
+AC_MSG_RESULT([no])
8faa3f8
+])
8faa3f8
+AM_CONDITIONAL(DWARF4, test x$ac_have_dwarf4 = xyes)
8faa3f8
+CFLAGS=$safe_CFLAGS
8faa3f8
+
8faa3f8
+
8faa3f8
 # does the linker support -Wl,--build-id=none ?  Note, it's
8faa3f8
 # important that we test indirectly via whichever C compiler
8faa3f8
 # is selected, rather than testing /usr/bin/ld or whatever
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/readdwarf.c	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/readdwarf.c	(revision 12491)
8faa3f8
@@ -1166,6 +1166,7 @@ void read_unitinfo_dwarf2( /*OUT*/UnitIn
8faa3f8
 void ML_(read_debuginfo_dwarf3)
8faa3f8
         ( struct _DebugInfo* di,
8faa3f8
           UChar* debug_info_img, Word debug_info_sz, /* .debug_info */
8faa3f8
+          UChar* debug_types_img, Word debug_types_sz, /* .debug_types */
8faa3f8
           UChar* debug_abbv_img, Word debug_abbv_sz, /* .debug_abbrev */
8faa3f8
           UChar* debug_line_img, Word debug_line_sz, /* .debug_line */
8faa3f8
           UChar* debug_str_img,  Word debug_str_sz ) /* .debug_str */
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/readelf.c	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/readelf.c	(revision 12491)
8faa3f8
@@ -2072,6 +2072,7 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
       UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
8faa3f8
       UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
8faa3f8
       UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
8faa3f8
+      UChar*     debug_types_img  = NULL; /* .debug_types  (dwarf4) */
8faa3f8
       UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
8faa3f8
       UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
8faa3f8
       UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
8faa3f8
@@ -2093,6 +2094,7 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
       SizeT      stabstr_sz      = 0;
8faa3f8
       SizeT      debug_line_sz   = 0;
8faa3f8
       SizeT      debug_info_sz   = 0;
8faa3f8
+      SizeT      debug_types_sz   = 0;
8faa3f8
       SizeT      debug_abbv_sz   = 0;
8faa3f8
       SizeT      debug_str_sz    = 0;
8faa3f8
       SizeT      debug_ranges_sz = 0;
8faa3f8
@@ -2168,6 +2170,7 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
 
8faa3f8
          FIND(".debug_line",    debug_line_sz,   debug_line_img)
8faa3f8
          FIND(".debug_info",    debug_info_sz,   debug_info_img)
8faa3f8
+         FIND(".debug_types",   debug_types_sz,  debug_types_img)
8faa3f8
          FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
8faa3f8
          FIND(".debug_str",     debug_str_sz,    debug_str_img)
8faa3f8
          FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
8faa3f8
@@ -2425,6 +2428,8 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
             FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
8faa3f8
             FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
8faa3f8
             FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
8faa3f8
+            FIND(need_dwarf2, ".debug_types",  debug_types_sz,
8faa3f8
+		                                            debug_types_img)
8faa3f8
             FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
8faa3f8
             FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
8faa3f8
             FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 
8faa3f8
@@ -2516,6 +2521,7 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
          /* The old reader: line numbers and unwind info only */
8faa3f8
          ML_(read_debuginfo_dwarf3) ( di,
8faa3f8
                                       debug_info_img, debug_info_sz,
8faa3f8
+                                      debug_types_img, debug_types_sz,
8faa3f8
                                       debug_abbv_img, debug_abbv_sz,
8faa3f8
                                       debug_line_img, debug_line_sz,
8faa3f8
                                       debug_str_img,  debug_str_sz );
8faa3f8
@@ -2528,6 +2534,7 @@ Bool ML_(read_elf_debug_info) ( struct _
8faa3f8
              || VG_(clo_read_var_info) /* the user asked for it */) {
8faa3f8
             ML_(new_dwarf3_reader)(
8faa3f8
                di, debug_info_img,   debug_info_sz,
8faa3f8
+                   debug_types_img,   debug_types_sz,
8faa3f8
                    debug_abbv_img,   debug_abbv_sz,
8faa3f8
                    debug_line_img,   debug_line_sz,
8faa3f8
                    debug_str_img,    debug_str_sz,
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf.h	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf.h	(revision 12491)
8faa3f8
@@ -45,6 +45,7 @@ extern
8faa3f8
 void ML_(read_debuginfo_dwarf3)
8faa3f8
         ( struct _DebugInfo* di,
8faa3f8
           UChar* debug_info_img, Word debug_info_sz,  /* .debug_info */
8faa3f8
+          UChar* debug_types_img, Word debug_types_sz,  /* .debug_types */
8faa3f8
           UChar* debug_abbv_img, Word debug_abbv_sz,  /* .debug_abbrev */
8faa3f8
           UChar* debug_line_img, Word debug_line_sz,  /* .debug_line */
8faa3f8
           UChar* debug_str_img,  Word debug_str_sz ); /* .debug_str */
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/readdwarf3.c	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/readdwarf3.c	(revision 12491)
8faa3f8
@@ -140,6 +140,7 @@
8faa3f8
 #include "pub_core_libcassert.h"
8faa3f8
 #include "pub_core_libcprint.h"
8faa3f8
 #include "pub_core_libcsetjmp.h"   // setjmp facilities
8faa3f8
+#include "pub_core_hashtable.h"
8faa3f8
 #include "pub_core_options.h"
8faa3f8
 #include "pub_core_tooliface.h"    /* VG_(needs) */
8faa3f8
 #include "pub_core_xarray.h"
8faa3f8
@@ -415,6 +416,9 @@ typedef
8faa3f8
       /* Where is .debug_info? */
8faa3f8
       UChar* debug_info_img;
8faa3f8
       UWord  debug_info_sz;
8faa3f8
+      /* Where is .debug_types? */
8faa3f8
+      UChar* debug_types_img;
8faa3f8
+      UWord  debug_types_sz;
8faa3f8
       /* --- Needed so we can add stuff to the string table. --- */
8faa3f8
       struct _DebugInfo* di;
8faa3f8
       /* --- a cache for set_abbv_Cursor --- */
8faa3f8
@@ -422,10 +426,57 @@ typedef
8faa3f8
       struct { ULong abbv_code; UWord posn; } saC_cache[N_ABBV_CACHE];
8faa3f8
       UWord saC_cache_queries;
8faa3f8
       UWord saC_cache_misses;
8faa3f8
+
8faa3f8
+      /* True if this came from .debug_types; otherwise it came from
8faa3f8
+         .debug_info.  */
8faa3f8
+      Bool is_type_unit;
8faa3f8
+      /* For a unit coming from .debug_types, these hold the TU's type
8faa3f8
+         signature and the uncooked DIE offset of the TU's signatured
8faa3f8
+         type.  For a unit coming from .debug_info, these are unused.  */
8faa3f8
+      ULong type_signature;
8faa3f8
+      ULong type_offset;
8faa3f8
+
8faa3f8
+      /* Signatured type hash; computed once and then shared by all
8faa3f8
+         CUs.  */
8faa3f8
+      VgHashTable signature_types;
8faa3f8
    }
8faa3f8
    CUConst;
8faa3f8
 
8faa3f8
 
8faa3f8
+/* Return the cooked value of DIE depending on whether CC represents a
8faa3f8
+   .debug_types unit.  To cook a DIE, we pretend that the .debug_info
8faa3f8
+   and .debug_types sections form a contiguous whole, so that DIEs
8faa3f8
+   coming from .debug_types are numbered starting at the end of
8faa3f8
+   .debug_info.  */
8faa3f8
+static UWord cook_die( CUConst* cc, UWord die )
8faa3f8
+{
8faa3f8
+   if (cc->is_type_unit)
8faa3f8
+      die += cc->debug_info_sz;
8faa3f8
+   return die;
8faa3f8
+}
8faa3f8
+
8faa3f8
+/* Like cook_die, but understand that DIEs coming from a
8faa3f8
+   DW_FORM_ref_sig8 reference are already cooked.  */
8faa3f8
+static UWord cook_die_using_form( CUConst *cc, UWord die, DW_FORM form)
8faa3f8
+{
8faa3f8
+   if (form == DW_FORM_ref_sig8)
8faa3f8
+      return die;
8faa3f8
+   return cook_die( cc, die );
8faa3f8
+}
8faa3f8
+
8faa3f8
+/* Return the uncooked offset of DIE and set *FLAG to true if the DIE
8faa3f8
+   came from the .debug_types section.  */
8faa3f8
+static UWord uncook_die( CUConst *cc, UWord die, /*OUT*/Bool *flag )
8faa3f8
+{
8faa3f8
+   if (die >= cc->debug_info_sz) {
8faa3f8
+      *flag = True;
8faa3f8
+      die -= cc->debug_info_sz;
8faa3f8
+   } else {
8faa3f8
+      *flag = False;
8faa3f8
+   }
8faa3f8
+   return die;
8faa3f8
+}
8faa3f8
+
8faa3f8
 /*------------------------------------------------------------*/
8faa3f8
 /*---                                                      ---*/
8faa3f8
 /*--- Helper functions for Guarded Expressions             ---*/
8faa3f8
@@ -778,7 +829,8 @@ static __attribute__((noinline))
8faa3f8
 void parse_CU_Header ( /*OUT*/CUConst* cc,
8faa3f8
                        Bool td3,
8faa3f8
                        Cursor* c, 
8faa3f8
-                       UChar* debug_abbv_img, UWord debug_abbv_sz )
8faa3f8
+                       UChar* debug_abbv_img, UWord debug_abbv_sz,
8faa3f8
+		       Bool type_unit )
8faa3f8
 {
8faa3f8
    UChar  address_size;
8faa3f8
    UWord  debug_abbrev_offset;
8faa3f8
@@ -816,6 +868,13 @@ void parse_CU_Header ( /*OUT*/CUConst* c
8faa3f8
       cc->barf( "parse_CU_Header: invalid address_size" );
8faa3f8
    TRACE_D3("   Pointer Size:  %d\n", (Int)address_size );
8faa3f8
 
8faa3f8
+   cc->is_type_unit = type_unit;
8faa3f8
+
8faa3f8
+   if (type_unit) {
8faa3f8
+      cc->type_signature = get_ULong( c );
8faa3f8
+      cc->type_offset = get_Dwarfish_UWord( c, cc->is_dw64 );
8faa3f8
+   }
8faa3f8
+
8faa3f8
    /* Set up so that cc->debug_abbv points to the relevant table for
8faa3f8
       this CU.  Set the szB so that at least we can't read off the end
8faa3f8
       of the debug_abbrev section -- potentially (and quite likely)
8faa3f8
@@ -926,6 +985,50 @@ void set_abbv_Cursor ( /*OUT*/Cursor* c,
8faa3f8
    cc->saC_cache[N_ABBV_CACHE/2].posn = get_position_of_Cursor(c);
8faa3f8
 }
8faa3f8
 
8faa3f8
+/* This represents a single signatured type.  It maps a type signature
8faa3f8
+   (a ULong) to a cooked DIE offset.  Objects of this type are stored
8faa3f8
+   in the type signature hash table.  */
8faa3f8
+typedef
8faa3f8
+   struct D3SignatureType {
8faa3f8
+      struct D3SignatureType *next;
8faa3f8
+      UWord data;
8faa3f8
+      ULong type_signature;
8faa3f8
+      UWord die;
8faa3f8
+   }
8faa3f8
+   D3SignatureType;
8faa3f8
+
8faa3f8
+/* Record a signatured type in the hash table.  */
8faa3f8
+static void record_signatured_type ( VgHashTable tab,
8faa3f8
+                                     ULong type_signature,
8faa3f8
+                                     UWord die )
8faa3f8
+{
8faa3f8
+   D3SignatureType *dstype = ML_(dinfo_zalloc) ( "di.readdwarf3.sigtype",
8faa3f8
+                                                 sizeof(D3SignatureType) );
8faa3f8
+   dstype->data = (UWord) type_signature;
8faa3f8
+   dstype->type_signature = type_signature;
8faa3f8
+   dstype->die = die;
8faa3f8
+   VG_(HT_add_node) ( tab, dstype );
8faa3f8
+}
8faa3f8
+
8faa3f8
+/* Given a type signature hash table and a type signature, return the
8faa3f8
+   cooked DIE offset of the type.  If the type cannot be found, call
8faa3f8
+   BARF.  */
8faa3f8
+static UWord lookup_signatured_type ( VgHashTable tab,
8faa3f8
+                                      ULong type_signature,
8faa3f8
+                                      void (*barf)( HChar* ) __attribute__((noreturn)) )
8faa3f8
+{
8faa3f8
+   D3SignatureType *dstype = VG_(HT_lookup) ( tab, (UWord) type_signature );
8faa3f8
+   /* This may be unwarranted chumminess with the hash table
8faa3f8
+      implementation.  */
8faa3f8
+   while ( dstype != NULL && dstype->type_signature != type_signature)
8faa3f8
+      dstype = dstype->next;
8faa3f8
+   if (dstype == NULL) {
8faa3f8
+      barf("lookup_signatured_type: could not find signatured type");
8faa3f8
+      /*NOTREACHED*/
8faa3f8
+      vg_assert(0);
8faa3f8
+   }
8faa3f8
+   return dstype->die;
8faa3f8
+}
8faa3f8
 
8faa3f8
 /* From 'c', get the Form data into the lowest 1/2/4/8 bytes of *cts.
8faa3f8
 
8faa3f8
@@ -1164,14 +1267,20 @@ void get_Form_contents ( /*OUT*/ULong* c
8faa3f8
       }
8faa3f8
       case DW_FORM_ref_sig8: {
8faa3f8
          ULong  u64b;
8faa3f8
-         UChar* block = get_address_of_Cursor(c);
8faa3f8
+         ULong  signature = get_ULong (c);
8faa3f8
+         ULong  work = signature;
8faa3f8
          TRACE_D3("8 byte signature: ");
8faa3f8
          for (u64b = 8; u64b > 0; u64b--) {
8faa3f8
-            UChar u8 = get_UChar(c);
8faa3f8
+            UChar u8 = work & 0xff;
8faa3f8
             TRACE_D3("%x ", (UInt)u8);
8faa3f8
+            work >>= 8;
8faa3f8
          }
8faa3f8
-         *cts = (ULong)(UWord)block;
8faa3f8
-         *ctsMemSzB = 8;
8faa3f8
+         /* Due to the way that the hash table is constructed, the
8faa3f8
+            resulting DIE offset here is already "cooked".  See
8faa3f8
+            cook_die_using_form.  */
8faa3f8
+         *cts = lookup_signatured_type (cc->signature_types, signature,
8faa3f8
+                                        c->barf);
8faa3f8
+         *ctsSzB = sizeof(UWord);
8faa3f8
          break;
8faa3f8
       }
8faa3f8
       case DW_FORM_indirect:
8faa3f8
@@ -1468,10 +1577,11 @@ static void parse_var_DIE (
8faa3f8
 
8faa3f8
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
8faa3f8
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
8faa3f8
+   Bool  debug_types_flag;
8faa3f8
 
8faa3f8
    varstack_preen( parser, td3, level-1 );
8faa3f8
 
8faa3f8
-   if (dtag == DW_TAG_compile_unit) {
8faa3f8
+   if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit) {
8faa3f8
       Bool have_lo    = False;
8faa3f8
       Bool have_hi1   = False;
8faa3f8
       Bool have_range = False;
8faa3f8
@@ -1685,7 +1795,7 @@ static void parse_var_DIE (
8faa3f8
             VG_(addToXA)(gexprs, &gexpr);
8faa3f8
          }
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            typeR = (UWord)cts;
8faa3f8
+            typeR = cook_die_using_form( cc, (UWord)cts, form );
8faa3f8
          }
8faa3f8
          if (attr == DW_AT_external && ctsSzB > 0 && cts > 0) {
8faa3f8
             external = True;
8faa3f8
@@ -1917,7 +2027,12 @@ static void parse_var_DIE (
8faa3f8
    set_position_of_Cursor( c_die,  saved_die_c_offset );
8faa3f8
    set_position_of_Cursor( c_abbv, saved_abbv_c_offset );
8faa3f8
    VG_(printf)("\nparse_var_DIE: confused by:\n");
8faa3f8
-   VG_(printf)(" <%d><%lx>: %s\n", level, posn, ML_(pp_DW_TAG)( dtag ) );
8faa3f8
+   posn = uncook_die( cc, posn, &debug_types_flag );
8faa3f8
+   VG_(printf)(" <%d><%lx>: %s", level, posn, ML_(pp_DW_TAG)( dtag ) );
8faa3f8
+   if (debug_types_flag) {
8faa3f8
+      VG_(printf)(" (in .debug_types)");
8faa3f8
+   }
8faa3f8
+   VG_(printf)("\n");
8faa3f8
    while (True) {
8faa3f8
       DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
8faa3f8
       DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
8faa3f8
@@ -2097,6 +2212,7 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
    TyEnt atomE;
8faa3f8
    TyEnt fieldE;
8faa3f8
    TyEnt boundE;
8faa3f8
+   Bool  debug_types_flag;
8faa3f8
 
8faa3f8
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
8faa3f8
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
8faa3f8
@@ -2111,7 +2227,7 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
       its children. */
8faa3f8
    typestack_preen( parser, td3, level-1 );
8faa3f8
 
8faa3f8
-   if (dtag == DW_TAG_compile_unit) {
8faa3f8
+   if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit) {
8faa3f8
       /* See if we can find DW_AT_language, since it is important for
8faa3f8
          establishing array bounds (see DW_TAG_subrange_type below in
8faa3f8
          this fn) */
8faa3f8
@@ -2272,7 +2388,7 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
             typeE.Te.TyPorR.szB = cts;
8faa3f8
          }
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            typeE.Te.TyPorR.typeR = (UWord)cts;
8faa3f8
+            typeE.Te.TyPorR.typeR = cook_die_using_form( cc, (UWord)cts, form );
8faa3f8
          }
8faa3f8
       }
8faa3f8
       /* Do we have something that looks sane? */
8faa3f8
@@ -2317,8 +2433,23 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
           /* we must know the size */
8faa3f8
           /* but not for Ada, which uses such dummy
8faa3f8
              enumerations as helper for gdb ada mode. */
8faa3f8
-          && parser->language != 'A')
8faa3f8
-         goto bad_DIE;
8faa3f8
+          && parser->language != 'A') {
8faa3f8
+         /* GCC has been seen to put an odd DIE like this into
8faa3f8
+            .debug_types:
8faa3f8
+
8faa3f8
+            <1><cb72>: DW_TAG_enumeration_type (in .debug_types)
8faa3f8
+            DW_AT_name        : (indirect string, offset: 0x3374a): exec_direction_kind
8faa3f8
+            DW_AT_declaration : 1	
8faa3f8
+
8faa3f8
+            It isn't clear what this means, but we accept it and
8faa3f8
+            assume that the enum is int-sized.  */
8faa3f8
+         if (cc->is_type_unit) {
8faa3f8
+            typeE.Te.TyEnum.szB = sizeof(int);
8faa3f8
+         } else {
8faa3f8
+            goto bad_DIE;
8faa3f8
+         }
8faa3f8
+      }
8faa3f8
+
8faa3f8
       /* On't stack! */
8faa3f8
       typestack_push( cc, parser, td3, &typeE, level );
8faa3f8
       goto acquire_Type;
8faa3f8
@@ -2487,7 +2618,7 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
                                     (UChar*)(UWord)cts );
8faa3f8
          }
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            fieldE.Te.Field.typeR = (UWord)cts;
8faa3f8
+            fieldE.Te.Field.typeR = cook_die_using_form( cc, (UWord)cts, form );
8faa3f8
          }
8faa3f8
          /* There are 2 different cases for DW_AT_data_member_location.
8faa3f8
             If it is a constant class attribute, it contains byte offset
8faa3f8
@@ -2567,7 +2698,8 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
          get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
8faa3f8
                             cc, c_die, False/*td3*/, form );
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            typeE.Te.TyArray.typeR = (UWord)cts;
8faa3f8
+            typeE.Te.TyArray.typeR = cook_die_using_form( cc, (UWord)cts,
8faa3f8
+                                                          form );
8faa3f8
          }
8faa3f8
       }
8faa3f8
       if (typeE.Te.TyArray.typeR == D3_INVALID_CUOFF)
8faa3f8
@@ -2690,7 +2822,8 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
                                     (UChar*)(UWord)cts );
8faa3f8
          }
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            typeE.Te.TyTyDef.typeR = (UWord)cts;
8faa3f8
+            typeE.Te.TyTyDef.typeR = cook_die_using_form( cc, (UWord)cts,
8faa3f8
+                                                          form );
8faa3f8
          }
8faa3f8
       }
8faa3f8
       /* Do we have something that looks sane? */
8faa3f8
@@ -2733,7 +2866,7 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
          get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
8faa3f8
                             cc, c_die, False/*td3*/, form );
8faa3f8
          if (attr == DW_AT_type && ctsSzB > 0) {
8faa3f8
-            typeE.Te.TyQual.typeR = (UWord)cts;
8faa3f8
+            typeE.Te.TyQual.typeR = cook_die_using_form( cc, (UWord)cts, form );
8faa3f8
             have_ty++;
8faa3f8
          }
8faa3f8
       }
8faa3f8
@@ -2813,7 +2946,12 @@ static void parse_type_DIE ( /*MOD*/XArr
8faa3f8
    set_position_of_Cursor( c_die,  saved_die_c_offset );
8faa3f8
    set_position_of_Cursor( c_abbv, saved_abbv_c_offset );
8faa3f8
    VG_(printf)("\nparse_type_DIE: confused by:\n");
8faa3f8
-   VG_(printf)(" <%d><%lx>: %s\n", level, posn, ML_(pp_DW_TAG)( dtag ) );
8faa3f8
+   posn = uncook_die( cc, posn, &debug_types_flag );
8faa3f8
+   VG_(printf)(" <%d><%lx>: %s", level, posn, ML_(pp_DW_TAG)( dtag ) );
8faa3f8
+   if (debug_types_flag) {
8faa3f8
+      VG_(printf)(" (in .debug_types)");
8faa3f8
+   }
8faa3f8
+   VG_(printf)("\n");
8faa3f8
    while (True) {
8faa3f8
       DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
8faa3f8
       DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
8faa3f8
@@ -3186,7 +3324,7 @@ static void read_DIE (
8faa3f8
    UWord  after_die_c_offset, after_abbv_c_offset;
8faa3f8
 
8faa3f8
    /* --- Deal with this DIE --- */
8faa3f8
-   posn      = get_position_of_Cursor( c );
8faa3f8
+   posn      = cook_die( cc, get_position_of_Cursor( c ) );
8faa3f8
    abbv_code = get_ULEB128( c );
8faa3f8
    set_abbv_Cursor( &abbv, td3, cc, abbv_code );
8faa3f8
    atag      = get_ULEB128( &abbv );
8faa3f8
@@ -3284,6 +3422,7 @@ void new_dwarf3_reader_wrk (
8faa3f8
    struct _DebugInfo* di,
8faa3f8
    __attribute__((noreturn)) void (*barf)( HChar* ),
8faa3f8
    UChar* debug_info_img,   SizeT debug_info_sz,
8faa3f8
+   UChar* debug_types_img,  SizeT debug_types_sz,
8faa3f8
    UChar* debug_abbv_img,   SizeT debug_abbv_sz,
8faa3f8
    UChar* debug_line_img,   SizeT debug_line_sz,
8faa3f8
    UChar* debug_str_img,    SizeT debug_str_sz,
8faa3f8
@@ -3310,6 +3449,8 @@ void new_dwarf3_reader_wrk (
8faa3f8
    Word  i, j, n;
8faa3f8
    Bool td3 = di->trace_symtab;
8faa3f8
    XArray* /* of TempVar* */ dioff_lookup_tab;
8faa3f8
+   Int pass;
8faa3f8
+   VgHashTable signature_types;
8faa3f8
 #if 0
8faa3f8
    /* This doesn't work properly because it assumes all entries are
8faa3f8
       packed end to end, with no holes.  But that doesn't always
8faa3f8
@@ -3443,13 +3584,6 @@ void new_dwarf3_reader_wrk (
8faa3f8
    }
8faa3f8
    TRACE_SYMTAB("\n");
8faa3f8
 
8faa3f8
-   /* Now loop over the Compilation Units listed in the .debug_info
8faa3f8
-      section (see D3SPEC sec 7.5) paras 1 and 2.  Each compilation
8faa3f8
-      unit contains a Compilation Unit Header followed by precisely
8faa3f8
-      one DW_TAG_compile_unit or DW_TAG_partial_unit DIE. */
8faa3f8
-   init_Cursor( &info, debug_info_img, debug_info_sz, 0, barf,
8faa3f8
-                "Overrun whilst reading .debug_info section" );
8faa3f8
-
8faa3f8
    /* We'll park the harvested type information in here.  Also create
8faa3f8
       a fake "void" entry with offset D3_FAKEVOID_CUOFF, so we always
8faa3f8
       have at least one type entry to refer to.  D3_FAKEVOID_CUOFF is
8faa3f8
@@ -3511,158 +3645,234 @@ void new_dwarf3_reader_wrk (
8faa3f8
    VG_(memset)( &varparser, 0, sizeof(varparser) );
8faa3f8
    varparser.sp = -1;
8faa3f8
 
8faa3f8
-   TRACE_D3("\n------ Parsing .debug_info section ------\n");
8faa3f8
-   while (True) {
8faa3f8
-      UWord   cu_start_offset, cu_offset_now;
8faa3f8
-      CUConst cc;
8faa3f8
-      /* It may be that the stated size of this CU is larger than the
8faa3f8
-         amount of stuff actually in it.  icc9 seems to generate CUs
8faa3f8
-         thusly.  We use these variables to figure out if this is
8faa3f8
-         indeed the case, and if so how many bytes we need to skip to
8faa3f8
-         get to the start of the next CU.  Not skipping those bytes
8faa3f8
-         causes us to misidentify the start of the next CU, and it all
8faa3f8
-         goes badly wrong after that (not surprisingly). */
8faa3f8
-      UWord cu_size_including_IniLen, cu_amount_used;
8faa3f8
-
8faa3f8
-      /* It seems icc9 finishes the DIE info before debug_info_sz
8faa3f8
-         bytes have been used up.  So be flexible, and declare the
8faa3f8
-         sequence complete if there is not enough remaining bytes to
8faa3f8
-         hold even the smallest conceivable CU header.  (11 bytes I
8faa3f8
-         reckon). */
8faa3f8
-      /* JRS 23Jan09: I suspect this is no longer necessary now that
8faa3f8
-         the code below contains a 'while (cu_amount_used <
8faa3f8
-         cu_size_including_IniLen ...'  style loop, which skips over
8faa3f8
-         any leftover bytes at the end of a CU in the case where the
8faa3f8
-         CU's stated size is larger than its actual size (as
8faa3f8
-         determined by reading all its DIEs).  However, for prudence,
8faa3f8
-         I'll leave the following test in place.  I can't see that a
8faa3f8
-         CU header can be smaller than 11 bytes, so I don't think
8faa3f8
-         there's any harm possible through the test -- it just adds
8faa3f8
-         robustness. */
8faa3f8
-      Word avail = get_remaining_length_Cursor( &info );
8faa3f8
-      if (avail < 11) {
8faa3f8
-         if (avail > 0)
8faa3f8
-            TRACE_D3("new_dwarf3_reader_wrk: warning: "
8faa3f8
-                     "%ld unused bytes after end of DIEs\n", avail);
8faa3f8
-         break;
8faa3f8
-      }
8faa3f8
+   signature_types = VG_(HT_construct) ("signature_types");
8faa3f8
+   
8faa3f8
+   /* Do an initial pass to scan the .debug_types section, if any, and
8faa3f8
+      fill in the signatured types hash table.  This lets us handle
8faa3f8
+      mapping from a type signature to a (cooked) DIE offset directly
8faa3f8
+      in get_Form_contents.  */
8faa3f8
+   if (debug_types_img != NULL) {
8faa3f8
+      init_Cursor( &info, debug_types_img, debug_types_sz, 0, barf,
8faa3f8
+                   "Overrun whilst reading .debug_types section" );
8faa3f8
+      TRACE_D3("\n------ Collecting signatures from .debug_types section ------\n");
8faa3f8
 
8faa3f8
-      /* Check the varparser's stack is in a sane state. */
8faa3f8
-      vg_assert(varparser.sp == -1);
8faa3f8
-      for (i = 0; i < N_D3_VAR_STACK; i++) {
8faa3f8
-         vg_assert(varparser.ranges[i] == NULL);
8faa3f8
-         vg_assert(varparser.level[i] == 0);
8faa3f8
-      }
8faa3f8
-      for (i = 0; i < N_D3_TYPE_STACK; i++) {
8faa3f8
-         vg_assert(typarser.qparentE[i].cuOff == D3_INVALID_CUOFF);
8faa3f8
-         vg_assert(typarser.qparentE[i].tag   == Te_EMPTY);
8faa3f8
-         vg_assert(typarser.qlevel[i] == 0);
8faa3f8
+      while (True) {
8faa3f8
+         UWord   cu_start_offset, cu_offset_now;
8faa3f8
+         CUConst cc;
8faa3f8
+
8faa3f8
+         cu_start_offset = get_position_of_Cursor( &info );
8faa3f8
+         TRACE_D3("\n");
8faa3f8
+         TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
8faa3f8
+         /* parse_CU_header initialises the CU's set_abbv_Cursor cache
8faa3f8
+            (saC_cache) */
8faa3f8
+         parse_CU_Header( &cc, td3, &info,
8faa3f8
+                          (UChar*)debug_abbv_img, debug_abbv_sz,
8faa3f8
+                          True );
8faa3f8
+
8faa3f8
+         /* Needed by cook_die.  */
8faa3f8
+         cc.debug_info_sz    = debug_info_sz;
8faa3f8
+
8faa3f8
+         record_signatured_type( signature_types, cc.type_signature,
8faa3f8
+                                 cook_die( &cc, cc.type_offset ));
8faa3f8
+
8faa3f8
+         /* Until proven otherwise we assume we don't need the icc9
8faa3f8
+            workaround in this case; see the DIE-reading loop below
8faa3f8
+            for details.  */
8faa3f8
+         cu_offset_now = (cu_start_offset + cc.unit_length
8faa3f8
+                          + (cc.is_dw64 ? 12 : 4));
8faa3f8
+
8faa3f8
+         if (cu_offset_now == debug_types_sz)
8faa3f8
+            break;
8faa3f8
+
8faa3f8
+         set_position_of_Cursor ( &info, cu_offset_now );
8faa3f8
       }
8faa3f8
+   }
8faa3f8
 
8faa3f8
-      cu_start_offset = get_position_of_Cursor( &info );
8faa3f8
-      TRACE_D3("\n");
8faa3f8
-      TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
8faa3f8
-      /* parse_CU_header initialises the CU's set_abbv_Cursor cache
8faa3f8
-         (saC_cache) */
8faa3f8
-      parse_CU_Header( &cc, td3, &info,
8faa3f8
-                       (UChar*)debug_abbv_img, debug_abbv_sz );
8faa3f8
-      cc.debug_str_img    = debug_str_img;
8faa3f8
-      cc.debug_str_sz     = debug_str_sz;
8faa3f8
-      cc.debug_ranges_img = debug_ranges_img;
8faa3f8
-      cc.debug_ranges_sz  = debug_ranges_sz;
8faa3f8
-      cc.debug_loc_img    = debug_loc_img;
8faa3f8
-      cc.debug_loc_sz     = debug_loc_sz;
8faa3f8
-      cc.debug_line_img   = debug_line_img;
8faa3f8
-      cc.debug_line_sz    = debug_line_sz;
8faa3f8
-      cc.debug_info_img   = debug_info_img;
8faa3f8
-      cc.debug_info_sz    = debug_info_sz;
8faa3f8
-      cc.cu_start_offset  = cu_start_offset;
8faa3f8
-      cc.di = di;
8faa3f8
-      /* The CU's svma can be deduced by looking at the AT_low_pc
8faa3f8
-         value in the top level TAG_compile_unit, which is the topmost
8faa3f8
-         DIE.  We'll leave it for the 'varparser' to acquire that info
8faa3f8
-         and fill it in -- since it is the only party to want to know
8faa3f8
-         it. */
8faa3f8
-      cc.cu_svma_known = False;
8faa3f8
-      cc.cu_svma       = 0;
8faa3f8
-
8faa3f8
-      /* Create a fake outermost-level range covering the entire
8faa3f8
-         address range.  So we always have *something* to catch all
8faa3f8
-         variable declarations. */
8faa3f8
-      varstack_push( &cc, &varparser, td3, 
8faa3f8
-                     unitary_range_list(0UL, ~0UL),
8faa3f8
-                     -1, False/*isFunc*/, NULL/*fbGX*/ );
8faa3f8
-
8faa3f8
-      /* And set up the file name table.  When we come across the top
8faa3f8
-         level DIE for this CU (which is what the next call to
8faa3f8
-         read_DIE should process) we will copy all the file names out
8faa3f8
-         of the .debug_line img area and use this table to look up the
8faa3f8
-         copies when we later see filename numbers in DW_TAG_variables
8faa3f8
-         etc. */
8faa3f8
-      vg_assert(!varparser.filenameTable );
8faa3f8
-      varparser.filenameTable 
8faa3f8
-         = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.5",
8faa3f8
-                       ML_(dinfo_free),
8faa3f8
-                       sizeof(UChar*) );
8faa3f8
-      vg_assert(varparser.filenameTable);
8faa3f8
+   /* Perform two DIE-reading passes.  The first pass reads DIEs from
8faa3f8
+      .debug_info, and the second pass reads DIEs from .debug_types.
8faa3f8
+      Moving the body of this loop into a separate function would
8faa3f8
+      require a large number of arguments to be passed in, so it is
8faa3f8
+      kept inline instead.  */
8faa3f8
+   for (pass = 0; pass < 2; ++pass) {
8faa3f8
+      UWord section_size;
8faa3f8
+
8faa3f8
+      if (pass == 0) {
8faa3f8
+         /* Now loop over the Compilation Units listed in the .debug_info
8faa3f8
+            section (see D3SPEC sec 7.5) paras 1 and 2.  Each compilation
8faa3f8
+            unit contains a Compilation Unit Header followed by precisely
8faa3f8
+            one DW_TAG_compile_unit or DW_TAG_partial_unit DIE. */
8faa3f8
+         init_Cursor( &info, debug_info_img, debug_info_sz, 0, barf,
8faa3f8
+                      "Overrun whilst reading .debug_info section" );
8faa3f8
+         section_size = debug_info_sz;
8faa3f8
 
8faa3f8
-      /* Now read the one-and-only top-level DIE for this CU. */
8faa3f8
-      vg_assert(varparser.sp == 0);
8faa3f8
-      read_DIE( rangestree,
8faa3f8
-                tyents, tempvars, gexprs,
8faa3f8
-                &typarser, &varparser,
8faa3f8
-                &info, td3, &cc, 0 );
8faa3f8
-
8faa3f8
-      cu_offset_now = get_position_of_Cursor( &info );
8faa3f8
-
8faa3f8
-      if (0) VG_(printf)("Travelled: %lu  size %llu\n",
8faa3f8
-                         cu_offset_now - cc.cu_start_offset,
8faa3f8
-                         cc.unit_length + (cc.is_dw64 ? 12 : 4));
8faa3f8
-
8faa3f8
-      /* How big the CU claims it is .. */
8faa3f8
-      cu_size_including_IniLen = cc.unit_length + (cc.is_dw64 ? 12 : 4);
8faa3f8
-      /* .. vs how big we have found it to be */
8faa3f8
-      cu_amount_used = cu_offset_now - cc.cu_start_offset;
8faa3f8
-
8faa3f8
-      if (1) TRACE_D3("offset now %ld, d-i-size %ld\n",
8faa3f8
-                      cu_offset_now, debug_info_sz);
8faa3f8
-      if (cu_offset_now > debug_info_sz)
8faa3f8
-         barf("toplevel DIEs beyond end of CU");
8faa3f8
-
8faa3f8
-      /* If the CU is bigger than it claims to be, we've got a serious
8faa3f8
-         problem. */
8faa3f8
-      if (cu_amount_used > cu_size_including_IniLen)
8faa3f8
-         barf("CU's actual size appears to be larger than it claims it is");
8faa3f8
-
8faa3f8
-      /* If the CU is smaller than it claims to be, we need to skip some
8faa3f8
-         bytes.  Loop updates cu_offset_new and cu_amount_used. */
8faa3f8
-      while (cu_amount_used < cu_size_including_IniLen
8faa3f8
-             && get_remaining_length_Cursor( &info ) > 0) {
8faa3f8
-         if (0) VG_(printf)("SKIP\n");
8faa3f8
-         (void)get_UChar( &info );
8faa3f8
-         cu_offset_now = get_position_of_Cursor( &info );
8faa3f8
-         cu_amount_used = cu_offset_now - cc.cu_start_offset;
8faa3f8
+         TRACE_D3("\n------ Parsing .debug_info section ------\n");
8faa3f8
+      } else {
8faa3f8
+         if (debug_types_img == NULL)
8faa3f8
+            continue;
8faa3f8
+         init_Cursor( &info, debug_types_img, debug_types_sz, 0, barf,
8faa3f8
+                      "Overrun whilst reading .debug_types section" );
8faa3f8
+         section_size = debug_types_sz;
8faa3f8
+
8faa3f8
+         TRACE_D3("\n------ Parsing .debug_types section ------\n");
8faa3f8
       }
8faa3f8
 
8faa3f8
-      /* Preen to level -2.  DIEs have level >= 0 so -2 cannot occur
8faa3f8
-         anywhere else at all.  Our fake the-entire-address-space
8faa3f8
-         range is at level -1, so preening to -2 should completely
8faa3f8
-         empty the stack out. */
8faa3f8
-      TRACE_D3("\n");
8faa3f8
-      varstack_preen( &varparser, td3, -2 );
8faa3f8
-      /* Similarly, empty the type stack out. */
8faa3f8
-      typestack_preen( &typarser, td3, -2 );
8faa3f8
+      while (True) {
8faa3f8
+         UWord   cu_start_offset, cu_offset_now;
8faa3f8
+         CUConst cc;
8faa3f8
+         /* It may be that the stated size of this CU is larger than the
8faa3f8
+            amount of stuff actually in it.  icc9 seems to generate CUs
8faa3f8
+            thusly.  We use these variables to figure out if this is
8faa3f8
+            indeed the case, and if so how many bytes we need to skip to
8faa3f8
+            get to the start of the next CU.  Not skipping those bytes
8faa3f8
+            causes us to misidentify the start of the next CU, and it all
8faa3f8
+            goes badly wrong after that (not surprisingly). */
8faa3f8
+         UWord cu_size_including_IniLen, cu_amount_used;
8faa3f8
+
8faa3f8
+         /* It seems icc9 finishes the DIE info before debug_info_sz
8faa3f8
+            bytes have been used up.  So be flexible, and declare the
8faa3f8
+            sequence complete if there is not enough remaining bytes to
8faa3f8
+            hold even the smallest conceivable CU header.  (11 bytes I
8faa3f8
+            reckon). */
8faa3f8
+         /* JRS 23Jan09: I suspect this is no longer necessary now that
8faa3f8
+            the code below contains a 'while (cu_amount_used <
8faa3f8
+            cu_size_including_IniLen ...'  style loop, which skips over
8faa3f8
+            any leftover bytes at the end of a CU in the case where the
8faa3f8
+            CU's stated size is larger than its actual size (as
8faa3f8
+            determined by reading all its DIEs).  However, for prudence,
8faa3f8
+            I'll leave the following test in place.  I can't see that a
8faa3f8
+            CU header can be smaller than 11 bytes, so I don't think
8faa3f8
+            there's any harm possible through the test -- it just adds
8faa3f8
+            robustness. */
8faa3f8
+         Word avail = get_remaining_length_Cursor( &info );
8faa3f8
+         if (avail < 11) {
8faa3f8
+            if (avail > 0)
8faa3f8
+               TRACE_D3("new_dwarf3_reader_wrk: warning: "
8faa3f8
+                        "%ld unused bytes after end of DIEs\n", avail);
8faa3f8
+            break;
8faa3f8
+         }
8faa3f8
+
8faa3f8
+         /* Check the varparser's stack is in a sane state. */
8faa3f8
+         vg_assert(varparser.sp == -1);
8faa3f8
+         for (i = 0; i < N_D3_VAR_STACK; i++) {
8faa3f8
+            vg_assert(varparser.ranges[i] == NULL);
8faa3f8
+            vg_assert(varparser.level[i] == 0);
8faa3f8
+         }
8faa3f8
+         for (i = 0; i < N_D3_TYPE_STACK; i++) {
8faa3f8
+            vg_assert(typarser.qparentE[i].cuOff == D3_INVALID_CUOFF);
8faa3f8
+            vg_assert(typarser.qparentE[i].tag   == Te_EMPTY);
8faa3f8
+            vg_assert(typarser.qlevel[i] == 0);
8faa3f8
+         }
8faa3f8
+
8faa3f8
+         cu_start_offset = get_position_of_Cursor( &info );
8faa3f8
+         TRACE_D3("\n");
8faa3f8
+         TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
8faa3f8
+         /* parse_CU_header initialises the CU's set_abbv_Cursor cache
8faa3f8
+            (saC_cache) */
8faa3f8
+         parse_CU_Header( &cc, td3, &info,
8faa3f8
+                          (UChar*)debug_abbv_img, debug_abbv_sz,
8faa3f8
+                          pass != 0 );
8faa3f8
+         cc.debug_str_img    = debug_str_img;
8faa3f8
+         cc.debug_str_sz     = debug_str_sz;
8faa3f8
+         cc.debug_ranges_img = debug_ranges_img;
8faa3f8
+         cc.debug_ranges_sz  = debug_ranges_sz;
8faa3f8
+         cc.debug_loc_img    = debug_loc_img;
8faa3f8
+         cc.debug_loc_sz     = debug_loc_sz;
8faa3f8
+         cc.debug_line_img   = debug_line_img;
8faa3f8
+         cc.debug_line_sz    = debug_line_sz;
8faa3f8
+         cc.debug_info_img   = debug_info_img;
8faa3f8
+         cc.debug_info_sz    = debug_info_sz;
8faa3f8
+         cc.debug_types_img  = debug_types_img;
8faa3f8
+         cc.debug_types_sz   = debug_types_sz;
8faa3f8
+         cc.cu_start_offset  = cu_start_offset;
8faa3f8
+         cc.di = di;
8faa3f8
+         /* The CU's svma can be deduced by looking at the AT_low_pc
8faa3f8
+            value in the top level TAG_compile_unit, which is the topmost
8faa3f8
+            DIE.  We'll leave it for the 'varparser' to acquire that info
8faa3f8
+            and fill it in -- since it is the only party to want to know
8faa3f8
+            it. */
8faa3f8
+         cc.cu_svma_known = False;
8faa3f8
+         cc.cu_svma       = 0;
8faa3f8
+
8faa3f8
+         cc.signature_types = signature_types;
8faa3f8
+
8faa3f8
+         /* Create a fake outermost-level range covering the entire
8faa3f8
+            address range.  So we always have *something* to catch all
8faa3f8
+            variable declarations. */
8faa3f8
+         varstack_push( &cc, &varparser, td3, 
8faa3f8
+                        unitary_range_list(0UL, ~0UL),
8faa3f8
+                        -1, False/*isFunc*/, NULL/*fbGX*/ );
8faa3f8
+
8faa3f8
+         /* And set up the file name table.  When we come across the top
8faa3f8
+            level DIE for this CU (which is what the next call to
8faa3f8
+            read_DIE should process) we will copy all the file names out
8faa3f8
+            of the .debug_line img area and use this table to look up the
8faa3f8
+            copies when we later see filename numbers in DW_TAG_variables
8faa3f8
+            etc. */
8faa3f8
+         vg_assert(!varparser.filenameTable );
8faa3f8
+         varparser.filenameTable 
8faa3f8
+            = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.5",
8faa3f8
+                          ML_(dinfo_free),
8faa3f8
+                          sizeof(UChar*) );
8faa3f8
+         vg_assert(varparser.filenameTable);
8faa3f8
+
8faa3f8
+         /* Now read the one-and-only top-level DIE for this CU. */
8faa3f8
+         vg_assert(varparser.sp == 0);
8faa3f8
+         read_DIE( rangestree,
8faa3f8
+                   tyents, tempvars, gexprs,
8faa3f8
+                   &typarser, &varparser,
8faa3f8
+                   &info, td3, &cc, 0 );
8faa3f8
 
8faa3f8
-      if (cu_offset_now == debug_info_sz)
8faa3f8
-         break;
8faa3f8
-      /* else keep going */
8faa3f8
+         cu_offset_now = get_position_of_Cursor( &info );
8faa3f8
 
8faa3f8
-      TRACE_D3("set_abbv_Cursor cache: %lu queries, %lu misses\n",
8faa3f8
-               cc.saC_cache_queries, cc.saC_cache_misses);
8faa3f8
+         if (0) VG_(printf)("Travelled: %lu  size %llu\n",
8faa3f8
+                            cu_offset_now - cc.cu_start_offset,
8faa3f8
+                            cc.unit_length + (cc.is_dw64 ? 12 : 4));
8faa3f8
+
8faa3f8
+         /* How big the CU claims it is .. */
8faa3f8
+         cu_size_including_IniLen = cc.unit_length + (cc.is_dw64 ? 12 : 4);
8faa3f8
+         /* .. vs how big we have found it to be */
8faa3f8
+         cu_amount_used = cu_offset_now - cc.cu_start_offset;
8faa3f8
 
8faa3f8
-      vg_assert(varparser.filenameTable );
8faa3f8
-      VG_(deleteXA)( varparser.filenameTable );
8faa3f8
-      varparser.filenameTable = NULL;
8faa3f8
+         if (1) TRACE_D3("offset now %ld, d-i-size %ld\n",
8faa3f8
+                         cu_offset_now, section_size);
8faa3f8
+         if (cu_offset_now > section_size)
8faa3f8
+            barf("toplevel DIEs beyond end of CU");
8faa3f8
+
8faa3f8
+         /* If the CU is bigger than it claims to be, we've got a serious
8faa3f8
+            problem. */
8faa3f8
+         if (cu_amount_used > cu_size_including_IniLen)
8faa3f8
+            barf("CU's actual size appears to be larger than it claims it is");
8faa3f8
+
8faa3f8
+         /* If the CU is smaller than it claims to be, we need to skip some
8faa3f8
+            bytes.  Loop updates cu_offset_new and cu_amount_used. */
8faa3f8
+         while (cu_amount_used < cu_size_including_IniLen
8faa3f8
+                && get_remaining_length_Cursor( &info ) > 0) {
8faa3f8
+            if (0) VG_(printf)("SKIP\n");
8faa3f8
+            (void)get_UChar( &info );
8faa3f8
+            cu_offset_now = get_position_of_Cursor( &info );
8faa3f8
+            cu_amount_used = cu_offset_now - cc.cu_start_offset;
8faa3f8
+         }
8faa3f8
+
8faa3f8
+         /* Preen to level -2.  DIEs have level >= 0 so -2 cannot occur
8faa3f8
+            anywhere else at all.  Our fake the-entire-address-space
8faa3f8
+            range is at level -1, so preening to -2 should completely
8faa3f8
+            empty the stack out. */
8faa3f8
+         TRACE_D3("\n");
8faa3f8
+         varstack_preen( &varparser, td3, -2 );
8faa3f8
+         /* Similarly, empty the type stack out. */
8faa3f8
+         typestack_preen( &typarser, td3, -2 );
8faa3f8
+
8faa3f8
+         TRACE_D3("set_abbv_Cursor cache: %lu queries, %lu misses\n",
8faa3f8
+                  cc.saC_cache_queries, cc.saC_cache_misses);
8faa3f8
+
8faa3f8
+         vg_assert(varparser.filenameTable );
8faa3f8
+         VG_(deleteXA)( varparser.filenameTable );
8faa3f8
+         varparser.filenameTable = NULL;
8faa3f8
+
8faa3f8
+         if (cu_offset_now == section_size)
8faa3f8
+            break;
8faa3f8
+         /* else keep going */
8faa3f8
+      }
8faa3f8
    }
8faa3f8
 
8faa3f8
    /* From here on we're post-processing the stuff we got
8faa3f8
@@ -3973,14 +4183,10 @@ void new_dwarf3_reader_wrk (
8faa3f8
    ML_(dinfo_free)( tyents_to_keep_cache );
8faa3f8
    tyents_to_keep_cache = NULL;
8faa3f8
 
8faa3f8
-   /* and the file name table (just the array, not the entries
8faa3f8
-      themselves).  (Apparently, 2008-Oct-23, varparser.filenameTable
8faa3f8
-      can be NULL here, for icc9 generated Dwarf3.  Not sure what that
8faa3f8
-      signifies (a deeper problem with the reader?)) */
8faa3f8
-   if (varparser.filenameTable) {
8faa3f8
-      VG_(deleteXA)( varparser.filenameTable );
8faa3f8
-      varparser.filenameTable = NULL;
8faa3f8
-   }
8faa3f8
+   vg_assert( varparser.filenameTable == NULL );
8faa3f8
+
8faa3f8
+   /* And the signatured type hash.  */
8faa3f8
+   VG_(HT_destruct) ( signature_types, ML_(dinfo_free) );
8faa3f8
 
8faa3f8
    /* record the GExprs in di so they can be freed later */
8faa3f8
    vg_assert(!di->admin_gexprs);
8faa3f8
@@ -4011,6 +4217,7 @@ void
8faa3f8
 ML_(new_dwarf3_reader) (
8faa3f8
    struct _DebugInfo* di,
8faa3f8
    UChar* debug_info_img,   SizeT debug_info_sz,
8faa3f8
+   UChar* debug_types_img,  SizeT debug_types_sz,
8faa3f8
    UChar* debug_abbv_img,   SizeT debug_abbv_sz,
8faa3f8
    UChar* debug_line_img,   SizeT debug_line_sz,
8faa3f8
    UChar* debug_str_img,    SizeT debug_str_sz,
8faa3f8
@@ -4034,6 +4241,7 @@ ML_(new_dwarf3_reader) (
8faa3f8
       /* try this ... */
8faa3f8
       new_dwarf3_reader_wrk( di, barf,
8faa3f8
                              debug_info_img,   debug_info_sz,
8faa3f8
+                             debug_types_img,  debug_types_sz,
8faa3f8
                              debug_abbv_img,   debug_abbv_sz,
8faa3f8
                              debug_line_img,   debug_line_sz,
8faa3f8
                              debug_str_img,    debug_str_sz,
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/readmacho.c	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/readmacho.c	(revision 12491)
8faa3f8
@@ -1068,6 +1068,7 @@ Bool ML_(read_macho_debug_info)( struct
8faa3f8
          /* The old reader: line numbers and unwind info only */
8faa3f8
          ML_(read_debuginfo_dwarf3) ( di,
8faa3f8
                                       debug_info_img, debug_info_sz,
8faa3f8
+				      NULL,           0,
8faa3f8
                                       debug_abbv_img, debug_abbv_sz,
8faa3f8
                                       debug_line_img, debug_line_sz,
8faa3f8
                                       debug_str_img,  debug_str_sz );
8faa3f8
@@ -1080,6 +1081,7 @@ Bool ML_(read_macho_debug_info)( struct
8faa3f8
              || VG_(clo_read_var_info) /* the user asked for it */) {
8faa3f8
             ML_(new_dwarf3_reader)(
8faa3f8
                di, debug_info_img,   debug_info_sz,
8faa3f8
+	           NULL,             0,
8faa3f8
                    debug_abbv_img,   debug_abbv_sz,
8faa3f8
                    debug_line_img,   debug_line_sz,
8faa3f8
                    debug_str_img,    debug_str_sz,
8faa3f8
--- valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf3.h	(revision 12490)
8faa3f8
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf3.h	(revision 12491)
8faa3f8
@@ -43,6 +43,7 @@ void
8faa3f8
 ML_(new_dwarf3_reader) (
8faa3f8
    struct _DebugInfo* di,
8faa3f8
    UChar* debug_info_img,   SizeT debug_info_sz,
8faa3f8
+   UChar* debug_types_img,  SizeT debug_types_sz,
8faa3f8
    UChar* debug_abbv_img,   SizeT debug_abbv_sz,
8faa3f8
    UChar* debug_line_img,   SizeT debug_line_sz,
8faa3f8
    UChar* debug_str_img,    SizeT debug_str_sz,