| /* | |
| * File hash.c - generate hash tables for Wine debugger symbols | |
| * | |
| * Copyright (C) 1993, Eric Youngdale. | |
| */ | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <sys/types.h> | |
| #include <neexe.h> | |
| #include <segmem.h> | |
| #include <prototypes.h> | |
| #include <wine.h> | |
| struct name_hash{ | |
| struct name_hash * next; | |
| unsigned int * address; | |
| char * name; | |
| }; | |
| #define NR_NAME_HASH 128 | |
| static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,}; | |
| static unsigned int name_hash(const char * name){ | |
| unsigned int hash = 0; | |
| const char * p; | |
| p = name; | |
| while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++; | |
| return hash % NR_NAME_HASH; | |
| } | |
| void add_hash(char * name, unsigned int * address){ | |
| struct name_hash * new; | |
| int hash; | |
| new = (struct name_hash *) malloc(sizeof(struct name_hash)); | |
| new->address = address; | |
| new->name = strdup(name); | |
| new->next = NULL; | |
| hash = name_hash(name); | |
| /* Now insert into the hash table */ | |
| new->next = name_hash_table[hash]; | |
| name_hash_table[hash] = new; | |
| } | |
| unsigned int * find_hash(char * name){ | |
| char buffer[256]; | |
| struct name_hash * nh; | |
| for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next) | |
| if(strcmp(nh->name, name) == 0) return nh->address; | |
| if(name[0] != '_'){ | |
| buffer[0] = '_'; | |
| strcpy(buffer+1, name); | |
| for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next) | |
| if(strcmp(nh->name, buffer) == 0) return nh->address; | |
| }; | |
| return (unsigned int *) 0xffffffff; | |
| } | |
| static char name_buffer[256]; | |
| char * find_nearest_symbol(unsigned int * address){ | |
| struct name_hash * nearest; | |
| struct name_hash start; | |
| struct name_hash * nh; | |
| int i; | |
| nearest = &start; | |
| start.address = (unsigned int *) 0; | |
| for(i=0; i<NR_NAME_HASH; i++) { | |
| for(nh = name_hash_table[i]; nh; nh = nh->next) | |
| if(nh->address <= address && nh->address > nearest->address) | |
| nearest = nh; | |
| }; | |
| if((unsigned int) nearest->address == 0) return NULL; | |
| sprintf(name_buffer, "%s+0x%x", nearest->name, ((unsigned int) address) - | |
| ((unsigned int) nearest->address)); | |
| return name_buffer; | |
| } | |
| void | |
| read_symboltable(char * filename){ | |
| FILE * symbolfile; | |
| unsigned int addr; | |
| int nargs; | |
| char type; | |
| char * cpnt; | |
| char buffer[256]; | |
| char name[256]; | |
| symbolfile = fopen(filename, "r"); | |
| if(!symbolfile) { | |
| fprintf(stderr,"Unable to open symbol table %s\n", filename); | |
| return; | |
| }; | |
| fprintf(stderr,"Reading symbols from file %s\n", filename); | |
| while (1) | |
| { | |
| fgets(buffer, sizeof(buffer), symbolfile); | |
| if (feof(symbolfile)) break; | |
| /* Strip any text after a # sign (i.e. comments) */ | |
| cpnt = buffer; | |
| while(*cpnt){ | |
| if(*cpnt == '#') {*cpnt = 0; break; }; | |
| cpnt++; | |
| }; | |
| /* Quietly ignore any lines that have just whitespace */ | |
| cpnt = buffer; | |
| while(*cpnt){ | |
| if(*cpnt != ' ' && *cpnt != '\t') break; | |
| cpnt++; | |
| }; | |
| if (!(*cpnt) || *cpnt == '\n') { | |
| continue; | |
| }; | |
| nargs = sscanf(buffer, "%x %c %s", &addr, &type, name); | |
| add_hash(name, (unsigned int *) addr); | |
| }; | |
| fclose(symbolfile); | |
| } | |
| /* Load the entry points from the dynamic linking into the hash tables. | |
| * This does not work yet - something needs to be added before it scans the | |
| * tables correctly | |
| */ | |
| void | |
| load_entrypoints(){ | |
| char buffer[256]; | |
| char * cpnt; | |
| int j, ordinal, len; | |
| unsigned int address; | |
| struct w_files * wpnt; | |
| for(wpnt = wine_files; wpnt; wpnt = wpnt->next){ | |
| cpnt = wpnt->nrname_table; | |
| while(1==1){ | |
| if( ((int) cpnt) - ((int)wpnt->nrname_table) > | |
| wpnt->ne_header->nrname_tab_length) break; | |
| len = *cpnt++; | |
| strncpy(buffer, cpnt, len); | |
| buffer[len] = 0; | |
| ordinal = *((unsigned short *) (cpnt + len)); | |
| j = GetEntryPointFromOrdinal(wpnt, ordinal); | |
| address = j & 0xffff; | |
| j = j >> 16; | |
| address |= (wpnt->selector_table[j].selector) << 16; | |
| fprintf(stderr,"%s -> %x\n", buffer, address); | |
| add_hash(buffer, (unsigned int *) address); | |
| cpnt += len + 2; | |
| }; | |
| }; | |
| return; | |
| } |