Release 950727
[wine] / debugger / hash.c
1 /*
2  * File hash.c - generate hash tables for Wine debugger symbols
3  *
4  * Copyright (C) 1993, Eric Youngdale.
5  */
6
7
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 "wine.h"
16
17 struct  name_hash{
18         struct name_hash * next;
19         unsigned int segment;
20         unsigned int address;
21         char * name;
22 };
23
24 #define NR_NAME_HASH 128
25
26 static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
27
28 static  unsigned int name_hash(const char * name){
29         unsigned int hash = 0;
30         const char * p;
31
32         p = name;
33
34         while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
35         return hash % NR_NAME_HASH;
36
37 }
38
39
40 void add_hash(char * name, unsigned int segment, unsigned int address)
41 {
42         struct name_hash  * new;
43         int hash;
44
45         new = (struct  name_hash *) malloc(sizeof(struct name_hash));
46         new->segment = segment;
47         new->address = address;
48         new->name = strdup(name);
49         new->next = NULL;
50         hash = name_hash(name);
51
52         /* Now insert into the hash table */
53         new->next = name_hash_table[hash];
54         name_hash_table[hash] = new;
55 }
56
57 unsigned int find_hash(char * name)
58 {
59         char buffer[256];
60         struct name_hash  * nh;
61
62         for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
63                 if(strcmp(nh->name, name) == 0) return nh->address;
64
65         if(name[0] != '_'){
66                 buffer[0] = '_';
67                 strcpy(buffer+1, name);
68                 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
69                         if(strcmp(nh->name, buffer) == 0) return nh->address;
70         };
71
72
73         return 0xffffffff;
74 }
75
76
77 static char name_buffer[256];
78
79 char * find_nearest_symbol(unsigned int segment, unsigned int address)
80 {
81         struct name_hash * nearest;
82         struct name_hash  * nh;
83         unsigned int nearest_address;
84         int i;
85         
86         nearest = NULL;
87         nearest_address = 0;
88         
89         for(i=0; i<NR_NAME_HASH; i++) {
90                 for(nh = name_hash_table[i]; nh; nh = nh->next)
91                         if (nh->segment == segment &&
92                             nh->address <= address &&
93                             nh->address >= nearest_address)
94                         {
95                             nearest_address = nh->address;
96                             nearest = nh;
97                         }
98         }
99         if (!nearest) return NULL;
100
101         if (address == nearest->address)
102             sprintf( name_buffer, "%s", nearest->name );
103         else
104             sprintf( name_buffer, "%s+0x%x", nearest->name,
105                      address - nearest->address );
106         return name_buffer;
107 }
108
109
110 void
111 read_symboltable(char * filename){
112         FILE * symbolfile;
113         unsigned int addr;
114         int nargs;
115         char type;
116         char * cpnt;
117         char buffer[256];
118         char name[256];
119
120         symbolfile = fopen(filename, "r");
121         if(!symbolfile) {
122                 fprintf(stderr,"Unable to open symbol table %s\n", filename);
123                 return;
124         };
125
126         fprintf(stderr,"Reading symbols from file %s\n", filename);
127
128
129         while (1)
130         {
131                 fgets(buffer, sizeof(buffer),  symbolfile);
132                 if (feof(symbolfile)) break;
133                 
134                 /* Strip any text after a # sign (i.e. comments) */
135                 cpnt = buffer;
136                 while(*cpnt){
137                         if(*cpnt == '#') {*cpnt = 0; break; };
138                         cpnt++;
139                 };
140                 
141                 /* Quietly ignore any lines that have just whitespace */
142                 cpnt = buffer;
143                 while(*cpnt){
144                         if(*cpnt != ' ' && *cpnt != '\t') break;
145                         cpnt++;
146                 };
147                 if (!(*cpnt) || *cpnt == '\n') {
148                         continue;
149                 };
150                 
151                 nargs = sscanf(buffer, "%x %c %s", &addr, &type, name);
152                 add_hash(name, 0, addr);
153       };
154       fclose(symbolfile);
155 }
156
157
158
159 void load_entrypoints( HMODULE hModule )
160 {
161     char buffer[256];
162     unsigned char *cpnt, *name;
163     NE_MODULE *pModule;
164     unsigned int address;
165
166     if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
167     name = (unsigned char *)pModule + pModule->name_table;
168
169       /* First search the resident names */
170
171     cpnt = (unsigned char *)pModule + pModule->name_table;
172     while (*cpnt)
173     {
174         cpnt += *cpnt + 1 + sizeof(WORD);
175         sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1,
176                  *cpnt, *cpnt, cpnt + 1 );
177         address = MODULE_GetEntryPoint( hModule, *(WORD *)(cpnt + *cpnt + 1) );
178         if (address) add_hash( buffer, HIWORD(address), LOWORD(address) );
179     }
180
181       /* Now search the non-resident names table */
182
183     if (!pModule->nrname_handle) return;  /* No non-resident table */
184     cpnt = (char *)GlobalLock( pModule->nrname_handle );
185     while (*cpnt)
186     {
187         cpnt += *cpnt + 1 + sizeof(WORD);
188         sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1,
189                  *cpnt, *cpnt, cpnt + 1 );
190         address = MODULE_GetEntryPoint( hModule, *(WORD *)(cpnt + *cpnt + 1) );
191         if (address) add_hash( buffer, HIWORD(address), LOWORD(address) );
192     }
193 }