formasm.c

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

C
889
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dis.h"
#include "formasm.h"
#include "langenv.h"
#include "memfuncs.h"
#include "buffer.h"
#include "hashtabl.h"
#include "pass1.h"
#include "pass2.h"
#include "print.h"
#include "main.h"
#include "init.h"

#define STRING_LINE_LEN 41
#define UNPRINT_MAX_LEN 6

extern hash_table       HandleToLabelListTable;
extern hash_table       HandleToRefListTable;
extern hash_table       SkipRefTable;
extern wd_options       Options;
extern dis_format_flags DFormat;
extern char             LabelChar;
extern char             QuoteChar;

static const char       * const masmTypes[] = {NULL,            // 0
                                "DB\t",         // 1
                                "DW\t",         // 2
                                NULL,           // 3
                                "DD\t",         // 4
                                NULL,           // 5
                                "DF\t",         // 6
                                NULL,           // 7
                                "DQ\t"          // 8
                                };

static const char       *const unixTypes[] = {NULL,             // 0
                                ".byte\t",      // 1
                                ".word\t",      // 2
                                NULL,           // 3
                                ".long\t",      // 4
                                NULL,           // 5
                                NULL,           // 6
                                NULL,           // 7
                                ".quad\t"       // 8
                                };

// do a strncpy with max # characters = sec_size - current_position
// if # chars copied == sec_size - current_position and last character
// is not a NULL
//     <<.ascii>>
// otherwise
//     <<.asciz>>
// print it out
// update the current position
// repeat until end of section reached

typedef enum {
    ASCII,
    ASCIZ
} string_type;

int IsMasmOutput( void )
{
    return( !( DFormat & DFF_X86_UNIX ) && ( GetFormat() == ORL_OMF ) );
}

static void printRawAndAddress( char * raw_data, orl_sec_offset address )
{
    switch( strlen( raw_data ) ) {
    case 0:
        BufferStore( "      00     %04X", address );
        break;
    case 1:
        BufferStore( "    00%02X     %04X", raw_data[0], address );
        break;
    case 2:
        BufferStore( "  00%02X%02X     %04X", raw_data[1], raw_data[0],
            address );
        break;
    case 3:
        BufferStore( "00%02X%02X%02X     %04X", raw_data[2], raw_data[1],
            raw_data[0], address );
        break;
    default:
        BufferStore( "%02X%02X%02X%02X     %04X", raw_data[3],
            raw_data[2], raw_data[1], raw_data[0], address );
        break;
    }
}

static bool printableChar( char c )
{
    // fixme: which characters should be printed as is and which not?
    if( isprint( c ) || c == '\n' || c == '\r' || c == '\t' || c == '\f' ) {
        return TRUE;
    } else {
        return FALSE;
    }
}

static bool printableString( char *s )
{
    int i;
    for( i = 0; i < strlen( s ); i++ ){
        if( !printableChar( s[i] ) ) {
            return FALSE;
        }
    }
    return TRUE;
}

static orl_sec_offset printString( char * string, string_type type )
{
    char                *buffer;
    orl_sec_offset      i,j;

    buffer = MemAlloc( strlen( string ) * 2 + 1 );
    for( i=0, j=0; i < strlen( string ); i++ ){
        switch( string[i] ){
            case '\n':
                buffer[j++] = '\\';
                buffer[j++] = 'n';
                break;
            case '\r':
                buffer[j++] = '\\';
                buffer[j++] = 'r';
                break;
            case '\t':
                buffer[j++] = '\\';
                buffer[j++] = 't';
                break;
            case '\f':
                buffer[j++] = '\\';
                buffer[j++] = 'f';
                break;
            case '\\':
                buffer[j++] = '\\';
                buffer[j++] = '\\';
                break;
            case '\"':
                buffer[j++] = QuoteChar;
                buffer[j++] = '\"';
                break;
            case '\'':
                buffer[j++] = '\\';
                buffer[j++] = '\'';
                break;
            default:
                buffer[j++] = string[i];
                break;
        }
    }
    buffer[j] = 0;

    BufferStore( "\"%s\"", buffer );
    BufferPrint();
    MemFree( buffer );
    switch( type ) {
        case ASCII:
            return( strlen( string ) );
        case ASCIZ:
            return( strlen( string ) + 1 );
    }
    // shouldn't get here, but compiler complains.
    return( 0 );
}

static orl_sec_offset tryDUP(char *string, orl_sec_offset i, orl_sec_size size)
{
    orl_sec_offset      d;
    unsigned int        dup;


    if( i >= ( size - ( 8 * MIN_DUP_LINES ) ) ) return( 0 );

    for( d = i + 8; d < ( size - 8 ); d += 8 ) {
        if( memcmp( &string[i], &string[d], 8 ) ) return( 0 );
    }

    d -= i;
    dup = d / 8;
    if( dup < MIN_DUP_LINES ) return( 0 );

    BufferStore( "0%XH DUP(", dup, string[i] );

    for( dup = 0; dup < 7; dup++ ) {
        BufferHex( 2, string[i + dup] );
        BufferConcat( "," );
    }
    BufferHex( 2, string[i + 7] );
    BufferConcat( ")" );
    return( d );
}

static void printRest( char *string, orl_sec_size size )
{
    orl_sec_offset      i;
    orl_sec_offset      d;
    char                *btype;
    int                 is_masm;

    is_masm = IsMasmOutput();
    if( is_masm ) {
        btype = "    DB\t";
    } else {
        btype = "    .byte\t";
    }
    BufferConcat( btype );
    for( i = 0; i < size; ) {
        // see if we can replace large chunks of homogenous
        // segment space by using the DUP macro
        if( is_masm && !( i % 8 ) ) {
            d = tryDUP( string, i, size );
            if( d > 0 ) {
                i += d;
                if( i < size ) {
                    BufferConcatNL();
                    BufferConcat( btype );
                    BufferPrint();
                }
                continue;
            }
        }

        BufferHex( 2, string[i] );
        if( i < size-1 ) {
            if( ( i % 8 ) == 7 ) {
                BufferConcatNL();
                BufferConcat( btype );
                BufferPrint();
            } else {
                BufferConcat(", ");
            }
        }
        i++;
    }
    BufferConcatNL();
    BufferPrint();
}

dis_value HandleAddend( ref_entry r_entry )
// sign-extend an addend value by the appropriate number of bits.
{
    dis_value   r_addend;
    int         bits;

    r_addend = r_entry->addend;
    switch( r_entry->type ) {
    case ORL_RELOC_TYPE_REL_14:
    case ORL_RELOC_TYPE_WORD_14:
    case ORL_RELOC_TYPE_TOCREL_14:
    case ORL_RELOC_TYPE_TOCVREL_14:
        bits = 14;
        break;
    case ORL_RELOC_TYPE_REL_24:
    case ORL_RELOC_TYPE_WORD_24:
    case ORL_RELOC_TYPE_PLTREL_24:
        bits = 24;
        break;
    case ORL_RELOC_TYPE_WORD_26:
        bits = 26;
        break;
    case ORL_RELOC_TYPE_REL_16:
    case ORL_RELOC_TYPE_WORD_16:
    case ORL_RELOC_TYPE_HALF_HI:
    case ORL_RELOC_TYPE_HALF_HA:
    case ORL_RELOC_TYPE_HALF_LO:
    case ORL_RELOC_TYPE_TOCREL_16:
    case ORL_RELOC_TYPE_TOCVREL_16:
    case ORL_RELOC_TYPE_GOT_16:
    case ORL_RELOC_TYPE_GOT_16_HI:
    case ORL_RELOC_TYPE_GOT_16_HA:
    case ORL_RELOC_TYPE_GOT_16_LO:
    case ORL_RELOC_TYPE_PLT_16_HI:
    case ORL_RELOC_TYPE_PLT_16_HA:
    case ORL_RELOC_TYPE_PLT_16_LO:
        bits = 16;
        break;
    case ORL_RELOC_TYPE_WORD_32:
    case ORL_RELOC_TYPE_WORD_32_NB:
    case ORL_RELOC_TYPE_JUMP:
    case ORL_RELOC_TYPE_SEC_REL:
    case ORL_RELOC_TYPE_REL_32:
    case ORL_RELOC_TYPE_REL_32_NOADJ:
    case ORL_RELOC_TYPE_REL_32_ADJ1:
    case ORL_RELOC_TYPE_REL_32_ADJ2:
    case ORL_RELOC_TYPE_REL_32_ADJ3:
    case ORL_RELOC_TYPE_REL_32_ADJ4:
    case ORL_RELOC_TYPE_REL_32_ADJ5:
    case ORL_RELOC_TYPE_PLTREL_32:
    case ORL_RELOC_TYPE_PLT_32:
    default:
        bits = 32;
        break;
    case ORL_RELOC_TYPE_REL_21_SH:
        // Will NEVER happen
        bits = 21;
        break;
    case ORL_RELOC_TYPE_WORD_64:
        // Will NEVER happen
        bits = 64;
        break;
    }
    if( (bits != 32) && (r_addend & (1 << (bits-1) ) ) ) {
        return( r_addend | ( 0xFFFFFFFF ^ ( (1<<bits) - 1 ) ) );
    } else {
        return( r_addend );
    }
}

int IsDataReloc( ref_entry r_entry )
{
    switch( r_entry->type ) {
    case ORL_RELOC_TYPE_ABSOLUTE:
    case ORL_RELOC_TYPE_WORD_32:
    case ORL_RELOC_TYPE_WORD_32_NB:
    case ORL_RELOC_TYPE_SECTION:
    case ORL_RELOC_TYPE_REL_32:
    case ORL_RELOC_TYPE_REL_32_NOADJ:
    case ORL_RELOC_TYPE_REL_32_ADJ1:
    case ORL_RELOC_TYPE_REL_32_ADJ2:
    case ORL_RELOC_TYPE_REL_32_ADJ3:
    case ORL_RELOC_TYPE_REL_32_ADJ4:
    case ORL_RELOC_TYPE_REL_32_ADJ5:
    case ORL_RELOC_TYPE_PLTREL_32:
    case ORL_RELOC_TYPE_PLT_32:
    case ORL_RELOC_TYPE_WORD_64:
        return( 1 );
    default:
        return( 0 );
    }
}

orl_sec_offset RelocSize( ref_entry r_entry )
{
    switch( r_entry->type ) {
    case ORL_RELOC_TYPE_ABSOLUTE:
    case ORL_RELOC_TYPE_WORD_32:
    case ORL_RELOC_TYPE_WORD_32_NB:
    case ORL_RELOC_TYPE_JUMP:
    case ORL_RELOC_TYPE_SECTION:
    case ORL_RELOC_TYPE_SEC_REL:
    case ORL_RELOC_TYPE_REL_21_SH:
    case ORL_RELOC_TYPE_WORD_24:
    case ORL_RELOC_TYPE_WORD_26:
    case ORL_RELOC_TYPE_REL_24:
    case ORL_RELOC_TYPE_REL_32:
    case ORL_RELOC_TYPE_REL_32_NOADJ:
    case ORL_RELOC_TYPE_REL_32_ADJ1:
    case ORL_RELOC_TYPE_REL_32_ADJ2:
    case ORL_RELOC_TYPE_REL_32_ADJ3:
    case ORL_RELOC_TYPE_REL_32_ADJ4:
    case ORL_RELOC_TYPE_REL_32_ADJ5:
    case ORL_RELOC_TYPE_PLTREL_24:
    case ORL_RELOC_TYPE_PLTREL_32:
    case ORL_RELOC_TYPE_PLT_32:
    case ORL_RELOC_TYPE_WORD_16_SEG:
    case ORL_RELOC_TYPE_REL_16_SEG:
        return 4;
    case ORL_RELOC_TYPE_WORD_16:
    case ORL_RELOC_TYPE_HALF_HI:
    case ORL_RELOC_TYPE_HALF_LO:
    case ORL_RELOC_TYPE_REL_16:
    case ORL_RELOC_TYPE_SEGMENT:
    case ORL_RELOC_TYPE_WORD_14:
    case ORL_RELOC_TYPE_REL_14:
    case ORL_RELOC_TYPE_TOCREL_16:
    case ORL_RELOC_TYPE_TOCREL_14:
    case ORL_RELOC_TYPE_TOCVREL_16:
    case ORL_RELOC_TYPE_TOCVREL_14:
    case ORL_RELOC_TYPE_GOT_16:
    case ORL_RELOC_TYPE_GOT_16_HI:
    case ORL_RELOC_TYPE_GOT_16_HA:
    case ORL_RELOC_TYPE_GOT_16_LO:
    case ORL_RELOC_TYPE_PLT_16_HI:
    case ORL_RELOC_TYPE_PLT_16_HA:
    case ORL_RELOC_TYPE_PLT_16_LO:
        return 2;
    case ORL_RELOC_TYPE_WORD_64:
        return 8;
    case ORL_RELOC_TYPE_WORD_32_SEG:
    case ORL_RELOC_TYPE_REL_32_SEG:
        return 6;
    case ORL_RELOC_TYPE_WORD_8:
    case ORL_RELOC_TYPE_REL_8:
    case ORL_RELOC_TYPE_WORD_HI_8:
    case ORL_RELOC_TYPE_REL_HI_8:
        return 1;
    default:
        // This should never happen, but 4 is the most likely size.
        return 4;
    }
}

orl_sec_offset HandleRefInData( ref_entry r_entry, void *data, bool asmLabels )
{
    orl_sec_offset      rv;
    const char          * const *types;
    char                buff[MAX_SYM_LEN];      // fixme: should be TS_MAX_OBJNAME or something

    if( IsMasmOutput() ) {
        types = masmTypes;
    } else {
        types = unixTypes;
    }

    rv = RelocSize( r_entry );
    switch( rv ) {
    case 6:
        if( asmLabels && types[rv] ) {
            BufferConcat( types[rv] );

⌨️ 快捷键说明

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