reloc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 498 行 · 第 1/2 页
C
498 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include "linkstd.h"
#include "alloc.h"
#include "reloc.h"
#include "fileio.h"
#include "spillio.h"
#include "loadfile.h"
#include "overlays.h"
typedef union {
unsigned long spill;
void * addr;
} spilladdr;
/* note: if either of these two structures get any bigger, the magic constants
* in the RLIDX_* macros will have to change to ensure that no allocation > 64k
* occurs. */
typedef struct reloc_info {
struct reloc_info * next;
unsigned sizeleft;
spilladdr loc;
} reloc_info;
typedef struct os2_reloc_header {
reloc_info * externals; /* external and segment style fixups */
reloc_info * internals; /* internal, non-segment fixups */
} os2_reloc_header;
#define RELOC_PAGE_SIZE 512
#define RELOC_SPILLED 0x8000
#define SIZELEFT_MASK 0x7FFF
unsigned FmtRelocSize;
reloc_info * FloatFixups;
extern void ResetReloc( void )
/****************************/
{
FloatFixups = NULL;
}
static reloc_info * AllocRelocInfo( void )
/****************************************/
/* allocate a relocation information block */
{
reloc_info * info;
_PermAlloc( info, sizeof( reloc_info ) ); /* allocate more */
info->sizeleft = RELOC_PAGE_SIZE;
_LnkAlloc( info->loc.addr, RELOC_PAGE_SIZE );
if( info->loc.addr == NULL ) {
info->loc.spill = SpillAlloc( RELOC_PAGE_SIZE );
info->sizeleft |= RELOC_SPILLED;
}
return( info );
}
static void * OS2PagedRelocInit( offset size, int unitsize )
/***************************************************************/
/* For some OS/2 formats we have to split up the structure off the grp_relocs
* field up into small bits to ensure that we don't get structure allocations
* > 64K. This is stored basically as a 2-d array */
{
void ** mem;
void ** start;
offset pageidx;
offset idxhigh;
unsigned idxlow;
unsigned allocsize;
pageidx = OSF_PAGE_COUNT( size );
idxhigh = OSF_RLIDX_HIGH( pageidx );
_PermAlloc( mem, ( idxhigh + 1 ) * sizeof( void * ) );
start = mem;
allocsize = OSF_RLIDX_MAX * unitsize;
while( idxhigh > 0 ) {
_ChkAlloc( *mem, allocsize );
memset( *mem, 0, allocsize );
mem++;
idxhigh--;
}
idxlow = OSF_RLIDX_LOW( pageidx );
if( idxlow != 0 ) {
allocsize = idxlow * unitsize;
_ChkAlloc( *mem, allocsize );
memset( *mem, 0, allocsize );
}
return( start );
}
static void * OS2FlatRelocInit( offset size )
/*******************************************/
/* initialize relocations for OS2 flat memory manager. */
{
return( OS2PagedRelocInit( size, sizeof( os2_reloc_header ) ) );
}
static void * PERelocInit( offset size )
/**************************************/
/* initialize relocations for PE executable format */
{
return( OS2PagedRelocInit( size, sizeof( reloc_info * ) ) );
}
static void DoWriteReloc( reloc_info **list, void *reloc, unsigned size )
/***********************************************************************/
{
reloc_info * info;
unsigned offset;
info = *list;
if( info == NULL ) {
info = AllocRelocInfo();
info->next = NULL;
*list = info;
}
if( ( info->sizeleft & SIZELEFT_MASK ) < size ) { /* if no space */
info = AllocRelocInfo();
info->next = *list;
*list = info;
}
offset = RELOC_PAGE_SIZE - ( info->sizeleft & SIZELEFT_MASK );
if( info->sizeleft & RELOC_SPILLED ) {
SpillWrite( info->loc.spill, offset, reloc, size );
} else {
memcpy( (char *)( info->loc.addr ) + offset, reloc, size );
}
info->sizeleft -= size;
}
extern void WriteReloc( group_entry *group, offset off, void *reloc,
unsigned size )
/******************************************************************/
/* write the given relocation to virtual memory */
{
os2_reloc_header ** pagelist;
reloc_info *** reloclist;
reloc_info ** header;
unsigned_32 idx;
if( FmtData.type & MK_PE ) {
reloclist = group->g.grp_relocs;
if( reloclist == NULL ) {
reloclist = PERelocInit( group->totalsize );
group->g.grp_relocs = reloclist;
}
idx = ( off - group->grp_addr.off ) >> OSF_PAGE_SHIFT;
header = &reloclist[OSF_RLIDX_HIGH( idx )][OSF_RLIDX_LOW( idx )];
DoWriteReloc( header, reloc, size );
} else if( FmtData.type & MK_OS2_FLAT ) {
pagelist = group->g.grp_relocs;
if( pagelist == NULL ) {
pagelist = OS2FlatRelocInit( group->totalsize );
group->g.grp_relocs = pagelist;
}
idx = ( off - group->grp_addr.off ) >> OSF_PAGE_SHIFT;
header = &pagelist[OSF_RLIDX_HIGH( idx )][OSF_RLIDX_LOW( idx )].externals;
switch( ((os2_flat_reloc_item *)reloc)->fmt.nr_flags & OSF_TARGET_MASK ) {
case INTERNAL_REFERENCE:
switch( ((os2_flat_reloc_item *)reloc)->fmt.nr_stype ) {
case OFFSET_ONLY:
case OFFSET48_ONLY:
case OFFSET48_RELATIVE:
//NYI: don't have to write this out if we can figure out
// how to tell the loader that we're doing it.
header =
&pagelist[OSF_RLIDX_HIGH( idx )][OSF_RLIDX_LOW( idx )].internals;
break;
}
break;
}
DoWriteReloc( header, reloc, size );
} else if( FmtData.type & ( MK_OS2_16BIT | MK_ELF ) ) {
DoWriteReloc( &group->g.grp_relocs, reloc, size );
} else {
DoWriteReloc( &group->section->reloclist, reloc, size );
}
group->section->relocs++;
}
#ifdef _QNXLOAD
extern void FloatReloc( reloc_item * item )
/****************************************/
{
DoWriteReloc( &FloatFixups, item, sizeof( qnx_reloc_item ) );
}
extern void QNXLinearReloc( group_entry * group, reloc_item * item )
/******************************************************************/
{
DoWriteReloc( &group->g.grp_relocs, item, sizeof( qnx_linear_item ) );
}
#endif
static bool FreeRelocList( reloc_info * list )
/********************************************/
/* free any reloc blocks pointed to by list */
{
while( list != NULL ) {
if( !( list->sizeleft & RELOC_SPILLED ) ) {
_LnkFree( list->loc.addr );
}
list = list->next;
}
return( FALSE ); /* needed for OS2 generic traversal routines */
}
static void FreeRelocSect( section *sect )
/****************************************/
{
FreeRelocList( sect->reloclist );
}
static bool TraverseRelocBlock( reloc_info ** reloclist, unsigned num,
bool (*fn)( reloc_info * ) )
/********************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?