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 + -
显示快捷键?