commit 58d9ce4730d95103c9388be264a170ab852432a9 Author: mjw Date: Thu Apr 11 17:55:39 2013 +0000 read_unitinfo_dwarf2 DW_FORM_ref_addr is address size in DWARF version 2. Bug #305513 contained a patch for some extra robustness checks. But the real cause of crashing in the read_unitinfo_dwarf2 DWARF reader seemed to have been this issue where DWARF version 2 DWZ partial_units were read and DW_FORM_ref_addr had an unexpected size. This combination is rare. DWARF version 4 is the current default version of GCC. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13367 a5019735-40e9-0310-863c-91ae7b9d1cf9 diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index ce34bc7..52a9099 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -991,7 +991,7 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, UInt acode, abcode; ULong atoffs, blklen; Int level; - /* UShort ver; */ + UShort ver; UChar addr_size; UChar* p = unitblock_img; @@ -1008,7 +1008,7 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, p += ui->dw64 ? 12 : 4; /* version should be 2, 3 or 4 */ - /* ver = ML_(read_UShort)(p); */ + ver = ML_(read_UShort)(p); p += 2; /* get offset in abbrev */ @@ -1122,7 +1122,7 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, case 0x0c: /* FORM_flag */ p++; break; case 0x0d: /* FORM_sdata */ read_leb128S( &p ); break; case 0x0f: /* FORM_udata */ read_leb128U( &p ); break; - case 0x10: /* FORM_ref_addr */ p += ui->dw64 ? 8 : 4; break; + case 0x10: /* FORM_ref_addr */ p += (ver == 2) ? addr_size : (ui->dw64 ? 8 : 4); break; case 0x11: /* FORM_ref1 */ p++; break; case 0x12: /* FORM_ref2 */ p += 2; break; case 0x13: /* FORM_ref4 */ p += 4; break; commit 4c3b2379fb2cb97f762617df7770b042b1f8a59c Author: mjw Date: Wed Apr 17 13:48:29 2013 +0000 Simplify read_unitinfo_dwarf2. Only try to read the first DIE. Bug #305513. We should only read the first DIE of a compilation unit. Each compilation unit header is followed by a single DW_TAG_compile_unit (or DW_TAG_partial_unit, but those aren't important here) and its children. There is no reason to read any of the children at this point. If the first DIE isn't a DW_TAG_compile_unit we are done, none of the child DIEs will provide any useful information. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13369 a5019735-40e9-0310-863c-91ae7b9d1cf9 diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 52a9099..764295c 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -965,12 +965,14 @@ static UChar* lookup_abbrev( UChar* p, UInt acode ) } /* Read general information for a particular compile unit block in - * the .debug_info section. + * the .debug_info section. In particular read the name, compdir and + * stmt_list needed to parse the line number information. * * Input: - unitblock is the start of a compilation * unit block in .debuginfo section * - debugabbrev is start of .debug_abbrev section * - debugstr is start of .debug_str section + * - debugstr_alt_img is start of .debug_str section in alt debug file * * Output: Fill members of ui pertaining to the compilation unit: * - ui->name is the name of the compilation unit @@ -990,7 +992,6 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, { UInt acode, abcode; ULong atoffs, blklen; - Int level; UShort ver; UChar addr_size; @@ -1021,39 +1022,32 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, end_img = unitblock_img + blklen + (ui->dw64 ? 12 : 4); /* End of this block */ - level = 0; /* Level in the abbrev tree */ abbrev_img = debugabbrev_img + atoffs; /* Abbreviation data for this block */ - /* Read the compilation unit entries */ - while ( p < end_img ) { - Bool has_child; + /* Read the compilation unit entry - this is always the first DIE. + * See DWARF4 para 7.5. */ + if ( p < end_img ) { UInt tag; acode = read_leb128U( &p ); /* abbreviation code */ - if ( acode == 0 ) { - /* NULL entry used for padding - or last child for a sequence - - see para 7.5.3 */ - level--; - continue; - } /* Read abbreviation header */ abcode = read_leb128U( &abbrev_img ); /* abbreviation code */ if ( acode != abcode ) { - /* We are in in children list, and must rewind to a - * previously declared abbrev code. This code works but is - * not triggered since we shortcut the parsing once we have - * read the compile_unit block. This should only occur when - * level > 0 */ + /* This isn't illegal, but somewhat unlikely. Normally the + * first abbrev describes the first DIE, the compile_unit. + * But maybe this abbrevation data is shared with another + * or it is a NULL entry used for padding. See para 7.5.3. */ abbrev_img = lookup_abbrev( debugabbrev_img + atoffs, acode ); } tag = read_leb128U( &abbrev_img ); - has_child = *(abbrev_img++) == 1; /* DW_CHILDREN_yes */ - if ( has_child ) - level++; + if ( tag != 0x0011 /*TAG_compile_unit*/ ) + return; /* Not a compile unit (might be partial) or broken DWARF. */ + + abbrev_img++; /* DW_CHILDREN_yes or DW_CHILDREN_no */ /* And loop on entries */ for ( ; ; ) { @@ -1151,16 +1145,9 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, else if ( name == 0x10 ) ui->stmt_list = cval; /* DW_AT_stmt_list */ } } - /* Shortcut the parsing once we have read the compile_unit block - * That's enough info for us, and we are not gdb ! */ - if ( tag == 0x0011 /*TAG_compile_unit*/ ) - break; - } /* Loop on each sub block */ - - /* This test would be valid if we were not shortcutting the parsing - if (level != 0) - VG_(printf)( "#### Exiting debuginfo block at level %d !!!\n", level ); - */ + } /* Just read the first DIE, if that wasn't the compile_unit then + * this might have been a partial unit or broken DWARF info. + * That's enough info for us, and we are not gdb ! */ }