distrib.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 553 行 · 第 1/2 页

C
553
字号
/****************************************************************************
*
*                            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:  routines for distributing libraries over overlays
*
****************************************************************************/

#include <string.h>
#include "linkstd.h"
#include "alloc.h"
#include "msg.h"
#include "pcobj.h"
#include "wlnkmsg.h"
#include "objpass1.h"
#include "objpass2.h"
#include "objfree.h"
#include "wcomdef.h"
#include "overlays.h"
#include "ring.h"
#include "distrib.h"
#include "specials.h"


static unsigned_16  CurrModThere;
static arcdata *    ArcBuffer;
static unsigned_32  ArcBufLen;
static mod_entry ** ModTable;
static unsigned_16  CurrModHandle;

section **          SectOvlTab;

/* forward declarations */

static bool NewRefVector( symbol *, unsigned_16, unsigned_16 );
static void ScanArcs( mod_entry *mod );

#define MOD_DEREF( x )  (ModTable[(x)])
#define INITIAL_MOD_ALLOC 32
#define INITIAL_ARC_ALLOC 32
#define MAX_NUM_MODULES   (8 * 1024)

extern void ResetDistrib( void )
/******************************/
{
    ArcBuffer = NULL;
    ModTable = NULL;
    SectOvlTab = NULL;
}

extern void InitModTable( void )
/******************************/
{
    CurrModThere = INITIAL_MOD_ALLOC;
    _ChkAlloc( ModTable, INITIAL_MOD_ALLOC * sizeof( mod_entry * ) );
    CurrModHandle = 0;
    ArcBufLen = INITIAL_ARC_ALLOC;
    _ChkAlloc( ArcBuffer, sizeof(arcdata)
                          + (INITIAL_ARC_ALLOC - 1) * sizeof(dist_arc));
    MakePass1Blocks();
}

extern void AddModTable( mod_entry * lp, unsigned_16 libspot )
/************************************************************/
/* add this module to the table, and make the arclist field point to a
 * scratch buffer */
// NYI: segdata changes have completely broken distributing libraries.
// fix this!
{
    mod_entry **    new;

    CurrModHandle++;
    if( CurrModHandle == CurrModThere ) {
        if( CurrModThere > MAX_NUM_MODULES ) {
            LnkMsg( FTL+MSG_TOO_MANY_LIB_MODS, NULL );
        }
        _ChkAlloc( new, sizeof( mod_entry * ) * CurrModThere * 2 );
        memcpy( new, ModTable, sizeof( mod_entry * ) * CurrModThere );
        _LnkFree( ModTable );
        ModTable = new;
        CurrModThere *= 2;
    }
    ModTable[ CurrModHandle ] = lp;
    lp->x.arclist = ArcBuffer;
    ArcBuffer->numarcs = 0;
    if( lp->modinfo & MOD_FIXED ) {
        ArcBuffer->ovlref = libspot;
    } else {
        ArcBuffer->ovlref = NO_ARCS_YET;
    }
}

extern void InitArcBuffer( mod_entry * mod )
/******************************************/
/* set up the mod_entry arcdata field for dead code elimination */
{
    if( !( ( FmtData.type & MK_OVERLAYS ) && FmtData.u.dos.distribute
                && ( LinkState & SEARCHING_LIBRARIES ) ) ) {
        _PermAlloc( mod->x.arclist, sizeof(arcdata) - DIST_ONLY_SIZE );
    }
}

static void MarkDead( void *_seg )
/********************************/
{
    segdata *seg = _seg;
        
    if( seg->isrefd )
        return;
    if( seg->isdead )
        return;

    if( seg->iscode ) {
        seg->isdead = 1;
    } else {
        if( FmtData.type & MK_PE ) {
            char *segname = seg->u.leader->segname;
            if( ( strcmp( segname, CoffPDataSegName ) == 0 )
                || ( strcmp(segname, CoffReldataSegName) == 0 ) ) {
                seg->isdead = 1;
            }
        }
    }
}

static void KillUnrefedSyms( void *_sym )
/***************************************/
{
    symbol  *sym = _sym;
    segdata *seg;

    seg = sym->p.seg;
    if( ( seg != NULL ) && !IS_SYM_IMPORTED(sym) && !IS_SYM_ALIAS(sym)
        && seg->isdead ) {
        if( seg->u.leader->combine == COMBINE_COMMON ) {
            seg = RingFirst( seg->u.leader->pieces );
            if( !seg->isdead ) {
                return;
            }
        }
        if( sym->e.def != NULL ) {
            WeldSyms( sym, sym->e.def );
        } else {
            sym->info |= SYM_DEAD;
        }
        if( LinkFlags & SHOW_DEAD ) {
            LnkMsg( MAP+MSG_SYMBOL_DEAD, "S", sym );
        }
    }
}

static void DefineOvlSegments( mod_entry *mod )
/*********************************************/
/* figure out which of the segments are live */
{
    Ring2Walk( mod->segs, MarkDead );
    Ring2Walk( mod->publist, KillUnrefedSyms );
}

extern void SetSegments( void )
/*****************************/
// now that we know where everything is, do all the processing that has been
// postponed until now.
{
    if( !( LinkFlags & STRIP_CODE ) )
        return;
    LinkState &= ~CAN_REMOVE_SEGMENTS;
    ObjFormat |= FMT_DEBUG_COMENT;
    if( ( FmtData.type & MK_OVERLAYS ) && FmtData.u.dos.distribute ) {
        _LnkFree( ArcBuffer );
        ArcBuffer = NULL;
    }
    if( LinkFlags & STRIP_CODE ) {
        WalkMods( DefineOvlSegments );
    }
#if 0           // NYI: distributing libraries completely broken.
    unsigned        index;
    mod_entry *     mod;
    unsigned_16     ovlref;
    mod_entry **    currmod;
    unsigned        num_segdefs;

    if( ( FmtData.type & MK_OVERLAYS ) && FmtData.u.dos.distribute ) {
        for( index = 1; index <= CurrModHandle; index++ ) {
            mod = ModTable[ index ];
            CurrMod = mod;
            ovlref = mod->x.arclist->ovlref;
            if( ovlref == NO_ARCS_YET ) {       // only data referenced
                CurrSect = Root;
            } else {
                CurrSect = SectOvlTab[ ovlref ];
            }
            DefModSegments( mod );
            mod->x.next = NULL;
            currmod = &CurrSect->u.dist_mods;
            while( *currmod != NULL ) {
                currmod = &((*currmod)->x.next);
            }
            *currmod = mod;
            mod->n.sect = CurrSect;
        }
    }
    FixGroupProblems();
    FindRedefs();
    if( ( FmtData.type & MK_OVERLAYS ) && FmtData.u.dos.distribute ) {
        _LnkFree( SectOvlTab );
        SectOvlTab = NULL;
    }
#endif
    ReleasePass1();
}

extern void FreeDistStuff( void )
/*******************************/
{
    unsigned    index;

    for( index = 1; index <= CurrModHandle; index++ ) {
        FreeAMod( ModTable[ index ] );
    }
    _LnkFree( ModTable );
    _LnkFree( ArcBuffer );
    _LnkFree( SectOvlTab );
    ReleasePass1();
}

extern void ProcDistMods( void )
/******************************/
{
    unsigned_16 index;
    mod_entry * mod;

    for( index = 1; index <= CurrModHandle; index++ ) {
        mod = ModTable[ index ];
        CurrSect = mod->n.sect;
        PModule( mod );
    }
}

#define SECT_VISITED 0x8000

extern unsigned_16 LowestAncestor( unsigned_16 ovl1, section * sect )
/*******************************************************************/
/* find the lowest common ancestor of the two overlay values by marking all of
 * the ancestors of the first overlay, and then looking for marked ancestors
 * of the other overlay */
{
    section *   list;

    list = sect;
    while( list != NULL ) {
        list->ovl_num |= SECT_VISITED;
        list = list->parent;
    }
    list = SectOvlTab[ ovl1 ];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?