genmsomf.c

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

C
681
字号
/****************************************************************************
*
*                            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:  Microsoft style OMF output routines.
*
****************************************************************************/


#include <string.h>
#include "watcom.h"
#include "womp.h"
#include "objprs.h"
#include "objio.h"
#include "pcobj.h"
#include "memutil.h"
#include "genmsomf.h"
#include "genutil.h"
#include "myassert.h"
#include "msdbg.h"
#include "objrec.h"

#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
#include "lifix.h"
STATIC lifix_list   lifList;
#endif

STATIC int writeMisc( obj_rec *objr, pobj_state *state ) {
/*
    For 16-bit records which are the same under Intel, PharLap, and MS OMFs
*/
    uint_8  *ptr;
    uint_16 len;
    uint_16 save;

/**/myassert( objr != NULL );
/**/myassert( objr->data != NULL );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
    save = ObjRTell( objr );
    ObjRSeek( objr, 0 );
    len = ObjRemain( objr );
    ptr = ObjGet( objr, len );
    ObjWriteRec( state->file_out, objr->command, len, ptr );
    ObjRSeek( objr, save );
    return( 0 );
}

#ifndef _WOMP_WATFOR_8086
STATIC int writeMisc32( obj_rec *objr, pobj_state *state ) {
/*
    For 32-bit records which are the same under Intel, PharLap, and MS OMFs
*/
    uint_8  *ptr;
    uint_16 len;
    uint_8  cmd;
    uint_16 save;

/**/myassert( objr != NULL );
/**/myassert( objr->data != NULL );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
    save = ObjRTell( objr );
    ObjRSeek( objr, 0 );
    len = ObjRemain( objr );
    ptr = ObjGet( objr, len );
    cmd = objr->command;
    if( objr->is_32 || objr->is_phar ) {
        cmd |= 0x01;
    }
    ObjWriteRec( state->file_out, cmd, len, ptr );
    ObjRSeek( objr, save );
    return( 0 );
}
#endif

STATIC int writeComent( obj_rec *objr, pobj_state *state ) {

    uint_8  *ptr;
    uint_16 len;
    uint_16 save;
    OBJ_WFILE *out;

/**/myassert( objr != NULL );
/**/myassert( objr->data != NULL );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
    out = state->file_out;
    ObjWBegRec( out, CMD_COMENT );
    ObjWrite8( out, objr->d.coment.attr );
    ObjWrite8( out, objr->d.coment.class );
    save = ObjRTell( objr );
    len = ObjRemain( objr );
    ptr = ObjGet( objr, len );
    ObjWrite( out, ptr, len );
    ObjRSeek( objr, save );
    ObjWEndRec( out );
    return( 0 );
}

STATIC int writeSegdef( obj_rec *objr, pobj_state *state ) {

    OBJ_WFILE   *out;
    int         is32;
    uint_8      acbp;
    uint_8      align;
#if ( _WOMP_OPT & _WOMP_NASM )
    obj_offset  patch;
#endif

/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_SEGDEF );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
    out = state->file_out;
#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
    is32 = objr->d.segdef.use_32;
#else
  #ifdef _WOMP_WATFOR_8086
    is32 = 0;
  #else
    is32 = 1;
  #endif
#endif
    ObjWBegRec( out, is32 ? CMD_SEGD32 : CMD_SEGDEF );
    acbp = ( objr->d.segdef.combine << 2 ) | ( is32 != 0 );
    align = objr->d.segdef.align;
    switch( align ) {
    case SEGDEF_ALIGN_ABS:      acbp |= ALIGN_ABS << 5;     break;
    case SEGDEF_ALIGN_BYTE:     acbp |= ALIGN_BYTE << 5;    break;
    case SEGDEF_ALIGN_WORD:     acbp |= ALIGN_WORD << 5;    break;
    case SEGDEF_ALIGN_PARA:     acbp |= ALIGN_PARA << 5;    break;
    case SEGDEF_ALIGN_PAGE:     acbp |= ALIGN_PAGE << 5;    break;
    case SEGDEF_ALIGN_DWORD:    acbp |= ALIGN_DWORD << 5;   break;
    case SEGDEF_ALIGN_4KPAGE:
        acbp |= ALIGN_PAGE;
#if _WOMP_OPT & _WOMP_EXTRAS
        PrtMsg( WRN|MSG_MS386_NO_4KPAGE );
#endif
        break;
    default:
/**/    never_reach();
    }
    if( is32 == 0 && objr->d.segdef.seg_length == 0x10000 ) {
        acbp |= 0x02;   /* BIG bit */ /* FIXME no support for 2**32 */
    }
    ObjWrite8( out, acbp );
#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
    if( align == SEGDEF_ALIGN_ABS ) {
        // absolut segment has frame=word and offset=byte
        // it isn't fixupp physical reference
        // and don't depend on segment size (16/32bit)
        ObjWrite16( out, objr->d.segdef.abs.frame );
        ObjWrite8( out, objr->d.segdef.abs.offset );
    }
#endif
    if( is32 ) {
        #if ( _WOMP_OPT & _WOMP_NASM )
            patch = ObjWSkip32( out );
        #else
            ObjWrite32( out, objr->d.segdef.seg_length );
        #endif
    } else {
        #if ( _WOMP_OPT & _WOMP_NASM )
            patch = ObjWSkip16( out );
        #else
            ObjWrite16( out, objr->d.segdef.seg_length & 0xffff );
        #endif
    }
    #if ( _WOMP_OPT & _WOMP_NASM )
/**/    myassert( objr->data != NULL );
        memcpy( objr->data, &patch, sizeof patch);
    #endif

    ObjWriteIndex( out, objr->d.segdef.seg_name_idx );
    ObjWriteIndex( out, objr->d.segdef.class_name_idx );
#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
    ObjWriteIndex( out, objr->d.segdef.ovl_name_idx );
#if ( _WOMP_OPT & _WOMP_EXTRAS )
    if( objr->d.segdef.access_valid ) {
        PrtMsg( MSG_MS386_NO_ACCESS );
    }
#endif
#else
    ObjWriteIndex( out, 1 );
#endif
    ObjWEndRec( out );
    return( 0 );
}

#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
STATIC int writeFixup( obj_rec *objr, pobj_state *state ) {

    OBJ_WFILE   *out;
    int         is32;
    fixup       *walk;
    char        buf[ FIX_GEN_MAX ];
    size_t      len;
    size_t      len_written;

/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_FIXUP );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
    walk = objr->d.fixup.fixup;
    if( walk == NULL ) {
            /* huh? this shouldn't really happen... */
        return( 0 );
    }
    out = state->file_out;
    is32 = objr->is_32 || objr->is_phar;
    /* we don't want to write FIXUP records that are too large, so we limit
       our records to approximately 1024 bytes */
    do {
        len_written = 0;
        ObjWBegRec( out, is32 ? CMD_FIXU32 : CMD_FIXUP );
        while( walk != NULL && len_written < 1024 - FIX_GEN_MAX ) {
            walk->loc_offset += LifixDelta( &lifList, walk->loc_offset );
#if _WOMP_OPT & _WOMP_WOMP
            if( Can2MsOS2Flat() &&
                ( walk->loc_method == FIX_OFFSET386
                || walk->loc_method == FIX_POINTER386 ) ) {
                /* zap FIXUPs for OS/2 2.0 linker 21-mar-91 AFS */
                switch( walk->lr.frame ) {
                case FRAME_SEG:
                case FRAME_GRP:
                case FRAME_TARG:
                    walk->lr.frame = FRAME_GRP;
                    walk->lr.frame_datum = ObjFLATIndex;
                    break;
                }
            }
#endif
            len = FixGenFix( walk, buf, is32 ? FIX_GEN_MS386 : FIX_GEN_INTEL );
            ObjWrite( out, buf, len );
            walk = walk->next;
            len_written += len;
        }
        ObjWEndRec( out );
    } while( walk != NULL );
    return( 0 );
}
#endif

STATIC int writeLedata( obj_rec *objr, pobj_state *state ) {

    OBJ_WFILE   *out;
    uint_16     save;
    uint_8      *ptr;
    uint_16     len;
    int         is32;

/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_LEDATA );
/**/myassert( state != NULL );
/**/myassert( state->pass == POBJ_WRITE_PASS );
#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0
    LifixDestroy( &lifList );
    LifixInit( &lifList );
#endif
    out = state->file_out;
    is32 = ( objr->is_32 || objr->is_phar ) != 0;
    ObjWBegRec( out, is32 ? CMD_LEDA32 : CMD_LEDATA );
    ObjWriteIndex( out, objr->d.ledata.idx );
    if( is32 ) {
        ObjWrite32( out, objr->d.ledata.offset );
    } else {
        ObjWrite16( out, objr->d.ledata.offset );
    }
    save = ObjRTell( objr );
    len = ObjRemain( objr );
    ptr = ObjGet( objr, len );
/**/myassert( len <= 1024 );
    ObjWrite( out, ptr, len );
    ObjWEndRec( out );
    ObjRSeek( objr, save );
    return( 0 );
}

#if ( _WOMP_OPT & _WOMP_WATFOR ) == 0

STATIC void id32Block( obj_rec *objr, OBJ_WFILE *out, int_16 *delta,
    uint_16 first_block_offset ) {
/*
    Since LIDATAs are different under PharLap and MicroSoft 386 formats,
    we have to do some magic.
*/
    uint_16 rpt_count;
    uint_16 blk_count;
    uint_8  data_count;
    uint_8  *ptr;

    rpt_count = ObjGet16( objr );
    ObjWrite32( out, rpt_count );
    *delta += 2;    /* ok, everything from here on will be at +2 offset */
    LifixAdd( &lifList, ObjRTell( objr ) - first_block_offset, *delta );
    blk_count = ObjGet16( objr );
    ObjWrite16( out, blk_count );
    if( blk_count == 0 ) {
        data_count = ObjGet8( objr );
        ObjWrite8( out, data_count );
        ptr = ObjGet( objr, data_count );
        ObjWrite( out, ptr, data_count );
    } else {
        for( ; blk_count != 0; --blk_count ) {
            id32Block( objr, out, delta, first_block_offset );
        }
    }
}

STATIC int writeLidata( obj_rec *objr, pobj_state *state ) {

    OBJ_WFILE   *out;
    uint_16     save;
    uint_8      *ptr;
    uint_16     len;
    int         is32;

/**/myassert( objr != NULL );

⌨️ 快捷键说明

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