pass2.c

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

C
652
字号
            if( (*r_entry)->no_val == 0 && !( GetMachineType() == ORL_MACHINE_TYPE_AMD64 ) ) {
                nvalue -= ins_size;
            }
            referenceString( *r_entry, sec_size, "", "", "", buff, flags );
            break;
        case ORL_RELOC_TYPE_TOCREL_14:
            nvalue &= ~0x3;
        case ORL_RELOC_TYPE_TOCREL_16:
            referenceString( *r_entry, sec_size, "[toc]", "[toc]", "@toc",
                             buff, flags );
            break;
        case ORL_RELOC_TYPE_TOCVREL_14:
            nvalue &= ~0x3;
        case ORL_RELOC_TYPE_TOCVREL_16:
            referenceString( *r_entry, sec_size, "[tocv]", "[tocv]", "@tocv",
                             buff, flags );
            break;
        case ORL_RELOC_TYPE_GOT_16:
            referenceString( *r_entry, sec_size, "", "", "@got", buff, flags );
            break;
        case ORL_RELOC_TYPE_GOT_16_HI:
            referenceString( *r_entry, sec_size, "", "", "@got@h", buff, flags );
            break;
        case ORL_RELOC_TYPE_GOT_16_HA:
            referenceString( *r_entry, sec_size, "", "", "@got@ha", buff, flags );
            break;
        case ORL_RELOC_TYPE_GOT_16_LO:
            referenceString( *r_entry, sec_size, "", "", "@got@l", buff, flags );
            break;
        case ORL_RELOC_TYPE_PLTREL_24:
        case ORL_RELOC_TYPE_PLTREL_32:
        case ORL_RELOC_TYPE_PLT_32:
            referenceString( *r_entry, sec_size, "", "", "@plt", buff, flags );
            break;
        case ORL_RELOC_TYPE_PLT_16_HI:
            referenceString( *r_entry, sec_size, "", "", "@plt@h", buff, flags );
            break;
        case ORL_RELOC_TYPE_PLT_16_HA:
            referenceString( *r_entry, sec_size, "", "", "@plt@ha", buff, flags );
            break;
        case ORL_RELOC_TYPE_PLT_16_LO:
            referenceString( *r_entry, sec_size, "", "", "@plt@l", buff, flags );
            break;
        default:
            continue;
        }
        // LTYP_UNNAMED labels are always at the correct location
        // if( nvalue != 0 && (*r_entry)->label->type != LTYP_UNNAMED ) {
        // not so - BBB Oct 28, 1996
        if(( (*r_entry)->no_val == 0 ) && ( nvalue != 0 )) {
            p = &buff[strlen(buff)];
            if( nvalue < 0 ) {
                *p++ = '-';
                nvalue = -nvalue;
            } else {
                *p++ = '+';
            }
            FmtHexNum( p, 0, nvalue );
        }
    }
    return( strlen( buff ) );
}

static void FmtSizedHexNum( char *buff, dis_dec_ins *ins, unsigned op_num )
{
    unsigned            size;
    unsigned            len;
    unsigned            i;
    int                  is_sparc = GetMachineType()==ORL_MACHINE_TYPE_SPARC;

    static const unsigned long mask[] = {
        0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff
    };
    if( is_sparc ) {
        size = 4;
        switch( ins->op[op_num].ref_type ) {
            case DRT_SPARC_BYTE:    size = 1;   break;
            case DRT_SPARC_HALF:    size = 2;   break;
            case DRT_SPARC_WORD:
            case DRT_SPARC_SFLOAT:  size = 4;   break;
            case DRT_SPARC_DWORD:
            case DRT_SPARC_DFLOAT:  size = 8;   break;
            default:                            break;
        }
    } else {
        switch( ins->op[op_num].ref_type ) {
            case DRT_X86_BYTE:      size = 1;   break;
            case DRT_X86_WORD:      size = 2;   break;
            case DRT_X86_DWORD:
            case DRT_X86_DWORDF:    size = 4;   break;
            default:                size = 0;
                    for ( i = 0; i < ins->num_ops; i++ ) {
                        switch( ins->op[i].ref_type ) {
                            case DRT_X86_BYTE:      len = 1;  break;
                            case DRT_X86_WORD:      len = 2;  break;
                            case DRT_X86_DWORD:
                            case DRT_X86_DWORDF:    len = 4;  break;
                            default:                len = 0;
                        }
                        if ( len > size ) {
                            size = len;
                        }
                    }
                    if ( size == 0 ) {
                        size = 4;
                    }
                    break;
        }
    }
    FmtHexNum( buff, size * 2, mask[size] & ins->op[op_num].value );
}

unsigned DisCliValueString( void *d, dis_dec_ins *ins, unsigned op_num,
                            char *buff )
{
    struct pass2        *pd = d;
    unsigned            len;
    dis_operand         *op;
    ref_flags           rf;

    buff[0] = '\0';

    rf = RFLAG_DEFAULT;
    op = &ins->op[op_num];
    switch( op->type & DO_MASK ) {
    case DO_RELATIVE:
    case DO_MEMORY_REL:
    case DO_ABSOLUTE:
    case DO_MEMORY_ABS:
        if( pd->r_entry != NULL ) {
            /* if there is an override we must avoid the frame
             */
            if( ( ins->flags & DIS_X86_SEG_OR ) && IsIntelx86() ) {
                rf |= RFLAG_NO_FRAME;
            }
            len = HandleAReference( op->value, ins->size, rf,
                        pd->loop + op->op_position, pd->size, &pd->r_entry,
                        buff );
            if( len != 0 ) return( len );
        }
        switch( op->type & DO_MASK ) {
            case DO_RELATIVE:
            case DO_MEMORY_REL:
                op->value += pd->loop;
                break;
        }
        if( op->base == DR_NONE && op->index == DR_NONE ) {
            FmtSizedHexNum( buff, ins, op_num );
        } else if( op->value > 0 ) {
            FmtHexNum( buff, 0, op->value );
        } else if( op->value < 0 ) {
            buff[0] = '-';
            FmtHexNum( &buff[1], 0, -op->value );
        }
        break;
    case DO_IMMED:
        if( pd->r_entry != NULL ) {
            rf |= RFLAG_IS_IMMED;
            len = HandleAReference( op->value, ins->size, rf,
                        pd->loop + op->op_position, pd->size, &pd->r_entry,
                        buff );
            if( len != 0 ) return( len );
        }
        FmtSizedHexNum( buff, ins, op_num );
        break;
    }
    return( strlen( buff ) );
}

static void processDataInCode( section_ptr sec, char *contents, struct pass2 *data,
                               orl_sec_size size, label_entry *l_entry )
{
    orl_sec_size        offset;

    offset = data->loop + size;
    if( DFormat & DFF_ASM ) {
        DumpASMDataFromSection( contents, data->loop, offset, l_entry,
                                &(data->r_entry), sec );
        BufferPrint();
    } else {
        DumpDataFromSection( contents, data->loop, offset, l_entry,
                             &(data->r_entry), sec );
    }
    while( data->r_entry && ( data->r_entry->offset < offset ) ) {
        data->r_entry = data->r_entry->next;
    }
    data->loop = offset;
}

num_errors DoPass2( section_ptr sec, char *contents, orl_sec_size size,
                    label_list sec_label_list, ref_list sec_ref_list )
// perform pass 2 on one section
{
    struct pass2        data;
    label_entry         l_entry;
    dis_dec_ins         decoded;
    char                name[ MAX_INS_NAME ];
    char                ops[ MAX_OBJ_NAME + 24 ];       // at most 1 label/relocation per instruction, plus room for registers, brackets and other crap
    unsigned            flags;
    scantab_ptr         st;
    int                 is_intel;

    routineBase = 0;
    st = sec->scan;
    data.size = size;
    if( sec_label_list != NULL ) {
        l_entry = sec_label_list->first;
    }
    if( sec_ref_list != NULL ) {
        data.r_entry = sec_ref_list->first;
    } else {
        data.r_entry = NULL;
    }
    data.disassembly_errors = 0;

    if( source_mix ) {
        GetSourceFile( sec );
    }

    PrintHeader( sec );
    if( size && sec_label_list )
        PrintAssumeHeader( sec );
    flags = 0;
    if( GetMachineType() == ORL_MACHINE_TYPE_I386 ) {
        if( ( GetFormat() != ORL_OMF ) ||
            ( ORLSecGetFlags( sec->shnd ) & ORL_SEC_FLAG_USE_32 ) ) {
            flags = DIF_X86_USE32_FLAGS;
        }
        is_intel = 1;
    } else {
        is_intel = IsIntelx86();
    }
    for( data.loop = 0; data.loop < size; data.loop += decoded.size ) {

        // process data in code segment
        while( st && ( data.loop > st->end ) ) {
            st = st->next;
        }
        if( st && ( data.loop >= st->start ) ) {
            decoded.size = 0;
            processDataInCode( sec, contents, &data, st->end - data.loop, &l_entry );
            st = st->next;
            continue;
        }
        // data may not be listed in scan table, but a fixup at this offset will
        // give it away
        while( data.r_entry &&
              ( (data.r_entry->offset < data.loop) || SkipRef(data.r_entry)) ) {
            data.r_entry = data.r_entry->next;
        }
        if( data.r_entry && ( data.r_entry->offset == data.loop ) ) {
            if( is_intel || IsDataReloc( data.r_entry ) ) {
                // we just skip the data
                decoded.size = 0;
                processDataInCode( sec, contents, &data, RelocSize( data.r_entry ),
                                   &l_entry );
                continue;
            }
        }

        if( source_mix ) {
            MixSource( data.loop );
        }
        DisDecodeInit( &DHnd, &decoded );
        decoded.flags |= flags;
        DisDecode( &DHnd, &contents[data.loop], &decoded );
        if( sec_label_list ) {
            l_entry = handleLabels( sec->name, data.loop, data.loop + decoded.size, l_entry, size );
            if( ( l_entry != NULL )
                && ( l_entry->offset > data.loop )
                && ( l_entry->offset < data.loop + decoded.size ) ) {
                /*
                    If we have a label planted in the middle of this
                    instruction (see inline memchr for example), put
                    out a couple of data bytes, and then restart decode
                    and label process from offset of actual label.
                */
                decoded.size = 0;
                processDataInCode( sec, contents, &data, l_entry->offset - data.loop, &l_entry );
                continue;
            }
        }
        DisFormat( &DHnd, &data, &decoded, DFormat, name, ops );
        if( !(DFormat & DFF_ASM) ) {
             static unsigned_64 *tmp_64;
             static unsigned_32 *tmp_32;
             static unsigned_16 *tmp_16;
             tmp_64 = (unsigned_64 *)(contents+data.loop);
             tmp_32 = (unsigned_32 *)(contents+data.loop);
             tmp_16 = (unsigned_16 *)(contents+data.loop);
             if( DHnd.need_bswap ) {
                switch( DisInsSizeInc( &DHnd ) ) {
                   //case 8: SWAP_64(*tmp_64); break;
                   case 4: SWAP_32(*tmp_32); break;
                   case 2: SWAP_16(*tmp_16); break;
                   default: break;
                }
            }
             PrintLinePrefix( contents, data.loop, size,
                                DisInsSizeInc( &DHnd ), decoded.size );
        }
        BufferStore( "    %*s %s", -DisInsNameMax( &DHnd ), name, ops );
        BufferStore("\n");
        BufferPrint();
    }
    if( sec_label_list ) {
        l_entry = handleLabels( sec->name, size, -1, l_entry, size );
    }
    if( !(DFormat & DFF_ASM) ) {
        routineSize = data.loop - routineBase;
        BufferConcatNL();
        BufferMsg( ROUTINE_SIZE );
        BufferStore(" %d ", routineSize );
        BufferMsg( BYTES );
        BufferConcat(",    ");
        BufferMsg( ROUTINE_BASE );
        BufferStore(" %s + %04X\n\n", sec->name, routineBase );
        BufferPrint();
    }
    if( source_mix ) {
        EndSourceMix();
    }
    PrintTail( sec );
    return( data.disassembly_errors );
}

⌨️ 快捷键说明

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