Blob Blame History Raw
diff -ru valgrind-3.7.0.orig/config.h valgrind-3.7.0/config.h
--- valgrind-3.7.0.orig/config.h	2012-07-25 12:33:29.212949007 +0200
+++ valgrind-3.7.0/config.h	2012-07-25 12:44:42.847307554 +0200
@@ -29,7 +29,7 @@
 /* #undef GLIBC_2_10 */
 
 /* Define to 1 if you're using glibc 2.11.x */
-#define GLIBC_2_11 1
+/* #undef GLIBC_2_11 */
 
 /* Define to 1 if you're using glibc 2.12.x */
 /* #undef GLIBC_2_12 */
@@ -38,7 +38,10 @@
 /* #undef GLIBC_2_13 */
 
 /* Define to 1 if you're using glibc 2.14.x */
-/* #undef GLIBC_2_14 */
+#define GLIBC_2_14 1
+
+/* Define to 1 if you're using glibc 2.15.x */
+/* #undef GLIBC_2_15 */
 
 /* Define to 1 if you're using glibc 2.2.x */
 /* #undef GLIBC_2_2 */
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/d3basics.c valgrind-3.7.0/coregrind/m_debuginfo/d3basics.c
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/d3basics.c	2012-07-25 12:33:29.191948686 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/d3basics.c	2012-07-25 12:44:30.217112438 +0200
@@ -180,6 +180,8 @@
       case DW_FORM_exprloc:   return "DW_FORM_exprloc";
       case DW_FORM_flag_present:return "DW_FORM_flag_present";
       case DW_FORM_ref_sig8:  return "DW_FORM_ref_sig8";
+      case DW_FORM_GNU_ref_alt:return "DW_FORM_GNU_ref_alt";
+      case DW_FORM_GNU_strp_alt:return "DW_FORM_GNU_strp_alt";
       default:                return "DW_FORM_???";
    }
 }
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/debuginfo.c valgrind-3.7.0/coregrind/m_debuginfo/debuginfo.c
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/debuginfo.c	2012-07-25 12:33:29.191948686 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/debuginfo.c	2012-07-25 12:44:30.219112468 +0200
@@ -859,7 +859,7 @@
 
    /* We're only interested in mappings of object files. */
 #  if defined(VGO_linux)
-   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
+   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
       return 0;
 #  elif defined(VGO_darwin)
    if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_d3basics.h valgrind-3.7.0/coregrind/m_debuginfo/priv_d3basics.h
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_d3basics.h	2012-07-25 12:33:29.192948701 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_d3basics.h	2012-07-25 12:44:30.235112717 +0200
@@ -199,7 +199,11 @@
     DW_FORM_sec_offset = 0x17,
     DW_FORM_exprloc = 0x18,
     DW_FORM_flag_present = 0x19,
-    DW_FORM_ref_sig8 = 0x20
+    DW_FORM_ref_sig8 = 0x20,
+    /* Extensions for DWZ multifile.
+       See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open .  */
+    DW_FORM_GNU_ref_alt = 0x1f20,
+    DW_FORM_GNU_strp_alt = 0x1f21
   }
   DW_FORM;
 
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readdwarf3.h valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf3.h
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readdwarf3.h	2012-07-25 12:33:29.192948701 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf3.h	2012-07-25 12:44:30.237112747 +0200
@@ -48,7 +48,11 @@
    UChar* debug_line_img,   SizeT debug_line_sz,
    UChar* debug_str_img,    SizeT debug_str_sz,
    UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz
+   UChar* debug_loc_img,    SizeT debug_loc_sz,
+   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
+   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
+   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
+   UChar* debug_str_alt_img,  SizeT debug_str_alt_sz
 );
 
 #endif /* ndef __PRIV_READDWARF3_H */
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readdwarf.h valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf.h
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readdwarf.h	2012-07-25 12:33:29.192948701 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_readdwarf.h	2012-07-25 12:44:30.238112762 +0200
@@ -48,7 +48,8 @@
           UChar* debug_types_img, Word debug_types_sz,  /* .debug_types */
           UChar* debug_abbv_img, Word debug_abbv_sz,  /* .debug_abbrev */
           UChar* debug_line_img, Word debug_line_sz,  /* .debug_line */
-          UChar* debug_str_img,  Word debug_str_sz ); /* .debug_str */
+          UChar* debug_str_img,  Word debug_str_sz,   /* .debug_str */
+          UChar* debug_str_alt_img, Word debug_str_alt_sz ); /* .debug_str */
 
 /* --------------------
    DWARF1 reader
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readelf.h valgrind-3.7.0/coregrind/m_debuginfo/priv_readelf.h
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/priv_readelf.h	2012-07-25 12:33:29.192948701 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/priv_readelf.h	2012-07-25 12:44:30.239112777 +0200
@@ -40,7 +40,7 @@
 
 /* Identify an ELF object file by peering at the first few bytes of
    it. */
-extern Bool ML_(is_elf_object_file)( void* image, SizeT n_image );
+extern Bool ML_(is_elf_object_file)( void* image, SizeT n_image, Bool rel_ok );
 
 /* The central function for reading ELF debug info.  For the
    object/exe specified by the SegInfo, find ELF sections, then read
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/readdwarf3.c valgrind-3.7.0/coregrind/m_debuginfo/readdwarf3.c
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/readdwarf3.c	2012-07-25 12:33:29.192948701 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/readdwarf3.c	2012-07-25 12:44:30.240112792 +0200
@@ -420,6 +420,16 @@
       /* Where is .debug_types? */
       UChar* debug_types_img;
       UWord  debug_types_sz;
+      /* Where is alternate .debug_info? */
+      UChar* debug_info_alt_img;
+      UWord  debug_info_alt_sz;
+      /* Where is alternate .debug_str ? */
+      UChar* debug_str_alt_img;
+      UWord  debug_str_alt_sz;
+      /* How much to add to .debug_types resp. alternate .debug_info offsets
+         in cook_die*.  */
+      UWord  types_cuOff_bias;
+      UWord  alt_cuOff_bias;
       /* --- Needed so we can add stuff to the string table. --- */
       struct _DebugInfo* di;
       /* --- a cache for set_abbv_Cursor --- */
@@ -440,40 +450,58 @@
       /* Signatured type hash; computed once and then shared by all
          CUs.  */
       VgHashTable signature_types;
+
+      /* True if this came from alternate .debug_info; otherwise
+         it came from normal .debug_info or .debug_types.  */
+      Bool is_alt_info;
    }
    CUConst;
 
 
 /* Return the cooked value of DIE depending on whether CC represents a
-   .debug_types unit.  To cook a DIE, we pretend that the .debug_info
-   and .debug_types sections form a contiguous whole, so that DIEs
-   coming from .debug_types are numbered starting at the end of
-   .debug_info.  */
+   .debug_types unit.  To cook a DIE, we pretend that the .debug_info,
+   .debug_types and optional alternate .debug_info sections form
+   a contiguous whole, so that DIEs coming from .debug_types are numbered
+   starting at the end of .debug_info and DIEs coming from alternate
+   .debug_info are numbered starting at the end of .debug_types.  */
 static UWord cook_die( CUConst* cc, UWord die )
 {
    if (cc->is_type_unit)
-      die += cc->debug_info_sz;
+      die += cc->types_cuOff_bias;
+   else if (cc->is_alt_info)
+      die += cc->alt_cuOff_bias;
    return die;
 }
 
 /* Like cook_die, but understand that DIEs coming from a
-   DW_FORM_ref_sig8 reference are already cooked.  */
+   DW_FORM_ref_sig8 reference are already cooked.  Also, handle
+   DW_FORM_GNU_ref_alt from within primary .debug_info or .debug_types
+   as reference to alternate .debug_info.  */
 static UWord cook_die_using_form( CUConst *cc, UWord die, DW_FORM form)
 {
    if (form == DW_FORM_ref_sig8)
       return die;
+   if (form == DW_FORM_GNU_ref_alt)
+      return die + cc->alt_cuOff_bias;
    return cook_die( cc, die );
 }
 
-/* Return the uncooked offset of DIE and set *FLAG to true if the DIE
-   came from the .debug_types section.  */
-static UWord uncook_die( CUConst *cc, UWord die, /*OUT*/Bool *flag )
+/* Return the uncooked offset of DIE and set *TYPE_FLAG to true if the DIE
+   came from the .debug_types section and *ALT_FLAG to true if the DIE
+   came from alternate .debug_info section.  */
+static UWord uncook_die( CUConst *cc, UWord die, /*OUT*/Bool *type_flag,
+                         Bool *alt_flag )
 {
+   *alt_flag = False;
+   *type_flag = False;
    if (die >= cc->debug_info_sz) {
-      *flag = True;
-      die -= cc->debug_info_sz;
-   } else {
-      *flag = False;
+      if (die >= cc->debug_info_sz + cc->debug_types_sz) {
+         *alt_flag = True;
+         die -= cc->debug_info_sz + cc->debug_types_sz;
+      } else {
+         *type_flag = True;
+         die -= cc->debug_info_sz;
+      }
    }
    return die;
 }
@@ -831,7 +859,8 @@
                        Bool td3,
                        Cursor* c, 
                        UChar* debug_abbv_img, UWord debug_abbv_sz,
-		       Bool type_unit )
+		       Bool type_unit,
+                       Bool alt_info )
 {
    UChar  address_size;
    UWord  debug_abbrev_offset;
@@ -870,6 +899,7 @@
    TRACE_D3("   Pointer Size:  %d\n", (Int)address_size );
 
    cc->is_type_unit = type_unit;
+   cc->is_alt_info = alt_info;
 
    if (type_unit) {
       cc->type_signature = get_ULong( c );
@@ -1289,6 +1319,37 @@
                             (DW_FORM)get_ULEB128(c));
          return;
 
+      case DW_FORM_GNU_ref_alt:
+         *cts = get_Dwarfish_UWord(c, cc->is_dw64);
+         *ctsSzB = cc->is_dw64 ? sizeof(ULong) : sizeof(UInt);
+         TRACE_D3("0x%lx", (UWord)*cts);
+         if (0) VG_(printf)("DW_FORM_GNU_ref_alt 0x%lx\n", (UWord)*cts);
+         if (/* the following 2 are surely impossible, but ... */
+             cc->debug_info_alt_img == NULL || cc->debug_info_alt_sz == 0
+             || *cts >= (ULong)cc->debug_info_alt_sz) {
+            /* Hmm.  Offset is nonsensical for this object's .debug_info
+               section.  Be safe and reject it. */
+            cc->barf("get_Form_contents: DW_FORM_ref_addr points "
+                     "outside alternate .debug_info");
+         }
+         break;
+
+      case DW_FORM_GNU_strp_alt: {
+         /* this is an offset into alternate .debug_str */
+         UChar* str;
+         UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 );
+         if (cc->debug_str_alt_img == NULL || uw >= cc->debug_str_alt_sz)
+            cc->barf("get_Form_contents: DW_FORM_GNU_strp_alt "
+                     "points outside alternate .debug_str");
+         /* FIXME: check the entire string lies inside debug_str,
+            not just the first byte of it. */
+         str = (UChar*)cc->debug_str_alt_img + uw;
+         TRACE_D3("(indirect alt string, offset: 0x%lx): %s", uw, str);
+         *cts = (ULong)(UWord)str;
+         *ctsMemSzB = 1 + (ULong)VG_(strlen)(str);
+         break;
+      }
+
       default:
          VG_(printf)(
             "get_Form_contents: unhandled %d (%s) at <%lx>\n",
@@ -1579,10 +1640,13 @@
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
    Bool  debug_types_flag;
+   Bool  alt_flag;
 
    varstack_preen( parser, td3, level-1 );
 
-   if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit) {
+   if (dtag == DW_TAG_compile_unit
+       || dtag == DW_TAG_type_unit
+       || dtag == DW_TAG_partial_unit) {
       Bool have_lo    = False;
       Bool have_hi1   = False;
       Bool have_range = False;
@@ -2028,11 +2092,14 @@
    set_position_of_Cursor( c_die,  saved_die_c_offset );
    set_position_of_Cursor( c_abbv, saved_abbv_c_offset );
    VG_(printf)("\nparse_var_DIE: confused by:\n");
-   posn = uncook_die( cc, posn, &debug_types_flag );
+   posn = uncook_die( cc, posn, &debug_types_flag, &alt_flag );
    VG_(printf)(" <%d><%lx>: %s", level, posn, ML_(pp_DW_TAG)( dtag ) );
    if (debug_types_flag) {
       VG_(printf)(" (in .debug_types)");
    }
+   else if (alt_flag) {
+      VG_(printf)(" (in alternate .debug_info)");
+   }
    VG_(printf)("\n");
    while (True) {
       DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
@@ -2214,6 +2281,7 @@
    TyEnt fieldE;
    TyEnt boundE;
    Bool  debug_types_flag;
+   Bool  alt_flag;
 
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
@@ -2228,7 +2296,9 @@
       its children. */
    typestack_preen( parser, td3, level-1 );
 
-   if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit) {
+   if (dtag == DW_TAG_compile_unit
+       || dtag == DW_TAG_type_unit
+       || dtag == DW_TAG_partial_unit) {
       /* See if we can find DW_AT_language, since it is important for
          establishing array bounds (see DW_TAG_subrange_type below in
          this fn) */
@@ -2947,10 +3017,12 @@
    set_position_of_Cursor( c_die,  saved_die_c_offset );
    set_position_of_Cursor( c_abbv, saved_abbv_c_offset );
    VG_(printf)("\nparse_type_DIE: confused by:\n");
-   posn = uncook_die( cc, posn, &debug_types_flag );
+   posn = uncook_die( cc, posn, &debug_types_flag, &alt_flag );
    VG_(printf)(" <%d><%lx>: %s", level, posn, ML_(pp_DW_TAG)( dtag ) );
    if (debug_types_flag) {
       VG_(printf)(" (in .debug_types)");
+   } else if (alt_flag) {
+      VG_(printf)(" (in alternate .debug_info)");
    }
    VG_(printf)("\n");
    while (True) {
@@ -3428,7 +3500,11 @@
    UChar* debug_line_img,   SizeT debug_line_sz,
    UChar* debug_str_img,    SizeT debug_str_sz,
    UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz
+   UChar* debug_loc_img,    SizeT debug_loc_sz,
+   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
+   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
+   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
+   UChar* debug_str_alt_img,  SizeT debug_str_alt_sz
 )
 {
    XArray* /* of TyEnt */     tyents;
@@ -3668,10 +3744,10 @@
             (saC_cache) */
          parse_CU_Header( &cc, td3, &info,
                           (UChar*)debug_abbv_img, debug_abbv_sz,
-                          True );
+                          True, False );
 
          /* Needed by cook_die.  */
-         cc.debug_info_sz    = debug_info_sz;
+         cc.types_cuOff_bias = debug_info_sz;
 
          record_signatured_type( signature_types, cc.type_signature,
                                  cook_die( &cc, cc.type_offset ));
@@ -3689,15 +3765,29 @@
       }
    }
 
-   /* Perform two DIE-reading passes.  The first pass reads DIEs from
-      .debug_info, and the second pass reads DIEs from .debug_types.
+   /* Perform three DIE-reading passes.  The first pass reads DIEs from
+      alternate .debug_info (if any), the second pass reads DIEs from
+      .debug_info, and the third pass reads DIEs from .debug_types.
       Moving the body of this loop into a separate function would
       require a large number of arguments to be passed in, so it is
       kept inline instead.  */
-   for (pass = 0; pass < 2; ++pass) {
+   for (pass = 0; pass < 3; ++pass) {
       UWord section_size;
 
       if (pass == 0) {
+         if (debug_info_alt_img == NULL)
+	    continue;
+         /* Now loop over the Compilation Units listed in the alternate
+            .debug_info section (see D3SPEC sec 7.5) paras 1 and 2.
+            Each compilation unit contains a Compilation Unit Header
+            followed by precisely one DW_TAG_compile_unit or
+            DW_TAG_partial_unit DIE. */
+         init_Cursor( &info, debug_info_alt_img, debug_info_alt_sz, 0, barf,
+                      "Overrun whilst reading alternate .debug_info section" );
+         section_size = debug_info_alt_sz;
+
+         TRACE_D3("\n------ Parsing alternate .debug_info section ------\n");
+      } else if (pass == 1) {
          /* Now loop over the Compilation Units listed in the .debug_info
             section (see D3SPEC sec 7.5) paras 1 and 2.  Each compilation
             unit contains a Compilation Unit Header followed by precisely
@@ -3769,21 +3859,32 @@
          TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
          /* parse_CU_header initialises the CU's set_abbv_Cursor cache
             (saC_cache) */
-         parse_CU_Header( &cc, td3, &info,
-                          (UChar*)debug_abbv_img, debug_abbv_sz,
-                          pass != 0 );
-         cc.debug_str_img    = debug_str_img;
-         cc.debug_str_sz     = debug_str_sz;
+         if (pass == 0)
+            parse_CU_Header( &cc, td3, &info,
+                             (UChar*)debug_abbv_alt_img, debug_abbv_alt_sz,
+                             False, True );
+         else
+            parse_CU_Header( &cc, td3, &info,
+                             (UChar*)debug_abbv_img, debug_abbv_sz,
+                             pass == 2, False );
+         cc.debug_str_img    = pass == 0 ? debug_str_alt_img : debug_str_img;
+         cc.debug_str_sz     = pass == 0 ? debug_str_alt_sz : debug_str_sz;
          cc.debug_ranges_img = debug_ranges_img;
          cc.debug_ranges_sz  = debug_ranges_sz;
          cc.debug_loc_img    = debug_loc_img;
          cc.debug_loc_sz     = debug_loc_sz;
-         cc.debug_line_img   = debug_line_img;
-         cc.debug_line_sz    = debug_line_sz;
-         cc.debug_info_img   = debug_info_img;
-         cc.debug_info_sz    = debug_info_sz;
+         cc.debug_line_img   = pass == 0 ? debug_line_alt_img : debug_line_img;
+         cc.debug_line_sz    = pass == 0 ? debug_line_alt_sz : debug_line_sz;
+         cc.debug_info_img   = pass == 0 ? debug_info_alt_img : debug_info_img;
+         cc.debug_info_sz    = pass == 0 ? debug_info_alt_sz : debug_info_sz;
          cc.debug_types_img  = debug_types_img;
          cc.debug_types_sz   = debug_types_sz;
+         cc.debug_info_alt_img = debug_info_alt_img;
+         cc.debug_info_alt_sz = debug_info_alt_sz;
+         cc.debug_str_alt_img = debug_str_alt_img;
+         cc.debug_str_alt_sz = debug_str_alt_sz;
+         cc.types_cuOff_bias = debug_info_sz;
+         cc.alt_cuOff_bias   = debug_info_sz + debug_types_sz;
          cc.cu_start_offset  = cu_start_offset;
          cc.di = di;
          /* The CU's svma can be deduced by looking at the AT_low_pc
@@ -3966,10 +4067,19 @@
    vg_assert(dioff_lookup_tab);
 
    n = VG_(sizeXA)( tempvars );
+   Word first_primary_var;
+   for (first_primary_var = 0;
+        debug_info_alt_sz && first_primary_var < n;
+        first_primary_var++) {
+      varp = *(TempVar**)VG_(indexXA)( tempvars, first_primary_var );
+      if (varp->dioff < debug_info_sz + debug_types_sz)
+         break;
+   }
    for (i = 0; i < n; i++) {
-      varp = *(TempVar**)VG_(indexXA)( tempvars, i );
-      if (i > 0) {
-         varp2 = *(TempVar**)VG_(indexXA)( tempvars, i-1 );
+      varp = *(TempVar**)VG_(indexXA)( tempvars, (i + first_primary_var) % n );
+      if (i > first_primary_var) {
+         varp2 = *(TempVar**)VG_(indexXA)( tempvars,
+                                           (i + first_primary_var - 1) % n );
          /* why should this hold?  Only, I think, because we've
             constructed the array by reading .debug_info sequentially,
             and so the array .dioff fields should reflect that, and be
@@ -4223,7 +4333,11 @@
    UChar* debug_line_img,   SizeT debug_line_sz,
    UChar* debug_str_img,    SizeT debug_str_sz,
    UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz
+   UChar* debug_loc_img,    SizeT debug_loc_sz,
+   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
+   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
+   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
+   UChar* debug_str_alt_img,  SizeT debug_str_alt_sz
 )
 {
    volatile Int  jumped;
@@ -4247,7 +4361,11 @@
                              debug_line_img,   debug_line_sz,
                              debug_str_img,    debug_str_sz,
                              debug_ranges_img, debug_ranges_sz,
-                             debug_loc_img,    debug_loc_sz );
+                             debug_loc_img,    debug_loc_sz,
+                             debug_info_alt_img, debug_info_alt_sz,
+                             debug_abbv_alt_img, debug_abbv_alt_sz,
+                             debug_line_alt_img, debug_line_alt_sz,
+                             debug_str_alt_img,  debug_str_alt_sz);
       d3rd_jmpbuf_valid = False;
       TRACE_D3("\n------ .debug_info reading was successful ------\n");
    } else {
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/readdwarf.c valgrind-3.7.0/coregrind/m_debuginfo/readdwarf.c
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/readdwarf.c	2012-07-25 12:33:29.191948686 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/readdwarf.c	2012-07-25 12:44:30.257113055 +0200
@@ -985,7 +985,8 @@
 void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
                                   UChar*    unitblock_img,
                                   UChar*    debugabbrev_img,
-                                  UChar*    debugstr_img )
+                                  UChar*    debugstr_img,
+                                  UChar*    debugstr_alt_img )
 {
    UInt   acode, abcode;
    ULong  atoffs, blklen;
@@ -1128,6 +1129,14 @@
             case 0x18: /* FORM_exprloc */   p += read_leb128U( &p ); break;
             case 0x19: /* FORM_flag_present */break;
             case 0x20: /* FORM_ref_sig8 */  p += 8; break;
+            case 0x1f20: /* FORM_GNU_ref_alt */ p += ui->dw64 ? 8 : 4; break;
+            case 0x1f21: /* FORM_GNU_strp_alt */
+                                            if (debugstr_alt_img && !ui->dw64)
+                                               sval = debugstr_alt_img + ML_(read_UInt)(p);
+                                            if (debugstr_alt_img && ui->dw64)
+                                               sval = debugstr_alt_img + ML_(read_ULong)(p);
+                                            p += ui->dw64 ? 8 : 4; 
+                                            break;
 
             default:
                VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n", form );
@@ -1169,7 +1178,8 @@
           UChar* debug_types_img, Word debug_types_sz, /* .debug_types */
           UChar* debug_abbv_img, Word debug_abbv_sz, /* .debug_abbrev */
           UChar* debug_line_img, Word debug_line_sz, /* .debug_line */
-          UChar* debug_str_img,  Word debug_str_sz ) /* .debug_str */
+          UChar* debug_str_img,  Word debug_str_sz, /* .debug_str */
+          UChar* debug_str_alt_img, Word debug_str_alt_sz ) /* .debug_str */
 {
    UnitInfo ui;
    UShort   ver;
@@ -1218,7 +1228,8 @@
          VG_(printf)( "Reading UnitInfo at 0x%lx.....\n",
                       block_img - debug_info_img + 0UL );
       read_unitinfo_dwarf2( &ui, block_img, 
-                                 debug_abbv_img, debug_str_img );
+                                 debug_abbv_img, debug_str_img,
+                                 debug_str_alt_img );
       if (0)
          VG_(printf)( "   => LINES=0x%llx    NAME=%s     DIR=%s\n", 
                       ui.stmt_list, ui.name, ui.compdir );
diff -ru valgrind-3.7.0.orig/coregrind/m_debuginfo/readelf.c valgrind-3.7.0/coregrind/m_debuginfo/readelf.c
--- valgrind-3.7.0.orig/coregrind/m_debuginfo/readelf.c	2012-07-25 12:33:29.191948686 +0200
+++ valgrind-3.7.0/coregrind/m_debuginfo/readelf.c	2012-07-25 12:53:09.377151832 +0200
@@ -111,7 +111,7 @@
 /* Identify an ELF object file by peering at the first few bytes of
    it. */
 
-Bool ML_(is_elf_object_file)( void* image, SizeT n_image )
+Bool ML_(is_elf_object_file)( void* image, SizeT n_image, Bool rel_ok )
 {
    ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
    Int ok = 1;
@@ -126,12 +126,14 @@
    ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
           && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
           && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
-   ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
+   ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
+          || (rel_ok && ehdr->e_type == ET_REL));
    ok &= (ehdr->e_machine == VG_ELF_MACHINE);
    ok &= (ehdr->e_version == EV_CURRENT);
    ok &= (ehdr->e_shstrndx != SHN_UNDEF);
    ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
-   ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
+   ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
+          || ehdr->e_type == ET_REL);
 
    if (ok)
       return True;
@@ -887,7 +889,7 @@
  * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
  */
 static
-Char *find_buildid(Addr image, UWord n_image)
+Char *find_buildid(Addr image, UWord n_image, Bool rel_ok)
 {
    Char* buildid = NULL;
    __attribute__((unused)) /* on Android, at least */
@@ -895,7 +897,7 @@
 
 #ifdef NT_GNU_BUILD_ID
    if (n_image >= sizeof(ElfXX_Ehdr) &&
-       ML_(is_elf_object_file)(ehdr, n_image)) {
+       ML_(is_elf_object_file)(ehdr, n_image, rel_ok)) {
       Word i;
 
       for (i = 0; i < ehdr->e_phnum; i++) {
@@ -927,7 +929,41 @@
                                + ((note->n_descsz + 3) & ~3);
             }            
          }
-      }    
+      }
+
+      if (buildid || !rel_ok)
+         return buildid;
+
+      for (i = 0; i < ehdr->e_shnum; i++) {
+         ElfXX_Shdr* shdr
+            = (ElfXX_Shdr*)(image + ehdr->e_shoff + i * ehdr->e_shentsize);
+
+         if (shdr->sh_type == SHT_NOTE) {
+            ElfXX_Off offset =  shdr->sh_offset;
+
+            while (offset < shdr->sh_offset + shdr->sh_size) {
+               ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
+               Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
+               UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
+               Word j2;
+
+               if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
+                   note->n_type == NT_GNU_BUILD_ID) {
+                  buildid = ML_(dinfo_zalloc)("di.fbi.1",
+                                              note->n_descsz * 2 + 1);
+                  
+                  for (j2 = 0; j2 < note->n_descsz; j2++) {
+                     VG_(sprintf)(buildid + VG_(strlen)(buildid), 
+                                  "%02x", desc[j2]);
+                  }
+               }
+
+               offset = offset + sizeof(ElfXX_Nhdr)
+                               + ((note->n_namesz + 3) & ~3)
+                               + ((note->n_descsz + 3) & ~3);
+            }            
+         }
+      }
    }
 #endif
 
@@ -1009,7 +1045,8 @@
  * not match the value from the main object file.
  */
 static
-Addr open_debug_file( Char* name, Char* buildid, UInt crc, /*OUT*/UWord* size )
+Addr open_debug_file( Char* name, Char* buildid, UInt crc, Bool rel_ok,
+                      /*OUT*/UWord* size )
 {
    SysRes fd, sres;
    struct vg_stat stat_buf;
@@ -1038,7 +1075,7 @@
       return 0;
 
    if (buildid) {
-      Char* debug_buildid = find_buildid(sr_Res(sres), *size);
+      Char* debug_buildid = find_buildid(sr_Res(sres), *size, rel_ok);
       if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
          SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
          vg_assert(!sr_isError(res));
@@ -1157,7 +1194,7 @@
 static
 void find_debug_file( struct _DebugInfo* di,
                       Char* objpath, Char* buildid,
-                      Char* debugname, UInt crc,
+                      Char* debugname, UInt crc, Bool rel_ok,
                       /*OUT*/Addr*  dimage,
                       /*OUT*/SizeT* n_dimage )
 {
@@ -1175,13 +1212,14 @@
       VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
                    buildid[0], buildid[1], buildid + 2);
 
-      if ((addr = open_debug_file(debugpath, buildid, 0, &size)) == 0) {
+      if ((addr = open_debug_file(debugpath, buildid, 0,
+                                  rel_ok, &size)) == 0) {
          ML_(dinfo_free)(debugpath);
          debugpath = NULL;
       }
    }
 
-   if (addr == 0 && debugname != NULL) {
+   if (addr == 0 && debugname != NULL && !rel_ok) {
       Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
       Char *objdirptr;
 
@@ -1194,11 +1232,11 @@
 
       VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
 
-      if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
+      if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
          VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
-         if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
+         if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
             VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
-            addr = open_debug_file(debugpath, NULL, crc, &size);
+            addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size);
          }
       }
 
@@ -1283,7 +1321,7 @@
    /* TOPLEVEL */
    Bool          res, ok;
    SysRes        fd, sres;
-   Word          i;
+   Word          i, i2;
    Bool          dynbss_present = False;
    Bool          sdynbss_present = False;
 
@@ -1295,6 +1333,10 @@
    Addr          dimage   = 0;
    UWord         n_dimage = 0;
 
+   /* Ditto for alternate ELF debuginfo file that we might happen to load. */
+   Addr          aimage   = 0;
+   UWord         n_aimage = 0;
+
    /* ELF header for the main file.  Should == oimage since is at
       start of file. */
    ElfXX_Ehdr* ehdr_img = NULL;
@@ -1417,7 +1459,7 @@
    ehdr_img = (ElfXX_Ehdr*)oimage;
 
    if (ok)
-      ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage);
+      ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage, False);
 
    if (!ok) {
       ML_(symerr)(di, True, "Invalid ELF Header");
@@ -2068,6 +2110,7 @@
       UChar*     dynstr_img       = NULL; /* .dynstr */
       ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
       UChar*     debuglink_img    = NULL; /* .gnu_debuglink */
+      UChar*     debugaltlink_img = NULL; /* .gnu_debugaltlink */
       UChar*     stab_img         = NULL; /* .stab         (stabs)  */
       UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
       UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
@@ -2078,6 +2121,10 @@
       UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
       UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
       UChar*     debug_frame_img  = NULL; /* .debug_frame  (dwarf2) */
+      UChar*     debug_line_alt_img = NULL; /* .debug_line (alternate) */
+      UChar*     debug_info_alt_img = NULL; /* .debug_info (alternate) */
+      UChar*     debug_abbv_alt_img = NULL; /* .debug_abbrev (alternate) */
+      UChar*     debug_str_alt_img = NULL; /* .debug_str   (alternate) */
       UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
       UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
       UChar*     opd_img          = NULL; /* .opd (dwarf2,
@@ -2090,16 +2137,21 @@
       SizeT      dynstr_sz       = 0;
       SizeT      dynsym_sz       = 0;
       SizeT      debuglink_sz    = 0;
+      SizeT      debugaltlink_sz = 0;
       SizeT      stab_sz         = 0;
       SizeT      stabstr_sz      = 0;
       SizeT      debug_line_sz   = 0;
       SizeT      debug_info_sz   = 0;
-      SizeT      debug_types_sz   = 0;
+      SizeT      debug_types_sz  = 0;
       SizeT      debug_abbv_sz   = 0;
       SizeT      debug_str_sz    = 0;
       SizeT      debug_ranges_sz = 0;
       SizeT      debug_loc_sz    = 0;
       SizeT      debug_frame_sz  = 0;
+      SizeT      debug_line_alt_sz = 0;
+      SizeT      debug_info_alt_sz = 0;
+      SizeT      debug_abbv_alt_sz = 0;
+      SizeT      debug_str_alt_sz = 0;
       SizeT      dwarf1d_sz      = 0;
       SizeT      dwarf1l_sz      = 0;
       SizeT      opd_sz_unused   = 0;
@@ -2164,6 +2216,7 @@
          FIND(".strtab",        strtab_sz,       strtab_img)
 
          FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
+         FIND(".gnu_debugaltlink", debugaltlink_sz, debugaltlink_img)
 
          FIND(".stab",          stab_sz,         stab_img)
          FIND(".stabstr",       stabstr_sz,      stabstr_img)
@@ -2209,7 +2262,7 @@
       vg_assert(dimage == 0 && n_dimage == 0);
 
       /* Look for a build-id */
-      buildid = find_buildid(oimage, n_oimage);
+      buildid = find_buildid(oimage, n_oimage, False);
 
       /* Look for a debug image */
       if (buildid != NULL || debuglink_img != NULL) {
@@ -2225,11 +2278,11 @@
 
             /* See if we can find a matching debug file */
             find_debug_file( di, di->fsm.filename, buildid,
-                             debuglink_img, crc, &dimage, &n_dimage );
+                             debuglink_img, crc, False, &dimage, &n_dimage );
          } else {
             /* See if we can find a matching debug file */
             find_debug_file( di, di->fsm.filename, buildid,
-                             NULL, 0, &dimage, &n_dimage );
+                             NULL, 0, False, &dimage, &n_dimage );
          }
       }
 
@@ -2252,7 +2305,7 @@
          SVMA/bias/size and image addresses out of it. */
       if (dimage != 0 
           && n_dimage >= sizeof(ElfXX_Ehdr)
-          && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
+          && ML_(is_elf_object_file)((void*)dimage, n_dimage, False)) {
 
          /* Pull out and validate program header and section header info */
          ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
@@ -2437,6 +2490,8 @@
             FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
             FIND(need_dwarf2, ".debug_frame",  debug_frame_sz,
                                                             debug_frame_img)
+            FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_sz,
+                                                            debugaltlink_img)
             FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
             FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
 
@@ -2444,6 +2499,100 @@
          } /* Find all interesting sections */
       } /* do we have a debug image? */
 
+      /* Look for alternate debug image */
+      if (debugaltlink_img != NULL) {
+         UInt buildid_offset = VG_(strlen)(debugaltlink_img)+1;
+
+         vg_assert(buildid_offset < debugaltlink_sz);
+
+         Char *altbuildid
+            = ML_(dinfo_zalloc)("di.fbi.4",
+                                (debugaltlink_sz - buildid_offset)
+                                * 2 + 1);
+
+         for (i2 = 0; i2 < debugaltlink_sz - buildid_offset; i2++)
+            VG_(sprintf)(altbuildid + 2 * i2, 
+                         "%02x", debugaltlink_img[buildid_offset + i2]);
+
+         /* See if we can find a matching debug file */
+         find_debug_file( di, di->fsm.filename, altbuildid,
+                          NULL, 0, True, &aimage, &n_aimage );
+
+         ML_(dinfo_free)(altbuildid);
+      }
+
+      /* TOPLEVEL */
+      /* If we were successful in finding alternate debug image, pull various
+         size and image addresses out of it. */
+      if (aimage != 0 
+          && n_aimage >= sizeof(ElfXX_Ehdr)
+          && ML_(is_elf_object_file)((void*)aimage, n_aimage, True)) {
+
+         /* Pull out and validate program header and section header info */
+         ElfXX_Ehdr* ehdr_aimg     = (ElfXX_Ehdr*)aimage;
+         ElfXX_Shdr* shdr_aimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_aimg)
+                                                       + ehdr_aimg->e_shoff );
+         UWord       shdr_dnent       = ehdr_aimg->e_shnum;
+         UWord       shdr_dent_szB    = ehdr_aimg->e_shentsize;
+         UChar*      shdr_strtab_aimg = NULL;
+
+         if (shdr_dnent == 0
+             || !contained_within(
+                    aimage, n_aimage,
+                    (Addr)shdr_aimg, shdr_dnent * shdr_dent_szB)) {
+            ML_(symerr)(di, True,
+                        "Missing or invalid ELF Section Header Table"
+                        " (alternate debuginfo file)");
+            goto out;
+         }
+
+         /* Also find the section header's string table, and validate. */
+         /* checked previously by is_elf_object_file: */
+         vg_assert( ehdr_aimg->e_shstrndx != SHN_UNDEF );
+
+         shdr_strtab_aimg
+            = (UChar*)( ((UChar*)ehdr_aimg)
+                        + shdr_aimg[ehdr_aimg->e_shstrndx].sh_offset);
+         if (!contained_within( 
+                 aimage, n_aimage,
+                 (Addr)shdr_strtab_aimg,
+                 1/*bogus, but we don't know the real size*/ )) {
+            ML_(symerr)(di, True, 
+                        "Invalid ELF Section Header String Table"
+                        " (alternate debuginfo file)");
+            goto out;
+         }
+
+         /* Find all interesting sections */
+         for (i = 0; i < ehdr_aimg->e_shnum; i++) {
+
+#           define FIND(sec_name, sec_size, sec_img) \
+            do { ElfXX_Shdr* shdr \
+                    = INDEX_BIS( shdr_aimg, i, shdr_dent_szB ); \
+               if (0 == VG_(strcmp)(sec_name, \
+                                    shdr_strtab_aimg + shdr->sh_name)) { \
+                  if (0 != sec_img) \
+                     VG_(core_panic)("repeated section!\n"); \
+                  sec_img  = (void*)(aimage + shdr->sh_offset); \
+                  sec_size = shdr->sh_size; \
+                  TRACE_SYMTAB( "%18s: aimg %p .. %p\n", \
+                                sec_name, \
+                                (UChar*)sec_img, \
+                                ((UChar*)sec_img) + sec_size - 1); \
+               } \
+            } while (0);
+
+            /*   NAME             SIZE           IMAGE addr */
+            FIND(".debug_line",   debug_line_alt_sz, debug_line_alt_img)
+            FIND(".debug_info",   debug_info_alt_sz, debug_info_alt_img)
+            FIND(".debug_abbrev", debug_abbv_alt_sz, debug_abbv_alt_img)
+            FIND(".debug_str",    debug_str_alt_sz,  debug_str_alt_img)
+
+#           undef FIND
+         } /* Find all interesting sections */
+      } /* do we have a debug image? */
+
+
       /* TOPLEVEL */
       /* Check some sizes */
       vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
@@ -2524,7 +2673,8 @@
                                       debug_types_img, debug_types_sz,
                                       debug_abbv_img, debug_abbv_sz,
                                       debug_line_img, debug_line_sz,
-                                      debug_str_img,  debug_str_sz );
+                                      debug_str_img,  debug_str_sz,
+                                      debug_str_alt_img, debug_str_alt_sz );
 
          /* The new reader: read the DIEs in .debug_info to acquire
             information on variable types and locations.  But only if
@@ -2539,7 +2689,11 @@
                    debug_line_img,   debug_line_sz,
                    debug_str_img,    debug_str_sz,
                    debug_ranges_img, debug_ranges_sz,
-                   debug_loc_img,    debug_loc_sz
+                   debug_loc_img,    debug_loc_sz,
+                   debug_info_alt_img, debug_info_alt_sz,
+                   debug_abbv_alt_img, debug_abbv_alt_sz,
+                   debug_line_alt_img, debug_line_alt_sz,
+                   debug_str_alt_img,  debug_str_alt_sz
             );
          }
       }