Release 960225
[wine.git] / debugger / hash.c
blob60be9104e6b4e23ef7ace809c6540ee630a165ee
1 /*
2 * File hash.c - generate hash tables for Wine debugger symbols
4 * Copyright (C) 1993, Eric Youngdale.
5 */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <neexe.h>
13 #include "module.h"
14 #include "selectors.h"
15 #include "debugger.h"
16 #include "toolhelp.h"
17 #include "xmalloc.h"
19 struct name_hash
21 struct name_hash * next;
22 char * name;
23 DBG_ADDR addr;
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;
33 const char * p;
35 p = name;
37 while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
38 return hash % NR_NAME_HASH;
42 /***********************************************************************
43 * DEBUG_AddSymbol
45 * Add a symbol to the table.
47 void DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr )
49 struct name_hash * new;
50 int hash;
52 new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
53 new->addr = *addr;
54 new->name = xstrdup(name);
55 new->next = NULL;
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 )
71 char buffer[256];
72 struct name_hash *nh;
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] != '_'))
79 buffer[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;
86 *addr = nh->addr;
87 return TRUE;
91 /***********************************************************************
92 * DEBUG_SetSymbolValue
94 * Set the address of a named symbol.
96 BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
98 char buffer[256];
99 struct name_hash *nh;
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] != '_'))
106 buffer[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;
113 nh->addr = *addr;
114 DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(DEBUG_context) );
115 return TRUE;
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;
130 int i;
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;
140 nearest = nh;
143 if (!nearest) return NULL;
145 if (addr->off == nearest->addr.off)
146 sprintf( name_buffer, "%s", nearest->name );
147 else
148 sprintf( name_buffer, "%s+0x%lx", nearest->name,
149 addr->off - nearest->addr.off );
150 return name_buffer;
154 /***********************************************************************
155 * DEBUG_ReadSymbolTable
157 * Read a symbol file into the hash table.
159 void DEBUG_ReadSymbolTable( const char * filename )
161 FILE * symbolfile;
162 DBG_ADDR addr = { 0, 0 };
163 int nargs;
164 char type;
165 char * cpnt;
166 char buffer[256];
167 char name[256];
169 if (!(symbolfile = fopen(filename, "r")))
171 fprintf( stderr, "Unable to open symbol table %s\n", filename );
172 return;
175 fprintf( stderr, "Reading symbols from file %s\n", filename );
177 while (1)
179 fgets( buffer, sizeof(buffer), symbolfile );
180 if (feof(symbolfile)) break;
182 /* Strip any text after a # sign (i.e. comments) */
183 cpnt = buffer;
184 while (*cpnt)
185 if(*cpnt++ == '#') { *cpnt = 0; break; }
187 /* Quietly ignore any lines that have just whitespace */
188 cpnt = buffer;
189 while(*cpnt)
191 if(*cpnt != ' ' && *cpnt != '\t') break;
192 cpnt++;
194 if (!(*cpnt) || *cpnt == '\n') continue;
196 nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
197 DEBUG_AddSymbol( name, &addr );
199 fclose(symbolfile);
203 /***********************************************************************
204 * DEBUG_LoadEntryPoints
206 * Load the entry points of all the modules into the hash table.
208 void DEBUG_LoadEntryPoints(void)
210 MODULEENTRY entry;
211 NE_MODULE *pModule;
212 DBG_ADDR addr;
213 char buffer[256];
214 unsigned char *cpnt, *name;
215 unsigned int address;
216 BOOL ok;
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;
228 while (*cpnt)
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 );
246 while (*cpnt)
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 );