omfreloc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 344 行
C
344 行
/****************************************************************************
*
* 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: OMFRELOC: routines specific processing relocations in OMF
*
****************************************************************************/
#include "linkstd.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "alloc.h"
#include "newmem.h"
#include "virtmem.h"
#include "reloc.h"
#include <pcobj.h>
#include <string.h>
#include "obj2supp.h"
#include "objnode.h"
#include "objio.h"
#include "overlays.h"
#include "objstrip.h"
#include "objomf.h"
#include "objpass2.h"
#include "ring.h"
#include "omfreloc.h"
typedef struct bakpatlist {
struct bakpatlist * next;
virt_mem addr;
unsigned_16 len;
byte loctype;
bool is32bit;
char data[1];
} bakpat_list;
static bakpat_list * BakPats;
#define MAX_THREADS 4
static frame_spec FrameThreads[MAX_THREADS];
static frame_spec TargThreads[MAX_THREADS];
static fix_type RelocTypeMap[] = {
FIX_OFFSET_8, // LOC_OFFSET_LO
FIX_OFFSET_16, // LOC_OFFSET
FIX_BASE, // LOC_BASE
FIX_BASE_OFFSET_16, // LOC_BASE_OFFSET
FIX_HIGH_OFFSET_8, // LOC_OFFSET_HI
FIX_OFFSET_32, // LOC_OFFSET_32
FIX_BASE_OFFSET_32, // LOC_BASE_OFFSET_32
FIX_OFFSET_16 | FIX_LOADER_RES // modified loader resolved off_16
};
static void GetTarget( unsigned loc, frame_spec *targ );
static void GetFrame( unsigned frame, frame_spec *refframe );
extern void ResetOMFReloc( void )
/*******************************/
{
BakPats = NULL;
}
extern void DoRelocs( void )
/**************************/
/* Process FIXUP records. */
{
fix_type fixtype;
unsigned typ;
unsigned omftype;
offset place_to_fix;
unsigned loc;
signed_32 addend;
frame_spec fthread;
frame_spec tthread;
if( ObjFormat & FMT_IGNORE_FIXUPP ) return;
if( ObjFormat & FMT_IS_LIDATA ) {
LnkMsg( LOC_REC+WRN+MSG_REL_IN_LIDATA, NULL );
return;
}
do {
typ = GET_U8_UN( ObjBuff );
++ObjBuff;
omftype = (typ >> 2) & 7;
if( (typ & 0x80) == 0 ) {/* thread */
if( typ & 0x40 ) {/* frame */
GetFrame( omftype, &FrameThreads[typ & 3] );
} else {/* target */
GetTarget( omftype, &TargThreads[typ & 3] );
}
} else { /* fixup */
if( typ & 0x20 ) { // used in 32-bit microsoft fixups.
switch( omftype ) {
case LOC_OFFSET:
case LOC_MS_LINK_OFFSET:
omftype = LOC_OFFSET_32;
break;
case LOC_BASE_OFFSET:
omftype = LOC_BASE_OFFSET_32;
break;
}
} else if( omftype == LOC_MS_LINK_OFFSET
&& !(ObjFormat & FMT_32BIT_REC) ) {
omftype = LOC_BASE_OFFSET_32 + 1; // index of special table.
}
fixtype = RelocTypeMap[omftype];
if( !(typ & 0x40) ) {
fixtype |= FIX_REL;
}
place_to_fix = ((typ & 3) << 8) + GET_U8_UN( ObjBuff );
++ObjBuff;
typ = *ObjBuff;
++ObjBuff;
loc = typ >> 4 & 7;
if( typ & 0x80 ) {
fthread = FrameThreads[loc & 3];
} else {
GetFrame( loc, &fthread );
}
loc = typ & 7;
if( typ & 8 ) {
tthread = TargThreads[loc & 3];
} else {
GetTarget( loc, &tthread );
}
addend = 0;
if( loc <= TARGET_ABSWD ) { /* if( (loc & 4) == 0 )then */
if( ObjFormat & FMT_32BIT_REC ) {
addend = *((signed_32 UNALIGN *)ObjBuff);
ObjBuff += sizeof( signed_32 );
} else {
addend = GET_U16_UN(ObjBuff);
ObjBuff += sizeof( unsigned_16 );
}
}
StoreFixup( place_to_fix, fixtype, &fthread, &tthread, addend );
}
} while( ObjBuff < EOObjRec );
}
static void GetFrame( unsigned frame, frame_spec *refframe )
/**********************************************************/
/* Get frame for fixup. */
{
extnode * ext;
grpnode * group;
segnode * seg;
unsigned index;
if( frame < FRAME_LOC ) {
index = GetIdx();
}
refframe->type = frame;
switch( frame ) {
case FRAME_SEG:
seg = (segnode *) FindNode( SegNodes, index );
refframe->u.sdata = seg->entry;
break;
case FRAME_GRP:
group = (grpnode *) FindNode( GrpNodes, index );
if( group->entry == NULL ) {
refframe->type = FIX_FRAME_FLAT;
} else {
refframe->u.group = group->entry;
}
break;
case FRAME_EXT:
ext = (extnode *) FindNode( ExtNodes, index );
if( IS_SYM_IMPORTED( ext->entry ) ) {
refframe->type = FIX_FRAME_TARG;
} else {
refframe->u.sym = ext->entry;
}
break;
case FRAME_TARG:
case FRAME_LOC:
break;
default:
BadObject();
}
}
static void GetTarget( unsigned loc, frame_spec *targ )
/*****************************************************/
{
extnode * ext;
grpnode * group;
segnode * seg;
targ->type = loc & 3;
switch( loc ) {
case TARGET_SEGWD:
case TARGET_SEG:
seg = (segnode *) FindNode( SegNodes, GetIdx() );
targ->u.sdata = seg->entry;
break;
case TARGET_GRPWD:
case TARGET_GRP:
group = (grpnode *) FindNode( GrpNodes, GetIdx() );
targ->u.group = group->entry;
break;
case TARGET_EXTWD:
case TARGET_EXT:
ext = (extnode *) FindNode( ExtNodes, GetIdx() );
targ->u.sym = ext->entry;
break;
case TARGET_ABSWD:
case TARGET_ABS:
_TargU16toHost( _GetU16UN( ObjBuff ), targ->u.abs );
ObjBuff += sizeof( unsigned_16 );
break;
}
}
static void StoreBakPat( segnode * seg, byte loctype )
/****************************************************/
/* store a bakpat record away for future processing. */
{
unsigned len;
bakpat_list * bkptr;
len = EOObjRec - ObjBuff;
_ChkAlloc( bkptr, sizeof(bakpat_list) + len - 1 );
bkptr->len = len;
bkptr->addr = seg->entry->data;
bkptr->loctype = loctype;
bkptr->is32bit = (ObjFormat & FMT_32BIT_REC) != 0;
memcpy( bkptr->data, ObjBuff, len );
LinkList( &BakPats, bkptr );
}
extern void ProcBakpat( void )
/****************************/
/* store the bakpat record away for future processing */
{
segnode * seg;
byte loctype;
seg = (segnode *) FindNode( SegNodes, GetIdx() );
if( seg->info & SEG_DEAD ) return;
loctype = *ObjBuff++;
StoreBakPat( seg, loctype );
}
extern void DoBakPats( void )
/***************************/
/* go through the list of stored bakpats and apply them all */
{
char * data;
bakpat_list * bkptr;
bakpat_list * next;
offset off;
offset value;
unsigned_8 value8;
unsigned_16 value16;
unsigned_32 value32;
virt_mem vmemloc;
bkptr = BakPats;
while( bkptr != NULL ) {
next = bkptr->next;
data = bkptr->data;
off = 0;
value = 0;
while( bkptr->len > 0 ) {
if( bkptr->is32bit ) {
_TargU32toHost( _GetU32( data ), off );
data += sizeof(unsigned_32);
_TargU32toHost( _GetU32( data ), value );
data += sizeof(unsigned_32);
bkptr->len -= 2 * sizeof(unsigned_32);
} else {
_TargU16toHost( _GetU16( data ), off );
data += sizeof(unsigned_16);
_TargU16toHost( _GetU16( data ), value );
data += sizeof(unsigned_16);
bkptr->len -= 2 * sizeof(unsigned_16);
}
vmemloc = bkptr->addr + off;
switch( bkptr->loctype ) {
case 0:
ReadInfo( vmemloc, &value8, sizeof(unsigned_8) );
value8 += value;
PutInfo( vmemloc, &value8, sizeof(unsigned_8) );
break;
case 1:
ReadInfo( vmemloc, &value16, sizeof(unsigned_16) );
value16 += value;
PutInfo( vmemloc, &value16, sizeof(unsigned_16) );
break;
case 2:
ReadInfo( vmemloc, &value32, sizeof(unsigned_32) );
value32 += value;
PutInfo( vmemloc, &value32, sizeof(unsigned_32) );
break;
}
}
_LnkFree( bkptr );
bkptr = next;
}
BakPats = NULL;
}
extern void ProcNbkpat( void )
/****************************/
/* process a named bakpat record */
{
list_of_names * symname;
symbol * sym;
segnode seg;
byte loctype;
loctype = *ObjBuff++;
symname = FindName( GetIdx() );
sym = RefISymbol( symname->name );
if( !IS_SYM_COMDAT(sym) ) return; /* can't handle these otherwise */
if( sym->info & SYM_DEAD ) return;
seg.entry = sym->p.seg;
StoreBakPat( &seg, loctype );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?