objpass1.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,236 行 · 第 1/3 页
C
1,236 行
section * sect;
class_entry * class;
bool isovlclass;
isovlclass = FALSE;
if( FmtData.type & MK_OVERLAYS ) {
sdata->iscode = CheckOvlClass( clname, &isovlclass );
}
if( sdata->iscode ) {
if( !sdata->is32bit ) {
LinkState |= HAVE_16BIT_CODE;
}
}
sect = DBIGetSect( clname );
if( sect == NULL ) {
if( !(FmtData.type & MK_OVERLAYS) || isovlclass ) {
sect = CurrSect;
} else {
sect = NonSect;
}
}
class = FindClass( sect, clname, sdata->is32bit, sdata->iscode );
AddSegment( sdata, class );
if( isovlclass ) {
sdata->u.leader->info |= SEG_OVERLAYED;
}
if( !sdata->isdead && !sdata->isuninit && !sdata->iscdat ) {
sdata->data = AllocStg( sdata->length );
}
}
static void CheckQNXSegMismatch( stateflag mask )
/***********************************************/
{
if( FmtData.type & MK_QNX && LinkState & mask
&& !FmtData.u.qnx.seen_mismatch ) {
LnkMsg( WRN+LOC+MSG_CANNOT_HAVE_16_AND_32, NULL );
FmtData.u.qnx.seen_mismatch = TRUE;
}
}
extern void AddSegment( segdata *sd, class_entry *class )
/*******************************************************/
/* Add a segment to the segment list for an object file */
{
unsigned_16 info;
unsigned_16 dbiflags;
DEBUG((DBG_OLD,"- adding segment %s, class %s",sd->u.name, class->name ));
DEBUG(( DBG_OLD, "- - size = %h, comb = %x, alignment = %x",
sd->length, sd->combine, sd->align ));
info = 0;
dbiflags = DBIColSeg( class );
if( sd->is32bit ) {
info |= USE_32;
if( dbiflags == NOT_DEBUGGING_INFO ) { //can use SEGD32 in 16-bit dbi
Set32BitMode();
CheckQNXSegMismatch( HAVE_16BIT_CODE );
}
} else if( dbiflags == NOT_DEBUGGING_INFO ) {
Set16BitMode();
CheckQNXSegMismatch( FMT_SEEN_32_BIT );
}
if( class->flags & CLASS_CODE ) {
info |= SEG_CODE;
}
if( sd->isabs ) {
info |= SEG_ABSOLUTE;
sd->isdefd = TRUE;
}
if( DBISkip( dbiflags ) ) {
sd->isdead = TRUE;
}
if( sd->isabs || sd->combine == COMBINE_INVALID ) {
MakeNewLeader( sd, class, info );
} else {
char *seg_name = sd->u.name;
FindALeader( sd, class, info );
if( (sd->u.leader->info & USE_32) != (info & USE_32) ) {
char *segname_16;
char *segname_32;
if( info & USE_32 ) {
segname_16 = sd->u.leader->segname;
segname_32 = seg_name;
} else {
segname_16 = seg_name;
segname_32 = sd->u.leader->segname;
}
LnkMsg( ERR+MSG_CANT_COMBINE_32_AND_16, "12", segname_32, segname_16 );
}
}
Ring2Append( &CurrMod->segs, sd );
sd->u.leader->dbgtype = dbiflags;
if( sd->isabs ) {
sd->u.leader->seg_addr.off = 0;
sd->u.leader->seg_addr.seg = sd->a.frame;
} else if( !sd->isdead ) {
DBIAddLocal( dbiflags, sd->length );
}
}
extern class_entry * FindClass( section *sect, char *name, bool is32bit,
bool iscode )
/*********************************************************************/
{
class_entry * currclass;
class_entry * lastclass;
unsigned namelen;
if( is32bit ) is32bit = CLASS_32BIT;
currclass = sect->classlist;
lastclass = currclass;
for(;;) {
if( currclass == NULL ) break;
if( stricmp( currclass->name, name ) == 0
&& !((currclass->flags & CLASS_32BIT) ^ is32bit) ) {
return( currclass );
}
lastclass = currclass;
currclass = currclass->next_class;
}
namelen = strlen( name );
currclass = CarveAlloc( CarveClass );
currclass->name = AddStringTable( &PermStrings, name, namelen + 1 );
currclass->segs = NULL;
currclass->section = sect;
currclass->flags = is32bit;
currclass->next_class = NULL;
if( lastclass == NULL ) {
sect->classlist = currclass;
} else {
lastclass->next_class = currclass;
}
DBIColClass( currclass );
if( iscode ) {
currclass->flags |= CLASS_CODE;
}
if( IsConstClass( name, namelen ) ) {
currclass->flags |= CLASS_READ_ONLY;
}
if( IsStackClass( name, namelen ) ) {
currclass->flags |= CLASS_STACK;
}
return( currclass );
}
static void CheckForLast( seg_leader *seg, class_entry *class )
/*************************************************************/
// check to see if this segment should be the last one in an autogroup.
{
if( CurrMod->modinfo & MOD_LAST_SEG && class->flags & CLASS_CODE ) {
if( LastCodeSeg != NULL ) { // more than one code seg
LastCodeSeg->info &= ~LAST_SEGMENT; // so don't end at previous
}
LastCodeSeg = seg;
seg->info |= LAST_SEGMENT;
}
}
static bool CheckClassName( void *_seg, void *_sdata )
/****************************************************/
{
seg_leader *seg = _seg;
segdata *sdata = _sdata;
return stricmp( seg->segname, sdata->u.name ) == 0 &&
seg->combine != COMBINE_INVALID;
}
static void AddToLeader( seg_leader *seg, segdata *sdata )
/********************************************************/
{
segdata * first;
offset length;
if( sdata->combine == COMBINE_COMMON ) {
first = RingFirst( seg->pieces );
length = max( first->length, sdata->length );
if( first->isuninit ) {
first->isdead = TRUE;
RingPush( &seg->pieces, sdata );
sdata->length = length;
} else {
sdata->isdead = TRUE;
RingAppend( &seg->pieces, sdata );
first->length = length;
}
} else { // it must be COMBINE_ADD
RingAppend( &seg->pieces, sdata );
}
}
static void FindALeader( segdata *sdata, class_entry *class, unsigned_16 info )
/*****************************************************************************/
{
seg_leader *seg;
seg = RingLookup( class->segs, CheckClassName, sdata );
if( seg == NULL ) {
MakeNewLeader( sdata, class, info );
} else {
sdata->u.leader = seg;
AddToLeader( seg, sdata );
}
}
extern seg_leader *InitLeader( char *segname, unsigned_16 info )
/**************************************************************/
{
seg_leader * seg;
seg = CarveAlloc( CarveLeader );
seg->next_seg = NULL;
seg->grp_next = NULL;
seg->pieces = NULL;
seg->class = NULL;
seg->size = 0;
seg->num = 0;
seg->seg_addr.off = NULL;
seg->seg_addr.seg = UNDEFINED;
seg->group = NULL;
seg->info = info;
seg->segname = StringStringTable( &PermStrings, segname );
seg->dbgtype = NOT_DEBUGGING_INFO;
seg->segflags = FmtData.def_seg_flags;
return( seg );
}
extern void FreeLeader( void *seg )
/*********************************/
{
RingWalk( ((seg_leader *)seg)->pieces, FreeSegData );
CarveFree( CarveLeader, seg );
}
static void MakeNewLeader( segdata *sdata, class_entry *class, unsigned_16 info)
/******************************************************************************/
{
sdata->u.leader = InitLeader( sdata->u.name, info );
sdata->u.leader->align = sdata->align;
sdata->u.leader->combine = sdata->combine;
sdata->u.leader->class = class;
CheckForLast( sdata->u.leader, class );
RingAppend( &class->segs, sdata->u.leader );
RingAppend( &sdata->u.leader->pieces, sdata );
}
static bool CmpLeaderPtr( void *a, void *b )
/******************************************/
{
return a == b;
}
extern void AddToGroup( group_entry *group, seg_leader *seg )
/***********************************************************/
{
if( Ring2Lookup( group->leaders, CmpLeaderPtr, seg ) ) return;
if( seg->group != NULL && seg->group != group ) {
LnkMsg( LOC+ERR+MSG_SEG_IN_TWO_GROUPS, "123", seg->segname,
seg->group->sym->name, group->sym->name );
return;
}
if( (group->leaders != NULL) && ((group->leaders->info & USE_32) != (seg->info & USE_32)) ) {
char *segname_16;
char *segname_32;
if( seg->info & USE_32 ) {
segname_16 = group->leaders->segname;
segname_32 = seg->segname;
} else {
segname_16 = seg->segname;
segname_32 = group->leaders->segname;
}
LnkMsg( ERR+MSG_CANT_COMBINE_32_AND_16, "12", segname_32, segname_16 );
}
seg->group = group;
Ring2Append( &group->leaders, seg );
}
extern void SetAddPubSym(symbol *sym, int type, mod_entry *mod, offset off,
unsigned_16 frame )
/*************************************************************************/
{
sym->mod = mod;
SET_SYM_TYPE( sym, type );
XDefSymAddr( sym, off, frame );
Ring2Append( &mod->publist, sym );
}
extern void DefineSymbol( symbol *sym, segnode *seg, offset off,
unsigned_16 frame )
/**************************************************************/
// do the object file independent public symbol definition.
{
unsigned name_len;
bool frame_ok;
if( seg != NULL ) {
frame = 0;
}
name_len = strlen( sym->name );
if( sym->addr.seg != UNDEFINED && !IS_SYM_COMMUNAL(sym) ) {
if( seg != NULL && sym->p.seg != NULL ) {
frame_ok = (sym->p.seg->u.leader == seg->entry->u.leader);
if( sym->p.seg->u.leader->combine != COMBINE_COMMON ) {
frame_ok = FALSE;
}
} else if( sym->p.seg != NULL ) {
frame_ok = FALSE;
} else if( frame != sym->addr.seg ) {
frame_ok = FALSE;
} else {
frame_ok = TRUE;
}
if( !(frame_ok && off == sym->addr.off) ) {
ReportMultiple( sym, sym->name, name_len );
}
} else {
if( IS_SYM_COMMUNAL(sym) || IS_SYM_IMPORTED(sym) ) {
sym = HashReplace( sym );
if( IS_SYM_COMMUNAL(sym) ) {
sym->p.seg = NULL;
}
}
ClearSymUnion( sym );
SetAddPubSym(sym, SYM_REGULAR, CurrMod, off, frame);
sym->info &= ~SYM_DISTRIB;
if( seg != NULL ) {
if( LinkFlags & STRIP_CODE ) {
DefStripSym( sym, seg->entry );
}
if( seg->info & SEG_CODE ) {
if( FmtData.type & MK_OVERLAYS && FmtData.u.dos.distribute
&& LinkState & SEARCHING_LIBRARIES ) {
sym->info |= SYM_DISTRIB;
}
}
sym->p.seg = seg->entry;
if( sym->p.seg->isabs )
sym->info |= SYM_ABSOLUTE;
TryDefVector( sym );
} else {
if( LinkFlags & STRIP_CODE ) {
CleanStripInfo( sym );
}
sym->info |= SYM_ABSOLUTE;
sym->p.seg = NULL;
}
}
}
static segdata *GetSegment( char *seg_name, char *class_name, char *group_name,
unsigned align, unsigned comb, bool use_16 )
/*****************************************************************************/
{
section * sect;
class_entry * class;
group_entry * group;
unsigned_16 info;
segdata * sdata;
sect = GetOvlSect( class_name );
class = FindClass( sect, class_name, !use_16, FALSE );
info = 0;
sdata = AllocSegData();
sdata->u.name = seg_name;
sdata->align = align;
sdata->combine = comb;
sdata->isuninit = TRUE;
if( !use_16 ) {
info |= USE_32;
sdata->is32bit = TRUE;
}
FindALeader( sdata, class, info );
Ring2Append( &CurrMod->segs, sdata );
if( group_name != NULL ) {
/* put in appropriate group */
group = GetGroup( group_name );
AddToGroup( group, sdata->u.leader );
}
return sdata;
}
static void NearAllocCommunal( symbol *sym, unsigned size )
/*********************************************************/
{
sym->p.seg = GetSegment( CommunalSegName, BSSClassName, DataGrpName,
2, COMBINE_ADD, !IS_SYM_COMM32(sym) );
sym->p.seg->length = size;
}
static void FarAllocCommunal( symbol *sym, unsigned size )
/********************************************************/
{
segdata * seg;
segdata * first;
first = NULL;
for(;;) {
seg = GetSegment( sym->name, FarDataClassName, NULL,
0, COMBINE_INVALID, !IS_SYM_COMM32(sym) );
if( first == NULL ) first = seg;
if( size < MAX_SEGMENT ) {
seg->length = size;
break;
} else {
seg->length = MAX_SEGMENT;
size -= MAX_SEGMENT;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?