static void dumpAbbrevs( const unsigned_8 *input, uint length ) { const uint_8 *p; uint_32 tmp; uint_32 attr; if( (NULL == input) || (0 == length) ) return; p = input; for( ;; ) { if( p > input + length ) break; p = DecodeULEB128( p, &tmp ); printf( "Code: %08lx\n", tmp ); if( tmp == 0 ) continue; if( p >= input + length ) break; p = DecodeULEB128( p, &tmp ); printf( "\t%s\n", getTAG( tmp ) ); if( *p == DW_CHILDREN_yes ) { printf( "has children\n" ); } else { printf( "childless\n" ); } p++; for( ; p <= input + length; ) { p = DecodeULEB128( p, &attr ); printf( "\t%-20s", getAT( attr ) ); if( p > input + length ) break; p = DecodeULEB128( p, &tmp ); printf( "\t%-15s\n", getFORM( tmp ) ); if( attr == 0 ) { break; } } } }
extern void dump_abbrevs( const uint_8 *input, uint length ) /**********************************************************/ { const uint_8 *p; uint_32 tmp; uint_32 attr; uint_32 abbr_off; // bool start; if( Sections[ DW_DEBUG_ABBREV ].data == 0 ) { Sections[ DW_DEBUG_ABBREV ].data = Wmalloc( length ); Sections[ DW_DEBUG_ABBREV ].max_offset = length; memcpy( Sections[ DW_DEBUG_ABBREV ].data, input, length ); } p = input; for( ;; ) { if( p > input + length ) break; abbr_off = tmp = p - input; p = DecodeULEB128( p, &tmp ); if( tmp == 0 ) { Wdputslc( "End_CU\n" ); // start = true; continue; /* compile unit separator */ } Wdputs( "Offset: " ); Puthex( abbr_off, 8 ); Wdputs( " Code: " ); Puthex( tmp, 8 ); Wdputslc( "\n" ); if( p >= input + length ) break; if( tmp == 0 ) continue; /* compile unit separator */ p = DecodeULEB128( p, &tmp ); Wdputs( " " ); getTAG( tmp ); Wdputslc( "\n" ); if( *p == DW_CHILDREN_yes ) { Wdputslc( "has children\n" ); } else { Wdputslc( "childless\n" ); } p++; for( ;; ) { if( p > input + length ) break; p = DecodeULEB128( p, &attr ); if( p > input + length ) break; p = DecodeULEB128( p, &tmp ); if( attr == 0 && tmp == 0 ) { Wdputslc( " End_form\n" ); break; } Wdputs( " " ); getAT( attr ); Wdputs( " " ); getFORM( tmp ); Wdputslc( "\n" ); if( attr == 0 ) { break; } } } }
static void dumpInfo( const uint_8 *input, uint length ) { const uint_8 *p; uint_32 abbrev_code; uint_32 abbrev_offset; uint_8 * abbrev; uint_32 tag; uint_32 attr; uint_32 form; uint_32 len; uint_32 tmp; int_32 stmp; uint_32 unit_length; int address_size; const uint_8 *unit_base; p = input; while( p - input < length ) { unit_length = getU32( (uint_32 *)p ); unit_base = p + sizeof( uint_32 ); address_size = *(p + 10); abbrev_offset = getU32( (uint_32 *)(p + 6) ); printf( "Length: %08lx\nVersion: %04x\nAbbrev: %08lx\nAddress Size %02x\n", unit_length, getU16( (uint_16 *)(p + 4) ), abbrev_offset, address_size ); p += 11; while( p - unit_base < unit_length ) { printf( "offset %08x: ", p - input ); p = DecodeULEB128( p, &abbrev_code ); printf( "Code: %08lx\n", abbrev_code ); if( abbrev_code == 0 ) continue; abbrev = findAbbrev( abbrev_code, abbrev_offset ); if( abbrev == NULL ) { printf( "can't find abbreviation %08lx\n", abbrev_code ); break; } if( p >= input + length ) break; abbrev = DecodeULEB128( abbrev, &tag ); printf( "\t%s\n", getTAG( tag ) ); abbrev++; for( ;; ) { abbrev = DecodeULEB128( abbrev, &attr ); abbrev = DecodeULEB128( abbrev, &form ); if( attr == 0 ) break; printf( "\t%-20s", getAT( attr ) ); decode_form: switch( form ) { case DW_FORM_addr: switch( address_size ) { case 4: tmp = getU32( (uint_32 *)p ); p += sizeof( uint_32 ); printf( "\t%08lx\n", tmp ); break; case 2: tmp = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); printf( "\t%04lx\n", tmp ); break; default: printf( "Unknown address size\n" ); p += address_size; break; } break; case DW_FORM_block: p = DecodeULEB128( p, &len ); printf( "\n" ); dumpHex( p, len, 0 ); p += len; break; case DW_FORM_block1: len = *p++; printf( "\n" ); dumpHex( p, len, 0 ); p += len; break; case DW_FORM_block2: len = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); printf( "\n" ); dumpHex( p, len, 0 ); p += len; break; case DW_FORM_block4: len = getU32( (uint_32 *)p ); p += sizeof( uint_32 ); printf( "\n" ); dumpHex( p, len, 0 ); p += len; break; case DW_FORM_data1: case DW_FORM_ref1: printf( "\t%02x\n", *p++ ); break; case DW_FORM_data2: case DW_FORM_ref2: printf( "\t%04x\n", getU16( (uint_16 *)p ) ); p += sizeof( uint_16 ); break; case DW_FORM_data4: case DW_FORM_ref4: printf( "\t%08lx\n", getU32( (uint_32 *)p ) ); p += sizeof( uint_32 ); break; case DW_FORM_flag: printf( "\t%s\n", *p++ ? "True" : "False" ); break; case DW_FORM_indirect: p = DecodeULEB128( p, &form ); printf( "\t(%s)", getFORM( form ) ); goto decode_form; case DW_FORM_sdata: p = DecodeLEB128( p, &stmp ); printf( "\t%08lx\n", stmp ); break; case DW_FORM_string: printf( "\t\"%s\"\n", p ); p += strlen( (const char *)p ) + 1; break; case DW_FORM_strp: /* 4 byte index into .debug_str */ printf_debug_str( getU32( (uint_32 *)p ) ); p += 4; break; case DW_FORM_udata: case DW_FORM_ref_udata: p = DecodeULEB128( p, &tmp ); printf( "\t%08lx\n", tmp ); break; case DW_FORM_ref_addr: //KLUDGE should really check addr_size printf( "\t%08lx\n", getU32( (uint_32 *)p ) ); p += sizeof(uint_32); break; default: printf( "unknown form!\n" ); return; } } } } }
static bool dump_tag( info_state *info ) /**************************************/ { uint_8 *abbrev; uint_32 attr; uint_32 offset; uint_32 form; uint_32 len; uint_32 tmp; int_32 itmp; bool is_loc; uint_8 const *p; p = info->p; abbrev = info->abbrev; for( ;; ) { abbrev = DecodeULEB128( abbrev, &attr ); abbrev = DecodeULEB128( abbrev, &form ); if( attr == 0 ) break; Wdputs( " " ); getAT( attr ); if( attr == DW_AT_location || attr == DW_AT_segment || attr == DW_AT_return_addr || attr == DW_AT_frame_base || attr == DW_AT_static_link || attr == DW_AT_data_member_location || attr == DW_AT_string_length || attr == DW_AT_vtable_elem_location || attr == DW_AT_WATCOM_parm_entry || attr == DW_AT_use_location ) { is_loc = true; } else { is_loc = false; } decode_form: switch( form ) { case DW_FORM_addr: if( info->addr_size == 4 ) { tmp = get_u32( (uint_32 *)p ); } else if( info->addr_size == 2 ) { tmp = get_u16( (uint_16 *)p ); } else if( info->addr_size == 1 ) { tmp = *(uint_8 *)p; } else { tmp = info->addr_size; Wdputs( "?addr:" ); } p += info->addr_size; Puthex( tmp, info->addr_size*2 ); Wdputslc( "\n" ); break; case DW_FORM_block: p = DecodeULEB128( p, &len ); if( is_loc ) { DmpLoc( p, len, info->addr_size ); } else { Wdputslc( "\n" ); dump_hex( p, len ); } p += len; break; case DW_FORM_block1: len = *p++; if( is_loc ) { DmpLoc( p, len, info->addr_size ); } else { Wdputslc( "\n" ); dump_hex( p, len ); } p += len; break; case DW_FORM_block2: len = get_u16( (uint_16 *)p ); p += sizeof( uint_16 ); if( is_loc ) { DmpLoc( p, len, info->addr_size ); } else { Wdputslc( "\n" ); dump_hex( p, len ); } p += len; break; case DW_FORM_block4: len = get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); if( is_loc ) { DmpLoc( p, len, info->addr_size ); } else { Wdputslc( "\n" ); dump_hex( p, len ); } p += len; break; case DW_FORM_data1: Puthex( *p++, 2 ); Wdputslc( "\n" ); break; case DW_FORM_ref1: Puthex( info->cu_header + *p++ , 2 ); Wdputslc( "\n" ); break; case DW_FORM_data2: Puthex( get_u16( (uint_16 *)p ), 4 ); Wdputslc( "\n" ); p += sizeof( uint_16 ); break; case DW_FORM_ref2: Puthex( info->cu_header + get_u16( (uint_16 *)p ), 4 ); Wdputslc( "\n" ); p += sizeof( uint_16 ); break; case DW_FORM_data4: if( is_loc ) { DmpLocList( get_u32( (uint_32 *)p ), info->addr_size ); } else { Puthex( get_u32( (uint_32 *)p ), 8 ); Wdputslc( "\n" ); } p += sizeof( uint_32 ); break; case DW_FORM_ref4: Puthex( info->cu_header + get_u32( (uint_32 *)p ), 8 ); Wdputslc( "\n" ); p += sizeof( uint_32 ); break; case DW_FORM_flag: Wdputs( *p++ ? "True" : "False" ); Wdputslc( "\n" ); break; case DW_FORM_indirect: p = DecodeULEB128( p, &form ); Wdputc( '(' ); getFORM( form ); Wdputc( ')' ); goto decode_form; case DW_FORM_sdata: p = DecodeSLEB128( p, &itmp ); Puthex( itmp, 8 ); Wdputslc( "\n" ); break; case DW_FORM_string: Wdputc( '"' ); Wdputs( (char *)p ); Wdputslc( "\"\n" ); p += strlen( (const char *)p ) + 1; break; case DW_FORM_strp: offset = get_u32( (uint_32 *)p ); if( offset > Sections[ DW_DEBUG_STR ].max_offset ) { Wdputslc( "Error: strp - invalid offset\n" ); } else { Wdputs( (const char *)Sections[ DW_DEBUG_STR ].data + offset ); Wdputslc( "\n" ); } p += sizeof( uint_32 ); break; case DW_FORM_udata: p = DecodeULEB128( p, &tmp ); Puthex( tmp, 8 ); Wdputslc( "\n" ); break; case DW_FORM_ref_udata: p = DecodeULEB128( p, &tmp ); Puthex( info->cu_header + tmp, 8 ); Wdputslc( "\n" ); break; case DW_FORM_ref_addr: if( is_loc ) { // history DmpLocList( get_u32( (uint_32 *)p ), info->addr_size ); } else { Puthex( get_u32( (uint_32 *)p ), 8 ); Wdputslc( "\n" ); } p += sizeof( uint_32 ); break; default: Wdputslc( "unknown form\n" ); info->p = p; return( false ); } } info->p = p; return( true ); }