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 + -
显示快捷键?