ovlsupp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 835 行 · 第 1/2 页
C
835 行
/****************************************************************************
*
* 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: OVLSUPP -- overlay support routines
*
****************************************************************************/
#include <string.h>
#include "linkstd.h"
#include "pcobj.h"
#include "newmem.h"
#include "msg.h"
#include "alloc.h"
#include "reloc.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "fileio.h"
#include "mapio.h"
#include "procfile.h"
#include "objcalc.h"
#include "objfree.h"
#include "dbgall.h"
#include "objpass1.h"
#include "loadfile.h"
#include "loaddos.h"
#include "objnode.h"
#include "distrib.h"
#include "overlays.h"
#include "ring.h"
#include "specials.h"
static segdata *OvlSegData;
static symbol *OverlayTable; /* symbol entry for overlay table */
static symbol *OverlayTableEnd;/* symbol entry for overlay table */
static symbol *OvlVecStart; /* symbol entry for overlay vector start */
static symbol *OvlVecEnd; /* symbol entry for overlay vector end */
static targ_addr OvlvecAddr; /* address of overlay vectors */
static targ_addr Stash;
unsigned_16 AreaSize;
static void AllocAreas( OVL_AREA *area );
static void ShortVectors( symbol *loadsym );
static void LongVectors( symbol *loadsym );
static void PutOvlInfo( unsigned off, void *src, unsigned len );
static unsigned EmitOvlAreaEntry( unsigned off, OVL_AREA *area );
extern void ResetOvlSupp( void )
/******************************/
{
AreaSize = 0xFFFF;
}
static void ParmWalkSections( section *sect, void (*rtn)( section *, void * ),
void *parm )
/*************************************************************************/
{
for( ; sect != NULL; sect = sect->next_sect ) {
rtn( sect, parm );
ParmWalkAreas( sect->areas, rtn, parm );
}
}
extern void ParmWalkAreas( OVL_AREA *ovl, void (*rtn)( section *, void * ),
void *parm )
/**********************************************************************/
{
for( ; ovl != NULL; ovl = ovl->next_area ) {
ParmWalkSections( ovl->sections, rtn, parm );
}
}
static void WalkSections( section *sect, void (*rtn)( section * ) )
/***************************************************************/
{
for( ; sect != NULL; sect = sect->next_sect ) {
rtn( sect );
WalkAreas( sect->areas, rtn );
}
}
extern void WalkAreas( OVL_AREA *ovl, void (*rtn)( section * ) )
/************************************************************/
{
for( ; ovl != NULL; ovl = ovl->next_area ) {
WalkSections( ovl->sections, rtn );
}
}
static void WriteVectors( void )
/******************************/
{
vecnode *vec;
int n;
targ_addr addr;
symbol * sym;
WriteMapNL( 2 );
XReportSymAddr( OverlayTable );
XReportSymAddr( OverlayTableEnd );
XReportSymAddr( OvlVecStart );
XReportSymAddr( OvlVecEnd );
WriteOvlHead();
n = 0;
vec = OvlVectors;
while( vec != NULL ) {
GetVecAddr( ++n, &addr );
sym = vec->entry;
WriteMap( "%a section %d : %S", &addr,
sym->p.seg->u.leader->class->section->ovl_num, sym );
vec = vec->next;
}
}
static void DoSecPubs( section *sec )
/***********************************/
{
WriteMapNL( 2 );
WriteMap( "Overlay section %d address %a", sec->ovl_num,
&sec->sect_addr );
WriteMap( "====================================" );
WriteSegs( sec->classlist );
StartMapSort();
if( MapFlags & MAP_FLAG ) {
WritePubHead();
}
ProcPubs( sec->mods, sec );
ProcOvlSectPubs( sec );
FinishMapSort();
}
extern void ProcOvlSectPubs( section *sec )
/*****************************************/
{
mod_entry * next;
if( sec->u.dist_mods != NULL ) {
for( CurrMod = sec->u.dist_mods; CurrMod != NULL; CurrMod = next ) {
next = CurrMod->x.next;
DoPubs( sec );
}
}
}
extern void ProcOvlPubs( void )
/*****************************/
{
WriteVectors();
ProcAllOvl( DoSecPubs );
}
extern void FillOutPtr( section *sec )
/************************************/
{
if( sec->outfile == NULL ) {
if( sec->parent != NULL ) {
sec->outfile = sec->parent->outfile; //same file as ancestor.
} else {
sec->outfile = Root->outfile;
}
}
}
static void AllocSections( section *first_sect )
/**********************************************/
/* Allocate parallel overlay sections */
{
targ_addr save;
targ_addr max;
section * sect;
unsigned long result;
unsigned ovl_size;
unsigned min_size;
bool area_specified;
CurrSect = first_sect; /* NormalizeAddr() needs to know the section */
MAlign( FmtData.SegShift ); /* as do some DBI routines. */
NormalizeAddr();
if( first_sect == NonSect ) {
if( FmtData.u.dos.dynamic ) {
ovl_size = CurrLoc.seg - Stash.seg;
min_size = ovl_size + OvlNum + 1; // need at least 1 para per sect. + 1
if( min_size < 64 ) {
min_size = 64; // reserve 1 K for the stack
}
area_specified = TRUE;
if( AreaSize == 0xFFFF ) { // default is twice the memory size
AreaSize = ovl_size * 2;
area_specified = FALSE;
} else if( AreaSize == 0 ) {
area_specified = FALSE;
}
if( AreaSize < min_size ) {
AreaSize = min_size;
if( area_specified ) {
LnkMsg( WRN+MSG_AREA_TOO_SMALL, "l",
(unsigned long)min_size << FmtData.SegShift );
}
}
result = CurrLoc.seg + (unsigned long) ( AreaSize - ovl_size );
if( result > 0xFFFF ) {
LnkMsg( WRN+MSG_CANT_RESERVE_SPACE, "l",
(unsigned long)AreaSize << FmtData.SegShift );
} else {
CurrLoc.seg = result;
}
}
AreaSize = CurrLoc.seg - Stash.seg;
}
save = CurrLoc;
max.off = 0;
max.seg = 0;
for( sect = first_sect; sect != NULL; sect = sect->next_sect ) {
CurrSect = sect;
sect->sect_addr = save;
AllocClasses( sect->classlist );
if( sect->areas != NULL ) {
AllocAreas( sect->areas );
}
NormalizeAddr(); /* avoid any overflow messages */
AddSize( 2 ); /* reserve some space for the overlay manager */
NormalizeAddr(); /* get canonical form */
if( ( CurrLoc.seg > max.seg )
|| ( CurrLoc.seg == max.seg ) && ( CurrLoc.off > max.off ) ) {
max = CurrLoc;
}
CurrLoc = save;
}
CurrLoc = max;
}
static void AllocAreas( OVL_AREA *area )
/**************************************/
{
/* now CurrLoc is beginning of overlay area */
DEBUG(( DBG_OLD, "Overlay area start %a", &CurrLoc ));
for( ; area != NULL; area = area->next_area ) {
AllocSections( area->sections );
}
}
extern void CalcOvl( void )
/*************************/
{
unsigned temp;
outfilelist * fnode;
CurrSect = Root;
/* record starting address of overlay table */
Align( 2 ); // for overlay table speed.
XDefSymAddr( OverlayTable, CurrLoc.off, CurrLoc.seg );
DEBUG(( DBG_OLD, "Overlay table address %a", &CurrLoc ));
OvltabAddr = CurrLoc;
/* calculate size of overlay table proper */
temp = sizeof( ovl_null_table ) + ( OvlNum - 1 ) * sizeof( ovltab_entry );
XDefSymAddr( OverlayTableEnd, CurrLoc.off + temp - sizeof( unsigned_16 ),
CurrLoc.seg );
fnode = OutFiles;
while( fnode != NULL ) {
fnode->ovlfnoff = temp;
temp += strlen( fnode->fname ) + 1;
fnode = fnode->next;
}
Root->outfile->ovlfnoff |= OVE_EXE_FILENAME; // indicate the .exe file.
/* calculate starting address of overlay vectors, record */
OvltabSize = temp; /* incl. NULLCHAR */
CurrentSeg = NULL;
AddSize( OvltabSize );
XDefSymAddr( OvlVecStart, CurrLoc.off, CurrLoc.seg );
DEBUG(( DBG_OLD, "Overlay vector start %a", &CurrLoc ));
OvlvecAddr = CurrLoc;
/* calculate start of overlay area */
if( FmtData.u.dos.ovl_short ) {
temp = VecNum * sizeof( svector );
} else {
temp = VecNum * sizeof( lvector );
}
AddSize( temp );
OvltabSize += temp;
XDefSymAddr( OvlVecEnd, CurrLoc.off, CurrLoc.seg );
AddSize( 2 ); // reserve some space for the ovl. manager.
Align( 4 );
NormalizeAddr();
Stash = CurrLoc;
AllocAreas( Root->areas );
MAlign( 4 ); /* don't add to section size */
NormalizeAddr(); /* now CurrLoc.seg points to next free para */
OvlGroup = AllocGroup( AutoGrpName, &Groups );
OvlGroup->grp_addr = OvltabAddr;
OvlGroup->section = Root;
OvlGroup->size = OvltabSize;
OvlGroup->totalsize = OvltabSize;
OvlGroup->num = 0;
OvlGroup->linear = 0;
Ring2Append( &OvlGroup->leaders, OvlSeg );
OvlSeg->group = OvlGroup;
OvlSeg->seg_addr = OvltabAddr;
OvlSegData->data = AllocStg( OvltabSize );
OvlSegData->length = OvltabSize;
RingAppend( &OvlSegData->u.leader->pieces, OvlSegData );
}
extern void FreeOvlStruct( void )
/*******************************/
{
OvlClasses = NULL;
OvlVectors = NULL;
if( OvlSeg != NULL ) {
FreeLeader( OvlSeg );
}
FreeDistStuff();
}
static bool IsAncestor( int elder, section *ceorl )
/*************************************************/
/* Is overlay section # "elder" an ancestor of section "ceorl" */
{
for( ; ; ) {
if( ceorl->ovl_num == elder )
return( TRUE );
if( ceorl->parent == NULL )
return( FALSE );
ceorl = ceorl->parent;
}
}
#define NO_VECTOR( sym ) ( ( IS_SYM_COMMUNAL( sym ) ) \
|| ( (sym)->u.d.ovlstate & OVL_FORCE ) )
extern void OvlDefVector( symbol * sym )
/**************************************/
{
segdata * sdata;
unsigned_16 ovl_num;
if( NO_VECTOR( sym ) )
return;
sdata = sym->p.seg;
if( sdata == NULL ) {
sym->u.d.ovlstate |= ( OVL_FORCE | OVL_NO_VECTOR );
return; /* NOTE: <--- premature return <----------- */
} else {
ovl_num = sdata->u.leader->class->section->ovl_num;
}
if( !sdata->iscode || ( ovl_num == 0 ) ) { // not code or in root
sym->u.d.ovlstate |= ( OVL_FORCE | OVL_NO_VECTOR );
} else {
if( sym->info & SYM_REFERENCED ) {
if( sym->u.d.ovlref != ovl_num ) {
/* first reference must have been a proper ancestor or cousin */
Vectorize( sym );
}
} else {
sym->u.d.ovlstate |= OVL_REF;
sym->u.d.ovlref = ovl_num;
}
}
}
extern void Vectorize( symbol * sym )
/***********************************/
/* allocate an overlay vector for a symbol */
{
vecnode *vec;
sym->u.d.ovlref = ++VecNum;
sym->u.d.ovlstate &= ~OVL_NO_VECTOR;
sym->u.d.ovlstate |= OVL_FORCE;
_PermAlloc( vec, sizeof( vecnode ) );
vec->entry = sym;
LinkList( &OvlVectors, vec );
DEBUG(( DBG_OLD, "Vectorize %d %S", VecNum, sym ));
}
static void OvlRefVector( symbol * sym )
/**************************************/
{
unsigned_16 ovl_num;
if( IS_SYM_COMMUNAL( sym ) )
return;
if( ( sym->u.d.ovlstate & OVL_VEC_MASK ) != OVL_UNDECIDED )
return;
if( !( sym->info & SYM_DEFINED ) ) {
if( !( sym->u.d.ovlstate & OVL_REF ) ) {
sym->u.d.ovlref = CurrSect->ovl_num;
sym->u.d.ovlstate |= OVL_REF;
} else if( FmtData.u.dos.distribute ) {
sym->u.d.ovlref = LowestAncestor( sym->u.d.ovlref, CurrSect );
}
} else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?