wcomdef.c

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

C
534
字号
    } else {
        StoreInfoData( info );
    }
    RingWalk( info->pieces, FreeCDatPiece );
    FreeCDatInfo( info );
}

extern void ResolveComdats( void )
/********************************/
{
    RingWalk( CDatList, FinishComdat );
    CDatList = NULL;
}

#if 0
static char * GetNewName( void )
/******************************/
/* get a new name for an automatically defined comdat segment */
{
    CDatSegNum++;
    ultoa( CDatSegNum, CDatSegName + CDAT_SEG_NUM_OFF, 36 );
    return CDatSegName;
}

static void AddToLinkerComdat( symbol *sym )
/******************************************/
/* this tries to add "size" bytes to an existing comdat segment, and if it
 * can't, it creates a new segment for the data */
{
    seg_leader *        leader;
    class_entry *       class;
    offset              seglen;
    section *           sect;
    segdata *           sdata;
    byte                alloc;
    byte                align;

    sdata = sym->p.seg;
    alloc = sdata->alloc;
    align = sdata->align;
    leader = CDatSegments[alloc];
    if( leader == NULL ) {
        sdata->u.name = GetNewName();
        sym->addr.off = 0;
        if( !(FmtData.type & MK_OVERLAYS) || !(alloc & 1) ) {
            sect = Root;
        } else {
            sect = NonSect;             /* data in an overlaid app */
        }
        class = FindClass( sect, CDatClassNames[alloc], alloc > 1, alloc & 1 );
    } else {
        class = leader->class;
        seglen = CAlign( leader->size, align ) + sdata->length;
        if( seglen > 0xFFFF && align <= 1 ) {
            sdata->u.name = GetNewName();
            sym->addr.off = 0;
        } else {
            sdata->u.name = leader->segname;
            sym->addr.off = seglen - sdata->length;
        }
    }
    AddSegment( sdata, class );
    sdata->data = AllocStg( sdata->length );
    CDatSegments[alloc] = sdata->u.leader;
    sym->p.seg = sdata;
}
#endif

static offset CountIDBlock( char ** buffptr )
/*******************************************/
/* this finds the length of an individual lidata block */
{
    offset      repeat;
    offset      size;
    char *      buff;
    unsigned_16 count;

    buff = *buffptr;
    if( ObjFormat & FMT_MS_386 ) {
        _TargU32toHost( _GetU32( buff ), repeat );
        buff += sizeof( unsigned_32 );
    } else {
        _TargU16toHost( _GetU16( buff ), repeat );
        buff += sizeof( unsigned_16 );
    }
    _TargU16toHost( _GetU16( buff ), count );
    buff += sizeof(unsigned_16);
    if( count == 0 ) {  // this is followed by actual data
        repeat *= *buff;
        buff += *buff + 1;
    } else {            // it is a series of id blocks
        size = 0;
        while( count > 0 ) {
            size += CountIDBlock( &buff );
            count--;
        }
        repeat *= size;
    }
    *buffptr = buff;
    return( repeat );
}

static offset CalcLIDataLength( void )
/************************************/
/* this finds the length of the equivalent of an lidata record */
{
    offset      total;
    char *      buff;

    total = 0;
    buff = ObjBuff;
    while( buff < EOObjRec ) {
        total += CountIDBlock( &buff );
    }
    return( total );
}

static bool CompInfoSym( void *info, void *sym )
/**********************************************/
{
    return ((comdat_info *)info)->sym == (symbol *)sym;
}

#ifdef _INT_DEBUG
static bool CheckSameComdat( void *info, void *sym )
/***********************************************************/
{
    if( (symbol *)sym == ((comdat_info *)info)->sym ) {
        LnkMsg( LOC_REC+ERR+MSG_INTERNAL, "s", "duplicate comdat found" );
        LnkMsg( ERR+MSG_INTERNAL, "s", ((symbol *)sym)->name );
    }
    return FALSE;
}
#endif

#define ST_COMDAT (ST_REFERENCE | ST_CREATE | ST_NOALIAS)

extern void ProcComdat( void )
/****************************/
/* process a comdat record */
{
    comdat_info *       info;
    comdat_piece *      piece;
    offset              dataoff;
    segdata *           sdata;
    segnode *           seg;
    list_of_names *     symname;
    symbol *            sym;
    int                 namelen;
    unsigned            attr;
    unsigned            flags;
    unsigned            align;
    unsigned            alloc;
    unsigned            segidx;
    bool                usealign;

    flags = *ObjBuff++;
    attr = *ObjBuff++;
    align = *ObjBuff++;
    if( align == 0 ) {
        usealign = TRUE;
    } else {
        usealign = FALSE;
        align = OMFAlignTab[align];
    }
    if( ObjFormat & FMT_32BIT_REC ) {
        _TargU32toHost( _GetU32UN( ObjBuff ), dataoff );
        ObjBuff += sizeof( unsigned_32 );
    } else {
        _TargU16toHost( _GetU16UN( ObjBuff ), dataoff );
        ObjBuff += sizeof( unsigned_16 );
    }
    SkipIdx();  /* not interested in the type index */
    alloc = attr & CDAT_ALLOC_MASK;
    if( alloc == 0 ) {  /* if explicit allocation */
        SkipIdx();                              /* get public base */
        segidx = GetIdx();
        if( segidx != 0 ) {
            seg = (segnode *) FindNode( SegNodes, segidx );
            if( usealign ) {
                align = seg->entry->align;
            }
        } else {
            BadObject();        // do not support absolute comdats
            return;             // NOTE: premature return
        }
    } else {    // do not support linker defined comdats
        BadObject();
        return;
    }
    piece = AllocCDatPiece();
    symname = FindName( GetIdx() );
    namelen = strlen( symname->name );
    if( flags & CDAT_STATIC ) {
        sym = SymOp( ST_COMDAT | ST_STATIC, symname->name, namelen );
    } else {
        sym = SymOp( ST_COMDAT, symname->name, namelen );
    }
    if( flags & CDAT_ITERATED ) {
        piece->length = CalcLIDataLength();
    } else {
        piece->length = EOObjRec - ObjBuff;
    }
    if( !CacheIsPerm() ) {
        _ChkAlloc( piece->data, piece->length );
        memcpy( piece->data, ObjBuff, piece->length );
        piece->free_data = TRUE;
    } else {
        piece->data = ObjBuff;
    }
    if( flags & CDAT_CONTINUATION ) {
        info = RingLookup( CDatList, CompInfoSym, sym );
        RingAppend( &info->pieces, piece );
        info->sdata->length += piece->length;
    } else {
        sdata = AllocSegData();
        sdata->length = piece->length;
        sdata->combine = COMBINE_ADD;
        sdata->iscdat = TRUE;
        sdata->isabs = seg == NULL;
        sdata->align = align;
        sdata->u.leader = seg->entry->u.leader;
        sdata->iscode = (seg->info & SEG_CODE) != 0;
        if( ObjFormat & FMT_32BIT_REC ) {
            sdata->is32bit = TRUE;
        }
        info = AllocCDatInfo();
        info->sdata = sdata;
        info->sym = sym;
        info->flags = (attr & CDAT_SELECT_MASK) << CDAT_SELECT_SHIFT;
        info->flags |= SYM_DEAD;        // assume redefined
        RingAppend( &info->pieces, piece );
#ifdef _INT_DEBUG
        RingLookup( CDatList, CheckSameComdat, sym );
#endif
        RingAppend( &CDatList, info );
        if( IS_SYM_COMDAT(sym) ) {
            CheckComdatSym( sym, info->flags & ~SYM_DEAD );
        } else if( !(IS_SYM_REGULAR(sym) && sym->info & SYM_DEFINED) ) {
            if( sym->info & SYM_DEFINED ) {
                sym = HashReplace( sym );
            }
            ClearSymUnion( sym );
            if( alloc == 0 ) {  /* explicit */
                seg->entry->u.leader->info |= SEG_LXDATA_SEEN;
                RingAppend( &sdata->u.leader->pieces, sdata );
                Ring2Append( &CurrMod->segs, sdata );
#if 0
            } else {    /* add it to a linker defined segment */
                sdata->iscode = alloc & 1;
                sdata->alloc = --alloc;
                AddToLinkerComdat( sym );
#endif
            }
            sym->info |= (attr & CDAT_SELECT_MASK) << CDAT_SELECT_SHIFT;
            SetComdatSym( sym, sdata );
            info->flags &= ~SYM_DEAD;
        }
    }
    if( info->flags & SYM_DEAD && !(LinkFlags & INC_LINK_FLAG) ) {
        ObjFormat |= FMT_IGNORE_FIXUPP;
    } else {
        ObjFormat &= ~FMT_IGNORE_FIXUPP;
    }
    SetCurrSeg( info->sdata, dataoff, piece->data );
}

⌨️ 快捷键说明

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