/* * File hash.c - generate hash tables for Wine debugger symbols * * Copyright (C) 1993, Eric Youngdale. */ #include #include #include #include #include #include "module.h" #include "selectors.h" #include "wine.h" struct name_hash{ struct name_hash * next; unsigned short segment; 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 short segment, unsigned int * address) { struct name_hash * new; int hash; new = (struct name_hash *) malloc(sizeof(struct name_hash)); new->segment = segment; 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 segment, 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; inext) if (nh->segment == segment && 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, 0, (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( HMODULE hModule ) { char buffer[256]; unsigned char *cpnt, *name; NE_MODULE *pModule; unsigned int address; if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return; name = (unsigned char *)pModule + pModule->name_table; /* First search the resident names */ cpnt = (unsigned char *)pModule + pModule->name_table; while (*cpnt) { cpnt += *cpnt + 1 + sizeof(WORD); sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1, *cpnt, *cpnt, cpnt + 1 ); address = MODULE_GetEntryPoint( hModule, *(WORD *)(cpnt + *cpnt + 1) ); if (address) add_hash(buffer, address >> 16, (unsigned int*)(address & 0xffff)); } /* Now search the non-resident names table */ if (!pModule->nrname_handle) return; /* No non-resident table */ cpnt = (char *)GlobalLock( pModule->nrname_handle ); while (*cpnt) { cpnt += *cpnt + 1 + sizeof(WORD); sprintf( buffer, "%*.*s.%*.*s", *name, *name, name + 1, *cpnt, *cpnt, cpnt + 1 ); address = MODULE_GetEntryPoint( hModule, *(WORD *)(cpnt + *cpnt + 1) ); if (address) add_hash(buffer, address >> 16, (unsigned int*)(address & 0xffff)); } }