2 * File hash.c - generate hash tables for Wine debugger symbols
4 * Copyright (C) 1993, Eric Youngdale.
11 #include <sys/types.h>
14 #include "selectors.h"
21 struct name_hash * next;
26 #define NR_NAME_HASH 128
28 static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
30 static unsigned int name_hash( const char * name )
32 unsigned int hash = 0;
37 while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
38 return hash % NR_NAME_HASH;
42 /***********************************************************************
45 * Add a symbol to the table.
47 void DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr )
49 struct name_hash * new;
52 new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
54 new->name = strdup(name);
56 hash = name_hash(name);
58 /* Now insert into the hash table */
59 new->next = name_hash_table[hash];
60 name_hash_table[hash] = new;
64 /***********************************************************************
65 * DEBUG_GetSymbolValue
67 * Get the address of a named symbol.
69 BOOL DEBUG_GetSymbolValue( const char * name, DBG_ADDR *addr )
74 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
75 if (!strcmp(nh->name, name)) break;
77 if (!nh && (name[0] != '_'))
80 strcpy(buffer+1, name);
81 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
82 if (!strcmp(nh->name, buffer)) break;
85 if (!nh) return FALSE;
91 /***********************************************************************
92 * DEBUG_SetSymbolValue
94 * Set the address of a named symbol.
96 BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
101 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
102 if (!strcmp(nh->name, name)) break;
104 if (!nh && (name[0] != '_'))
107 strcpy(buffer+1, name);
108 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
109 if (!strcmp(nh->name, buffer)) break;
112 if (!nh) return FALSE;
114 DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(DEBUG_context) );
119 /***********************************************************************
120 * DEBUG_FindNearestSymbol
122 * Find the symbol nearest to a given address.
124 const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr )
126 static char name_buffer[256];
127 struct name_hash * nearest = NULL;
128 struct name_hash * nh;
129 unsigned int nearest_address = 0;
132 for(i=0; i<NR_NAME_HASH; i++)
134 for (nh = name_hash_table[i]; nh; nh = nh->next)
135 if (nh->addr.seg == addr->seg &&
136 nh->addr.off <= addr->off &&
137 nh->addr.off >= nearest_address)
139 nearest_address = nh->addr.off;
143 if (!nearest) return NULL;
145 if (addr->off == nearest->addr.off)
146 sprintf( name_buffer, "%s", nearest->name );
148 sprintf( name_buffer, "%s+0x%lx", nearest->name,
149 addr->off - nearest->addr.off );
154 /***********************************************************************
155 * DEBUG_ReadSymbolTable
157 * Read a symbol file into the hash table.
159 void DEBUG_ReadSymbolTable( const char * filename )
162 DBG_ADDR addr = { 0, 0 };
169 if (!(symbolfile = fopen(filename, "r")))
171 fprintf( stderr, "Unable to open symbol table %s\n", filename );
175 fprintf( stderr, "Reading symbols from file %s\n", filename );
179 fgets( buffer, sizeof(buffer), symbolfile );
180 if (feof(symbolfile)) break;
182 /* Strip any text after a # sign (i.e. comments) */
185 if(*cpnt++ == '#') { *cpnt = 0; break; }
187 /* Quietly ignore any lines that have just whitespace */
191 if(*cpnt != ' ' && *cpnt != '\t') break;
194 if (!(*cpnt) || *cpnt == '\n') continue;
196 nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
197 DEBUG_AddSymbol( name, &addr );
203 /***********************************************************************
204 * DEBUG_LoadEntryPoints
206 * Load the entry points of all the modules into the hash table.
208 void DEBUG_LoadEntryPoints(void)
214 unsigned char *cpnt, *name;
215 unsigned int address;
218 fprintf( stderr, "Adding symbols from loaded modules\n" );
219 for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
221 if (!(pModule = (NE_MODULE *)GlobalLock( entry.hModule ))) continue;
223 name = (unsigned char *)pModule + pModule->name_table;
225 /* First search the resident names */
227 cpnt = (unsigned char *)pModule + pModule->name_table;
230 cpnt += *cpnt + 1 + sizeof(WORD);
231 sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1,
232 *cpnt, *cpnt, cpnt + 1 );
233 if ((address = MODULE_GetEntryPoint( entry.hModule,
234 *(WORD *)(cpnt + *cpnt + 1) )))
236 addr.seg = HIWORD(address);
237 addr.off = LOWORD(address);
238 DEBUG_AddSymbol( buffer, &addr );
242 /* Now search the non-resident names table */
244 if (!pModule->nrname_handle) continue; /* No non-resident table */
245 cpnt = (char *)GlobalLock( pModule->nrname_handle );
248 cpnt += *cpnt + 1 + sizeof(WORD);
249 sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1,
250 *cpnt, *cpnt, cpnt + 1 );
251 if ((address = MODULE_GetEntryPoint( entry.hModule,
252 *(WORD *)(cpnt + *cpnt + 1) )))
254 addr.seg = HIWORD(address);
255 addr.off = LOWORD(address);
256 DEBUG_AddSymbol( buffer, &addr );