⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omfload.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*
*                            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:  OMF file parsing routines.
*
****************************************************************************/


#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "pcobj.h"
#include "omfload.h"
#include "omfmunge.h"

/* Local definitions
 */
#define MAX_REC_SIZE    65536
#define TWO_BYTE_MASK   0x80


static void             setInitialData( omf_file_handle ofh )
{
    assert( ofh );

    /* Default will be 16-bit code
     */
    ofh->machine_type = ORL_MACHINE_TYPE_I8086;
    ofh->type = ORL_FILE_TYPE_OBJECT;
    ofh->flags = 0;
    ofh->flags |= ORL_FILE_FLAG_LITTLE_ENDIAN;
    ofh->flags |= ORL_FILE_FLAG_16BIT_MACHINE;
    ofh->debug_style = OMF_DBG_STYLE_CODEVIEW;
}


int                     OmfGetWordSize( int is32 )
{
    if( is32 ) {
        return( 4 );
    } else {
        return( 2 );
    }
}


static orl_sec_offset   getUWord( omf_bytes buffer, int wordsize )
{
    orl_sec_offset      result = 0;

    assert( buffer );

    switch( wordsize ) {
    case( 4 ):
        result |= buffer[3] << 24;
        result |= buffer[2] << 16;
    case( 2 ):
        result |= buffer[1] << 8;
    default:
        result |= buffer[0];
    }
    return( result );
}


static int              check32Bit( omf_file_handle ofh, omf_rectyp typ )
{
    int is32;

    is32 = _Is32BitRec( typ ) || ( ofh->status & OMF_STATUS_EASY_OMF );
    return( is32 );
}


static orl_sec_alignment getAlignment( int val )
{
    switch( val ) {
    case( ALIGN_ABS ):          /* absolute segment - no alignment      */
    case( ALIGN_BYTE ):         /* relocatable seg - byte aligned       */
        return( 0 );
    case( ALIGN_WORD ):         /* relocatable seg - word aligned       */
        return( 1 );
    case( ALIGN_PARA ):         /* relocatable seg - para aligned       */
        return( 4 );
    case( ALIGN_PAGE ):         /* relocatable seg - page aligned       */
        return( 8 );
    case( ALIGN_DWORD ):        /* relocatable seg - dword aligned      */
                                /* 32-bit ALIGN_UNABS unnamed absolute  *
                                 * segment, this is currently not       *
                                 * supported by the linker.             */
        return( 2 );
    case( ALIGN_LTRELOC ):      /* load-time relocatable segment        */
                                /* 32-bit ALIGN_4KPAGE relocatable      *
                                 * seg - 4k page aligned                */
        return( 12 );
    default:
        assert( 0 );
        return( 0 );
    }
}


static orl_return       loadRecord( omf_file_handle ofh )
{
    long                len;
    omf_bytes           buff;
    uint_8              record_chksum;
    uint_8              chksum;

    assert( ofh );

    buff = _ClientRead( ofh, 2 );
    if( !buff ) return( ORL_ERROR );
    len = getUWord( buff, 2 );
    if( len <= 0 ) return( ORL_ERROR );
    ofh->parsebuf = _ClientRead( ofh, len );
    if( !ofh->parsebuf ) return( ORL_ERROR );
    ofh->parselen = len - 1;

    record_chksum = ofh->parsebuf[ ofh->parselen ];
    // some slob compilers put out 0 for all chksum's, so
    // only check if it is non-zero
    if( record_chksum != 0 ) {
        chksum = ofh->last_rec + buff[0] + buff[1];
        while( len ) {
            len--;
            chksum += ofh->parsebuf[len];
        }

        if( chksum ) return( ORL_ERROR );
    }
    return( ORL_OKAY );
}


omf_idx loadIndex( omf_bytes *buffer, long *len )
{
    omf_bytes           deref;
    long                pos;
    omf_idx             idx;

    assert( buffer );
    assert( *buffer );
    assert( len );

    deref = *buffer;
    pos = *len;

    if( deref[0] & TWO_BYTE_MASK ) {
        idx = ( ( deref[0] & 0x7f ) << 8 ) | deref[1];
        deref += 2;
        pos -= 2;
    } else {
        idx = deref[0];
        deref++;
        pos--;
    }
    *len = pos;
    *buffer = deref;
    return( idx );
}


static orl_return       processExplicitFixup( omf_file_handle ofh, int is32,
                                            omf_bytes *buffer, long *cur )
{
    omf_bytes           buf;
    long                len;
    int                 m;
    int                 location;
    int                 offset;
    int                 fmethod;
    omf_idx             fidx = 0;
    int                 thred;
    int                 tmethod;
    omf_idx             tidx;
    uint_8              datum;
    int                 wordsize;
    orl_sec_offset      displacement;

    assert( ofh );
    assert( buffer );
    assert( *buffer );
    assert( cur );
    assert( *cur > 0 );
    assert( **buffer & 0x80 );

    wordsize = OmfGetWordSize( is32 );

    buf = *buffer;
    len = *cur;

    datum = buf[0];
    m = ( datum & 0x40 ) != 0;
    location = ( datum >> 2 ) & 0x0f;
    offset = ( ( datum & 0x03 ) << 8 ) | buf[1];
    datum = buf[2];
    buf += 3;
    len -= 3;

    if( 0x80 & datum ) {
        thred = ( datum >> 4 ) & 0x03;
        fmethod = ofh->frame_thred[thred].method;
        fidx = ofh->frame_thred[thred].idx;
    } else {
        fmethod = ( datum >> 4 ) & 0x07;
        switch( fmethod ) {
        case( FRAME_SEG ):                  /* segment index                */
        case( FRAME_GRP ):                  /* group index                  */
        case( FRAME_EXT ):                  /* external index               */
            fidx = loadIndex( &buf, &len );
            break;
        case( FRAME_LOC ):                  /* frame containing location    */
        case( FRAME_ABS ):                  /* absolute frame number        */
        case( FRAME_TARG ):                 /* frame same as target         */
        case( FRAME_NONE ):                 /* no frame                     */
            fidx = 0;
            break;
        }
    }

    if( 0x08 & datum ) {
        thred = datum & 0x03;
        tmethod = ofh->target_thred[thred].method;
        tidx = ofh->target_thred[thred].idx;
    } else {
        tmethod = datum & 0x07;
        tidx = loadIndex( &buf, &len );
        if( fmethod == FRAME_TARG ) {
            /* fmethod becomes the same as tmethod (1 of first 3)
             */
            fmethod = tmethod & 0x03;
            fidx = tidx;
        }
    }

    if( datum & 0x04 ) {
        displacement = 0;
    } else {
        displacement = getUWord( buf, wordsize );
        buf += wordsize;
        len -= wordsize;
    }

    *buffer = buf;
    *cur = len;
    return( OmfAddFixupp( ofh, is32, m, location, offset, fmethod, fidx,
                          tmethod, tidx, displacement ) );
}


static orl_return       processThreadFixup( omf_file_handle ofh,
                                            omf_bytes *buffer, long *cur )
{
    omf_bytes           buf;
    long                len;
    int                 d;
    int                 method;
    int                 thred;
    uint_8              datum;
    omf_thred_fixup     *thredp;

    assert( ofh );
    assert( buffer );
    assert( *buffer );
    assert( cur );
    assert( *cur > 0 );
    assert( !( **buffer & 0x80 ) );

    buf = *buffer;
    len = *cur;

    datum = buf[0];
    d = ( datum & 0x40 ) != 0;
    method = ( datum >> 2 ) & 0x07;
    thred = datum & 0x03;
    buf++;
    len--;

    if( d ) {
        thredp = &ofh->frame_thred[thred];
    } else {
        thredp = &ofh->target_thred[thred];
    }

    thredp->method = method;

    /* If Index expected
     */
    if( !d || ( method < 3 ) ) {
        thredp->idx = loadIndex( &buf, &len );
    }

    *buffer = buf;
    *cur = len;
    return( ORL_OKAY );
}


static orl_return       doTHEADR( omf_file_handle ofh )
{
    orl_return  err;
    int         len;

    assert( ofh );

    err = loadRecord( ofh );
    if( err != ORL_OKAY ) return( err );
    if( ofh->modnamelen ) return( ORL_ERROR );
    len = ofh->parsebuf[0];
    if( len > ofh->parselen ) return( ORL_ERROR );
    memcpy( ofh->modname, ofh->parsebuf + 1, len );
    ofh->modname[len] = 0;
    ofh->modnamelen = len;
    return( ORL_OKAY );
}


static orl_return       doCOMENT( omf_file_handle ofh )
{
    orl_return          err;
    uint_8              class;
    uint_8              flags;
    omf_bytes           buffer;
    unsigned int        len;

    assert( ofh );

    err = loadRecord( ofh );
    if( err != ORL_OKAY ) return( err );

    buffer = ofh->parsebuf;
    len = ofh->parselen;
    flags = buffer[0];
    class = buffer[1];
    buffer += 2;
    if( len < 2 ) return( ORL_ERROR );
    len -= 2;

    err = OmfAddComment( ofh, class, flags, buffer, len );
    if( err != ORL_OKAY ) return( err );

    switch( class ) {
    case( CMT_WAT_PROC_MODEL ):
    case( CMT_MS_PROC_MODEL ):
        /* Determine CPU
         */
        if( !len ) break;
        switch( *buffer ) {
        case( '2' ):
        case( '0' ):
            /* 16 bit code
             */
            ofh->machine_type = ORL_MACHINE_TYPE_I8086;
            _SetWordSize( ofh->flags, ORL_FILE_FLAG_16BIT_MACHINE );
            break;
        case( '3' ):
        default:
            ofh->machine_type = ORL_MACHINE_TYPE_I386;
            _SetWordSize( ofh->flags, ORL_FILE_FLAG_32BIT_MACHINE );
            break;
        }

        /* we do not use any of the other info, so we don't look at it.
         * see dmpobj source code for format of this coment record
         */
        break;

⌨️ 快捷键说明

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