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