/* * Dump the type and offsets. */ static void dmp_type_offset( unsigned_32 bsize ) /**********************************************/ { unsigned_32 i; unsigned prev; pe_fixup_entry entry; Wdputslc( "type:offset type --\n" ); Wdputslc( "0 = ABSOLUTE, 1 = LOW, 2 = HIGH, 3 = HIGHLOW, 4 = HIGHADJUST, 5 = MIPSJMPADDR\n" ); prev = 0; for( i = 0; i < bsize; i++ ) { Wread( &entry, sizeof( pe_fixup_entry ) ); if( i != 0 ) { if( (i) % 8 == 0 ) { Wdputslc( "\n" ); } else { Wdputs( " " ); } } if( prev == 4 ) { Wdputc( ' ' ); Puthex( entry, 4 ); prev = 0; } else { prev = entry >> 12; Puthex( prev, 1 ); Wdputc( ':' ); Puthex( entry, 3 ); } } Wdputslc( "\n" ); }
/* * desc_array - dump info */ static void desc_array( unsigned_8 *ptr, bool is386 ) /***************************************************/ { addr32_ptr *p32; addr48_ptr *p48; Wdputs( " scalar type 1 = " ); scalar_type( ptr[0] ); Wdputs( " scalar type 2 = " ); scalar_type( ptr[1] ); ptr += 2; Wdputslc( "\n addr = " ); if( is386 ) { p48 = (addr48_ptr *)ptr; ptr += sizeof(addr48_ptr); Puthex( p48->segment, 4 ); Wdputc( ':' ); Puthex( p48->offset, 8 ); } else { p32 = (addr32_ptr *)ptr; ptr += sizeof(addr32_ptr); Puthex( p32->segment, 4 ); Wdputc( ':' ); Puthex( p32->offset, 4 ); } base_type_index( ptr ); } /* desc_array */
/* * Dump segments. */ static void dmp_seg( unsigned_16 size ) /*************************************/ { unsigned_16 i; unsigned_32 seg; if( !size ) { return; } Wdputslc( "segments = type:size\n" ); Wdputslc( "type 0==read/write, 1==read-only, 2==execute/read, 3==execute-only\n" ); for( i = 0; i < size; i++ ) { if( i != 0 ) { if( i % 6 == 0 ) { Wdputslc( "\n" ); } else { Wdputs( " " ); } } Wread( &seg, sizeof( unsigned_32 ) ); Puthex( seg >> 28, 1 ); Wdputc( ':' ); Puthex( seg, 7 ); } Wdputslc( "\n" ); }
/* * dump_global_info - dump out global info */ static void dump_global_info( section_dbg_header *sdh ) /*****************************************************/ { unsigned_32 total_bytes; unsigned_32 bytes_read; v3_gbl_info *gi; long cpos; char name[256]; total_bytes = sdh->addr_offset - sdh->gbl_offset; print_info_title( "Global" ); bytes_read = 0; gi = (v3_gbl_info *) Wbuff; cpos = Curr_sectoff + sdh->gbl_offset; while( bytes_read < total_bytes ) { Wlseek( cpos ); Wread( Wbuff, sizeof( v3_gbl_info ) + 255 ); bytes_read += sizeof( v3_gbl_info ) + gi->name[0]; cpos += sizeof( v3_gbl_info ) + gi->name[0]; get_len_prefix_string( name, gi->name ); Wdputs( " Name: " ); Wdputs( name ); Wdputslc( "\n" ); Wdputs( " address = " ); Puthex( gi->addr.segment, 4 ); Wdputc( ':' ); Puthex( gi->addr.offset, 8 ); Wdputslc( "\n" ); Wdputs( " module index = " ); Putdec( gi->mod ); Wdputslc( "\n" ); Wdputs( " kind: " ); if( gi->kind & GBL_KIND_STATIC ) { Wdputs( " (static pubdef)" ); } if( gi->kind & GBL_KIND_CODE ) { Wdputs( " (code)" ); } if( gi->kind & GBL_KIND_DATA ) { Wdputs( " (data)" ); } Wdputslc( "\n" ); } Wdputslc( "\n" ); } /* dump_global_info */
/* * Dump the Resource Id's. */ static void dmp_res_name_id( unsigned_16 count, bool is_name ) /***********************************************************/ { unsigned_16 i, j, cnt; unsigned_32 offset, tmp_off; resource_dir_header pe_res_name; resource_dir_entry pe_res_dir; res_name name; if( count == 0 ) return; offset = Res_off + sizeof( resource_dir_header ); for( i = 0; i < count; i++ ) { Wlseek( offset ); Wread( &pe_res_dir, sizeof( resource_dir_entry ) ); offset += sizeof( resource_dir_entry ); tmp_off = Res_off +( pe_res_dir.id_name & PE_RESOURCE_MASK ); if( is_name ) { name = get_name( tmp_off ); } else { name.len = 0; name.rname = NULL; } tmp_off = Res_off +( pe_res_dir.entry_rva & PE_RESOURCE_MASK ); Wlseek( tmp_off ); Wread( &pe_res_name, sizeof( resource_dir_header ) ); tmp_off += sizeof( resource_dir_header ); cnt = pe_res_name.num_name_entries + pe_res_name.num_id_entries; for( j = 0; j < cnt; j++ ) { if( is_name ) { Wdputs( name.rname ); for( j = name.len; j <= SLEN; j++ ) { Wdputc( ' ' ); } } else { Puthex( pe_res_dir.id_name, 8 ); Wdputs( " " ); } if( j >= pe_res_name.num_name_entries ) { dmp_name_id( tmp_off, FALSE ); } else { dmp_name_id( tmp_off, TRUE ); } tmp_off += sizeof( resource_dir_entry ); Wdputslc( "\n" ); } } }
static void getAT( uint_32 value ) /********************************/ { const char *result; int i; result = Getname( value, readableATs, NUM_ATS ); if( result == NULL ) { Wdputs( "AT_" ); Puthex( value, 8 ); Wdputs( " " ); } else { Wdputs( result ); for( i = strlen( result ); i < 30; i++ ) { Wdputc( ' ' ); } } }
static void getFORM( uint_32 value ) /**********************************/ { const char *result; int i; result = Getname( value, readableFORMs, NUM_FORMS ); if( result == NULL ) { Wdputs( "FORM_" ); Puthex( value, 8 ); Wdputs( " " ); } else { Wdputs( result ); for( i = strlen( result ); i < 18; i++ ) { Wdputc( ' ' ); } } }
static void get_reference_op( uint_8 value ) /******************************************/ { const char *result; int i; result = Getname( value, readableReferenceOps, NUM_REFERENCE_OPS ); if( result == NULL ) { Wdputs( "REF_" ); Puthex( value, 2 ); Wdputs( " " ); } else { Wdputs( result ); for( i = strlen( result ); i < 16; i++ ) { Wdputc( ' ' ); } } }
/* * printout a resource name */ static void dmp_resrc_nam( unsigned_16 res_type ) /***********************************************/ { char *name; Wdputc( ' ' ); if( res_type & SEG_RESRC_HIGH ) { res_type &= ~SEG_RESRC_HIGH; Wdputs( "resource id: " ); Putdec( res_type ); Wdputslc( "\n" ); } else { name = get_resrc_nam( res_type ); Wdputs( name ); Wdputslc( "\n" ); free( name ); } }
static void get_standard_op( uint_8 value ) /*****************************************/ { const char *result; int i; result = Getname( value, readableStandardOps, NUM_STANDARD_OPS ); if( result == NULL ) { Wdputs( "OP_" ); Puthex( value, 2 ); Wdputs( " " ); } else { Wdputs( result ); for( i = strlen( result ); i < 24; i++ ) { Wdputc( ' ' ); } } }
/* * Dump external reference (import) table. */ static void dmp_external_ref( void ) /**********************************/ { unsigned_32 i,j; unsigned_8 len; char *name; unsigned_32 num; unsigned_32 reloc; if( Nlm_head.numberOfExternalReferences == 0 ) { return; } Wdputslc( "\n" ); Wlseek( Nlm_head.externalReferencesOffset ); Banner( "External Reference (Import) Table" ); Wdputslc( "80000000H = relocation not relative to current position\n" ); Wdputslc( "40000000H = relocation to code segment\n" ); for( i = 0; i < Nlm_head.numberOfExternalReferences; i++ ) { Wread( &len, sizeof( unsigned_8 ) ); name = Wmalloc( len ); Wread( name, len ); name[len] = '\0'; Wdputs( name ); Wdputs( ", relocations:" ); Wdputslc( "\n" ); Wread( &num, sizeof( unsigned_32 ) ); Wdputs( " " ); for( j = 0; j < num; j++ ) { Wread( &reloc, sizeof( unsigned_32 ) ); if( j != 0 ) { if( (j) % 4 == 0 ) { Wdputslc( "\n " ); } else { Wdputs( " " ); } } Putdecl( j, 2 ); Wdputc( ':' ); Puthex( reloc, 8 ); } Wdputslc( "\n" ); } }
static void dump_hex( const uint_8 *input, uint length ) /******************************************************/ { char *p; int i; uint offset; uint old_offset; char hex[ 80 ]; char printable[ 17 ]; int ch; offset = 0; for( ;; ) { i = 0; p = hex; old_offset = offset; for( ;; ) { if( offset == length ) break; if( i > 0xf ) break; if( i == 0x8 ) { *p++ = ' '; } ch = input[ offset ]; p += sprintf( p, " %02x", ch ); printable[ i ] = isprint( ch ) ? ch : '.'; ++i; ++offset; } *p = '\0'; printable[i] = '\0'; Puthex( old_offset, 8 ); Wdputc( ':' ); Wdputs( hex ); Wdputs( " <" ); Wdputs( printable ); Wdputslc( ">\n" ); // Wdputs( "%08lx:%-49s <%s>\n", old_offset, hex, printable ); p = printable; i = 0; if( offset == length ) break; } }
/* * Dump Segment Table Entry */ static void dmp_seg_ent( struct segment_record *seg_ent ) /*******************************************************/ { Wdputc( ' ' ); Puthex( (unsigned_32)seg_ent->address << Os2_head.align, 8 ); Wdputc( ' ' ); Puthex( seg_ent->size, 4 ); Wdputc( ' ' ); Puthex( seg_ent->min, 4 ); Wdputc( ' ' ); Wdputc( ' ' ); Puthex( seg_ent->info >> SEG_SHIFT_PRI_LVL , 4 ); Wdputc( ' ' ); Wdputc( ' ' ); Puthex( seg_ent->info >> SEG_SHIFT_PMODE_LVL, 4 ); Wdputc( ' ' ); Puthex( seg_ent->info, 4 ); Wdputslc( "\n" ); dmp_seg_flag( seg_ent->info ); Wdputslc( "\n" ); }
/* * Dump the Resource Names. */ static void dmp_name_id( unsigned_32 offset, bool is_name ) /*********************************************************/ { unsigned_16 i, j, cnt; resource_dir_entry pe_res_dir, tmp_dir; resource_dir_header pe_res_lang; res_name name; Wlseek( offset ); Wread( &pe_res_dir, sizeof( resource_dir_entry ) ); offset = Res_off +( pe_res_dir.id_name & PE_RESOURCE_MASK ); if( is_name ) { name = get_name( offset ); Wdputs( name.rname ); for( j = name.len; j <= SLEN; j++ ) { Wdputc( ' ' ); } } else { Puthex( pe_res_dir.id_name, 8 ); Wdputs( " " ); } offset = Res_off +( pe_res_dir.entry_rva & PE_RESOURCE_MASK ); if( pe_res_dir.entry_rva & PE_RESOURCE_MASK_ON ) { Wlseek( offset ); Wread( &pe_res_lang, sizeof( resource_dir_header ) ); offset += sizeof( resource_dir_header ); Wlseek( offset ); cnt = pe_res_lang.num_id_entries; for( i = 0; i < cnt; i++ ) { Wread( &tmp_dir, sizeof( resource_dir_entry ) ); Puthex( tmp_dir.id_name, 8 ); if( i != cnt - 1 ) { Wdputslc( "\n " ); } } offset = Res_off +( tmp_dir.entry_rva & PE_RESOURCE_MASK ); } if( Data_off == 0 ) { Data_off = offset; } }
/* * Dump fixups. */ static void dmp_fixup( unsigned_16 size, bool float_pt ) /******************************************************/ { lmf_data fixup; unsigned_16 i; Wdputslc( "\n" ); if( float_pt ) { Banner( "Floating Point Fixup Table" ); } else { Banner( "Fixup Table" ); } Wdputs( "size = " ); Puthex( size, 4 ); if( Options_dmp & FIX_DMP ) { if( float_pt ) { Wdputslc( " segment : type:offset\n" ); } else { Wdputslc( " segment : offset\n" ); } for( i = 0; i < size / sizeof( lmf_data ); i++ ) { Wread( &fixup, sizeof( lmf_data ) ); if( i != 0 ) { if( i % 4 == 0 ) { Wdputslc( "\n" ); } else { Wdputs( " " ); } } Puthex( fixup.segment, 4 ); Wdputs( " : " ); if( float_pt ) { Puthex( fixup.offset >> 28, 1 ); Wdputc( ':' ); Puthex( fixup.offset, 7 ); } else { Puthex( fixup.offset, 8 ); } } }
/* * printout a resource type name */ static void dmp_resrc_type_nam( unsigned_16 res_type ) /****************************************************/ { char *name; Wdputc( ' ' ); if( res_type & SEG_RESRC_HIGH ) { res_type &= ~SEG_RESRC_HIGH; if( res_type > 15 ) { Wdputs( "Type number: " ); Putdec( res_type ); Wdputslc( "\n" ); } else { Wdputslc( resource_type[ res_type ] ); } } else { name = get_resrc_nam( res_type ); Wdputs( name ); Wdputslc( "\n" ); free( name ); } }
static int parse_options( int argc, char * const *argv ) /******************************************************/ { int c; char *arg; Options_dmp = EXE_INFO; Segspec = 0; Hexoff = 0; for( ;; ) { while(optind < argc && (c = getopt( argc, argv, ":aA:bB:dD:efipqrsS:x" )) != -1 ) { switch( c ) { case 'A': Options_dmp |= FIX_DMP | PAGE_DMP | RESRC_DMP | EXE_INFO | DOS_SEG_DMP | OS2_SEG_DMP; Segspec = atoi( optarg ); if( Segspec == 0 ) { Options_dmp &= ~OS2_SEG_DMP; } else { Options_dmp &= ~DOS_SEG_DMP; } break; case 'a': Options_dmp |= FIX_DMP | PAGE_DMP | RESRC_DMP | EXE_INFO | DOS_SEG_DMP | OS2_SEG_DMP; break; case 'B': Hexoff = strtol( optarg, NULL, 16 ); /* fall through */ case 'b': Options_dmp |= BINARY_DMP; Options_dmp &= ~EXE_INFO; break; case 'D': Debug_options = 0; arg = optarg; while( islower( *arg ) || isupper( *arg ) ) { debug_opts( *arg++ ); } /* fall through */ case 'd': Options_dmp |= DEBUG_INFO; Options_dmp &= ~EXE_INFO; break; case 'e': Options_dmp |= EXE_INFO; break; case 'f': Options_dmp |= EXE_INFO; Options_dmp |= FIX_DMP; break; case 'i': Options_dmp |= IMPORT_LIB; Options_dmp |= QUIET; Options_dmp &= ~EXE_INFO; break; case 'p': Options_dmp |= EXE_INFO | PAGE_DMP; break; case 'q': Options_dmp |= QUIET; break; case 'r': Options_dmp |= EXE_INFO | RESRC_DMP; break; case 'S': Options_dmp |= EXE_INFO | DOS_SEG_DMP | OS2_SEG_DMP; Segspec = atoi( optarg ); if( Segspec == 0 ) { Options_dmp &= ~OS2_SEG_DMP; } else { Options_dmp &= ~DOS_SEG_DMP; } break; case 's': Options_dmp |= EXE_INFO | DOS_SEG_DMP | OS2_SEG_DMP; break; case 'x': Options_dmp |= IMPORT_DEF; Options_dmp |= QUIET; Options_dmp &= ~EXE_INFO; break; case ':': Wdputs( "wdump: option requires argument: -" ); Wdputc( optopt ); Wdputslc( "\n" ); return( 1 ); case '?': usage(); return( 1 ); default: Wdputs( "wdump: invalid option: -" ); Wdputc( c ); Wdputslc( "\n" ); return( 1 ); } } if( optind < argc ) { if( Name == NULL ) { Name = argv[optind++]; } else { Wdputs( "wdump: multiple pathnames not accepted\n" ); return( 1 ); } } else { break; } } return( 0 ); }
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" ); } }
/* * Dump the program and section headers. */ static void dmp_prog_sec( unsigned_32 start ) /*******************************************/ { Elf32_Phdr elf_prog; Elf32_Shdr elf_sec; unsigned_32 offset; char *string_table; int i; // grab the string table, if it exists if( Options_dmp & DEBUG_INFO ) { set_dwarf( start ); } if( Elf_head.e_shstrndx ) { offset = Elf_head.e_shoff + Elf_head.e_shstrndx * Elf_head.e_shentsize+start; Wlseek( offset ); Wread( &elf_sec, sizeof( Elf32_Shdr ) ); swap_shdr( &elf_sec ); string_table = Wmalloc( elf_sec.sh_size ); Wlseek( elf_sec.sh_offset + start ); Wread( string_table, elf_sec.sh_size ); } else { string_table = 0; } if( Elf_head.e_phnum ) { Banner( "ELF Program Header" ); offset = Elf_head.e_phoff + start; for( i = 0; i < Elf_head.e_phnum; i++ ) { Wdputs( " Program Header #" ); Putdec( i + 1 ); Wdputslc( "\n" ); if( start != 0 ) { Wdputs("File Offset:"); Puthex( offset, 8 ); Wdputslc( "\n"); } Wlseek( offset ); Wread( &elf_prog, sizeof( Elf32_Phdr ) ); swap_phdr( &elf_prog ); // elf_prog.p_offset += start; //Relocate file pos offset += sizeof( Elf32_Phdr ); Data_count++; dmp_prog_type( elf_prog.p_type ); Dump_header( &elf_prog, elf_prog_msg ); dmp_prog_flgs( elf_prog.p_flags ); if( Options_dmp & (DOS_SEG_DMP | OS2_SEG_DMP) ) { if( Segspec == 0 || Segspec == Data_count ) { Dmp_seg_data( elf_prog.p_offset + start, elf_prog.p_filesz ); } } else if( elf_prog.p_type == PT_NOTE ) { dmp_sec_note( elf_prog.p_offset + start, elf_prog.p_filesz ); } Wdputslc( "\n" ); } } if( Elf_head.e_shnum ) { Banner( "ELF Section Header" ); offset = Elf_head.e_shoff+start; for( i = 0; i < Elf_head.e_shnum; i++ ) { Wlseek( offset ); Wread( &elf_sec, sizeof( Elf32_Shdr ) ); swap_shdr( &elf_sec ); // elf_sec.sh_offset += start; // relocate file pos Wdputs( " Section Header #" ); Putdec( i ); if( string_table ) { Wdputs( " \"" ); Wdputs( &(string_table[elf_sec.sh_name]) ); Wdputs( "\"" ); } Wdputslc( "\n" ); if( start != 0 ) { Wdputs( "File Offset:" ); Puthex( offset, 8 ); Wdputslc( "\n" ); } dmp_sec_type( elf_sec.sh_type ); Dump_header( &elf_sec.sh_name, elf_sec_msg ); dmp_sec_flgs( elf_sec.sh_flags ); if( Options_dmp & FIX_DMP ) { if( elf_sec.sh_type==SHT_REL || elf_sec.sh_type==SHT_RELA ) { Elf32_Shdr rel_sec; Elf32_Rela elf_rela; int loc, ctr, rel_size; Wdputs( "relocation information for section #" ); Putdec( elf_sec.sh_info ); Wlseek( Elf_head.e_shoff + start + Elf_head.e_shentsize * elf_sec.sh_info ); Wread( &rel_sec, sizeof( Elf32_Shdr ) ); swap_shdr( &rel_sec ); if( string_table ) { Wdputs( " \"" ); Wdputs( &string_table[rel_sec.sh_name] ); Wdputs( "\"" ); } else { Wdputs( " no_name (no associated string table)" ); } Wdputslc( ":\n" ); Wdputs( "symbol index refers to section #" ); Putdec( elf_sec.sh_link ); Wdputslc( "\n" ); Wdputslc( "Offset Sym Idx Addend Type Offset Sym Idx Addend Type\n" ); rel_size = (elf_sec.sh_type == SHT_REL ? sizeof( Elf32_Rel ) : sizeof( Elf32_Rela )); for( loc = 0, ctr = 0; loc < elf_sec.sh_size; loc += rel_size, ctr++ ) { Wlseek( elf_sec.sh_offset + start + loc ); Wread( &elf_rela, rel_size ); Puthex( elf_rela.r_offset, 8 ); Wdputc( ' ' ); Puthex( ELF32_R_SYM( elf_rela.r_info ), 8 ); Wdputc( ' ' ); if( elf_sec.sh_type == SHT_RELA ) { Puthex( elf_rela.r_addend, 8 ); } else { Wdputs( "n/a " ); } Wdputc( ' ' ); Puthex( ELF32_R_TYPE( elf_rela.r_info ), 2 ); if( ctr % 2 == 1 ) { Wdputslc( "\n" ); } else { Wdputs( " " ); } } if( ctr % 2 != 0 ) { Wdputslc( "\n" ); } } } if( Options_dmp & DEBUG_INFO ) { Wdputslc( "\n" ); if( string_table ) { dmp_sec_data( &(string_table[elf_sec.sh_name]), elf_sec.sh_type, elf_sec.sh_offset+start, elf_sec.sh_size ); } else { dmp_sec_data( NULL, elf_sec.sh_type, elf_sec.sh_offset+start, elf_sec.sh_size ); } } else if( Options_dmp & OS2_SEG_DMP ) { if( elf_sec.sh_size && elf_sec.sh_type != SHT_NOBITS ) { Wdputslc( "Section dump:\n" ); Dmp_seg_data( elf_sec.sh_offset + start, elf_sec.sh_size ); } } Wdputslc( "\n" ); offset += Elf_head.e_shentsize; } } if( string_table ) { free( string_table ); } }
/* * dump_locals - dump all local variable information */ static void dump_locals( mod_info *mi ) /*************************************/ { int i; unsigned_32 *offs; int cnt; unsigned_32 coff; unsigned_8 buff[256]; char name[256]; set_base *sb; set_base386 *sb386; unsigned_8 *ptr; addr32_ptr *p32; addr48_ptr *p48; unsigned_16 index; cnt = mi->di[DMND_LOCALS].u.entries; if( cnt == 0 ) { return; } Wdputslc( "\n" ); Wdputslc( " *** Locals ***\n" ); Wdputslc( " ==============\n" ); offs = alloca( (cnt+1) * sizeof( unsigned_32 ) ); if( offs == NULL ) { Wdputslc( "Error! Not enough stack.\n" ); longjmp( Se_env, 1 ); } Wlseek( Curr_sectoff + mi->di[DMND_LOCALS].info_off ); Wread( offs, (cnt+1) * sizeof( unsigned_32 ) ); for( i = 0; i < cnt; i++ ) { coff = 0; Wdputs( " Data " ); Putdec( i ); Wdputs( ": offset " ); Puthex( offs[i], 8 ); Wdputslc( "\n" ); for( ;; ) { Wlseek( coff + Curr_sectoff + offs[i] ); Wread( buff, sizeof( buff ) ); Wdputs( " " ); Puthex( coff, 4 ); Wdputs( ": " ); switch( buff[1] ) { case MODULE: Wdputslc( "MODULE\n" ); ptr = buff+2; p32 = (addr32_ptr *)ptr; ptr += sizeof( addr32_ptr ); ptr = Get_type_index( ptr, &index ); Get_local_name( name, ptr, buff ); Wdputs( " \"" ); Wdputs( name ); Wdputs( "\" addr = " ); Puthex( p32->segment, 4 ); Wdputc( ':' ); Puthex( p32->offset, 4 ); Wdputs( ", type = " ); Putdec( index ); Wdputslc( "\n" ); break; case LOCAL: Wdputslc( "LOCAL\n" ); ptr = buff+2; Wdputs( " address: " ); ptr = Dump_location_expression( ptr, " " ); ptr = Get_type_index( ptr, &index ); Get_local_name( name, ptr, buff ); Wdputs( " name = \"" ); Wdputs( name ); Wdputs( "\", type = " ); Putdec( index ); Wdputslc( "\n" ); break; case MODULE_386: Wdputslc( "MODULE_386\n" ); ptr = buff+2; p48 = (addr48_ptr *)ptr; ptr += sizeof( addr48_ptr ); ptr = Get_type_index( ptr, &index ); Get_local_name( name, ptr, buff ); Wdputs( " \"" ); Wdputs( name ); Wdputs( "\" addr = " ); Puthex( p48->segment, 4 ); Wdputc( ':' ); Puthex( p48->offset, 8 ); Wdputs( ", type = " ); Putdec( index ); Wdputslc( "\n" ); break; case MODULE_LOC: Wdputslc( "MODULE_LOC\n" ); ptr = buff+2; Wdputs( " address: " ); ptr = Dump_location_expression( ptr, " " ); ptr = Get_type_index( ptr, &index ); Get_local_name( name, ptr, buff ); Wdputs( " name = \"" ); Wdputs( name ); Wdputs( "\", type = " ); Putdec( index ); Wdputslc( "\n" ); break; case BLOCK: Wdputslc( "BLOCK\n" ); dump_block( buff, FALSE ); break; case NEAR_RTN: Wdputslc( "NEAR_RTN\n" ); dump_rtn( buff ); break; case FAR_RTN: Wdputslc( "FAR_RTN\n" ); dump_rtn( buff ); break; case BLOCK_386: Wdputslc( "BLOCK_386\n" ); dump_block( buff, TRUE ); break; case NEAR_RTN_386: Wdputslc( "NEAR_RTN_386\n" ); dump_rtn386( buff ); break; case FAR_RTN_386: Wdputslc( "FAR_RTN_386\n" ); dump_rtn386( buff ); break; case MEMBER_SCOPE: Wdputslc( "MEMBER_SCOPE\n" ); index = 5; ptr = buff+2; Wdputs( " parent offset = " ); Puthex( *ptr, 4 ); ptr += 2; if( *ptr & 0x80 ) { index = 6; } Wdputs( " class type = " ); ptr = Get_type_index( ptr, &index ); Putdec( index ); if( buff[0] > index ) { Wdputslc( "\n object ptr type = " ); Puthex( *ptr++, 2 ); Wdputs( " object loc = " ); Dump_location_expression( ptr, " " ); } Wdputslc( "\n" ); break; case ADD_PREV_SEG: Wdputslc( "ADD_PREV_SEG\n" ); Wdputs( " segment increment = " ); Puthex( *(buff+2), 4 ); Wdputslc( "\n" ); break; case SET_BASE: Wdputslc( "SET_BASE\n" ); sb = (set_base *) buff; Wdputs( " base = " ); Puthex( sb->seg, 4 ); Wdputc( ':' ); Puthex( sb->off, 4 ); Wdputslc( "\n" ); break; case SET_BASE_386: Wdputslc( "SET_BASE_386\n" ); sb386 = (set_base386 *) buff; Wdputs( " base = " ); Puthex( sb386->seg, 4 ); Wdputc( ':' ); Puthex( sb386->off, 8 ); Wdputslc( "\n" ); break; } coff += buff[0]; if( coff >= (offs[i+1] - offs[i]) ) { break; } } } } /* dump_locals */
/* * dump_single_location_entry - dump a single location expression entry */ static unsigned_8 *dump_single_location_entry( unsigned_8 *buff ) /***************************************************************/ { unsigned_8 type; addr32_ptr *p32; addr48_ptr *p48; int i; int num; type = *buff; buff++; switch( type ) { case 0: Wdputslc( "<none>\n" ); break; case BP_OFFSET_BYTE: Wdputs( "BP_OFFSET_BYTE( " ); Puthex( *buff, 2 ); Wdputslc( " )\n" ); buff++; break; case BP_OFFSET_WORD: Wdputs( "BP_OFFSET_WORD( " ); Puthex( *buff, 4 ); Wdputslc( " )\n" ); buff += sizeof( unsigned_16 ); break; case BP_OFFSET_DWORD: Wdputs( "BP_OFFSET_DWORD( " ); Puthex( *buff, 8 ); Wdputslc( " )\n" ); buff += sizeof( unsigned_32 ); break; case CONST_ADDR286: p32 = (addr32_ptr *) buff; buff += sizeof( addr32_ptr ); Wdputs( "CONST_ADDR286( " ); Puthex( p32->segment, 4 ); Wdputc( ':' ); Puthex( p32->offset, 4 ); Wdputslc( " )\n" ); break; case CONST_ADDR386: p48 = (addr48_ptr *) buff; buff += sizeof( addr48_ptr ); Wdputs( "CONST_ADDR386( " ); Puthex( p48->segment, 4 ); Wdputc( ':' ); Puthex( p48->offset, 8 ); Wdputslc( " )\n" ); break; case CONST_INT_1: Wdputs( "CONST_INT_1( " ); Puthex( *buff, 2 ); Wdputslc( " )\n" ); buff++; break; case CONST_INT_2: Wdputs( "CONST_INT_2( " ); Puthex( *buff, 4 ); Wdputslc( " )\n" ); buff += sizeof( unsigned_16 ); break; case CONST_INT_4: Wdputs( "CONST_INT_4( " ); Puthex( *buff, 8 ); Wdputslc( " )\n" ); buff += sizeof( unsigned_32 ); break; case IND_REG_CALLOC_NEAR: Wdputs( "IND_REG_CALLOC_NEAR( " ); Wdputs( regLocStrs[ *buff ] ); Wdputslc( " )\n" ); buff++; break; case IND_REG_CALLOC_FAR: Wdputs( "IND_REG_CALLOC_FAR( " ); Wdputs( regLocStrs[ *buff ] ); Wdputc( ':' ); Wdputs( regLocStrs[ *(buff+1) ] ); Wdputslc( " )\n" ); buff += 2; break; case IND_REG_RALLOC_NEAR: Wdputs( "IND_REG_RALLOC_NEAR( " ); Wdputs( regLocStrs[ *buff ] ); Wdputslc( " )\n" ); buff++; break; case IND_REG_RALLOC_FAR: Wdputs( "IND_REG_RALLOC_FAR( " ); Wdputs( regLocStrs[ *buff ] ); Wdputc( ':' ); Wdputs( regLocStrs[ *(buff+1) ] ); Wdputslc( " )\n" ); buff += 2; break; case OPERATOR_IND_2: Wdputslc( "OPERATOR_IND_2\n" ); break; case OPERATOR_IND_4: Wdputslc( "OPERATOR_IND_4\n" ); break; case OPERATOR_IND_ADDR286: Wdputslc( "OPERATOR_IND_ADDR286\n" ); break; case OPERATOR_IND_ADDR386: Wdputslc( "OPERATOR_IND_ADDR386\n" ); break; case OPERATOR_ZEB: Wdputslc( "OPERATOR_ZEB\n" ); break; case OPERATOR_ZEW: Wdputslc( "OPERATOR_ZEW\n" ); break; case OPERATOR_MK_FP: Wdputslc( "OPERATOR_MK_FP\n" ); break; case OPERATOR_POP: Wdputslc( "OPERATOR_POP\n" ); break; case OPERATOR_XCHG: Wdputs( "OPERATOR_XCHG: " ); Puthex( *buff, 2 ); Wdputslc( "\n" ); buff++; break; case OPERATOR_ADD: Wdputslc( "OPERATOR_ADD\n" ); break; case OPERATOR_DUP: Wdputslc( "OPERATOR_DUP\n" ); break; case OPERATOR_NOP: Wdputslc( "OPERATOR_NOP\n" ); break; default: if( type & 0x30 ) { num = (type & 0x0f)+1; Wdputs( "MULTI_REG(" ); Putdec( num ); Wdputs( "): " ); for( i=0;i<num;i++ ) { Wdputs( regLocStrs[ *buff ] ); if( i != num-1 ) { Wdputs( ", " ); } else { Wdputslc( "\n" ); } buff++; } } else if( type & 0x40 ) { Wdputs( "REG: " ); Wdputs( regLocStrs[ type & 0x0f ] ); Wdputslc( "\n" ); } else { Wdputslc( "**** UNKNOWN LOCATION EXPRESSION!! ****\n" ); } break; } return( buff ); } /* dump_single_location_entry */
/* * Dump_types - dump all typing information */ void Dmp_type( int cnt, unsigned_32 *offs ) /*****************************************/ { int i; addr32_ptr *p32; addr48_ptr *p48; unsigned_8 *ptr; unsigned_16 index; unsigned_16 curr_index; unsigned_32 coff; char name[256]; unsigned_8 buff[256]; for( i = 0; i < cnt; i++ ) { coff = 0; Wdputs( " Data " ); Putdec( i ); Wdputs( ": offset " ); Puthex( offs[i], 8 ); Wdputslc( "\n" ); curr_index = 0; for( ;; ) { Wlseek( coff + Curr_sectoff + offs[i] ); Wread( buff, sizeof( buff ) ); Wdputs( " " ); Puthex( coff, 4 ); Wdputs( ": " ); ptr = buff+2; switch( buff[1] ) { case SCALAR: StartType( "SCALAR", ++curr_index ); ptr = buff+3; Get_local_name( name, ptr, buff ); Wdputs( " \"" ); Wdputs( name ); Wdputs( "\" scalar type = " ); scalar_type( buff[2] ); Wdputslc( "\n" ); break; case SCOPE: StartType( "SCOPE", ++curr_index); Get_local_name( name, ptr, buff ); Wdputs( " \"" ); Wdputs( name ); Wdputslc( "\"\n" ); break; case NAME: StartType( "NAME", ++curr_index); ptr = Get_type_index( ptr, &index ); ptr = Get_type_index( ptr, &index ); Get_local_name( name, ptr, buff ); Wdputs( " \"" ); Wdputs( name ); Wdputs( "\" type idx = " ); Putdec( index ); Wdputs( " scope idx = " ); ptr = Get_type_index( buff+2, &index ); Putdec( index ); Wdputslc( "\n" ); break; case CUE_TABLE: Wdputs( "cue table offset=" ); Puthex( *(unsigned_32 *)ptr, 8 ); Wdputslc( "\n" ); break; case TYPE_EOF: return; case BYTE_INDEX: StartType( "BYTE_INDEX ARRAY", ++curr_index); array_index( ptr, 1 ); break; case WORD_INDEX: StartType( "WORD_INDEX ARRAY", ++curr_index); array_index( ptr, 2 ); break; case LONG_INDEX: StartType( "LONG_INDEX ARRAY", ++curr_index); array_index( ptr, 4 ); break; case TYPE_INDEX: StartType( "TYPE_INDEX ARRAY", ++curr_index); Wdputs( " index type = " ); ptr = Get_type_index( ptr, &index ); Putdec( index ); base_type_index( ptr ); break; case DESC_INDEX: StartType( "DESC_INDEX ARRAY", ++curr_index); desc_array( ptr, false ); break; case DESC_INDEX_386: StartType( "DESC_INDEX ARRAY", ++curr_index); desc_array( ptr, true ); break; case BYTE_RANGE: StartType( "BYTE_RANGE", ++curr_index); range( ptr, 1 ); break; case WORD_RANGE: StartType( "WORD_RANGE", ++curr_index); range( ptr, 2 ); break; case LONG_RANGE: StartType( "LONG_RANGE", ++curr_index); range( ptr, 4 ); break; case PTR_NEAR: StartType( "NEAR PTR", ++curr_index); Wdputs( " " ); near_ptr( buff ); break; case PTR_FAR: StartType( "FAR PTR", ++curr_index); Wdputs( " " ); base_type_index( ptr ); break; case PTR_HUGE: StartType( "HUGE PTR", ++curr_index); Wdputs( " " ); base_type_index( ptr ); break; case PTR_NEAR_DEREF: StartType( "NEAR_DEREF PTR", ++curr_index); Wdputs( " " ); near_ptr( buff ); break; case PTR_FAR_DEREF: StartType( "FAR_DEREF PTR", ++curr_index); Wdputs( " " ); base_type_index( ptr ); break; case PTR_HUGE_DEREF: StartType( "HUGE_DEREF PTR", ++curr_index); Wdputs( " " ); base_type_index( ptr ); break; case PTR_NEAR386: StartType( "NEAR386 PTR", ++curr_index); Wdputs( " " ); near_ptr( buff ); break; case PTR_FAR386: StartType( "FAR386 PTR", ++curr_index); Wdputs( " " ); base_type_index( ptr ); break; case PTR_NEAR386_DEREF: StartType( "NEAR386_DEREF PTR", ++curr_index); Wdputs( " " ); near_ptr( buff ); break; case PTR_FAR386_DEREF: StartType( "FAR386_DEREF PTR", ++curr_index); Wdputs( "\n " ); base_type_index( ptr ); break; case CLIST: StartType( "ENUM_LIST", ++curr_index); Wdputs( " number of consts = " ); Puthex( *ptr, 4 ); Wdputs( " scalar type = " ); scalar_type( buff[4] ); Wdputslc( "\n" ); break; case CONST_BYTE: Wdputslc( "CONST_BYTE\n" ); enum_const( buff, 1 ); break; case CONST_WORD: Wdputslc( "CONST_WORD\n" ); enum_const( buff, 2 ); break; case CONST_LONG: Wdputslc( "CONST_LONG\n" ); enum_const( buff, 4 ); break; case FLIST: StartType( "FIELD_LIST", ++curr_index); Wdputs( " number of fields = " ); Puthex( *ptr, 4 ); if( buff[0] > 4 ) { Wdputs( " size = " ); ptr += 2; Puthex( *ptr, 8 ); } Wdputslc( "\n" ); break; case FIELD_BYTE: Wdputslc( "FIELD_BYTE\n" ); bit_field_struct( buff, 1, false ); break; case FIELD_WORD: Wdputslc( "FIELD_WORD\n" ); bit_field_struct( buff, 2, false ); break; case FIELD_LONG: Wdputslc( "FIELD_LONG\n" ); bit_field_struct( buff, 4, false ); break; case BIT_BYTE: Wdputslc( "BIT_BYTE\n" ); bit_field_struct( buff, 1, true ); break; case BIT_WORD: Wdputslc( "BIT_WORD\n" ); bit_field_struct( buff, 2, true ); break; case BIT_LONG: Wdputslc( "BIT_LONG\n" ); bit_field_struct( buff, 4, true ); break; case FIELD_CLASS: Wdputslc( "FIELD_CLASS\n" ); bit_field_class( buff, false ); break; case BIT_CLASS: Wdputslc( "BIT_CLASS\n" ); bit_field_class( buff, true ); break; case INHERIT_CLASS: Wdputslc( "INHERIT_CLASS\n" ); Wdputs( " adjust locator = " ); ptr = Dump_location_expression( ptr, " " ); Wdputs( " ancestor type = " ); Get_type_index( ptr, &index ); Putdec( index ); Wdputslc( "\n" ); break; case PNEAR: StartType( "NEAR PROC", ++curr_index); near_far_proc( buff ); break; case PFAR: StartType( "FAR PROC", ++curr_index); near_far_proc( buff ); break; case PNEAR386: StartType( "NEAR386 PROC", ++curr_index); near_far_proc( buff ); break; case PFAR386: StartType( "FAR386 PROC", ++curr_index); near_far_proc( buff ); break; case EXT_PARMS: Wdputslc( "EXT_PARMS\n" ); param_type_index( (unsigned_8)buff[0]-2, ptr ); break; case CHAR_BYTE: StartType( "CHAR_BYTE", ++curr_index); Wdputs( " length = " ); Puthex( *ptr, 2 ); Wdputslc( "\n" ); break; case CHAR_WORD: StartType( "CHAR_WORD", ++curr_index); Wdputs( " length = " ); Puthex( *ptr, 4 ); Wdputslc( "\n" ); break; case CHAR_LONG: StartType( "CHAR_LONG", ++curr_index); Wdputs( " length = " ); Puthex( *ptr, 8 ); Wdputslc( "\n" ); break; case CHAR_IND: StartType( "CHAR_IND", ++curr_index); Wdputs( " scalar type = " ); scalar_type( buff[2] ); p32 = (addr32_ptr *)ptr; Puthex( p32->segment, 4 ); Wdputc( ':' ); Puthex( p32->offset, 4 ); Wdputslc( "\n" ); break; case CHAR_IND_386: StartType( "CHAR_IND_386", ++curr_index); Wdputs( " scalar type = " ); scalar_type( buff[2] ); p48 = (addr48_ptr *)ptr; Puthex( p48->segment, 4 ); Wdputc( ':' ); Puthex( p48->offset, 8 ); Wdputslc( "\n" ); break; case CHAR_LOCATION: StartType( "CHAR_LOC", ++curr_index); Wdputs( " scalar type = " ); scalar_type( buff[2] ); Wdputs( " size locator = " ); ptr = Dump_location_expression( ptr + 1, " " ); Wdputslc( "\n" ); break; } coff += buff[0]; if( coff >= (offs[i+1] - offs[i]) ) { break; } } } } /* Dmp_type */
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 ); }