obj2supp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,658 行 · 第 1/4 页
C
1,658 行
if( fix.imported ) {
/*
Under PE, the imported symbol address is set to the
transfer code (JMP [xxxxx]) that is generated by the linker.
*/
fix.tgt_addr = targ->u.sym->addr;
fix.imported = FALSE;
}
}
Relocate( save, &fix, targ );
}
extern unsigned IncExecRelocs( void *_save )
/******************************************/
{
save_fixup *save = _save;
segdata * sdata;
frame_spec targ;
frame_spec frame;
if( save->flags & FIX_CHANGE_SEG ) {
sdata = (segdata *)( save->flags & ~FIX_CHANGE_SEG );
if( LinkFlags & INC_LINK_FLAG ) {
save->flags = (unsigned_32) CarveGetIndex( CarveSegData, sdata );
save->flags |= FIX_CHANGE_SEG;
}
if( !sdata->isdead ) {
LoadObj( sdata );
LastSegData = sdata;
} else {
LastSegData = NULL;
}
} else {
targ.type = FIX_GET_TARGET( save->flags );
targ.u.ptr = save->target;
frame.type = FIX_GET_FRAME( save->flags );
if( FRAME_HAS_DATA( frame.type ) ) {
frame.u.ptr = *((void **)( save + 1 ));
}
UpdateFramePtr( &targ );
UpdateFramePtr( &frame );
if( LastSegData != NULL ) {
BuildReloc( save, &targ, &frame );
}
if( LinkFlags & INC_LINK_FLAG ) {
MapFramePtr( &targ, &save->target );
MapFramePtr( &frame, (void **)( save + 1 ) );
}
}
return( CalcSavedFixSize( save->flags ) );
}
static void FixFrameValue( frame_type type, void **target )
/*********************************************************/
{
switch( type ) {
case FIX_FRAME_SEG:
*target = CarveMapIndex( CarveSegData, *target );
break;
case FIX_FRAME_EXT:
*target = CarveMapIndex( CarveSymbol, *target );
break;
}
}
extern unsigned RelocMarkSyms( void *_fix )
/*****************************************/
{
save_fixup *fix = _fix;
segdata * sdata;
frame_type frame;
symbol * sym;
if( fix->flags & FIX_CHANGE_SEG ) {
sdata = CarveMapIndex( CarveSegData,
(void *)( fix->flags & ~FIX_CHANGE_SEG ) );
fix->flags = (unsigned_32) sdata | FIX_CHANGE_SEG;
} else {
frame = FIX_GET_FRAME( fix->flags );
if( FRAME_HAS_DATA( frame ) ) {
FixFrameValue( frame, (void **)( fix + 1 ) );
}
frame = FIX_GET_TARGET( fix->flags );
FixFrameValue( frame, &fix->target );
if( frame == FIX_FRAME_EXT ) {
sym = (symbol *)fix->target;
sym->info |= SYM_RELOC_REFD;
sym = UnaliasSym( ST_FIND, sym );
sym->info |= SYM_RELOC_REFD;
}
}
return( CalcSavedFixSize( fix->flags ) );
}
static bool MemIsZero( char *mem, unsigned size )
/***********************************************/
{
while( size > 0 ) {
if( *mem != '\0' )
return( FALSE );
mem++;
size--;
}
return( TRUE );
}
extern void StoreFixup( offset off, fix_type type, frame_spec *frame,
frame_spec *targ, offset addend )
/*******************************************************************/
{
save_fixup save;
fix_data fix;
unsigned size;
char buff[2 * sizeof( unsigned_32 )];
if( LastSegData != CurrRec.seg ) {
DbgAssert( CurrRec.seg != NULL );
LastSegData = CurrRec.seg;
save.flags = (unsigned_32) CurrRec.seg;
save.flags |= FIX_CHANGE_SEG; // DANGER! assume pointers word aligned
PermSaveFixup( &save, sizeof( unsigned_32 ) );
}
save.flags = type;
save.flags |= (unsigned_32)targ->type << FIX_TARGET_SHIFT;
save.flags |= (unsigned_32)frame->type << FIX_FRAME_SHIFT;
save.off = off + CurrRec.obj_offset;
save.target = targ->u.ptr;
if( ObjFormat & FMT_UNSAFE_FIXUPP ) {
save.flags |= FIX_UNSAFE;
}
size = CalcFixupSize( type );
if( CurrRec.data != NULL ) {
memcpy( buff, CurrRec.data + off, size );
} else {
ReadInfo( CurrRec.seg->data + save.off, buff, size );
}
fix.type = type;
fix.data = buff;
if( ( type & ( FIX_OFFSET_MASK | FIX_HIGH ) ) == FIX_HIGH_OFFSET_16 ) {
addend += FixupOverflow << 16;
}
PatchOffset( &fix, addend, TRUE );
if( MemIsZero( buff, size ) ) {
save.flags |= FIX_ADDEND_ZERO;
}
PermSaveFixup( &save, sizeof( save_fixup ) );
if( FRAME_HAS_DATA( frame->type ) ) {
PermSaveFixup( &frame->u.abs, sizeof( unsigned_32 ) );
}
if( !( save.flags & FIX_ADDEND_ZERO ) ) {
PermSaveFixup( buff, CalcAddendSize( save.flags ) );
}
TraceFixup( save.flags, targ );
if( CurrRec.data != NULL ) {
memcpy( CurrRec.data + off, buff, size );
} else {
PutInfo( CurrRec.seg->data + save.off, buff, size );
}
}
extern unsigned IncSaveRelocs( void *_save )
/******************************************/
{
save_fixup *save = _save;
segdata * sdata;
frame_spec targ;
unsigned fixsize;
unsigned datasize;
char * data;
fixsize = CalcSavedFixSize( save->flags );
if( save->flags & FIX_CHANGE_SEG ) {
sdata = (segdata *)( save->flags & ~FIX_CHANGE_SEG );
if( !sdata->isdead ) {
LastSegData = sdata;
} else {
LastSegData = NULL;
}
} else if( LastSegData != NULL ) {
targ.type = FIX_GET_TARGET( save->flags );
targ.u.ptr = save->target;
datasize = CalcFixupSize( save->flags );
if( save->flags & FIX_ADDEND_ZERO ) {
PutNulls( LastSegData->data + save->off, datasize );
} else {
data = (char *)save + ( fixsize - CalcAddendSize( save->flags ) );
PutInfo( LastSegData->data + save->off, data, datasize );
}
TraceFixup( save->flags, &targ );
}
PermSaveFixup( save, fixsize );
return( fixsize );
}
static void DumpReloc( base_reloc *curr )
/***************************************/
{
if( curr->isfloat ) {
FloatReloc( &curr->item );
} else if( curr->isqnxlinear ) {
QNXLinearReloc( CurrRec.seg->u.leader->group, &curr->item );
} else {
WriteReloc( CurrRec.seg->u.leader->group, curr->fix_off,
&curr->item, curr->rel_size );
if( FmtData.type & MK_OS2_FLAT ) {
if( OSF_PAGE_SIZE - ( curr->fix_off & OSF_PAGE_MASK ) < curr->fix_size ) {
/* stupid relocation has been split across two
pages, have to duplicate the entry */
curr->item.os2f.fmt.r32_soff -= OSF_PAGE_SIZE;
WriteReloc( CurrRec.seg->u.leader->group,
curr->fix_off + OSF_PAGE_SIZE, &curr->item,
curr->rel_size );
}
}
}
}
static void InitReloc( base_reloc *reloc )
/****************************************/
{
reloc->isfloat = FALSE;
reloc->isqnxlinear = FALSE;
reloc->rel_size = FmtRelocSize;
}
static unsigned FindGroupIdx( segment seg )
/******************************************/
{
group_entry *group;
unsigned index;
index = 1;
for( group = Groups; group != NULL; group = group->next_group ) {
if( group->grp_addr.seg == seg ) {
return( index );
}
index++;
}
return( 0 );
}
static void PatchOffset( fix_data *fix, unsigned_32 val, bool isdelta )
/*********************************************************************/
/* patch offsets into the loaded object */
{
byte * code;
unsigned_32 oldval;
signed_32 sval;
FixupOverflow = 0;
if( val == 0 )
return;
code = fix->data;
if( fix->type & FIX_SHIFT ) {
if( val & 3 ) {
LnkMsg( LOC+WRN+MSG_REL_NOT_ALIGNED, "a", &fix->loc_addr );
}
val >>= 2;
}
switch( fix->type & FIX_OFFSET_MASK ) {
case FIX_OFFSET_8:
if( fix->type & FIX_HIGH ) {
val >>= 8;
}
PUT_U8( code, GET_U8( code ) + val );
break;
case FIX_OFFSET_16:
if( fix->type & FIX_HIGH ) {
val >>= 16;
} // NOTE the fall through
case FIX_NO_OFFSET: // used for FIX_BASE
if( fix->type & FIX_SIGNED ) {
if( isdelta ) {
sval = (signed_32)GET_S16( code ) + val;
val = sval;
if( sval > 0x7FFF ) {
val = val & 0xFFFF;
if( val > 0x7FFF ) {
FixupOverflow = 1;
val -= 0x10000;
}
}
} else {
oldval = val;
sval = (signed_32)GET_S16( code );
val += sval;
if( ( oldval >> 16 ) < ( val >> 16 ) ) {
FixupOverflow = 1;
} else if( ( fix->type & FIX_SIGNED )
&& ( oldval >> 16 ) == ( val >> 16 )
&& ( (signed_16)( val & 0xFFFF ) < 0 ) ) {
FixupOverflow = 1;
}
}
} else {
val += GET_U16( code );
}
PUT_U16( code, val );
break;
case FIX_OFFSET_21:
oldval = GET_U32( code );
val += oldval;
oldval &= 0xFFE00000;
val &= 0x001FFFFF;
PUT_U32( code, oldval | val );
break;
case FIX_OFFSET_26: // Processing is the same, except FIX_OFFSET_26
case FIX_OFFSET_24: // uses FIX_SHIFT (it's really a 28-bit offset)
oldval = GET_U32( code );
val += oldval;
oldval &= 0xFC000000;
val &= 0x03FFFFFF;
PUT_U32( code, oldval | val );
break;
case FIX_OFFSET_32:
PUT_U32( code, GET_U32( code ) + val );
break;
default:
LnkMsg( LOC+ERR+MSG_BAD_RELOC_TYPE, NULL );
}
}
static void MakeQNXFloatReloc( fix_data *fix )
/********************************************/
{
base_reloc new_reloc;
if( FmtData.u.qnx.gen_seg_relocs ) {
InitReloc( &new_reloc );
new_reloc.isfloat = TRUE;
new_reloc.item.qnx.reloc_offset = fix->loc_addr.off
| ( (unsigned_32)fix->ffix << 28 );
new_reloc.item.qnx.segment = ToQNXIndex( fix->loc_addr.seg );
DumpReloc( &new_reloc );
}
}
static byte WinFFixMap[] = {
0,
WIN_FFIX_WR_SYMBOL,
WIN_FFIX_DR_SYMBOL,
WIN_FFIX_ES_OVERRIDE,
WIN_FFIX_CS_OVERRIDE,
WIN_FFIX_SS_OVERRIDE,
WIN_FFIX_DS_OVERRIDE
};
static void MakeWindowsFloatReloc( fix_data *fix )
/************************************************/
{
base_reloc new_reloc;
os2_reloc_item * os2item;
InitReloc( &new_reloc );
os2item = &new_reloc.item.os2;
os2item->addr_type = MapOS2FixType( fix->type );
os2item->reloc_offset = fix->loc_addr.off
- CurrRec.seg->u.leader->group->grp_addr.off;
os2item->reloc_type = OSFIXUP | ADDITIVE;
os2item->put.fltpt = WinFFixMap[ fix->ffix ];
DumpReloc( &new_reloc );
}
static offset GetSegOff( segdata *sdata )
/***************************************/
{
return( sdata->a.delta + sdata->u.leader->seg_addr.off );
}
static void CheckPartialRange( fix_data *fix, signed_32 off,
unsigned_32 mask, unsigned_32 topbit )
/*******************************************************************/
{
unsigned_32 utemp;
signed_32 temp;
utemp = GET_U32( fix->data ) & mask;
if( utemp & topbit ) { // it is negative
utemp |= ~mask; // do a bogus sign extension
}
temp = utemp;
if( fix->type & FIX_SHIFT ) {
temp += off / 4;
} else {
temp += off;
}
if( ( temp < -topbit ) || ( temp >= topbit ) ) {
LnkMsg( LOC+ERR+MSG_FIXUP_OFF_RANGE, "a", &fix->loc_addr );
}
}
static bool CheckSpecials( fix_data *fix, frame_spec *targ )
/**********************************************************/
{
signed_32 off;
unsigned_32 uoff;
signed_32 temp;
signed_32 pos;
unsigned fixsize;
group_entry *group;
segdata * sdata;
fix_type special;
if( FmtData.type & MK_ELF ) {
if( !( fix->type & FIX_REL ) )
return( FALSE );
#if 0
XXX: this is not the right thing to do for elf-i386
if( fix->loc_addr.seg != fix->tgt_addr.seg )
return( FALSE );
#endif
}
if( ( FmtData.type & ( MK_QNX | MK_WINDOWS ) )
&& ( fix->ffix != FFIX_NOT_A_FLOAT ) ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?