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