toc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 339 行
C
339 行
/****************************************************************************
*
* 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!
*
****************************************************************************/
/*
* toc.c: Keep track of table of contents for NT PPC or of
global offset table (GOT) for OS/2 PPC
*/
#include <string.h>
#include "linkstd.h"
#include "toc.h"
#include "hash.h"
#include "alloc.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "reloc.h"
#include "obj2supp.h"
#include "loadpe.h"
#include "loadfile.h"
#include "specials.h"
#include "objpass1.h"
#include "objstrip.h"
#define BOGUS 0xa5a5a5a5
static pHTable Toc;
static char * TocName;
static symbol * TocSym;
offset TocSize;
offset TocShift;
typedef struct {
segdata *sdata; // If sdata == NULL, use sym to get address
// else use off and sdata->addr get address
union {
offset off; // relative to sdata->addr
symbol * sym;
};
} TocEntryId;
typedef struct {
TocEntryId e;
int pos;
} TocEntry;
extern void ResetToc( void )
/**************************/
{
Toc = NULL;
TocSize = 0;
TocName = NULL;
TocSym = NULL;
}
extern void CleanToc( void )
/**************************/
{
ZapHTable(Toc, LFree);
}
static unsigned TocEntryHashFunc( void *_e, unsigned size )
/*********************************************************/
{
TocEntry *e = _e;
return DataHashFunc(&e->e, sizeof e->e, size);
}
static int TocEntryCmp( const void *_e1, const void *_e2 )
/********************************************************/
{
const TocEntry *e1 = _e1;
const TocEntry *e2 = _e2;
return memcmp(&e1->e, &e2->e, sizeof e1->e);
}
extern void InitToc(void)
/***********************/
{
Toc = CreateHTable( 1024, TocEntryHashFunc, TocEntryCmp, ChkLAlloc, LFree );
TocSize = 0;
if( IS_PPC_PE ) {
TocName = TocSymName;
TocShift = 0x8000;
} else {
TocName = GotSymName;
TocShift = BOGUS;
// It is an error to use TocShift until PrepareToc is called
}
}
extern void CheckIfTocSym( symbol *sym )
/**************************************/
{
if( TocName != NULL && TocSym == NULL ) {
if( strcmp(sym->name, TocName) == 0 ) {
TocSym = sym;
}
}
}
extern bool IsTocSym( symbol *sym )
/*********************************/
{
return TocSym == sym;
}
static void AddToToc( TocEntryId *e )
/***********************************/
{
TocEntry searchEntry;
TocEntry * entry;
searchEntry.e = *e;
if( FindHTableElem(Toc, &searchEntry) == NULL ) {
entry = ChkLAlloc(sizeof *entry);
entry->e = *e;
entry->pos = TocSize;
TocSize += sizeof(offset);
AddHTableElem(Toc, entry);
}
}
extern void AddSymToToc( symbol *sym )
/************************************/
{
TocEntryId e;
e.sdata = NULL;
e.sym = sym;
AddToToc(&e);
}
extern void AddSdataOffToToc( segdata *sdata, offset off )
/********************************************************/
{
TocEntryId e;
DbgAssert( sdata != NULL );
e.sdata = sdata;
e.off = off;
AddToToc(&e);
}
static void ConvertTocEntryId( TocEntryId *e )
/********************************************/
{
if( e->sdata != NULL ) {
// do nothing: already in sdata/offset form
} else {
symbol *sym = e->sym;
segdata *seg = sym->p.seg;
if( IS_SYM_IMPORTED(sym) || seg == NULL ) {
// do not convert; keep symbol around
} else {
e->sdata = seg;
e->off = sym->addr.off - seg->a.delta -
seg->u.leader->seg_addr.off;
}
}
return;
}
static void ConvertTocEntry( void *e)
/***********************************/
{
ConvertTocEntryId(&((TocEntry *)e)->e);
}
#define GOT_RESERVED_NEG_SIZE (2* sizeof(long))
#define GOT_RESERVED_POS0_SIZE (3* sizeof(long))
#define GOT_RESERVED_SIZE (GOT_RESERVED_NEG_SIZE+GOT_RESERVED_POS0_SIZE)
#if 0 // OS/2 PPC development temporarly on hold
static void AdjustGotEntry( TocEntry *e, offset *middle) {
if( e->pos < *middle) {
e->pos -= GOT_RESERVED_NEG_SIZE;
} else {
e->pos += GOT_RESERVED_POS0_SIZE;
}
}
#endif
extern void PrepareToc( void )
/****************************/
{
if( Toc == NULL ) return;
WalkHTable(Toc, ConvertTocEntry);
RehashHTable(Toc);
if( IS_PPC_OS2 ) {
// Development temporarly on hold
#if 0
offset middle = (TocSize/2) & ~0x3;
WalkHTableCookie(Toc, AdjustGotEntry, &middle);
TocShift = middle+GOT_RESERVED_NEG_SIZE;
TocSize += GOT_RESERVED_SIZE;
#endif
}
if( TocSym != NULL) {
TocSym->info |= SYM_DCE_REF|SYM_DEFINED;
SetAddPubSym( TocSym, SYM_REGULAR, FakeModule, 0, 0 );
if( LinkFlags & STRIP_CODE ) {
CleanStripInfo( TocSym );
}
}
}
extern void SetTocAddr( offset off, group_entry *group )
/******************************************************/
{
if( Toc == NULL || TocSym == NULL ) return;
XDefSymAddr( TocSym, off + TocShift, group->grp_addr.seg );
}
static signed_32 OffFromToc( offset off )
/***************************************/
{
offset toff;
toff = off - TocShift;
if( ((signed_16) toff) != (signed_32) toff ) {
LnkMsg( ERR+MSG_TOC_TOO_BIG, NULL );
}
return toff;
}
extern signed_32 FindEntryPosInToc( TocEntryId *e )
/*************************************************/
{
TocEntry searchEntry;
TocEntry * entry;
searchEntry.e = *e;
entry = FindHTableElem(Toc, &searchEntry);
if (entry != NULL) {
return OffFromToc(entry->pos);
} else {
return BOGUS; // return bogus position; likely to cause alignment exception
}
}
extern signed_32 FindSdataOffPosInToc( segdata *sdata, offset off )
/*****************************************************************/
{
TocEntryId e;
DbgAssert( sdata != NULL );
e.sdata = sdata;
e.off = off;
return FindEntryPosInToc(&e);
}
extern signed_32 FindSymPosInToc( symbol * sym )
/**********************************************/
{
TocEntryId e;
e.sdata = NULL;
e.sym = sym;
ConvertTocEntryId(&e);
return FindEntryPosInToc(&e);
}
static void WriteOutTokElem( void *_elem, void *buf )
/***************************************************/
{
TocEntry *elem = _elem;
offset addr;
segdata * sdata;
seg_leader *leader;
if( elem->e.sdata ) {
sdata = elem->e.sdata;
leader = sdata->u.leader;
addr = elem->e.off + sdata->a.delta + leader->group->linear
+ leader->seg_addr.off + FmtData.base;
} else {
addr = SymbolAbsAddr(elem->e.sym);
}
DbgAssert(elem->pos >= 0);
PutInfo((*((virt_mem *)buf)) + elem->pos, &(addr), sizeof addr);
}
extern void WriteToc( virt_mem buf )
/**********************************/
{
if( Toc == NULL ) return;
WalkHTableCookie( Toc, WriteOutTokElem, &buf );
if( IS_PPC_OS2 ) {
// Development temporarly on hold
#if 0
offset res[GOT_RESERVED_SIZE/sizeof(offset)] = { 0 };
enum { zero = GOT_RESERVED_NEG_SIZE/sizeof(offset) };
enum { blrl_opcode = 0x4E800021 };
DbgAssert(TocShift >= GOT_RESERVED_NEG_SIZE);
res[zero-1] = blrl_opcode;
res[zero] = IDataGroup->linear + FmtData.base;
PutInfo(buf+TocShift-GOT_RESERVED_NEG_SIZE, res, GOT_RESERVED_SIZE);
#endif
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?