assymbol.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 467 行
C
467 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "as.h"
#define HASH_TABLE_SIZE 211
static sym_handle hashTable[ HASH_TABLE_SIZE ];
typedef struct sym_reloc_handle *sym_reloc_hdl_list;
struct sym_reloc_handle {
sym_handle hdl;
sym_reloc_hdl_list prev;
sym_reloc_hdl_list next;
};
typedef struct {
sym_reloc_hdl_list head;
sym_reloc_hdl_list tail;
} sym_reloc_hdls;
// These lists link all the sym_handles that have relocs hanging
// off of them, so that we can check for unemitted relocs at the end.
static sym_reloc_hdls hi_reloc_hdls = { NULL, NULL };
static sym_reloc_hdls lo_reloc_hdls = { NULL, NULL };
static void hdl_append( sym_reloc_hdls *hdls, sym_handle sym ) {
//**************************************************************
// Append a sym_handle to the list of symbols that have relocs to them.
sym_reloc_hdl_list hdl;
// make sure you only append symbols that have hi/lo relocs to them,
// depending on what hdls is.
hdl = MemAlloc( sizeof( struct sym_reloc_handle ) );
hdl->hdl = sym;
hdl->prev = NULL;
hdl->next = NULL;
if( !hdls->head ) {
hdls->head = hdls->tail = hdl;
} else {
hdl->prev = hdls->tail;
hdls->tail->next = hdl;
hdls->tail = hdl;
}
}
static void hdl_remove( sym_reloc_hdls *hdls, sym_handle sym ) {
//**************************************************************
// Getting rid of a symbol from the list since it doesn't have relocs to
// it any more.
sym_reloc_hdl_list hdl;
// make sure you remove only when there aren't any hi/lo relocs to the
// symbol, depending on what hdls is.
hdl = hdls->head;
while( hdl ) {
if( hdl->hdl == sym ) {
if( hdl->prev ) {
hdl->prev->next = hdl->next;
} else {
hdls->head = hdl->next;
}
if( hdl->next ) {
hdl->next->prev = hdl->prev;
} else {
hdls->tail = hdl->prev;
}
MemFree( hdl );
return;
}
hdl = hdl->next;
}
assert( FALSE ); // sym should be in the list!
}
static uint_32 symHash( const char *sym ) {
//*****************************************
return( AsHashVal( sym, HASH_TABLE_SIZE ) );
}
static sym_handle symAlloc( const char *name ) {
//**********************************************
// Alloc a symbol for a given name and return it
sym_handle sym;
sym = MemAlloc( sizeof( asm_symbol ) + strlen( name ) );
strcpy( sym->name, name );
return( sym );
}
static void symFree( sym_handle sym ) {
//*************************************
// Free up a symbol.
// The 2 lists should be cleaned up already
assert( sym->hi_relocs == NULL );
assert( sym->lo_relocs == NULL );
MemFree( sym );
}
extern void SymInit() {
//***********************
// Init routine for Symbol Table library
}
extern sym_handle SymLookup( const char *sym_name ) {
//***************************************************
// Return a handle for a symbol with the given name, or
// NULL if we don't have anything which matches
// move to front would probably be useful here
sym_handle sym;
sym = hashTable[ symHash( sym_name ) ];
while( sym != NULL ) {
if( !strcmp( sym_name, sym->name ) ) break;
sym = sym->next;
}
return( sym );
}
extern sym_handle SymAdd( const char *sym_name, sym_class class ) {
//*****************************************************************
// Add a symbol with the given name and class to our symbol table.
// Other symbol attrs will have to be added individually.
sym_handle sym;
sym_handle *bucket;
assert( SymLookup( sym_name ) == NULL );
bucket = &hashTable[ symHash( sym_name ) ];
sym = symAlloc( sym_name );
sym->class = class;
sym->flags = SF_EXTERN;
sym->linkage = SL_UNKNOWN;
sym->hi_relocs = sym->lo_relocs = NULL;
sym->obj_hdl = NULL;
sym->next = *bucket;
*bucket = sym;
return( sym );
}
#ifndef _STANDALONE_
extern bool SymLocationKnown( sym_handle sym ) {
//**********************************************
// Return TRUE if we know where a given label is
// going to be located.
assert( sym->class == SYM_LABEL );
return( sym->flags & SF_LOC_KNOWN );
}
extern sym_handle SymSetLocation( sym_handle sym, sym_location loc ) {
//********************************************************************
// Mark the symbol given as residing at location x. The sym_handle is
// returned, as a matter of convenience.
assert( sym->class == SYM_LABEL );
sym->u.location = loc;
sym->flags |= SF_LOC_KNOWN;
return( sym );
}
extern sym_location SymGetLocation( sym_handle sym ) {
//****************************************************
// Return the location for a symbol - yes, this does return a
// struct - forgive me
assert( sym->class == SYM_LABEL );
return( sym->u.location );
}
#endif
#ifdef _STANDALONE_
extern bool SymIsSectionSymbol( sym_handle sym ) {
//************************************************
return( sym->flags & SF_SECTION );
}
extern void SymSetSection( sym_handle sym ) {
//*******************************************
// Set the section flag and so SymIsSectionSymbol will know if the symbol is
// a valid section symbol.
sym->flags |= SF_SECTION;
}
#endif
extern sym_handle SymSetLink( sym_handle sym, sym_link link ) {
//*************************************************************
// set the link field of the symbol - either the instruction or directive
// pointer for instructions and directives respectively
assert( sym->class == SYM_INSTRUCTION || sym->class == SYM_DIRECTIVE );
sym->u.link = link;
return( sym );
}
extern sym_link SymGetLink( sym_handle sym ) {
//********************************************
// return the link field of the symbol - used for
// remembering symbol specific info for instructions and directives.
assert( sym->class == SYM_INSTRUCTION || sym->class == SYM_DIRECTIVE );
return( sym->u.link );
}
extern sym_class SymClass( sym_handle sym ) {
//*******************************************
return( sym->class );
}
extern sym_linkage SymGetLinkage( sym_handle sym ) {
//**************************************************
assert( sym->class == SYM_LABEL );
return( sym->linkage );
}
extern sym_handle SymSetLinkage( sym_handle sym, sym_linkage linkage ) {
//**********************************************************************
assert( sym->class == SYM_LABEL );
sym->linkage = linkage;
return( sym );
}
extern char *SymName( sym_handle sym ) {
//**************************************
return( sym->name );
}
#ifdef _STANDALONE_
extern sym_obj_hdl SymObjHandle( sym_handle sym ) {
//*************************************************
assert( sym->class == SYM_LABEL );
if( sym->obj_hdl == NULL ) {
sym->obj_hdl = ObjSymbolInit( sym->name );
}
return( sym->obj_hdl );
}
#endif
extern void SymStackReloc( bool is_high, sym_handle sym, sym_section section, sym_offset offset, bool named ) {
//*************************************************************************************************************
sym_reloc reloc;
sym_reloc *curr;
sym_reloc_hdls *hdls_ptr;
assert( sym != NULL );
assert( sym->class == SYM_LABEL );
reloc = MemAlloc( sizeof( struct sym_reloc_entry ) );
reloc->location.section = section;
reloc->location.offset = offset;
reloc->prev = reloc->next = NULL;
reloc->named = named;
if( is_high ) {
curr = &sym->hi_relocs;
hdls_ptr = &hi_reloc_hdls;
} else {
curr = &sym->lo_relocs;
hdls_ptr = &lo_reloc_hdls;
}
if( *curr ) {
(*curr)->prev = reloc;
reloc->next = *curr;
} else { // First element in the list; add sym to the hdls list
hdl_append( hdls_ptr, sym );
}
*curr = reloc;
}
extern void SymDestroyReloc( sym_handle sym, sym_reloc reloc ) {
//**************************************************************
assert( sym->class == SYM_LABEL );
assert( reloc );
if( reloc->prev ) {
reloc->prev->next = reloc->next;
} else { // the head element
if( sym->hi_relocs == reloc ) {
sym->hi_relocs = reloc->next;
if( sym->hi_relocs == NULL ) { // list empty; remove hdl from hdls
hdl_remove( &hi_reloc_hdls, sym );
}
} else {
assert( sym->lo_relocs == reloc );
sym->lo_relocs = reloc->next;
if( sym->lo_relocs == NULL ) { // list empty; remove hdl from hdls
hdl_remove( &lo_reloc_hdls, sym );
}
}
}
if( reloc->next ) {
reloc->next->prev = reloc->prev;
}
MemFree( reloc );
}
extern sym_reloc SymMatchReloc( bool is_high, sym_handle sym, sym_section section ) {
//***********************************************************************************
sym_reloc curr;
assert( sym->class == SYM_LABEL );
curr = ( is_high ? sym->hi_relocs : sym->lo_relocs );
while( curr ) {
if( curr->location.section == section ) { // want same section handle
return( curr );
}
curr = curr->next;
}
return( curr );
}
extern sym_reloc SymGetReloc( bool is_high, sym_handle *get_hdl ) {
//*****************************************************************
// This function returns a sym_reloc from the list of handle with relocs if one
// is available, and returns NULL otherwise. Caller should call SymDestroyReloc
// to free the reloc after its use.
sym_reloc_hdl_list lhdl;
if( is_high ) { // getting a high reloc
if( ( lhdl = hi_reloc_hdls.head ) == NULL ) return( NULL );
assert( lhdl->hdl->hi_relocs != NULL );
*get_hdl = lhdl->hdl;
return( lhdl->hdl->hi_relocs );
}
// getting a low reloc
if( ( lhdl = lo_reloc_hdls.head ) == NULL ) return( NULL );
assert( lhdl->hdl->lo_relocs != NULL );
*get_hdl = lhdl->hdl;
return( lhdl->hdl->lo_relocs );
}
#ifndef NDEBUG
extern bool SymRelocIsClean( bool is_clean ) {
//********************************************
// Just a debug tool to see whether I've cleaned up.
static bool isClean = FALSE;
bool prev;
prev = isClean;
isClean = is_clean;
return( prev );
}
#endif
extern void SymFini() {
//*********************
// Fini routine for Symbol Table library
sym_handle sym;
sym_handle next;
int i;
int n;
sym_reloc reloc;
#ifndef NDEBUG
#ifdef _STANDALONE_
if( _IsOption( DUMP_SYMBOL_TABLE ) ) DumpSymbolTable();
#endif
#endif
reloc = SymGetReloc( TRUE, &sym );
while( reloc != NULL ) {
assert( SymRelocIsClean( FALSE ) == FALSE );
SymDestroyReloc( sym, reloc );
reloc = SymGetReloc( TRUE, &sym );
}
reloc = SymGetReloc( FALSE, &sym );
while( reloc != NULL ) {
assert( SymRelocIsClean( FALSE ) == FALSE );
SymDestroyReloc( sym, reloc );
reloc = SymGetReloc( FALSE, &sym );
}
assert( hi_reloc_hdls.head == NULL && hi_reloc_hdls.tail == NULL );
assert( lo_reloc_hdls.head == NULL && lo_reloc_hdls.tail == NULL );
n = sizeof( hashTable ) / sizeof( hashTable[ 0 ] );
for( i = 0; i < n; i++ ) {
for( sym = hashTable[ i ]; sym != NULL; sym = next ) {
next = sym->next;
symFree( sym );
}
hashTable[ i ] = 0;
}
}
#ifdef _STANDALONE_
#ifndef NDEBUG
static char classChar[] = { 'I', 'D', 'L' };
extern void DumpSymbol( sym_handle sym ) {
//****************************************
printf( "%s(addr=%x; next=%x; class = %c; ", sym->name, sym, sym->next, classChar[ sym->class ] );
if( sym->class == SYM_LABEL ) {
printf( "location = %x:%x )", sym->u.location.section, sym->u.location.offset );
} else {
printf( "link = %x )", sym->u.link );
}
}
extern void DumpSymbolTable() {
//*****************************
int i;
sym_handle curr;
for( i = 0; i < HASH_TABLE_SIZE; i++ ) {
curr = hashTable[ i ];
if( curr == NULL ) continue;
printf( "Bucket %d: ", i );
while( curr != NULL ) {
DumpSymbol( curr );
printf( " " );
curr = curr->next;
}
printf( "\n" );
}
}
#endif
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?