testdump.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,165 行 · 第 1/3 页

C
1,165
字号

    uint_32     result;
    uint        shift;
    uint_8      byte;

    result = 0;
    shift = 0;
    for(;;) {
        byte = *input++;
        result |= ( byte & 0x7f ) << shift;
        if( ( byte & 0x80 ) == 0 ) break;
        shift += 7;
    }
    *value = result;
    return( (uint_8 *)input );
}


uint_8 *DecodeLEB128( const uint_8 *input, int_32 *value ) {

    int_32      result;
    uint        shift;
    uint_8      byte;

    result = 0;
    shift = 0;
    for(;;) {
        byte = *input++;
        result |= ( byte & 0x7f ) << shift;
        shift += 7;
        if( ( byte & 0x80 ) == 0 ) break;
    }
    if( ( shift < 32 ) && ( byte & 0x40 ) ) {
        result |= - ( 1 << shift );
    }
    *value = result;
    return( (uint_8 *)input );
}

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 printf_debug_str( unsigned int offset )
{
    if( offset > Sections[ DW_DEBUG_STR ].max_offset ) {
        printf( "\tstring @ .debug_str+%u (invalid offset)\n",
               offset );
    } else {
        printf( "\t\"%s\"\n", Sections[ DW_DEBUG_STR ].data + offset );
    }
}

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: %04lx\nAbbrev: %08lx\nAddress Size %02lx\n",
            unit_length, getU16( (uint_16 *)(p+4) ), abbrev_offset, address_size );
        p += 11;
        while( p - unit_base < unit_length ) {
            printf( "offset %08lx: ", 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 );
                    p += len;
                    break;
                case DW_FORM_block1:
                    len = *p++;
                    printf( "\n" );
                    dumpHex( p, len );
                    p += len;
                    break;
                case DW_FORM_block2:
                    len = getU16( (uint_16 *)p );
                    p += sizeof( uint_16 );
                    printf( "\n" );
                    dumpHex( p, len );
                    p += len;
                    break;
                case DW_FORM_block4:
                    len = getU32( (uint_32 *)p );
                    p += sizeof( uint_32 );
                    printf( "\n" );
                    dumpHex( p, len );
                    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( p ) + 1;
                    break;
                case DW_FORM_strp:  /* 4 byte index into .debug_str */
                    printf_debug_str( getU32( (unsigned long *)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 dumpAbbrevs( const char *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(;;) {
            if( p > input + length ) break;
            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;
        }
    }
}


static char *getStandardOp( uint_8 value ) {

    static char                 buf[ 30 ];
    char *                      result;

    result = getName( value, readableStandardOps, NUM_STANDARD_OPS );
    if( result == NULL ) {
        sprintf( buf, "OP_%02x", value );
        return( buf );
    }
    return( result );
}

typedef struct {
    uint_32                     address;
    uint                        file;
    uint_32                     line;
    uint_32                     column;
    uint_8                      is_stmt : 1;
    uint_8                      basic_block : 1;
    uint_8                      end_sequence : 1;
} state_info;


static void initState( state_info *state, int default_is_stmt ) {

    state->address = 0;
    state->file = 1;
    state->line = 1;
    state->column = 0;
    state->is_stmt = default_is_stmt;
    state->basic_block = 0;
    state->end_sequence = 0;
}


static void dumpState( state_info *state ) {

    printf( "-- file %d addr %08lx line %d column %d",
        state->file, state->address, state->line, state->column );
    if( state->is_stmt ) printf( " is_stmt" );
    if( state->basic_block ) printf( " basic_block" );
    if( state->end_sequence ) printf( " end_sequence" );
    printf( "\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( "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 = %08lx\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( 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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?