static uint_8 *findAbbrev( uint_32 code, uint_32 start ) { uint_8 *p; uint_8 *stop; uint_32 tmp; uint_32 attr; p = Sections[DW_DEBUG_ABBREV].data + start; stop = p + Sections[DW_DEBUG_ABBREV].max_offset; for( ;; ) { if( p >= stop ) return( NULL ); p = DecodeULEB128( p, &tmp ); if( tmp == code ) return( p ); if( p >= stop ) return( NULL ); p = DecodeULEB128( p, &tmp ); if( p >= stop ) return( NULL ); p++; for( ;; ) { p = DecodeULEB128( p, &attr ); if( p >= stop ) return( NULL ); p = DecodeULEB128( p, &tmp ); if( p >= stop ) return( NULL ); if( attr == 0 ) { break; } } } }
static void dumpRef( const uint_8 *input, uint length ) { const uint_8 *p; uint_8 op_code; uint_32 tmp; int_32 itmp; uint_32 unit_length; const uint_8 *unit_base; p = input; while( p - input < length ) { unit_length = getU32( (uint_32 *)p ); p += sizeof( uint_32 ); unit_base = p; printf( "total_length: %08lx\n", getU32( (uint_32 *)p ) ); while( p - unit_base < unit_length ) { op_code = *p++; if( op_code < REF_CODE_BASE ) { printf( "%s", getReferenceOp( op_code ) ); switch( op_code ) { case REF_BEGIN_SCOPE: printf( " %08lx\n", getU32( (uint_32 *)p ) ); p += sizeof( uint_32 ); break; case REF_END_SCOPE: case REF_COPY: printf( "\n" ); break; case REF_SET_FILE: case REF_SET_LINE: case REF_SET_COLUMN: p = DecodeULEB128( p, &tmp ); printf( " %lu\n", tmp ); break; case REF_ADD_LINE: case REF_ADD_COLUMN: p = DecodeLEB128( p, &itmp ); printf( " %ld\n", itmp ); break; } } else { op_code -= REF_CODE_BASE; printf( "REF line += %d, column += %d, %08lx\n", op_code / REF_COLUMN_RANGE, op_code % REF_COLUMN_RANGE, getU32( (uint_32 *)p ) ); p += sizeof( uint_32 ); } } } }
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; } } } }
void Dump_lines( const uint_8 *input, uint length ) /*************************************************/ { const uint_8 *p; const uint_8 *stmt_start; uint opcode_base; uint *opcode_lengths; uint u; uint file_index; const uint_8 *name; uint_32 mod_time; uint_32 file_length; uint_32 directory; uint_8 op_code; uint_32 op_len; uint_32 tmp; uint line_range; int line_base; int_32 itmp; int default_is_stmt; state_info state; uint min_instr; uint_32 unit_length; const uint_8 *unit_base; p = input; while( p - input < length ) { unit_length = get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); unit_base = p; Wdputs( "total_length: " ); Puthex( unit_length, 8 ); Wdputslc( "\nversion: " ); Puthex( get_u16( (uint_16 *)p ), 4 ); p += sizeof( uint_16 ); Wdputslc( "\nprologue_length: " ); Puthex( get_u32( (uint_32 *)p ), 8 ); stmt_start = p; stmt_start += get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); stmt_start += sizeof( uint_32 ); min_instr = *p; Wdputslc( "\nminimum_instruction_length: " ); Puthex( min_instr, 2 ); p += 1; default_is_stmt = *p; Wdputslc( "\ndefault_is_stmt: " ); Puthex( default_is_stmt, 2 ); p += 1; line_base = *(int_8 *)p; Wdputslc( "\nline_base: " ); Puthex( line_base, 2 ); p += 1; line_range = *(uint_8 *)p; Wdputslc( "\nline_range: " ); Puthex( line_range, 2 ); p += 1; opcode_base = *p; Wdputslc( "\nopcode_base: " ); Puthex( opcode_base, 2 ); Wdputslc( "\n" ); p += 1; opcode_lengths = malloc( sizeof( uint ) * opcode_base ); Wdputslc( "standard_opcode_lengths:\n" ); for( u = 0; u < opcode_base - 1; ++u ) { opcode_lengths[ u ] = *p; ++p; Putdecl( u, 4 ); Wdputs( ": " ); Putdec( opcode_lengths[ u ] ); Wdputslc( "\n" ); } Wdputs( "-- current_offset = " ); Puthex( p - input, 8 ); Wdputslc( "\n" ); if( p - input >= length ) return; Wdputslc( "include directories\n" ); file_index = 0; while( *p != 0 ) { ++file_index; name = p; p += strlen( (char *)p ) + 1; Wdputs( "path " ); Putdec( file_index ); Wdputs( ": '" ); Wdputs( (char *)name ); Wdputslc( "'\n" ); if( p - input >= length ) return; } p++; Wdputslc( "file names\n" ); file_index = 0; while( *p != 0 ) { ++file_index; name = p; p += strlen( (char *)p ) + 1; p = DecodeULEB128( p, &directory ); p = DecodeULEB128( p, &mod_time ); p = DecodeULEB128( p, &file_length ); Wdputs( "file " ); Putdec( file_index ); Wdputs( ": '" ); Wdputs( (char *)name ); Wdputs( "' directory " ); Putdec( directory ); Wdputs( " mod_time " ); Puthex( mod_time, 8 ); Wdputs( " length " ); Puthex( file_length, 8 ); Wdputslc( "\n" ); if( p - input >= length ) return; } p++; init_state( &state, default_is_stmt ); Wdputs( "-- current_offset = " ); Puthex( p - input, 8 ); if( p != stmt_start ) { Wdputs( ":***Prologue length off***" ); } Wdputslc( "\n" ); while( p - unit_base < unit_length ) { op_code = *p; ++p; if( op_code == 0 ) { /* extended op_code */ p = DecodeULEB128( p, &op_len ); Wdputs( "len: " ); Putdecl( op_len, 3 ); Wdputc( ' ' ); op_code = *p; ++p; --op_len; switch( op_code ) { case DW_LNE_end_sequence: Wdputslc( "END_SEQUENCE\n" ); state.end_sequence = 1; dump_state( &state ); init_state( &state, default_is_stmt ); p+= op_len; break; case DW_LNE_set_address: Wdputs( "SET_ADDRESS " ); if( op_len == 4 ) { tmp = get_u32( (uint_32 *)p ); } else if( op_len == 2 ) { tmp = get_u16( (uint_16 *)p ); } else { tmp = 0xffffffff; } state.address = tmp; Puthex( tmp, op_len*2 ); Wdputslc( "\n" ); p += op_len; break; case DW_LNE_set_segment: Wdputs( "SET_SEGMENT " ); if( op_len == 4 ) { tmp = get_u32( (uint_32 *)p ); } else if( op_len == 2 ) { tmp = get_u16( (uint_16 *)p ); } else { tmp = 0xffffffff; } state.segment = tmp; Puthex( tmp, op_len*2 ); Wdputslc( "\n" ); p += op_len; break; case DW_LNE_define_file: ++file_index; name = p; p += strlen( (char *)p ) + 1; p = DecodeULEB128( p, &directory ); p = DecodeULEB128( p, &mod_time ); p = DecodeULEB128( p, &file_length ); Wdputs( "DEFINE_FILE " ); Putdec( file_index ); Wdputs( ": '" ); Wdputs( (char *)name ); Wdputs( "' directory " ); Putdec( directory ); Wdputs( " mod_time " ); Puthex( mod_time, 8 ); Wdputs( " length " ); Puthex( file_length, 8 ); break; default: Wdputs( "** unknown extended opcode: " ); Puthex( op_code, 2 ); Wdputslc( "\n" ); p += op_len; break; } } else if( op_code < opcode_base ) { get_standard_op( op_code ); switch( op_code ) { case DW_LNS_copy: dump_state( &state ); state.basic_block = 0; break; case DW_LNS_advance_pc: p = DecodeLEB128( p, &itmp ); Putdec( itmp ); state.address += itmp * min_instr; break; case DW_LNS_advance_line: p = DecodeLEB128( p, &itmp ); Putdec( itmp ); state.line += itmp; break; case DW_LNS_set_file: p = DecodeLEB128( p, &itmp ); Putdec( itmp ); state.file = itmp; break; case DW_LNS_set_column: p = DecodeLEB128( p, &itmp ); Putdec( itmp ); state.column = itmp; break; case DW_LNS_negate_stmt: state.is_stmt = !state.is_stmt; break; case DW_LNS_set_basic_block: state.basic_block = 1; break; case DW_LNS_const_add_pc: state.address += ( ( 255 - opcode_base ) / line_range ) * min_instr; break; case DW_LNS_fixed_advance_pc: tmp = get_u16( (uint_16 *)p ); p += sizeof( uint_16 ); Puthex( tmp, 4 ); state.address += tmp; break; default: for( u = 0; u < opcode_lengths[ op_code - 1 ]; ++u ) { p = DecodeLEB128( p, &itmp ); Puthex( itmp, 8 ); } } } else { Wdputs( "SPECIAL " ); Puthex( op_code, 2 ); op_code -= opcode_base; Wdputs( ": addr incr: " ); Putdec( op_code / line_range ); Wdputs( " line incr: " ); Putdec( line_base + op_code % line_range ); state.line += line_base + op_code % line_range; state.address += ( op_code / line_range ) * min_instr; dump_state( &state ); state.basic_block = 0; } Wdputslc( "\n" ); } free( opcode_lengths ); Wdputs( "-- current_offset = " ); Puthex( p - input, 8 ); Wdputslc( "\n" ); } }
static void dumpLines( const uint_8 *input, uint length ) { const uint_8 *p; uint opcode_base; uint *opcode_lengths; uint u; uint file_index; const uint_8 *name; uint_32 dir_index; uint_32 mod_time; uint_32 file_length; uint_32 directory; uint_8 op_code; uint_8 op_len; uint_32 tmp; uint_16 tmp_seg; uint line_range; int line_base; int_32 itmp; int default_is_stmt; state_info state; uint min_instr; uint_32 unit_length; const uint_8 *unit_base; p = input; while( p - input < length ) { unit_length = getU32( (uint_32 *)p ); p += sizeof( uint_32 ); unit_base = p; printf( "total_length: 0x%08lx (%u)\n", unit_length, unit_length ); printf( "=== unit dump start ===\n" ); dumpHex( unit_base - sizeof( uint_32 ), unit_length + sizeof (uint_32 ), 1 ); printf( "=== unit dump end ===\n" ); printf( "version: 0x%04x\n", getU16( (uint_16 *)p ) ); p += sizeof( uint_16 ); printf( "prologue_length: 0x%08lx (%u)\n", getU32( (uint_32 *)p ), getU32( (uint_32 *)p ) ); p += sizeof( uint_32 ); min_instr = *p; printf( "minimum_instruction_length: 0x%02x (%u)\n", min_instr, min_instr ); p += 1; default_is_stmt = *p; printf( "default_is_stmt: 0x%02x (%u)\n", default_is_stmt, default_is_stmt ); p += 1; line_base = *(int_8 *)p; printf( "line_base: 0x%02x (%d)\n", (unsigned char)line_base, line_base ); p += 1; line_range = *(uint_8 *)p; printf( "line_range: 0x%02x (%u)\n", line_range, line_range ); p += 1; opcode_base = *p; printf( "opcode_base: 0x%02x (%u)\n", opcode_base, opcode_base ); p += 1; opcode_lengths = alloca( sizeof( uint ) * opcode_base ); printf( "standard_opcode_lengths:\n" ); for( u = 0; u < opcode_base - 1; ++u ) { opcode_lengths[u] = *p; ++p; printf( "%4u: %u\n", u + 1, opcode_lengths[u] ); } printf( "-- current_offset = %08x\n", p - input ); if( p - input >= length ) return; printf( "-- start include paths --\n"); file_index = 0; while( *p != 0 ) { ++file_index; name = p; p += strlen( (const char *)p ) + 1; printf( "path %u: '%s'\n", file_index, name ); if( p - input >= length ) { return; } } printf( "-- end include paths --\n"); p++; printf( "-- start files --\n"); file_index = 0; while( *p != 0 ) { ++file_index; name = p; p += strlen( (const char *)p ) + 1; p = DecodeULEB128( p, &dir_index ); p = DecodeULEB128( p, &mod_time ); p = DecodeULEB128( p, &file_length ); printf( "file %u: '%s' dir_index %08lx mod_time %08lx length %08lx\n", file_index, name, dir_index, mod_time, file_length ); if( p - input >= length ) { return; } } printf( "-- end files --\n"); p++; initState( &state, default_is_stmt ); while( p - unit_base < unit_length ) { op_code = *p; ++p; if( op_code == 0 ) { printf( "EXTENDED 0x%02x: ", op_code ); /* extended op_code */ op_len = *p; ++p; printf( "len: %03d ", op_len ); op_code = *p; ++p; switch( op_code ) { case DW_LNE_end_sequence: printf( "END_SEQUENCE\n" ); state.end_sequence = 1; dumpState( &state ); initState( &state, default_is_stmt ); break; case DW_LNE_set_address: if( op_len == 3 ) { tmp = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); } else { tmp = getU32( (uint_32 *)p ); p += sizeof( uint_32 ); } #if 0 /* Why did they choose 6 byte here? */ tmp_seg = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); printf( "SET_ADDRESS %04x:%08lx\n", tmp_seg, tmp ); #else tmp_seg = 0; /* stop warning */ printf( "SET_ADDRESS %08lx\n", tmp ); #endif break; case DW_LNE_WATCOM_set_segment_OLD: case DW_LNE_WATCOM_set_segment: tmp_seg = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); printf( "SET_ADDRESS_SEG %04x\n", tmp_seg ); break; case DW_LNE_define_file: ++file_index; name = p; p += strlen( (const char *)p ) + 1; p = DecodeULEB128( p, &directory ); p = DecodeULEB128( p, &mod_time ); p = DecodeULEB128( p, &file_length ); printf( "DEFINE_FILE %u: '%s' directory %ld mod_time %08lx length %08lx\n", file_index, name, directory, mod_time, file_length ); break; default: printf( "** unknown extended opcode: %02x - %u bytes\n", op_code, op_len ); printf( "** losing %u bytes\n", unit_length - ( p - unit_base )); dumpHex( p-3, (unit_length - ( p - unit_base )) + 3, 1 ); p = unit_base + unit_length; goto hacky; // return; } } else if( op_code < opcode_base ) { printf( "%s", getStandardOp( op_code ) ); switch( op_code ) { case DW_LNS_copy: printf( "\n" ); dumpState( &state ); state.basic_block = 0; break; case DW_LNS_advance_pc: p = DecodeLEB128( p, &itmp ); printf( " %ld\n", itmp ); state.address += itmp * min_instr; break; case DW_LNS_advance_line: p = DecodeLEB128( p, &itmp ); printf( " %ld\n", itmp ); state.line += itmp; break; case DW_LNS_set_file: p = DecodeLEB128( p, &itmp ); printf( " %ld\n", itmp ); state.file = itmp; break; case DW_LNS_set_column: p = DecodeLEB128( p, &itmp ); printf( " %ld\n", itmp ); state.column = itmp; break; case DW_LNS_negate_stmt: printf( "\n" ); state.is_stmt = !state.is_stmt; break; case DW_LNS_set_basic_block: printf( "\n" ); state.basic_block = 1; break; case DW_LNS_const_add_pc: printf( "\n" ); state.address += ( ( 255 - opcode_base ) / line_range ) * min_instr; break; case DW_LNS_fixed_advance_pc: tmp = getU16( (uint_16 *)p ); p += sizeof( uint_16 ); printf( " %04x\n", tmp ); state.address += tmp; break; default: for( u = 0; u < opcode_lengths[op_code - 1]; ++u ) { p = DecodeLEB128( p, &itmp ); printf( " %08lx", itmp ); } printf( "\n" ); } } else { printf( "SPECIAL 0x%02x:", op_code ); op_code -= opcode_base; printf( " addr incr: %d line incr: %d\n", op_code / line_range, line_base + op_code % line_range ); state.line += line_base + op_code % line_range; state.address += ( op_code / line_range ) * min_instr; dumpState( &state ); state.basic_block = 0; } } hacky: printf( "-- current_offset = %08x\n", p - input ); } }
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; } } } } }
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 dump_info_headers( const char *input, uint length ) /*************************************************************/ { const uint_8 *p; uint_32 abbrev_code; uint_32 abbrev_offset; uint_8 * abbrev; uint_32 tag; uint_32 unit_length; uint_32 tag_offset; const uint_8 *unit_base; info_state state; bool found; p = input; state.addr_size = 0; found = false; while( p - input < length ) { state.cu_header = p - input; unit_length = get_u32( (uint_32 *)p ); unit_base = p + sizeof( uint_32 ); Wdputs( "Length: " ); Puthex( unit_length, 8 ); Wdputslc( "\nVersion: " ); Puthex( get_u16( (uint_16 *)(p + 4) ), 4 ); Wdputslc( "\nAbbrev: " ); abbrev_offset = get_u32( (uint_32 *)(p + 6) ); Puthex( abbrev_offset, 8 ); state.addr_size = *(p + 10); Wdputslc( "\nAddress Size " ); Puthex( *(p + 10), 2 ); Wdputslc( "\n" ); p += 11; while( p - unit_base < unit_length ) { tag_offset = p - input; p = DecodeULEB128( p, &abbrev_code ); if( abbrev_code == 0 ) continue; abbrev = find_abbrev( abbrev_offset, abbrev_code ); if( abbrev == NULL ) { Wdputs( "can't find abbreviation " ); Puthex( abbrev_code, 8 ); Wdputslc( "\n" ); break; } if( p >= input + length ) break; abbrev = DecodeULEB128( abbrev, &tag ); abbrev++; state.abbrev = abbrev; state.p = p; if( tag_offset == 0x59a125 ) { found = true; } if( found ) { Wdputs( "Offset: " ); Puthex( tag_offset, 8 ); Wdputs( " Code: " ); Puthex( abbrev_code, 8 ); Wdputslc( "\n" ); Wdputs( " " ); getTAG( tag ); Wdputslc( "\n" ); if( !dump_tag( &state ) )break; } else { skip_tag( &state ); } p = state.p; } if( found )break; } }
static bool skip_tag( info_state *info ) /*****************************************************/ { uint_8 *abbrev; uint_32 attr; uint_32 form; uint_32 len; uint_32 tmp; int_32 itmp; bool is_loc; char const *p; p = info->p; abbrev = info->abbrev; for( ;; ) { abbrev = DecodeULEB128( abbrev, &attr ); abbrev = DecodeULEB128( abbrev, &form ); if( attr == 0 ) break; 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_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; break; case DW_FORM_block: p = DecodeULEB128( p, &len ); p += len; break; case DW_FORM_block1: len = *p++; p += len; break; case DW_FORM_block2: len = get_u16( (uint_16 *)p ); p += sizeof( uint_16 ); p += len; break; case DW_FORM_block4: len = get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); p += len; break; case DW_FORM_data1: ++p; break; case DW_FORM_ref1: ++p; break; case DW_FORM_data2: p += sizeof( uint_16 ); break; case DW_FORM_ref2: p += sizeof( uint_16 ); break; case DW_FORM_data4: p += sizeof( uint_32 ); break; case DW_FORM_ref4: p += sizeof( uint_32 ); break; case DW_FORM_flag: ++p; break; case DW_FORM_indirect: p = DecodeULEB128( p, &form ); goto decode_form; case DW_FORM_sdata: p = DecodeSLEB128( p, &itmp ); break; case DW_FORM_string: p += strlen( p ) + 1; break; case DW_FORM_strp: abort(); break; case DW_FORM_udata: p = DecodeULEB128( p, &tmp ); break; case DW_FORM_ref_udata: p = DecodeULEB128( p, &tmp ); break; case DW_FORM_ref_addr: p += sizeof( uint_32 ); break; default: Wdputslc( "unknown form\n" ); info->p = p; return( false ); } } info->p = p; return( true ); }
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 ); }
static void DmpLoc( uint_8 const *p, uint length, uint addr_size ) /****************************************************************/ { uint_8 const *end; uint_8 op; dw_locop_op opr; int_32 op1s; uint_32 op1u; int_32 op2s; uint_32 addr; end = &p[length]; Wdputslc( "\n Loc expr: " ); if( p == end ) { Wdputslc( "<NULL>\n" ); } while( p < end ) { op = *p; ++p; Wdputs( OpName[ op ] ); opr = LocOpr[ op ]; if( opr == DW_LOP_REG1 || opr == DW_LOP_BRG1 ) { Wdputs( "/" ); } else { Wdputs( " " ); } switch( opr ) { case DW_LOP_NOOP: break; case DW_LOP_ADDR: if( addr_size == 4 ) { addr = *(uint_32 *)p; } else if( addr_size == 2 ) { addr = *(uint_16 *)p; } else if( addr_size == 1 ) { addr = *(uint_8 *)p; } else { addr = 0; } Puthex( addr, addr_size * 2 ); p += addr_size; break; case DW_LOP_OPU1: op1u = *(uint_8 *)p; p += sizeof( uint_8 ); Putdec( op1u ); break; case DW_LOP_OPS1: op1s = *(int_8 *)p; p += sizeof(int_8 ); Putdec( op1s ); break; case DW_LOP_OPU2: op1u = get_u16( (uint_16 *)p ); p += sizeof( uint_16 ); Putdec( op1u ); break; case DW_LOP_OPS2: op1s = get_s16( (int_16 *)p ); p += sizeof( int_16 ); Putdec( op1s ); break; case DW_LOP_OPU4: op1u = get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); Putdec( op1u ); break; case DW_LOP_OPS4: op1s = get_s32( (int_32 *)p ); p += sizeof( int_32 ); Putdec( op1s ); break; case DW_LOP_U128: p = DecodeULEB128( p, &op1u ); Putdec( op1u ); break; case DW_LOP_S128: p = DecodeSLEB128( p, &op1s ); Putdecs( op1s ); break; case DW_LOP_U128_S128: p = DecodeULEB128( p, &op1u ); p = DecodeSLEB128( p, &op2s ); Putdec( op1u ); Wdputs( "," ); Putdecs( op2s ); break; case DW_LOP_LIT1: op1u = op-DW_OP_lit0; op = DW_OP_lit0; break; case DW_LOP_REG1: op1u = op-DW_OP_reg0; op = DW_OP_reg0; Wdputs( RegName[ op1u] ); break; case DW_LOP_BRG1: op1u = op-DW_OP_breg0; p = DecodeSLEB128( p, &op2s ); Wdputs( RegName[ op1u] ); if( op2s < 0 ) { Wdputs( " -" ); op2s = -op2s; } else { Wdputs( " +" ); } Putdec( op2s ); op = DW_OP_breg0; break; } Wdputslc( " " ); } Wdputslc( "\n" ); }
static void dump_ref( const uint_8 *input, uint length ) /******************************************************/ { const uint_8 *p; uint_8 op_code; uint_32 tmp; int_32 itmp; uint_32 unit_length; const uint_8 *unit_base; ref_info registers = { { 0, 0, NULL }, 0L, 1L, 1L, 1 }; p = input; while( p - input < length ) { unit_length = get_u32( (uint_32 *)p ); p += sizeof( uint_32 ); unit_base = p; Wdputs( "total_length: " ); Puthex( get_u32( (uint_32 *)p ), 8 ); Wdputslc( "\n" ); while( p - unit_base < unit_length ) { op_code = *p++; if( op_code < REF_CODE_BASE ) { get_reference_op( op_code ); switch( op_code ) { case REF_BEGIN_SCOPE: Puthex( get_u32( (uint_32 *)p ), 8 ); ScopePush( ®isters.scope, get_u32( (uint_32 *)p ) ); p += sizeof( uint_32 ); break; case REF_END_SCOPE: ScopePop( ®isters.scope ); break; case REF_COPY: Wdputs( " " ); PutRefRegisters( ®isters ); break; case REF_SET_FILE: p = DecodeULEB128( p, &tmp ); Putdec( tmp ); registers.file = tmp; break; case REF_SET_LINE: p = DecodeULEB128( p, &tmp ); Putdec( tmp ); registers.line = tmp; registers.column = 0; break; case REF_SET_COLUMN: p = DecodeULEB128( p, &tmp ); Putdec( tmp ); registers.column = tmp; break; case REF_ADD_LINE: p = DecodeSLEB128( p, &itmp ); Putdecs( itmp ); registers.line += itmp; break; case REF_ADD_COLUMN: p = DecodeULEB128( p, &tmp ); Putdec( tmp ); registers.column += tmp; break; } } else { op_code -= REF_CODE_BASE; Wdputs( "REF line += " ); Putdec( op_code / REF_COLUMN_RANGE ); registers.line += op_code / REF_COLUMN_RANGE; Wdputs( ", column += " ); Putdec( op_code % REF_COLUMN_RANGE ); registers.column += op_code % REF_COLUMN_RANGE; Wdputs( ", " ); Puthex( get_u32( (uint_32 *)p ), 8 ); registers.dependent = get_u32( (uint_32 *)p ); Wdputs( " " ); PutRefRegisters( ®isters ); p += sizeof( uint_32 ); } Wdputslc( "\n" ); } } }