/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/hash.c,v 1.19 2001/07/25 15:05:07 dawes Exp $ */ /* * * Copyright 1995-1998 by Metro Link, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Metro Link, Inc. not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Metro Link, Inc. makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "os.h" #include "Xos.h" #undef abs #include #include "sym.h" #include "loader.h" #include "hash.h" #if defined(Lynx) #define MAXINT 32000 #else #include #undef MAXINT #define MAXINT INT_MAX #endif /* Prototypes for static functions. */ static unsigned int hashFunc(const char *); static itemPtr LoaderHashFindNearest( #if NeedFunctionPrototypes unsigned long #endif ); static itemPtr LoaderhashTable[ HASHSIZE ] ; #ifdef DEBUG static int hashhits[ HASHSIZE ] ; void DumpHashHits(void) { int i; int depth=0; int dev=0; for(i=0;iname ) ; itemPtr oentry; if ((oentry = LoaderHashFind(entry->name)) != NULL) LoaderDuplicateSymbol(entry->name, oentry->handle); entry->next = LoaderhashTable[ bucket ] ; LoaderhashTable[ bucket ] = entry ; return; } void LoaderAddSymbols(handle, module, list) int handle; int module; LOOKUP *list ; { LOOKUP *l = list, *exports = NULL; itemPtr i, exportsItem = NULL; char *modname; if (!list) return; /* * First look for a symbol called ExportedSymbols. If it exists, * only export the symbols that are listed in that array. Otherwise * export all of the external symbols. */ modname = _LoaderHandleToCanonicalName(handle); if (modname) { char *exportname; exportname = xf86loadermalloc(strlen("ExportedSymbols") + strlen(modname) + 1); if (exportname) { sprintf(exportname, "%sExportedSymbols", modname); while (l->symName) { if (strcmp(l->symName, exportname) == 0) { exports = l; ErrorF("LoaderAddSymbols: %s: %s found\n", modname, exportname); break; } l++; } } } /* * Allocate the exports list item first. */ if (exports) { exportsItem = xf86loadermalloc( sizeof( itemRec )) ; exportsItem->name = exports->symName ; exportsItem->address = (char *) exports->offset ; exportsItem->handle = handle ; exportsItem->module = module ; exportsItem->exports = NULL; LoaderHashAdd( exportsItem ); } /* * Visit every symbol in the lookup table, tagging it with the * reference to the export list, if present. */ l = list; while ( l->symName ) { if (l != exports) { i = xf86loadermalloc( sizeof( itemRec )) ; i->name = l->symName ; i->address = (char *) l->offset ; i->handle = handle ; i->module = module ; i->exports = exportsItem; LoaderHashAdd( i ); } l ++ ; } } itemPtr LoaderHashDelete(string) const char *string; { int bucket = hashFunc( string ) ; itemPtr entry; itemPtr *entry2; entry = LoaderhashTable[ bucket ] ; entry2= &(LoaderhashTable[ bucket ]); while ( entry ) { if (! strcmp( entry->name, string )) { *entry2=entry->next; xf86loaderfree(entry->name); xf86loaderfree( entry ) ; return 0 ; } entry2 = &(entry->next) ; entry = entry->next ; } return 0 ; } itemPtr LoaderHashFind(string) const char *string; { int bucket = hashFunc( string ) ; itemPtr entry ; entry = LoaderhashTable[ bucket ] ; while ( entry ) { if (!strcmp(entry->name, string)) { return entry; } entry = entry->next; } return 0; } static itemPtr LoaderHashFindNearest(address) unsigned long address; { int i ; itemPtr entry, best_entry = 0 ; long best_difference = MAXINT; for ( i = 0 ; i < HASHSIZE ; i ++ ) { entry = LoaderhashTable[ i ] ; while ( entry ) { long difference = (long) address - (long) entry->address ; if ( difference >= 0 ) { if ( best_entry ) { if ( difference < best_difference ) { best_entry = entry ; best_difference = difference ; } } else { best_entry = entry ; best_difference = difference ; } } entry = entry->next ; } } return best_entry ; } void LoaderPrintSymbol(address) unsigned long address; { itemPtr entry; entry=LoaderHashFindNearest(address); if (entry) { const char *module, *section; #if defined(__alpha__) || defined(__ia64__) ErrorF("0x%016lx %s+%lx\n", entry->address, entry->name, address - (unsigned long) entry->address); #else ErrorF("0x%x %s+%x\n", entry->address, entry->name, address - (unsigned long) entry->address); #endif if ( _LoaderAddressToSection(address, &module, §ion) ) ErrorF("\tModule \"%s\"\n\tSection \"%s\"\n",module, section ); } else { ErrorF("(null)\n"); } } void LoaderPrintItem(itemPtr pItem) { if (pItem) { const char *module, *section; #if defined(__alpha__) || defined(__ia64__) ErrorF("0x%016lx %s\n", pItem->address, pItem->name); #else ErrorF("0x%lx %s\n", pItem->address, pItem->name); #endif if ( _LoaderAddressToSection((unsigned long)pItem->address, &module, §ion) ) ErrorF("\tModule \"%s\"\n\tSection \"%s\"\n",module, section ); } else ErrorF("(null)\n"); } void LoaderPrintAddress(symbol) const char *symbol; { itemPtr entry; entry = LoaderHashFind(symbol); LoaderPrintItem(entry); } void LoaderHashTraverse(card, fnp) void *card; int (*fnp)(void *, itemPtr); { int i ; itemPtr entry, last_entry = 0 ; for ( i = 0 ; i < HASHSIZE ; i ++ ) { last_entry = 0 ; entry = LoaderhashTable[ i ] ; while ( entry ) { if (( * fnp )( card, entry )) { if ( last_entry ) { last_entry->next = entry->next ; xf86loaderfree( entry->name ) ; xf86loaderfree( entry ) ; entry = last_entry->next ; } else { LoaderhashTable[ i ] = entry->next ; xf86loaderfree( entry->name ) ; xf86loaderfree( entry ) ; entry = LoaderhashTable[ i ] ; } } else { last_entry = entry ; entry = entry->next ; } } } } void LoaderDumpSymbols() { itemPtr entry; int j; for (j=0; jnext; } } }