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