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
= xstrdup(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
);