symtable.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,080 行 · 第 1/3 页
C
1,080 行
char buff[20];
char *stringpad = NULL;
int stringpadlen = 0;
SortSymbols();
// figure out this dictionary sizes
switch( Options.libtype ) {
case WL_TYPE_AR:
dict1_size = sizeof( unsigned_32 )
+ NumSymbols * sizeof(unsigned_32)
+ RoundWord( TotalSymbolLength );
dict2_size = sizeof( unsigned_32 )
+ NumFiles * sizeof( unsigned_32 )
+ sizeof( unsigned_32 )
+ NumSymbols * sizeof( unsigned_16 )
+ RoundWord( TotalSymbolLength );
header_size = AR_IDENT_LEN
+ 3 * AR_HEADER_SIZE
+ dict1_size
+ dict2_size
+ RoundWord( TotalNameLength );
stringpad = "\0";
stringpadlen= 1;
break;
case WL_TYPE_MLIB:
dict2_size = sizeof( unsigned_32 )
+ NumSymbols * (1 + sizeof( unsigned_32 ) )
+ TotalSymbolLength;
header_size = LIBMAG_LEN + LIB_CLASS_LEN + LIB_DATA_LEN
+ 3 * LIB_HEADER_SIZE
+ RoundWord( dict2_size )
+ RoundWord( TotalNameLength )
+ RoundWord( TotalFFNameLength );
stringpad = LIB_LONG_NAME_END_STRING;
stringpadlen= LIB_LONG_NAME_END_STRING_LEN;
break;
}
// calculate the object files offsets
index = 0;
obj_offset = 0;
for( file = FileTable.first; file != NULL; file = file->next ) {
file->new_offset = obj_offset + header_size;
file->index = ++index;
obj_offset += RoundWord( file->arch.size ) + AR_HEADER_SIZE;
}
switch( Options.libtype ) {
case WL_TYPE_AR:
WriteNew( AR_IDENT, AR_IDENT_LEN );
break;
case WL_TYPE_MLIB:
WriteNew( LIBMAG, LIBMAG_LEN );
WriteNew( LIB_CLASS_DATA_SHOULDBE, LIB_CLASS_LEN + LIB_DATA_LEN );
break;
}
// write the useless dictionary
arch.date = currenttime;
arch.uid = 0;
arch.gid = 0;
arch.mode = 0;
if( Options.libtype == WL_TYPE_AR ) {
arch.size = dict1_size;
arch.name = "/";
WriteFileHeader( &arch );
WriteBigEndian32( NumSymbols );
for( file = FileTable.first; file != NULL; file = file->next ) {
for( sym = file->first; sym != NULL; sym = sym->next ) {
WriteBigEndian32( sym->file->new_offset );
}
}
for( file = FileTable.first; file != NULL; file = file->next ) {
for( sym = file->first; sym != NULL; sym = sym->next ) {
WriteNew( sym->name, sym->len+1 );
}
}
WritePad( TotalSymbolLength );
}
// write the useful dictionary
arch.size = dict2_size;
arch.name = "/";
WriteFileHeader( &arch );
if( Options.libtype == WL_TYPE_AR ) {
WriteLittleEndian32( NumFiles );
for( file = FileTable.first; file != NULL; file = file->next ) {
WriteLittleEndian32( file->new_offset );
}
}
WriteLittleEndian32( NumSymbols );
switch( Options.libtype ) {
case WL_TYPE_AR:
for( i = 0; i < NumSymbols; ++i ) {
WriteLittleEndian16( SortedSymbols[i]->file->index );
}
break;
case WL_TYPE_MLIB:
for( i = 0; i < NumSymbols; ++i ) {
WriteLittleEndian32( SortedSymbols[i]->file->index );
}
for( i=0; i < NumSymbols; ++i ) {
WriteNew( &(SortedSymbols[i]->info), 1 );
}
break;
}
for( i = 0; i < NumSymbols; ++i ) {
WriteNew( SortedSymbols[i]->name, SortedSymbols[i]->len + 1 );
}
switch( Options.libtype ) {
case WL_TYPE_AR:
WritePad( TotalSymbolLength );
break;
case WL_TYPE_MLIB:
WritePad( dict2_size );
break;
}
// write the string table
arch.size = TotalNameLength;
arch.name = "//";
WriteFileHeader( &arch );
for( file = FileTable.first; file != NULL; file = file->next ) {
if( file->name_offset == -1 ) continue;
// Always write the "full" filename for AR
if( Options.libtype == WL_TYPE_AR && file->arch.ffname ) {
WriteNew( file->arch.ffname, file->ffname_length );
} else {
WriteNew( file->arch.name, file->name_length );
}
WriteNew( stringpad, stringpadlen );
}
WritePad( TotalNameLength );
// write the full filename table
if( Options.libtype == WL_TYPE_MLIB ) {
arch.size = TotalFFNameLength;
arch.name = "///";
WriteFileHeader( &arch );
for( file=FileTable.first; file != NULL; file = file->next ) {
WriteNew( file->arch.ffname, file->ffname_length + 1 );
}
WritePad( TotalFFNameLength );
}
for( file = FileTable.first; file != NULL; file = file->next ) {
arch = file->arch;
buff[0] = '/';
itoa( file->name_offset, buff+1, 10 );
arch.name = buff;
WriteFileHeader( &arch );
if( file->import == NULL ){
if( file->inlib_offset != 0 ) {
LibSeek( InLibHandle( file->inlib ), file->inlib_offset, SEEK_SET );
Copy( InLibHandle( file->inlib ), NewLibrary, arch.size );
} else {
io = LibOpen( file->full_name, LIBOPEN_BINARY_READ );
Copy( io, NewLibrary, arch.size );
LibClose( io );
}
}else{
switch( file->import->type ) {
case ELF:
case ELFRENAMED:
ElfWriteImport( NewLibrary, file );
break;
default:
CoffWriteImport( NewLibrary, file );
break;
}
}
WritePad( file->arch.size );
}
}
void WriteFileTable( void )
/*************************/
{
if( Options.libtype == 0 && Options.omf_found ) {
if( Options.coff_found ) {
Options.libtype = WL_TYPE_AR;
} else {
Options.libtype = WL_TYPE_OMF;
}
}
if( Options.coff_found && (Options.libtype == 0 || Options.libtype == WL_TYPE_OMF) ) {
Options.libtype = WL_TYPE_AR;
}
if( Options.elf_found && (Options.libtype == 0 || Options.libtype == WL_TYPE_OMF) ) {
Options.libtype = WL_TYPE_AR;
}
if( Options.libtype == WL_TYPE_AR || Options.libtype == WL_TYPE_MLIB ) {
WriteArMlibFileTable();
} else {
WriteOmfFileTable();
}
}
static int Hash( char *string, unsigned *plen )
/*********************************************/
{
unsigned long g;
unsigned long h;
h = 0;
*plen = 0;
while( *string != 0 ) {
h = ( h << 4 ) + *string;
if( (g = h & 0xf0000000) ) {
h = h ^ ( g >> 24 );
h = h ^ g;
}
++string;
++*plen;
}
return( h % HASH_SIZE );
}
void AddSym( char *name, symbol_strength strength, unsigned char info )
/*********************************************************************/
{
sym_entry *sym,**owner;
int hash;
unsigned name_len;
hash = Hash( name, &name_len );
for( sym = HashTable[ hash ]; sym != NULL; sym = sym->hash ) {
if( sym->len != name_len ) continue;
if( SymbolNameCmp( sym->name, name ) == 0 ) {
if( strength > sym->strength ) {
owner = &sym->file->first;
while( *owner != sym ) {
owner = &(*owner)->next;
}
*owner = sym->next;
owner = &HashTable[ hash ];
while( *owner != sym ) {
owner = &(*owner)->hash;
}
*owner = sym->hash;
MemFreeGlobal( sym );
break; //db
} else if( strength == sym->strength ) {
if( strength == SYM_STRONG ) {
Warning( ERR_DUPLICATE_SYMBOL, FormSym( name ) );
}
}
return;
}
}
sym = MemAllocGlobal( sizeof(sym_entry) + name_len );
sym->len = name_len;
sym->strength = strength;
sym->info = info;
memcpy( sym->name, name, name_len + 1 );
sym->next = CurrFile->first;
CurrFile->first = sym;
sym->file = CurrFile;
sym->hash = HashTable[ hash ];
HashTable[ hash ] = sym;
}
#ifdef __DEBUG__
void DumpFileTable( void )
{
sym_file *file;
sym_entry *entry;
sym_entry *hash;
unsigned len;
int hval;
long files = 0L;
long symbols = 0L;
printf("----------------------------------------------------------\n");
printf("File Table Dump\n");
printf("----------------------------------------------------------\n");
for (file = FileTable.first; file; file = file->next) {
++files;
printf("File: \"%s\"\n", file->full_name);
for (entry = file->first; entry; entry = entry->next) {
++symbols;
hval = Hash(entry->name, &len);
printf("\t\"%s\" (%d, %u, \"%s\")", entry->name, hval, len,
(HashTable[hval] ? HashTable[hval]->name : "(NULL)"));
for (hash = entry->hash; hash; hash = hash->hash) {
printf(" -> \"%s\"", hash->name);
fflush(stdout);
}
printf("\n");
}
}
printf("----------------------------------------------------------\n");
printf("Files : %ld\n", files);
printf("Symbols : %ld\n", symbols);
printf("----------------------------------------------------------\n");
} /* DumpFileTable() */
void DumpHashTable( void )
{
sym_entry *hash;
int i;
int length;
printf("----------------------------------------------------------\n");
printf("Hash Table Dump\n");
printf("----------------------------------------------------------\n");
for (i = 0; i < HASH_SIZE; ++i) {
length = 0;
if (HashTable[i]) {
for (hash = HashTable[i]; hash; hash = hash->next) {
++length;
}
}
printf("Offset %6d: %d\n", i, length);
}
printf("----------------------------------------------------------\n");
} /* DumpHashTable() */
#endif // __DEBUG__
bool RemoveObjectSymbols( char *name )
/************************************/
{
sym_file *file;
sym_file *prev;
sym_entry *sym;
prev = NULL;
for( file = FileTable.first; file != NULL; file = file->next ) {
if( SymbolNameCmp( file->full_name, name ) == 0 ) {
if (prev) { /* Not deleting from head of list */
prev->next = file->next;
if( FileTable.add_to == &file->next ){ /* Last node in list */
FileTable.add_to = &prev->next;
}
} else {
if (FileTable.add_to == &file->next) { /* Only node in list */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?