📄 omfmunge.c
字号:
static orl_return addToSymbolTable( omf_file_handle ofh,
omf_symbol_handle sym )
{
omf_sec_handle sh;
assert( ofh );
assert( sym );
sh = ofh->symbol_table;
if( !sh ) {
sh = newSection( ofh, OMF_SEC_SYM_TABLE_INDEX, ORL_SEC_TYPE_SYM_TABLE );
if( !sh ) return( ORL_OUT_OF_MEMORY );
ofh->symbol_table = sh;
sh->flags |= ORL_SEC_FLAG_REMOVE;
sh->assoc.sym.hash_tab = ORLHashTableCreate( ofh->omf_hnd->funcs, 257,
ORL_HASH_STRING,
(orl_hash_comparison_func)stricmp );
if( !sh->assoc.sym.hash_tab ) return( ORL_OUT_OF_MEMORY );
}
assert( sh->assoc.sym.hash_tab );
sh->assoc.sym.syms = checkArraySize( ofh, sh->assoc.sym.syms,
sh->assoc.sym.num, STD_INC,
sizeof( omf_symbol_handle ) );
if( !sh->assoc.sym.syms ) return( ORL_OUT_OF_MEMORY );
sh->assoc.sym.syms[sh->assoc.sym.num] = sym;
sh->assoc.sym.num++;
return( ORLHashTableInsert( sh->assoc.sym.hash_tab,
(orl_hash_value)sym->name, sym ) );
}
static orl_return addReloc( omf_file_handle ofh, omf_reloc_handle orh )
{
omf_sec_handle sh;
assert( ofh );
assert( orh );
if( !ofh->relocs ) {
ofh->relocs = newSection( ofh, OMF_SEC_RELOC_INDEX,
ORL_SEC_TYPE_RELOCS );
if( !ofh->relocs ) return( ORL_OUT_OF_MEMORY );
ofh->relocs->flags |= ORL_SEC_FLAG_REMOVE;
}
sh = ofh->relocs;
sh->assoc.reloc.relocs = checkArraySize( ofh, sh->assoc.reloc.relocs,
sh->assoc.reloc.num, STD_INC,
sizeof( omf_reloc_handle ) );
if( !sh->assoc.reloc.relocs ) return( ORL_OUT_OF_MEMORY );
sh->assoc.reloc.relocs[sh->assoc.reloc.num] = orh;
sh->assoc.reloc.num++;
return( ORL_OKAY );
}
static omf_tmp_fixup findMatchingFixup( omf_tmp_fixup tf, int lo, int hi )
{
if( hi < lo ) {
hi = lo;
}
while( tf ) {
if( ( tf->offset >= lo ) && ( tf->offset <= hi ) ) break;
tf = tf->next;
}
return( tf );
}
static orl_return writeAndFixupLIData( omf_file_handle ofh,
omf_sec_handle sh,
omf_bytes buffer )
{
int wordsize;
long tmp;
uint_32 repeat;
long block;
int size;
int used;
int hi;
int lo;
omf_bytes ptr;
orl_return err = ORL_OKAY;
omf_tmp_fixup ftr;
omf_tmp_fixup ntr;
int x;
assert( ofh );
assert( ofh->lidata );
assert( sh );
assert( sh->contents );
assert( buffer );
if( ofh->status & OMF_STATUS_EASY_OMF ) {
wordsize = OmfGetWordSize( 0 );
} else {
wordsize = OmfGetWordSize( ofh->lidata->is32 );
}
tmp = wordsize + 2;
if( ofh->lidata->size < tmp ) return( ORL_ERROR );
used = ofh->lidata->used;
size = ofh->lidata->size;
ptr = buffer + used;
repeat = getUWord( ptr, wordsize );
ptr += wordsize;
block = getUWord( ptr, 2 );
ptr += 2;
lo = used;
hi = lo + tmp;
size -= tmp;
used += tmp;
if( findMatchingFixup( ofh->lidata->first_fixup, lo, hi ) ) {
return( ORL_ERROR );
} else if( block ) {
while( repeat ) {
repeat--;
ofh->lidata->used = used;
ofh->lidata->size = size;
for( x = 0; x < block; x++ ) {
err = writeAndFixupLIData( ofh, sh, buffer );
if( err != ORL_OKAY ) break;
}
}
} else {
tmp = *ptr;
ptr++;
used++;
size--;
lo = used;
hi = used + tmp - 1;
while( repeat ) {
buffer = sh->contents + sh->assoc.seg.cur_offset;
memcpy( buffer, ptr, tmp );
/* create appropriate fixup records
*/
ftr = findMatchingFixup( ofh->lidata->first_fixup, lo, hi );
while( ftr ) {
ntr = _ClientAlloc( ofh, sizeof( omf_tmp_fixup_struct ) );
if( !ntr ) return( ORL_OUT_OF_MEMORY );
memcpy( ntr, ftr, sizeof( omf_tmp_fixup_struct ) );
/* determine new offset as if this was an LEData we were
* doing a fixup for
*/
ntr->offset = ofh->lidata->offset - used + ftr->offset;
/* insert into new fixup queue
*/
if( ofh->lidata->new_fixup ) {
ofh->lidata->last_fixup->next = ntr;
} else {
ofh->lidata->new_fixup = ntr;
}
ofh->lidata->last_fixup = ntr;
ftr = findMatchingFixup( ftr->next, lo, hi );
}
ofh->lidata->offset += tmp;
sh->assoc.seg.cur_offset += tmp;
repeat--;
}
ofh->lidata->size = size - tmp;
ofh->lidata->used = used + tmp;
err = ORL_OKAY;
}
return( err );
}
static orl_return expandPrevLIData( omf_file_handle ofh )
{
omf_sec_handle sh;
int size;
omf_bytes buffer;
orl_return err = ORL_OKAY;
unsigned char tmp[1024];
omf_tmp_fixup ftr;
orl_sec_offset offset;
assert( ofh );
assert( ofh->work_sec );
assert( ofh->lidata );
sh = ofh->work_sec;
size = ofh->lidata->size;
if( size > 1024 ) {
buffer = _ClientAlloc( ofh, size );
if( !buffer ) return( ORL_OUT_OF_MEMORY );
} else {
buffer = tmp;
}
/* we must remember to save the current offset of the lidata and then
* restore it
*/
ofh->lidata->last_fixup = NULL;
offset = sh->assoc.seg.cur_offset;
/* make a working copy of the LIDATA
*/
memcpy( buffer, sh->contents + offset, size );
while( ofh->lidata->size > 0 ) {
err = writeAndFixupLIData( ofh, sh, buffer );
if( err != ORL_OKAY ) return( err );
}
sh->assoc.seg.cur_offset = offset;
if( size > 1024 ) {
_ClientFree( ofh, buffer );
}
assert( !( ofh->status & OMF_STATUS_ADD_MASK ) );
/* Destroy original fixups
*/
while( ofh->lidata->first_fixup ) {
ftr = ofh->lidata->first_fixup;
ofh->lidata->first_fixup = ftr->next;
_ClientFree( ofh, ftr );
}
/* Add the generated fixups
*/
while( ofh->lidata->new_fixup ) {
ftr = ofh->lidata->new_fixup;
err = OmfAddFixupp( ofh, ftr->is32, ftr->mode, ftr->location,
ftr->offset, ftr->fmethod, ftr->fidx, ftr->tmethod,
ftr->tidx, ftr->disp );
if( err != ORL_OKAY ) break;
ofh->lidata->new_fixup = ftr->next;
_ClientFree( ofh, ftr );
}
ofh->lidata->last_fixup = NULL;
return( err );
}
static orl_return finishPrevWork( omf_file_handle ofh )
{
orl_return err = ORL_OKAY;
assert( ofh );
if( ofh->status & OMF_STATUS_ADD_LIDATA ) {
ofh->status &= ~OMF_STATUS_ADD_LIDATA;
err = expandPrevLIData( ofh );
}
assert( !( ofh->status & OMF_STATUS_ADD_MASK ) );
return( err );
}
static orl_sec_offset calcLIDataLength( int is32, omf_bytes *input, int *len )
{
int size;
omf_bytes buffer;
int wordsize;
long tmp;
uint_32 repeat;
long block;
long result = 0;
assert( input );
assert( *input );
assert( len );
buffer = *input;
size = *len;
wordsize = OmfGetWordSize( is32 );
tmp = wordsize + 2;
if( size < tmp ) return( 0 );
repeat = getUWord( buffer, wordsize );
buffer += wordsize;
block = getUWord( buffer, 2 );
buffer += 2;
size -= tmp;
if( block ) {
while( block ) {
tmp = calcLIDataLength( is32, &buffer, &size );
if( !tmp ) return( 0 );
result += tmp;
block--;
}
} else {
result = buffer[0];
size -= ( result + 1 );
if( size < 0 ) return( 0 );
buffer += result + 1;
}
result *= repeat;
*input = buffer;
*len = size;
return( result );
}
static orl_return checkSegmentLength( omf_sec_handle sh, uint_32 max )
{
omf_bytes conts;
assert( sh );
if( max > sh->size ) return( ORL_ERROR );
if( max > sh->assoc.seg.cur_size ) {
max = ( max / STD_CODE_SIZE ) + 1;
max *= STD_CODE_SIZE;
conts = _ClientAlloc( sh->omf_file_hnd, max );
if( !conts ) return( ORL_OUT_OF_MEMORY );
memset( conts, 0, max );
if( sh->contents ) {
memcpy( conts, sh->contents, sh->assoc.seg.cur_size );
_ClientFree( sh->omf_file_hnd, sh->contents );
}
sh->contents = conts;
sh->assoc.seg.cur_size = max;
}
return( ORL_OKAY );
}
static omf_bytes strNUpper( omf_bytes buffer, int len )
{
assert( buffer );
len--;
while( len >= 0 ) {
buffer[ len ] = toupper( buffer[ len ] );
len--;
}
return( buffer );
}
static orl_sec_flags getSegSecFlags( omf_file_handle ofh, omf_idx name,
omf_idx class, orl_sec_alignment align,
int combine, int use32 )
{
char lname[257];
int slen;
orl_sec_flags flags = 0;
align = align; combine = combine;
assert( ofh );
slen = OmfGetLName( ofh->lnames, class, lname );
if( slen > 0 ) {
lname[slen] = '\0';
strNUpper( lname, slen );
if( ( slen > 3 ) &&
( !strcmp( "CODE", &lname[slen - 4] ) ||
!strcmp( "TEXT", &lname[slen - 4] ) ) ) {
flags |= ORL_SEC_FLAG_EXEC | ORL_SEC_FLAG_EXECUTE_PERMISSION |
ORL_SEC_FLAG_READ_PERMISSION;
} else if( ( slen > 3 ) && !strcmp( "DATA", &lname[slen - 4] ) ) {
flags |= ORL_SEC_FLAG_READ_PERMISSION;
slen = OmfGetLName( ofh->lnames, name, lname );
if( slen > 0 ) {
lname[slen] = '\0';
strNUpper( lname, slen );
if( strstr( "CONST", lname ) ) {
flags |= ORL_SEC_FLAG_INITIALIZED_DATA;
}
}
} else if( ( slen > 4 ) && !strcmp( "CONST", &lname[slen - 5] ) ) {
flags |= ORL_SEC_FLAG_READ_PERMISSION |
ORL_SEC_FLAG_INITIALIZED_DATA;
} else if( ( slen > 2 ) && !strcmp( "BSS", &lname[slen - 3] ) ) {
flags |= ORL_SEC_FLAG_READ_PERMISSION |
ORL_SEC_FLAG_WRITE_PERMISSION |
ORL_SEC_FLAG_UNINITIALIZED_DATA;
} else if( ( slen > 4 ) && !strcmp( "STACK", &lname[slen - 5] ) ) {
flags |= ORL_SEC_FLAG_READ_PERMISSION |
ORL_SEC_FLAG_WRITE_PERMISSION |
ORL_SEC_FLAG_UNINITIALIZED_DATA;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -