ovlsupp.c

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

C
835
字号
        if( sym->p.seg == NULL )
            return;
        /* at this point, we know it has already been defined, but does */
        /* not have an overlay vector, and is not data */
        ovl_num = sym->p.seg->u.leader->class->section->ovl_num;
        if( IsAncestor( ovl_num, CurrSect ) )
            return;
        /* overlay vector necessary */
        Vectorize( sym );
    }
}

extern void TryRefVector( symbol * sym )
/**************************************/
{
    if( !( FmtData.type & MK_OVERLAYS ) )
        return;
    if( ( LinkState & SEARCHING_LIBRARIES ) && FmtData.u.dos.distribute ) {
        RefDistribSym( sym );
    } else {
        OvlRefVector( sym );
    }
}

extern void OvlUseVector( symbol * sym, extnode *newnode )
/********************************************************/
{
    if( !( FmtData.type & MK_OVERLAYS ) )
        return;
    if( IS_SYM_COMMUNAL( sym ) )
        return;
    if( ( sym->u.d.ovlstate & OVL_VEC_MASK ) != OVL_MAKE_VECTOR )
        return;
    if( IsAncestor( sym->p.seg->u.leader->class->section->ovl_num, CurrSect ) ) {
         return;
    }
    /* use overlay vector for all calls */
    newnode->ovlref = sym->u.d.ovlref;
}

extern void IndirectCall( symbol *sym )
/*************************************/
{
    unsigned_16 ovl_num;

    if( !( FmtData.type & MK_OVERLAYS ) )
        return;
    if( NO_VECTOR( sym ) )
        return;
    if( sym->info & SYM_DEFINED ) {
        if( sym->info & SYM_DISTRIB ) {
            DistIndCall( sym );
        } else if( sym->p.seg != NULL ) {
            ovl_num = sym->p.seg->u.leader->class->section->ovl_num;
            if( ( ovl_num != 0 ) && sym->p.seg->iscode ) {
                Vectorize( sym );
            }
        }
    } else {
        // indicate a reference from the root for purposes of vector generation
        sym->u.d.ovlstate |= OVL_REF;
        sym->u.d.ovlref = 0;
    }
}

extern void GetVecAddr( int vecnum, targ_addr *addr )
/***************************************************/
/* return address of overlay vector in canonical form */
{
    *addr = OvlvecAddr;
    if( FmtData.u.dos.ovl_short ) {
        /* short address -- fits into 16 bits */
        addr->off += ( vecnum - 1 ) * sizeof( svector ) + ( addr->seg << FmtData.SegShift );
        addr->seg = 0;
    } else {
        addr->off += ( vecnum - 1 ) * sizeof( lvector );
    }
}

extern bool CheckOvlClass( char *clname, bool *isovlclass )
/*********************************************************/
/* check if among overlay classes, and return TRUE if it is code. */
{
    list_of_names *     cnamelist;
    bool                retval;

    retval = IsCodeClass( clname, strlen( clname ) );
    cnamelist = OvlClasses;
    if( cnamelist == NULL ) {   /* check for anything ending in code */
        *isovlclass = retval;
        return( retval );
    } else {
        do {
            if( stricmp( clname, cnamelist->name ) == 0 ) {
                *isovlclass = TRUE;
                return( retval );
            }
            cnamelist = cnamelist->next_name;
        } while( cnamelist != NULL );
    }
    *isovlclass = FALSE;
    return( FALSE );
}

extern section * CheckOvlSect( char *clname )
/*******************************************/
{
    section *   sect;
    bool        dummy;

    sect = DBIGetSect( clname );
    if( sect == NULL ) {
        if( CheckOvlClass( clname, &dummy ) ) {
            sect = CurrSect;
        } else {
            sect = NonSect;
        }
    }
    return( sect );
}

extern void EmitOvlVectors( void )
/********************************/
{
    symbol *    symptr;
    dos_addr    addr;
    char *      loader_name;
    bool        isshort;

    /* output relocation items for overlay table */
    addr.seg = OvlGroup->grp_addr.seg;
    addr.off = OvltabAddr.off + offsetof( ovltab_prolog, start.seg );
    WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );
    addr.off = OvltabAddr.off + offsetof( ovltab_prolog, delta );
    WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );

    isshort = FALSE;
    if( FmtData.u.dos.dynamic ) {
        loader_name = _DynamicOvlldr;
    } else if( FmtData.u.dos.ovl_short ) {
        loader_name = _ShortOvlldr;
        isshort = TRUE;
    } else {
        loader_name = _LongOvlldr;
    }
    symptr = RefISymbol( loader_name );
    if( !( symptr->info & SYM_DEFINED ) ) {
        LnkMsg( ERR+MSG_NO_OVERLAY_LOADER, NULL );
    } else if( isshort ) {
        ShortVectors( symptr );
    } else {
        LongVectors( symptr );
    }
}

static void ShortVectors( symbol *loadsym )
/*****************************************/
{
    vecnode             *vec;
    unsigned            vect_off;
    unsigned_32         loadval;
    unsigned_32         temp;
    signed_32           diff;
    int                 vecnum;
    svector             template;

    vect_off = OvlvecAddr.off;
    temp = MK_REAL_ADDR( OvlvecAddr.seg, OvlvecAddr.off );
    /* get loader address */
    loadval = MK_REAL_ADDR( loadsym->addr.seg, loadsym->addr.off );
    /* fill in overlay vector template */
    template.call_op = 0xe8;
    template.jmp_op = 0xe9;
    vecnum = 1;
    for( vec = OvlVectors; vec != NULL; vec = vec->next ) {
        temp = vect_off + offsetof( svector, ldr_addr ) + sizeof( unsigned_16 );
        diff = loadval - temp;
        if( ( diff < -32768 ) || ( diff > 32767 ) ) {
            LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
        }
        _HostU16toTarg( diff, template.ldr_addr );
        loadsym = vec->entry;
        _HostU16toTarg( loadsym->p.seg->u.leader->class->section->ovl_num,
                        template.sec_num );
        temp = vect_off + offsetof( svector, target ) + sizeof( unsigned_16 );
        diff = MK_REAL_ADDR( loadsym->addr.seg, loadsym->addr.off ) - temp;
        if( ( diff < -32768 ) || ( diff > 32767 ) ) {
            LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
        }
        _HostU16toTarg( diff, template.target );
        PutOvlInfo( vect_off, &template, sizeof( svector ) );
        vect_off += sizeof( svector );
        ++vecnum;
    }
}

static void LongVectors( symbol *loadsym )
/****************************************/
{
    vecnode             *vec;
    unsigned            vect_off;
    lvector             template;
    dos_addr            addr;
    signed_32           diff;
    unsigned_32         loadval;
    unsigned_32         temp;
    int                 vecnum;

    vect_off = OvlvecAddr.off;
    /* fill in overlay vector template */
    template.u.v.call_op = 0xe8;
    template.jmp_op = 0xea;
    loadval = loadsym->addr.off;
    addr.seg = OvlGroup->grp_addr.seg;
    vecnum = 1;
    for( vec = OvlVectors; vec != NULL; vec = vec->next ) {
        temp = vect_off + offsetof( lvector, u.v.ldr_addr ) + sizeof( unsigned_16 );
        diff = loadval - temp;
        if( ( diff < -32768 ) || ( diff > 32767 ) ) {
            LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
        }
        _HostU16toTarg( diff, template.u.v.ldr_addr );
        loadsym = vec->entry;
        _HostU16toTarg( loadsym->p.seg->u.leader->class->section->ovl_num,
                        template.u.v.sec_num );
        _HostU16toTarg( loadsym->addr.off, template.target.off );
        if( FmtData.u.dos.dynamic ) {
            _HostU16toTarg( loadsym->addr.seg
                            - loadsym->p.seg->u.leader->group->grp_addr.seg,
                                                   template.target.seg );
        } else {
            _HostU16toTarg( loadsym->addr.seg, template.target.seg );
            addr.off = vect_off + offsetof( lvector, target.seg );
            WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );
        }
        PutOvlInfo( vect_off, &template, sizeof( lvector ) );
        vect_off += sizeof( lvector );
        vecnum++;
    }
}


extern void SetOvlStartAddr( void )
/*********************************/
{
    symbol *    sym;

    /* stuff overlay init routine address in header */
    Stash = StartInfo.addr;

    if( FmtData.u.dos.dynamic ) {
        sym = FindISymbol( _DynamicInitRtn );
    } else if( FmtData.u.dos.ovl_short ) {
        sym = FindISymbol( _ShortOvlInitRtn );
    } else {
        sym = FindISymbol( _LongOvlInitRtn );
    }
    if( sym == NULL )
        return;
    if( sym->info & SYM_DEFINED ) {
        StartInfo.addr = sym->addr;
    }
}

extern void OvlPass1( void )
/**************************/
{
    symbol *    sym;

    ProcAllOvl( LoadObjFiles );

    /* define symbols for overlay table */
    OverlayTable = DefISymbol( _OvltabName );
    OverlayTableEnd = DefISymbol( _OvltabEndName );
    OvlVecStart = DefISymbol( _OvlVecStartName );
    OvlVecEnd = DefISymbol( _OvlVecEndName );

    OvlSeg = InitLeader( "", 0 );
    OvlSeg->class = FindClass( Root, OvlMgrClass, 0, 1 );
    OvlSeg->combine = COMBINE_INVALID;
    OvlSegData = AllocSegData();
    OvlSegData->u.leader = OvlSeg;

    OverlayTable->p.seg = OvlSegData;
    OverlayTableEnd->p.seg = OvlSegData;
    OvlVecStart->p.seg = OvlSegData;
    OvlVecEnd->p.seg = OvlSegData;

    /* generate reference for overlay loader */
    if( FmtData.u.dos.dynamic ) {
        RefISymbol( _DynamicInitRtn );
        sym = RefISymbol( _DynamicOvlldr );
    } else if( FmtData.u.dos.ovl_short ) {
        RefISymbol( _ShortOvlInitRtn );
        sym = RefISymbol( _ShortOvlldr );
    } else {
        RefISymbol( _LongOvlInitRtn );
        sym = RefISymbol( _LongOvlldr );
    }
    sym->u.d.ovlref = 0;
    sym->u.d.ovlstate |= OVL_REF;
}

static unsigned EmitOvlEntry( unsigned off, section *sect )
/*********************************************************/
{
    ovltab_entry        entry;
    offset              len;
    unsigned_16         flags_anc;
    unsigned_16         start_para;

    _HostU16toTarg( 0, entry.code_handle );
    for( ; sect != NULL; sect = sect->next_sect ) {/* write out table entry */
        flags_anc = sect->parent->ovl_num;
        if( sect == NonSect ) {
            flags_anc |= OVE_FLAG_PRELOAD;/*  pre-load the data area */
        }
        _HostU16toTarg( sect->outfile->ovlfnoff, entry.fname );
        _HostU16toTarg( sect->relocs, entry.relocs );
        _HostU16toTarg( flags_anc, entry.flags_anc );
        start_para = sect->sect_addr.seg + ( sect->sect_addr.off >> FmtData.SegShift );
        _HostU16toTarg( start_para, entry.start_para );
        len = sect->size + 15 >> 4;
        _HostU16toTarg( len, entry.num_paras );
        _HostU32toTarg( sect->u.file_loc, entry.disk_addr );
        PutOvlInfo( off, &entry, sizeof( entry ) );
        off += sizeof( ovltab_entry );
        off = EmitOvlAreaEntry( off, sect->areas );
    }
    return( off );
}

static unsigned EmitOvlAreaEntry( unsigned off, OVL_AREA *area )
{
    for( ; area != NULL; area = area->next_area ) {
        off = EmitOvlEntry( off, area->sections );
    }
    return( off );
}

extern void EmitOvlTable( void )
/******************************/
/* generate overlay table */
{
    unsigned            off;
    ovltab_prolog       template;
    unsigned_16         u16;
    int                 len;
    outfilelist *       fnode;

    off = OvltabAddr.off;
/*
    Generate prolog :
*/
    template.major = OVL_MAJOR_VERSION;
    template.minor = OVL_MINOR_VERSION;
/*
    output start address for program
    reloc for this was emitted by EmitOvlVectors
*/
    _HostU16toTarg( Stash.off, template.start.off );
    _HostU16toTarg( Stash.seg, template.start.seg );
/*
    this should give us the paragraph of the load module start
    reloc for this was emitted by EmitOvlVectors
*/
    _HostU16toTarg( 0, template.delta );
    _HostU16toTarg( AreaSize, template.ovl_size );

    PutOvlInfo( off, &template, sizeof( template ) );
/*
    Generate entries :
*/
    off += sizeof( template );
    off = EmitOvlAreaEntry( off, Root->areas );
/*
    Generate epilog :
*/
    u16 = OVLTAB_TERMINATOR;
    PutOvlInfo( off, &u16, sizeof( unsigned_16 ) );
    off += sizeof( unsigned_16 );
    /* generate overlay filenames, including NULLCHARS*/
    fnode = OutFiles;
    while( fnode != NULL ) {
        len = strlen( fnode->fname ) + 1;
        PutOvlInfo( off, fnode->fname, len );
        off += len;
        fnode = fnode->next;
    }
}

extern void PadOvlFiles( void )
/*****************************/
// The overlay files must contain a complete paragraph at the end of the file
// for the overlay loader to be able to correctly read it.
{
    outfilelist *   fnode;
    unsigned        pad;

    fnode = OutFiles;
    for( fnode = OutFiles; fnode != NULL; fnode = fnode->next ) {
        pad = FmtData.SegMask + 1 - ( fnode->file_loc & FmtData.SegMask );
        if( pad != 16 ) {
            if( fnode->handle == NIL_HANDLE ) {
                OpenOvlFile( fnode );
            }
            PadBuffFile( fnode, pad );
        }
    }
}

static void PutOvlInfo( unsigned off, void *src, unsigned len )
/*************************************************************/
{
   PutInfo( OvlSegData->data + off - OvlGroup->grp_addr.off, src, len );
}

⌨️ 快捷键说明

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