pass2.c

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

C
652
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Disassembler pass 2.
*
****************************************************************************/


#include <stdio.h>
#include <string.h>
#include "global.h"
#include "dis.h"
#include "pass2.h"
#include "buffer.h"
#include "srcmix.h"
#include "formasm.h"
#include "init.h"
#include "main.h"
#include "print.h"

#define COMMENT_TAB_POS 4
#define OPS_REP_TAB_POS 10
#define DIS_X86_SEG_OR  ( DIF_X86_CS | DIF_X86_DS | DIF_X86_ES | DIF_X86_FS | \
                          DIF_X86_GS | DIF_X86_SS )

struct pass2 {
    orl_sec_offset      loop;
    orl_sec_size        size;
    num_errors          disassembly_errors;
    ref_entry           r_entry;
};

extern wd_options               Options;
extern char                     LabelChar;
extern dis_handle               DHnd;
extern bool                     Prettify;
extern section_list_struct      Sections;
extern hash_table               HandleToSectionTable;
extern hash_table               SymbolToLabelTable;
extern dis_format_flags         DFormat;
extern bool                     source_mix;
extern char *                   CommentString;

static orl_sec_offset   routineBase = 0;
static orl_sec_size     routineSize = 0;

dis_return DisCliGetData( void *d, unsigned off, unsigned size, void *buff )
{
    //NYI: need to handle going beyond the end of the section
    memcpy( buff, (char *)d + off, size );
    return( DR_OK );
}

static label_entry handleLabels( char *sec_name, orl_sec_offset offset, orl_sec_offset end,
                             label_entry l_entry, orl_sec_size size )
// handle any labels at this offset and skip all unused non-label symbols
{
    for( ; ( l_entry != NULL ) && ( l_entry->offset < end ); l_entry = l_entry->next ) {
        switch( l_entry->type ) {
        case LTYP_SECTION:
        case LTYP_NAMED:
            if( strcmp( l_entry->label.name, sec_name ) == 0 )
                continue;
            /* fall through */
        case LTYP_UNNAMED:
            if( l_entry->offset > offset )
                return( l_entry );
            break;
        case LTYP_ABSOLUTE:
        case LTYP_FUNC_INFO:
        default:
            continue;
        }
        switch( l_entry->type ) {
        case LTYP_NAMED:
            if( !( DFormat & DFF_ASM ) ) {
                if( offset != 0 && l_entry->binding == ORL_SYM_BINDING_GLOBAL ) {
                    routineSize = offset - routineBase;
                    BufferConcatNL();
                    BufferMsg( ROUTINE_SIZE );
                    BufferStore(" %d ", routineSize );
                    BufferMsg( BYTES );
                    BufferConcat(",    ");
                    BufferMsg( ROUTINE_BASE );
                    BufferStore(" %s + %04X\n\n", sec_name, routineBase );
                    routineBase = offset;
                }
            }
        case LTYP_SECTION:
            if( !( DFormat & DFF_ASM ) ) {
                PrintLinePrefix( NULL, offset, size, 1, 0 );
            }
            BufferStore( "%s:\n", l_entry->label.name );
            break;
        case LTYP_UNNAMED:
            if( !( DFormat & DFF_ASM ) ) {
                PrintLinePrefix( NULL, offset, size, 1, 0 );
            }
            BufferStore( "%c$%d:\n", LabelChar, l_entry->label.number );
            break;
        }
        BufferPrint();
    }
    return( l_entry );
}

static return_val referenceString( ref_entry r_entry, orl_sec_size size,
                                   char *ext_pref, char *int_pref, char *post,
                                   char *buff, ref_flags flags )
{
    label_entry         l_entry;
    char                *sep = ":";
    char                *frame;
    char                temp[15];

    frame = r_entry->frame;
    if( !frame || ( flags & RFLAG_NO_FRAME ) ) {
        frame = "";
        sep = "";
    }

    l_entry = r_entry->label;
    if( Options & METAWARE_COMPATIBLE || (ext_pref[0]==0 && int_pref[0]==0) ) {
        switch( l_entry->type ) {
            case LTYP_ABSOLUTE:
                FmtHexNum( temp, 0, l_entry->offset );
                if( *frame == 0 && ( ( flags & RFLAG_NO_FRAME ) == 0 ) )
                    frame = "ds:";
                sprintf( buff, "%s%s[%s]", frame, sep, temp);
                break;
            case LTYP_UNNAMED:
                sprintf( buff, "%s%s%c$%d%s", frame, sep, LabelChar,
                         l_entry->label.number, post );
                break;
            default:
                sprintf( buff, "%s%s%s%s", frame, sep, l_entry->label.name,
                         post );
                break;
        }
    } else {
        switch( l_entry->type ) {
            case LTYP_EXTERNAL_NAMED:
                sprintf( buff, "%s%s%s%s", ext_pref, frame, sep,
                         l_entry->label.name );
                break;
            case LTYP_NAMED:
            case LTYP_SECTION:
            case LTYP_GROUP:
                sprintf( buff, "%s%s%s%s", int_pref, frame, sep,
                         l_entry->label.name );
                break;

            case LTYP_ABSOLUTE:
                FmtHexNum( temp, 0, l_entry->offset );
                if( *frame == 0 && ( ( flags & RFLAG_NO_FRAME ) == 0 ) )
                    frame = "ds:";
                sprintf( buff, "%s%s%s[%s]", int_pref, frame, sep, temp);
                break;

            default:
                sprintf( buff, "%s%s%s%c$%d", int_pref, frame, sep,
                         LabelChar, l_entry->label.number );
                if( l_entry->offset > size ) {
                    return( ERROR );
                }
                break;
        }
    }
    return( OKAY );
}

unsigned HandleAReference( dis_value value, int ins_size, ref_flags flags,
                           orl_sec_offset offset, orl_sec_size sec_size,
                           ref_entry * r_entry, char *buff )
// handle any references at this offset
{
    return_val          error;
    dis_value           nvalue;
    char                *p;

    buff[0] = '\0';
    for( ; *r_entry && (*r_entry)->offset == offset; *r_entry = (*r_entry)->next ) {
        if( (*r_entry)->no_val == 0 ) {
            nvalue = value;
        } else if( (*r_entry)->addend ) {
            nvalue = HandleAddend( *r_entry );
        } else {
            nvalue = 0;
        }
        switch( (*r_entry)->type ) {
        case ORL_RELOC_TYPE_MAX + 1:
        case ORL_RELOC_TYPE_JUMP:
        case ORL_RELOC_TYPE_REL_21_SH:
        case ORL_RELOC_TYPE_WORD_26:
            error = referenceString( *r_entry, sec_size, "j^", "", "",
                                     buff, flags );
            if( error != OKAY ) {
                // label is defined to be beyond the boundaries of the section!
                if( !(DFormat & DFF_ASM) ){
                    BufferStore("\t     %04X", offset );
                    BufferAlignToTab( COMMENT_TAB_POS );
                } else {
                    BufferConcat("\t" );
                }
                BufferConcat( CommentString );
                BufferMsg( LABEL_BEYOND_SECTION );
                BufferConcatNL();
                BufferPrint();
                *r_entry = (*r_entry)->next;
                return( 0 );
            }
            continue; // Don't print addend
            break;
        case ORL_RELOC_TYPE_SEC_REL:
            referenceString( *r_entry, sec_size, "s^", "s^", "@s", buff,
                             flags );
            break;
        case ORL_RELOC_TYPE_HALF_HI:
            referenceString( *r_entry, sec_size, "h^", "h^", "@h", buff,
                             flags );
            break;
        case ORL_RELOC_TYPE_HALF_HA:
            referenceString( *r_entry, sec_size, "ha^", "ha^", "@ha", buff,
                             flags );
            break;
        case ORL_RELOC_TYPE_HALF_LO:
            referenceString( *r_entry, sec_size, "l^", "l^", "@l", buff,
                             flags );
            break;
        case ORL_RELOC_TYPE_REL_14:
        case ORL_RELOC_TYPE_REL_24:
        case ORL_RELOC_TYPE_WORD_14:
        case ORL_RELOC_TYPE_WORD_24:
            nvalue &= ~0x3;
        case ORL_RELOC_TYPE_WORD_16:
        case ORL_RELOC_TYPE_WORD_32:
        case ORL_RELOC_TYPE_WORD_64:
            if( ( (*r_entry)->label->type != LTYP_GROUP ) &&
              ( flags & RFLAG_IS_IMMED ) && IsMasmOutput() ) {
                referenceString( *r_entry, sec_size, "offset ", "offset ",
                                 "", buff, flags );
            } else {
                referenceString( *r_entry, sec_size, "", "", "", buff,
                                 flags );
            }
            break;
        case ORL_RELOC_TYPE_REL_16:
            if( IsIntelx86() && !(*r_entry)->no_val ) {
                nvalue -= ins_size;
            }
            if( ( (*r_entry)->label->type != LTYP_GROUP ) &&
              ( flags & RFLAG_IS_IMMED ) && IsMasmOutput() ) {
                referenceString( *r_entry, sec_size, "offset ", "offset ",
                                 "", buff, flags );
            } else {
                referenceString( *r_entry, sec_size, "", "", "", buff,
                                 flags  );
            }
            break;
        case ORL_RELOC_TYPE_WORD_8:
        case ORL_RELOC_TYPE_WORD_16_SEG:
        case ORL_RELOC_TYPE_WORD_HI_8:
        case ORL_RELOC_TYPE_WORD_32_SEG:
            // Keep these seperate because they are OMF specific
            referenceString( *r_entry, sec_size, "", "", "", buff, flags );
            break;
        case ORL_RELOC_TYPE_SEGMENT:
            if( ( (*r_entry)->label->type != LTYP_GROUP )
                && ( (*r_entry)->label->type != LTYP_SECTION )
                && ( flags & RFLAG_IS_IMMED )
                && IsMasmOutput() ) {
                referenceString( *r_entry, sec_size, "seg ", "seg ", "",
                                 buff, flags );
            } else {
                referenceString( *r_entry, sec_size, "", "", "", buff,
                                 flags );
            }
            break;
        
        case ORL_RELOC_TYPE_REL_32_NOADJ:
            // this is a little kluge because Brian's ELF files seem to have
            // -4 in the implicit addend for calls and such BBB May 09, 1997
            nvalue += 4;
            // fall through
        case ORL_RELOC_TYPE_REL_8:
        case ORL_RELOC_TYPE_REL_16_SEG:
        case ORL_RELOC_TYPE_REL_HI_8:
        case ORL_RELOC_TYPE_REL_32_SEG:
        case ORL_RELOC_TYPE_REL_32:
        case ORL_RELOC_TYPE_REL_32_ADJ5:
        case ORL_RELOC_TYPE_REL_32_ADJ4:
        case ORL_RELOC_TYPE_REL_32_ADJ3:
        case ORL_RELOC_TYPE_REL_32_ADJ2:
        case ORL_RELOC_TYPE_REL_32_ADJ1:
            // For some reason we add the instruction size to the value
            // of the displacement in a relative call and get a bad
            // offset, due to CORE implementation
            //
            // Main reason :
            // instruction size with displacement and with addend is correct for
            // relative addresses without relocate
            //
            // in amd64 code the instruction size will be added in pass1.c!

⌨️ 快捷键说明

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