📄 omfload.c
字号:
/****************************************************************************
*
* 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 + -