symtab.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,572 行 · 第 1/3 页
C
1,572 行
0x3F91,
0x76B4,
0x6FD2,
0x7BF1,
0x06E2,
0x1984,
0x2926,
0x27EB,
0x390E,
0x6D65,
0x42B3,
0x2D99,
0x2382,
0x1743,
0x43BB,
0x1F5E,
0x3A28,
0x04CD,
0x535A,
0x2966,
0x6450,
0x14F2,
0x3D4F,
0x4482,
0x2C5C,
0x4C1F,
0x778B,
0x3AC6,
0x3E2D,
0x1035,
0x747C,
0x59E4,
0x6051,
0x284C,
0x4E16,
0x6F47,
0x53E9,
0x7C2A,
0x15A6,
0x69EF,
0x475B,
0x4F81,
0x5456,
0x3E0F,
0x47BD,
0x74EC,
0x087F,
0x6668,
0x5CFC,
0x34A8,
0x2BB2,
0x1F63,
0x3CD0,
0x6312,
0x0D84,
0x37F1,
0x4060,
0x62E4,
0x0F1D,
0x1423,
0x08B4,
0x0F2F,
0x0B7F,
0x3D88,
0x7DDF,
0x4918,
0x7897
#endif
};
extern void ResetSym( void )
/**************************/
{
NameLen = 0;
SymList = NULL;
HeadSym = NULL;
LastSym = NULL;
CmpRtn = memicmp;
GetSymBlock();
ClearHashPointers();
}
extern void InitSym( void )
/*************************/
{
_ChkAlloc( GlobalSymPtrs, GLOBAL_TABALLOC );
_ChkAlloc( StaticSymPtrs, STATIC_TABALLOC );
}
#ifdef _INT_DEBUG
static void DumpTable( symbol **table, unsigned tabsize )
/*******************************************************/
{
unsigned mask;
unsigned min;
unsigned max;
unsigned val;
unsigned_32 numsyms;
unsigned index;
symbol * sym;
numsyms = 0;
min = 0xFFFF;
max = 0;
for( index = 0; index < tabsize; index++ ) {
mask = DBG_ALWAYS;
if( index % 15 != 14 ) {
mask |= DBG_NOCRLF;
}
val = 0;
sym = table[index];
while( sym != 0 ) {
val++;
sym = sym->hash;
}
DEBUG(( mask, "%x ", val ));
if( val > max ) {
max = val;
}
if( val < min ) {
min = val;
}
numsyms += val;
}
DEBUG(( DBG_ALWAYS, "" )); // put out a blank line.
DEBUG(( DBG_ALWAYS, "# of syms: %l, max height %d, min height %d",
numsyms, max, min ));
}
static void DumpHashTable( void )
/*******************************/
{
if( LinkState & INTERNAL_DEBUG ) {
DEBUG(( DBG_ALWAYS, "symbol table load" ));
DumpTable( GlobalSymPtrs, GLOBAL_TABSIZE );
DumpTable( StaticSymPtrs, STATIC_TABSIZE );
}
}
#endif
static void WipeSym( symbol *sym )
/********************************/
{
if( IS_SYM_IMPORTED(sym) && !(FmtData.type & MK_ELF) ) {
if( FmtData.type & MK_NOVELL ) {
if( sym->p.import != DUMMY_IMPORT_PTR ) {
_LnkFree( sym->p.import );
}
} else {
FreeImport( sym->p.import );
}
sym->p.import = NULL;
} else if( IS_SYM_ALIAS(sym) ) {
if( sym->info & SYM_FREE_ALIAS ) {
_LnkFree( sym->p.alias );
}
sym->u.aliaslen = 0; // make sure this is nulled again
}
}
static void FreeSymbol( symbol *sym )
/***********************************/
{
WipeSym( sym );
CarveFree( CarveSymbol, sym );
}
extern void CleanSym( void )
/*************************/
{
symbol * sym;
symbol * next;
#ifdef _INT_DEBUG
DumpHashTable();
#endif
if( !(LinkFlags & INC_LINK_FLAG) ) {
for( sym = HeadSym; sym != NULL; sym = next ) {
next = sym->link;
FreeSymbol( sym );
}
}
RelSymBlock();
ReleasePass1();
}
extern void FiniSym( void )
/*************************/
{
_LnkFree( GlobalSymPtrs );
_LnkFree( StaticSymPtrs );
}
static void PrepHashTable( symbol **table, unsigned size )
/********************************************************/
{
while( size > 0 ) {
*table = CarveGetIndex( CarveSymbol, *table );
table++;
size--;
}
}
extern void WriteHashPointers( void *cookie )
/*******************************************/
{
PrepHashTable( StaticSymPtrs, STATIC_TABSIZE );
WritePermFile( cookie, StaticSymPtrs, STATIC_TABALLOC );
PrepHashTable( GlobalSymPtrs, GLOBAL_TABSIZE );
WritePermFile( cookie, GlobalSymPtrs, GLOBAL_TABALLOC );
}
static void RebuildHashTable( symbol **table, unsigned size )
/***********************************************************/
{
while( size > 0 ) {
*table = CarveMapIndex( CarveSymbol, *table );
table++;
size--;
}
}
extern void ReadHashPointers( void *cookie )
/******************************************/
{
ReadPermFile( cookie, StaticSymPtrs, STATIC_TABALLOC );
ReadPermFile( cookie, GlobalSymPtrs, GLOBAL_TABALLOC );
RebuildHashTable( StaticSymPtrs, STATIC_TABSIZE );
RebuildHashTable( GlobalSymPtrs, GLOBAL_TABSIZE );
}
extern void ClearHashPointers( void )
/***********************************/
{
memset( GlobalSymPtrs, 0, GLOBAL_TABSIZE * sizeof(symbol *) );
memset( StaticSymPtrs, 0, STATIC_TABSIZE * sizeof(symbol *) );
}
extern void SetSymCase( void )
/****************************/
{
if( LinkFlags & CASE_FLAG ) {
CmpRtn = memcmp;
} else {
CmpRtn = memicmp;
}
}
extern void SymModStart( void )
/*****************************/
/* do necessary symbol table processing before the start of a module in pass1 */
{
SymList = LastSym;
}
extern void SymModEnd( void )
/***************************/
/* go through the list of symbols generated in this module, and find all
* references to symbols which are in this module only. */
{
symbol * sym;
if( SymList == NULL ) {
sym = HeadSym;
} else {
sym = SymList;
if( sym != NULL ) { // symlist points to previous one
sym = sym->link;
}
}
while( sym != NULL ) {
sym->info &= ~SYM_IN_CURRENT;
sym->info |= SYM_OLDHAT;
if( sym->info & SYM_REFERENCED && sym->info & SYM_DEFINED ) {
sym->info &= ~SYM_REFERENCED;
sym->info |= SYM_LOCAL_REF;
}
sym = sym->link;
}
SymList = NULL;
}
extern void ClearRefInfo( symbol *sym )
/*************************************/
{
symbol * save;
if( !(sym->info & SYM_EXPORTED) ) {
save = *(sym->e.vfdata);
_LnkFree( sym->e.vfdata );
sym->e.def = save;
}
}
extern void ClearSymUnion( symbol * sym )
/***************************************/
/* clear the symbol unions of any possible allocated data */
{
sym->info &= ~SYM_LINK_GEN;
if( IS_SYM_VF_REF(sym) ) {
ClearRefInfo( sym );
} else {
WipeSym( sym );
}
}
extern symbol * RefISymbol( char *name )
/**************************************/
{
return SymOp( ST_CREATE | ST_REFERENCE, name, strlen( name ) );
}
extern symbol * DefISymbol( char * name )
/***************************************/
{
symbol * sym;
sym = RefISymbol( name );
if( sym->info & SYM_DEFINED && !(sym->info & SYM_LINK_GEN) ) {
LnkMsg( ERR+MSG_RESERVED_SYM_DEFINED, "s", name );
}
sym->info |= SYM_DEFINED | SYM_LINK_GEN;
return sym;
}
extern symbol * FindISymbol( char *name )
/***************************************/
{
return SymOp( ST_FIND | ST_REFERENCE, name, strlen( name ) );
}
extern symbol * SymXOp( sym_flags op, char *name, int length )
/************************************************************/
{
char * symname;
symname = alloca( length + 1 );
if( symname == NULL ) {
name[length - 1] = '\0';
LnkMsg( ERR+MSG_SYMBOL_NAME_TOO_LONG, "s", name );
symname = name;
} else {
memcpy( symname, name, length );
symname[ length ] = '\0';
}
return( SymOp( op, symname, length ) );
}
extern symbol * SymXOpNWPfx( sym_flags op, char *name, int length, char * prefix, int prefixLen)
/************************************************************/
{
symbol * retsym = SymXOp(op, name, length);
if( NULL == retsym )
return NULL;
if( ((NULL != prefix) && (0 != prefixLen)) || (NULL != CmdFile->symprefix) ) {
char * pfxname = alloca(255+1); /* max len of PString - used to be prefixLen+1 */
if( NULL == pfxname ) {
LnkMsg( ERR+MSG_SYMBOL_NAME_TOO_LONG, "s", prefix );
return NULL;
}
if( prefix ) {
memcpy( pfxname, prefix, prefixLen );
pfxname[ prefixLen] = '\0';
}
else
strcpy( pfxname, CmdFile->symprefix );
if( NULL == (retsym->prefix = AddStringTable( &PrefixStrings, pfxname, strlen( pfxname ) + 1 )) ) {
LnkMsg( ERR+MSG_INTERNAL, "s", "no memory for prefix symbol");
return NULL;
}
}
return retsym;
}
extern void MakeSymAlias( char *name, int namelen, char *target, int targetlen )
/******************************************************************************/
/* make a symbol table alias */
{
symbol * sym;
if( namelen == targetlen && (*CmpRtn)( name, target, namelen ) == 0 ) {
LnkMsg( WRN+MSG_CIRCULAR_ALIAS_FOUND, "s", target );
_LnkFree( target );
return; // <--------- NOTE: premature return!!!!
}
sym = SymXOp( ST_CREATE | ST_NOALIAS, name, namelen );
if( IS_SYM_ALIAS( sym ) ) {
LnkMsg( WRN+MSG_MULTIPLE_ALIASES, "S", sym );
if( sym->info & SYM_FREE_ALIAS ) {
_LnkFree( sym->p.alias );
}
} else if( sym->info & SYM_DEFINED ) {
_LnkFree( target );
return; // <--------- NOTE: premature return!!!!
}
sym->info |= SYM_FREE_ALIAS;
SetSymAlias( sym, target, targetlen );
/*
* need to defined aliased symbol as well, so aliases in .obj files can be
* hauled in from libraries
*/
SymOp( ST_CREATE, target, targetlen );
}
extern void WeldSyms( symbol * src, symbol * targ )
/*************************************************/
/* make all references to src refer to targ. (alias src to targ) */
{
if( targ != NULL ) {
SetSymAlias( src, targ->name, strlen(targ->name) );
}
}
static void SetSymAlias( symbol * sym, char *target, int targetlen )
/******************************************************************/
{
SET_SYM_TYPE( sym, SYM_ALIAS );
sym->p.alias = target;
sym->u.aliaslen = targetlen;
sym->info |= SYM_DEFINED; /* an alias can't be undefined */
sym->info &= ~SYM_WAS_LAZY;
}
static symbol * GlobalSearchSym( char *symname, int hash, int len )
/*****************************************************************/
/* search through the given chain for the given name */
{
symbol * sym;
sym = GlobalSymPtrs[ hash ];
while( sym != NULL ) {
if( len == sym->namelen ) {
if( (*CmpRtn)( symname, sym->name, len ) == 0 )
break;
}
sym = sym->hash;
}
return( sym );
}
static symbol * StaticSearchSym( char *symname, unsigned hash, int len )
/**********************************************************************/
/* search through the given chain for the given name */
{
symbol * sym;
sym = StaticSymPtrs[ hash ];
while( sym != NULL ) {
if( sym->info & SYM_IN_CURRENT && len == sym->namelen ) {
if( memcmp( symname, sym->name, len ) == 0 )
break;
}
sym = sym->hash;
}
return( sym );
}
static symbol * DoSymOp( byte op, char *symname, int length )
/***********************************************************/
{
unsigned hash;
symbol * sym;
int searchlen;
DEBUG(( DBG_OLD, "SymOp( %d, %s, %d )", op, symname, length ));
if( NameLen != 0 && NameLen < length ) {
searchlen = NameLen;
} else {
searchlen = length + 1 ; /* include NULLCHAR in comparison */
}
if( op & ST_STATIC ) {
hash = StaticHashFn( symname, searchlen );
sym = StaticSearchSym( symname, hash, searchlen );
} else {
hash = GlobalHashFn( symname, searchlen );
sym = GlobalSearchSym( symname, hash, searchlen );
}
DEBUG(( DBG_OLD, "- hash %d", hash ));
if( sym != NULL ) {
DEBUG(( DBG_OLD, "found symbol %s", symname ));
DEBUG(( DBG_OLD, " - handle = %h", sym ));
return( sym );
}
if( !(op & ST_FIND) ) {
sym = AddSym();
sym->name = AddStringTable( &PermStrings, symname, length + 1 );
sym->namelen = searchlen;
if( op & ST_STATIC ) {
sym->info |= SYM_STATIC;
sym->hash = StaticSymPtrs[hash];
StaticSymPtrs[hash] = sym;
} else {
sym->hash = GlobalSymPtrs[hash];
GlobalSymPtrs[hash] = sym;
}
DEBUG((DBG_OLD, "added symbol %s", symname ));
}
return( sym );
}
extern symbol * UnaliasSym( sym_flags op, symbol *sym )
/*****************************************************/
{
symbol *orig_sym = sym;
while( sym != NULL && IS_SYM_ALIAS(sym) ) {
sym = DoSymOp( op, sym->p.alias, sym->u.aliaslen );
/* circular ref, may be a weak symbol ! */
if( sym == orig_sym )
break;
}
return sym;
}
extern symbol * SymOp( sym_flags op, char *symname, int length )
/**************************************************************/
/* search for symbols, handling aliases */
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?