Commit eef83b38 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- some more fixes to elf module's symbol table handling (including

static/global diff for variables) - now re-synchronizing ELF list in all cases (no longer depending on RT_CONSISTENT state) - now should be able to differentiate properly a native from a builtin module - in symbol lookup, now using size of symbol (if known) - SymGetTypeInfo now checks and uses BaseAddress - in MSC-CV, really generate thunk objects
parent 20f25c34
...@@ -35,6 +35,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); ...@@ -35,6 +35,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
* + we should store the underlying type for an enum in the symt_enum struct * + we should store the underlying type for an enum in the symt_enum struct
* - most options (dbghelp_options) are not used (loading lines, decoration, * - most options (dbghelp_options) are not used (loading lines, decoration,
* deferring reading of module symbols, public symbols...) * deferring reading of module symbols, public symbols...)
* - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when
* we're supposed to use RE, it doesn't make use of our hash tables. Therefore,
* we could use hash if name isn't a RE, and fall back to a full search when we
* get a full RE
* - in most of the module enumeration for symbol lookup, we don't search in
* the ELF modules (should we turn wine extented flag for ELF modules on ?)
* - (un)decoration is not handled (should make winedump's code a (.a) library * - (un)decoration is not handled (should make winedump's code a (.a) library
* and link it to winedump, and potentially to msvcrt and dbghelp (check best * and link it to winedump, and potentially to msvcrt and dbghelp (check best
* way not to duplicate code in msvcrt & dbghelp) * way not to duplicate code in msvcrt & dbghelp)
......
...@@ -253,8 +253,11 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt ...@@ -253,8 +253,11 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt
switch (sym->symt.tag) switch (sym->symt.tag)
{ {
case SymTagFunction: case SymTagFunction:
if (((struct symt_function*)sym)->address != module->elf_info->elf_addr) if (((struct symt_function*)sym)->address != module->elf_info->elf_addr &&
((struct symt_function*)sym)->size)
{
break; break;
}
symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
((struct symt_function*)sym)->container); ((struct symt_function*)sym)->container);
if (symp) if (symp)
...@@ -274,8 +277,12 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt ...@@ -274,8 +277,12 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt
symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
((struct symt_data*)sym)->container); ((struct symt_data*)sym)->container);
if (symp) if (symp)
{
((struct symt_data*)sym)->u.address = module->elf_info->elf_addr + ((struct symt_data*)sym)->u.address = module->elf_info->elf_addr +
symp->st_value; symp->st_value;
((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ?
DataIsFileStatic : DataIsGlobal;
}
break; break;
default:; default:;
} }
...@@ -285,6 +292,8 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt ...@@ -285,6 +292,8 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt
break; break;
} }
} }
/* since we may have changed some addresses & sizes, mark the module to be resorted */
module->sortlist_valid = FALSE;
} }
/****************************************************************** /******************************************************************
...@@ -301,6 +310,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt ...@@ -301,6 +310,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
struct hash_table_iter hti; struct hash_table_iter hti;
struct symtab_elt* ste; struct symtab_elt* ste;
DWORD addr; DWORD addr;
int idx;
hash_table_iter_init(ht_symtab, &hti, NULL); hash_table_iter_init(ht_symtab, &hti, NULL);
while ((ste = hash_table_iter_up(&hti))) while ((ste = hash_table_iter_up(&hti)))
...@@ -330,25 +340,56 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt ...@@ -330,25 +340,56 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
symt_new_thunk(module, compiland, ste->ht_elt.name, thunks[j].ordinal, symt_new_thunk(module, compiland, ste->ht_elt.name, thunks[j].ordinal,
addr, ste->symp->st_size); addr, ste->symp->st_size);
} }
else if (symt_find_nearest(module, addr) == -1) else
{ {
/* creating public symbols for all the ELF symbols which haven't been DWORD ref_addr;
* used yet (ie we have no debug information on them)
* That's the case, for example, of the .spec.c files idx = symt_find_nearest(module, addr);
*/ if (idx != -1)
if (ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC) symt_get_info(&module->addr_sorttab[idx]->symt,
TI_GET_ADDRESS, &ref_addr);
if (idx == -1 || addr != ref_addr)
{ {
symt_new_function(module, compiland, ste->ht_elt.name, /* creating public symbols for all the ELF symbols which haven't been
addr, ste->symp->st_size, NULL); * used yet (ie we have no debug information on them)
* That's the case, for example, of the .spec.c files
*/
if (ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC)
{
symt_new_function(module, compiland, ste->ht_elt.name,
addr, ste->symp->st_size, NULL);
}
else
{
symt_new_global_variable(module, compiland, ste->ht_elt.name,
ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL,
addr, ste->symp->st_size, NULL);
}
/* FIXME: this is a hack !!!
* we are adding new symbols, but as we're parsing a symbol table
* (hopefully without duplicate symbols) we delay rebuilding the sorted
* module table until we're done with the symbol table
* Otherwise, as we intertwine symbols's add and lookup, performance
* is rather bad
*/
module->sortlist_valid = TRUE;
} }
else else if (strcmp(ste->ht_elt.name, module->addr_sorttab[idx]->hash_elt.name))
{ {
symt_new_global_variable(module, compiland, ste->ht_elt.name, DWORD xaddr = 0, xsize = 0;
FALSE /* FIXME */,
addr, ste->symp->st_size, NULL); symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_ADDRESS, &xaddr);
symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_LENGTH, &xsize);
FIXME("Duplicate in %s: %s<%08lx-%08x> %s<%08lx-%08lx>\n",
module->module.ModuleName,
ste->ht_elt.name, addr, ste->symp->st_size,
module->addr_sorttab[idx]->hash_elt.name, xaddr, xsize);
} }
} }
} }
/* see comment above */
module->sortlist_valid = FALSE;
return TRUE; return TRUE;
} }
...@@ -522,7 +563,8 @@ SYM_TYPE elf_load_debug_info(struct module* module) ...@@ -522,7 +563,8 @@ SYM_TYPE elf_load_debug_info(struct module* module)
FIXME("Unsupported Dwarf2 information\n"); FIXME("Unsupported Dwarf2 information\n");
sym_type = SymNone; sym_type = SymNone;
} }
if (strstr(module->module.ModuleName, "<elf>")) if (strstr(module->module.ModuleName, "<elf>") ||
!strcmp(module->module.ModuleName, "<wine-loader>"))
{ {
/* add the thunks for native libraries */ /* add the thunks for native libraries */
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
...@@ -788,8 +830,7 @@ BOOL elf_synchronize_module_list(struct process* pcs) ...@@ -788,8 +830,7 @@ BOOL elf_synchronize_module_list(struct process* pcs)
struct module* module; struct module* module;
if (!pcs->dbg_hdr_addr) return FALSE; if (!pcs->dbg_hdr_addr) return FALSE;
if (!read_mem(pcs->handle, pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)) || if (!read_mem(pcs->handle, pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
dbg_hdr.r_state != RT_CONSISTENT)
return FALSE; return FALSE;
for (module = pcs->lmodules; module; module = module->next) for (module = pcs->lmodules; module; module = module->next)
...@@ -889,8 +930,7 @@ struct module* elf_load_module(struct process* pcs, const char* name) ...@@ -889,8 +930,7 @@ struct module* elf_load_module(struct process* pcs, const char* name)
xname = strrchr(name, '/'); xname = strrchr(name, '/');
if (!xname++) xname = name; if (!xname++) xname = name;
if (!read_mem(pcs->handle, pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)) || if (!read_mem(pcs->handle, pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
dbg_hdr.r_state != RT_CONSISTENT)
return NULL; return NULL;
for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next) for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
......
...@@ -48,10 +48,18 @@ static void module_fill_module(const char* in, char* out, unsigned size) ...@@ -48,10 +48,18 @@ static void module_fill_module(const char* in, char* out, unsigned size)
if (len > 4 && if (len > 4 &&
(!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe"))) (!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe")))
out[len - 4] = '\0'; out[len - 4] = '\0';
else else
{
if (len > 7 && if (len > 7 &&
(!strcasecmp(&out[len - 7], ".dll.so") || !strcasecmp(&out[len - 7], ".exe.so"))) (!strcasecmp(&out[len - 7], ".dll.so") || !strcasecmp(&out[len - 7], ".exe.so")))
strcpy(&out[len - 7], "<elf>"); strcpy(&out[len - 7], "<elf>");
else if (len > 7 &&
out[len - 7] == '.' && !strcasecmp(&out[len - 3], ".so"))
{
if (len + 3 < size) strcpy(&out[len - 3], "<elf>");
else WARN("Buffer too short: %s\n", out);
}
}
while ((*out = tolower(*out))) out++; while ((*out = tolower(*out))) out++;
} }
...@@ -227,6 +235,29 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr ...@@ -227,6 +235,29 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
return module; return module;
} }
static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
const char* ModuleName)
{
char buffer[MAX_PATH];
size_t len;
struct module* module;
if (!ModuleName)
{
module_fill_module(ImageName, buffer, sizeof(buffer));
ModuleName = buffer;
}
len = strlen(ModuleName);
for (module = pcs->lmodules; module; module = module->next)
{
if (!strncasecmp(module->module.ModuleName, ModuleName, len) &&
module->type == DMT_ELF &&
!strcmp(module->module.ModuleName + len, "<elf>"))
return TRUE;
}
return FALSE;
}
/*********************************************************************** /***********************************************************************
* SymLoadModule (DBGHELP.@) * SymLoadModule (DBGHELP.@)
*/ */
...@@ -243,19 +274,28 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName, ...@@ -243,19 +274,28 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
pcs = process_find_by_handle(hProcess); pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE; if (!pcs) return FALSE;
/* this is a Wine extension to the API */ /* force transparent ELF loading / unloading */
if (!ImageName && !hFile) elf_synchronize_module_list(pcs);
/* this is a Wine extension to the API just to redo the synchronisation */
if (!ImageName && !hFile) return 0;
if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
{ {
elf_synchronize_module_list(pcs); /* force the loading of DLL as builtin */
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
goto done;
WARN("Couldn't locate %s\n", ImageName);
return 0; return 0;
} }
TRACE("Assuming %s as native DLL\n", ImageName);
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll))) if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
{ {
unsigned len = strlen(ImageName); unsigned len = strlen(ImageName);
if (!strcmp(ImageName + len - 3, ".so") && if (!strcmp(ImageName + len - 3, ".so") &&
(module = elf_load_module(pcs, ImageName))) goto done; (module = elf_load_module(pcs, ImageName))) goto done;
FIXME("should no longer happen\n");
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll))) if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
goto done; goto done;
WARN("Couldn't locate %s\n", ImageName); WARN("Couldn't locate %s\n", ImageName);
...@@ -274,8 +314,6 @@ done: ...@@ -274,8 +314,6 @@ done:
} }
strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName)); strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0'; module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0';
/* force transparent ELF loading / unloading */
if (module->type != DMT_ELF) elf_synchronize_module_list(pcs);
return module->module.BaseOfImage; return module->module.BaseOfImage;
} }
......
...@@ -2240,11 +2240,10 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root ...@@ -2240,11 +2240,10 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
memcpy(symname, sym->thunk.name, sym->thunk.namelen); memcpy(symname, sym->thunk.name, sym->thunk.namelen);
symname[sym->thunk.namelen] = '\0'; symname[sym->thunk.namelen] = '\0';
flt = codeview_get_linetab(linetab, sym->thunk.segment, sym->thunk.offset); flt = codeview_get_linetab(linetab, sym->thunk.segment, sym->thunk.offset);
symt_new_function(msc_dbg->module, flt ? flt->compiland : NULL, symt_new_thunk(msc_dbg->module, flt ? flt->compiland : NULL,
symname, symname, sym->thunk.thtype,
codeview_get_address(msc_dbg, sym->thunk.segment, sym->thunk.offset), codeview_get_address(msc_dbg, sym->thunk.segment, sym->thunk.offset),
sym->thunk.thunk_len, sym->thunk.thunk_len);
codeview_get_type(sym->thunk.thtype, FALSE));
break; break;
/* /*
......
...@@ -89,6 +89,7 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul ...@@ -89,6 +89,7 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul
WINE_TRACE("Processing DBG file %s\n", dbg_name); WINE_TRACE("Processing DBG file %s\n", dbg_name);
tmp[0] = '\0';
if ((hFile = FindDebugInfoFile((char*)dbg_name, pcs->search_path, tmp)) != NULL && if ((hFile = FindDebugInfoFile((char*)dbg_name, pcs->search_path, tmp)) != NULL &&
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) && ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)) ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
...@@ -114,10 +115,8 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul ...@@ -114,10 +115,8 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul
hdr->DebugDirectorySize / sizeof(*dbg)); hdr->DebugDirectorySize / sizeof(*dbg));
} }
else else
{ WINE_ERR("-Unable to peruse .DBG file %s (%s)\n", dbg_name, debugstr_a(tmp));
WINE_ERR("-Unable to peruse .DBG file %s (%s)\n",
dbg_name, debugstr_a(tmp));
}
if (dbg_mapping) UnmapViewOfFile((void*)dbg_mapping); if (dbg_mapping) UnmapViewOfFile((void*)dbg_mapping);
if (hMap) CloseHandle(hMap); if (hMap) CloseHandle(hMap);
if (hFile != NULL) CloseHandle(hFile); if (hFile != NULL) CloseHandle(hFile);
...@@ -324,7 +323,8 @@ struct module* pe_load_module(struct process* pcs, char* name, ...@@ -324,7 +323,8 @@ struct module* pe_load_module(struct process* pcs, char* name,
else if (name) strcpy(loaded_name, name); else if (name) strcpy(loaded_name, name);
else if (dbghelp_options & SYMOPT_DEFERRED_LOADS) else if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
FIXME("Trouble ahead (no module name passed in deferred mode)\n"); FIXME("Trouble ahead (no module name passed in deferred mode)\n");
if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) if (!(module = module_find_by_name(pcs, loaded_name, DMT_PE)) &&
(hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
{ {
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
{ {
......
...@@ -94,14 +94,15 @@ static inline void re_append(char** mask, unsigned* len, char ch) ...@@ -94,14 +94,15 @@ static inline void re_append(char** mask, unsigned* len, char ch)
* + 1 or more of preceding char * + 1 or more of preceding char
* escapes \ on #, ?, [, ], *, +. don't work on - * escapes \ on #, ?, [, ], *, +. don't work on -
*/ */
static void compile_regex(const char* str, regex_t* re) static void compile_regex(const char* str, int numchar, regex_t* re)
{ {
char* mask = HeapAlloc(GetProcessHeap(), 0, 1); char* mask = HeapAlloc(GetProcessHeap(), 0, 1);
unsigned len = 1; unsigned len = 1;
BOOL in_escape = FALSE; BOOL in_escape = FALSE;
re_append(&mask, &len, '^'); re_append(&mask, &len, '^');
while (*str)
while (*str && numchar--)
{ {
/* FIXME: this shouldn't be valid on '-' */ /* FIXME: this shouldn't be valid on '-' */
if (in_escape) if (in_escape)
...@@ -130,7 +131,7 @@ static void compile_regex(const char* str, regex_t* re) ...@@ -130,7 +131,7 @@ static void compile_regex(const char* str, regex_t* re)
} }
re_append(&mask, &len, '$'); re_append(&mask, &len, '$');
mask[len - 1] = '\0'; mask[len - 1] = '\0';
regcomp(re, mask, REG_NOSUB); if (regcomp(re, mask, REG_NOSUB)) FIXME("Couldn't compile %s\n", mask);
HeapFree(GetProcessHeap(), 0, mask); HeapFree(GetProcessHeap(), 0, mask);
} }
...@@ -421,7 +422,6 @@ struct symt_thunk* symt_new_thunk(struct module* module, ...@@ -421,7 +422,6 @@ struct symt_thunk* symt_new_thunk(struct module* module,
{ {
struct symt_thunk* sym; struct symt_thunk* sym;
TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n", TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n",
module->module.ModuleName, name, addr, addr + size - 1); module->module.ModuleName, name, addr, addr + size - 1);
...@@ -535,7 +535,7 @@ static void symt_fill_sym_info(const struct module* module, ...@@ -535,7 +535,7 @@ static void symt_fill_sym_info(const struct module* module,
sym, sym_info->Name, sym_info->Size, sym_info->Address); sym, sym_info->Name, sym_info->Size, sym_info->Address);
} }
static BOOL symt_enum_module(struct module* module, const char* mask, static BOOL symt_enum_module(struct module* module, regex_t* regex,
PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user) PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user)
{ {
char buffer[sizeof(SYMBOL_INFO) + 256]; char buffer[sizeof(SYMBOL_INFO) + 256];
...@@ -543,11 +543,7 @@ static BOOL symt_enum_module(struct module* module, const char* mask, ...@@ -543,11 +543,7 @@ static BOOL symt_enum_module(struct module* module, const char* mask,
void* ptr; void* ptr;
struct symt_ht* sym = NULL; struct symt_ht* sym = NULL;
struct hash_table_iter hti; struct hash_table_iter hti;
regex_t preg;
assert(mask);
assert(mask[0] != '!');
compile_regex(mask, &preg);
hash_table_iter_init(&module->ht_symbols, &hti, NULL); hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti))) while ((ptr = hash_table_iter_up(&hti)))
{ {
...@@ -559,7 +555,7 @@ static BOOL symt_enum_module(struct module* module, const char* mask, ...@@ -559,7 +555,7 @@ static BOOL symt_enum_module(struct module* module, const char* mask,
sym->symt.tag == SymTagPublicSymbol) continue; sym->symt.tag == SymTagPublicSymbol) continue;
if (sym->hash_elt.name && if (sym->hash_elt.name &&
regexec(&preg, sym->hash_elt.name, 0, NULL, 0) == 0) regexec(regex, sym->hash_elt.name, 0, NULL, 0) == 0)
{ {
sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO); sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
...@@ -567,7 +563,6 @@ static BOOL symt_enum_module(struct module* module, const char* mask, ...@@ -567,7 +563,6 @@ static BOOL symt_enum_module(struct module* module, const char* mask,
if (!cb(sym_info, sym_info->Size, user)) break; if (!cb(sym_info, sym_info->Size, user)) break;
} }
} }
regfree(&preg);
return sym ? FALSE : TRUE; return sym ? FALSE : TRUE;
} }
...@@ -615,7 +610,7 @@ static BOOL resort_symbols(struct module* module) ...@@ -615,7 +610,7 @@ static BOOL resort_symbols(struct module* module)
int symt_find_nearest(struct module* module, DWORD addr) int symt_find_nearest(struct module* module, DWORD addr)
{ {
int mid, high, low; int mid, high, low;
DWORD ref; DWORD ref_addr, ref_size;
if (!module->sortlist_valid && !resort_symbols(module)) return -1; if (!module->sortlist_valid && !resort_symbols(module)) return -1;
...@@ -625,13 +620,14 @@ int symt_find_nearest(struct module* module, DWORD addr) ...@@ -625,13 +620,14 @@ int symt_find_nearest(struct module* module, DWORD addr)
low = 0; low = 0;
high = module->module.NumSyms; high = module->module.NumSyms;
symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref); symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref) return -1; if (addr < ref_addr) return -1;
if (high) if (high)
{ {
symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref); symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
/* FIXME: use the size of symbol here if known */ if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
if (addr > ref + 0x1000) return -1; ref_size = 0x1000; /* arbitrary value */
if (addr >= ref_addr + ref_size) return -1;
} }
while (high > low + 1) while (high > low + 1)
...@@ -651,16 +647,22 @@ int symt_find_nearest(struct module* module, DWORD addr) ...@@ -651,16 +647,22 @@ int symt_find_nearest(struct module* module, DWORD addr)
*/ */
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol) if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
{ {
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref); symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (low > 0 && if (low > 0 &&
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol && module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
!cmp_sorttab_addr(module, low - 1, ref)) !cmp_sorttab_addr(module, low - 1, ref_addr))
low--; low--;
else if (low < module->module.NumSyms - 1 && else if (low < module->module.NumSyms - 1 &&
module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol && module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol &&
!cmp_sorttab_addr(module, low + 1, ref)) !cmp_sorttab_addr(module, low + 1, ref_addr))
low++; low++;
} }
/* finally check that we fit into the found symbol */
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref_addr) return -1;
if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
ref_size = 0x1000; /* arbitrary value */
if (addr >= ref_addr + ref_size) return -1;
return low; return low;
} }
...@@ -733,7 +735,7 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask, ...@@ -733,7 +735,7 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
BOOL ret; BOOL ret;
regex_t preg; regex_t preg;
compile_regex(mask ? mask : "*", &preg); compile_regex(mask ? mask : "*", -1, &preg);
ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback, ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback,
UserContext, sym_info, UserContext, sym_info,
&((struct symt_function*)sym)->vchildren); &((struct symt_function*)sym)->vchildren);
...@@ -748,6 +750,13 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask, ...@@ -748,6 +750,13 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
/****************************************************************** /******************************************************************
* SymEnumSymbols (DBGHELP.@) * SymEnumSymbols (DBGHELP.@)
* *
* cases BaseOfDll = 0
* !foo fails always (despite what MSDN states)
* RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2
* no ! in Mask, lookup in local Context
* cases BaseOfDll != 0
* !foo fails always (despite what MSDN states)
* RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is)
*/ */
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask, BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
...@@ -755,6 +764,9 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask, ...@@ -755,6 +764,9 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
{ {
struct process* pcs = process_find_by_handle(hProcess); struct process* pcs = process_find_by_handle(hProcess);
struct module* module; struct module* module;
struct module* dbg_module;
const char* bang;
regex_t mod_regex, sym_regex;
TRACE("(%p %08lx %s %p %p)\n", TRACE("(%p %08lx %s %p %p)\n",
hProcess, BaseOfDll, debugstr_a(Mask), EnumSymbolsCallback, UserContext); hProcess, BaseOfDll, debugstr_a(Mask), EnumSymbolsCallback, UserContext);
...@@ -763,41 +775,42 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask, ...@@ -763,41 +775,42 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
if (BaseOfDll == 0) if (BaseOfDll == 0)
{ {
if (Mask && Mask[0] == '!') /* do local variables ? */
if (!Mask || !(bang = strchr(Mask, '!')))
return symt_enum_locals(pcs, Mask, EnumSymbolsCallback, UserContext);
if (bang == Mask) return FALSE;
compile_regex(Mask, bang - Mask, &mod_regex);
compile_regex(bang + 1, -1, &sym_regex);
for (module = pcs->lmodules; module; module = module->next)
{ {
if (!Mask[1]) if (module->type == DMT_PE && (dbg_module = module_get_debug(pcs, module)))
{ {
/* FIXME: is this really what's intended ??? */ if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0)
for (module = pcs->lmodules; module; module = module->next) symt_enum_module(dbg_module, &sym_regex, EnumSymbolsCallback, UserContext);
{
if (module->module.SymType != SymNone &&
!symt_enum_module(module, "*", EnumSymbolsCallback, UserContext))
break;
}
return TRUE;
} }
module = module_find_by_name(pcs, &Mask[1], DMT_UNKNOWN);
Mask++;
} }
else return symt_enum_locals(pcs, Mask, EnumSymbolsCallback, UserContext); regfree(&mod_regex);
regfree(&sym_regex);
return TRUE;
} }
else module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module)))
return FALSE;
/* we always ignore module name from Mask when BaseOfDll is defined */
if (Mask && (bang = strchr(Mask, '!')))
{ {
module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); if (bang == Mask) return FALSE;
if (Mask && Mask[0] == '!') Mask = bang + 1;
{
if (!Mask[1] ||
strcmp(&Mask[1], module->module.ModuleName))
{
FIXME("Strange call mode\n");
return FALSE;
}
Mask = "*";
}
else if (!Mask) Mask = "*";
} }
if ((module = module_get_debug(pcs, module)))
symt_enum_module(module, Mask, EnumSymbolsCallback, UserContext); compile_regex(Mask ? Mask : "*", -1, &sym_regex);
symt_enum_module(module, &sym_regex, EnumSymbolsCallback, UserContext);
regfree(&sym_regex);
return TRUE; return TRUE;
} }
...@@ -889,32 +902,45 @@ BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol) ...@@ -889,32 +902,45 @@ BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol)
struct hash_table_iter hti; struct hash_table_iter hti;
void* ptr; void* ptr;
struct symt_ht* sym = NULL; struct symt_ht* sym = NULL;
const char* name;
TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol); TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol);
if (!pcs) return FALSE; if (!pcs) return FALSE;
if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
for (module = pcs->lmodules; module; module = module->next) name = strchr(Name, '!');
if (name)
{
char tmp[128];
assert(name - Name < sizeof(tmp));
memcpy(tmp, Name, name - Name);
tmp[name - Name] = '\0';
module = module_find_by_name(pcs, tmp, DMT_UNKNOWN);
if (!module) return FALSE;
Name = (char*)(name + 1);
}
else module = pcs->lmodules;
/* FIXME: Name could be made out of a regular expression */
while (module)
{ {
if (module->module.SymType != SymNone) if (module->module.SymType == SymNone) continue;
if (module->module.SymType == SymDeferred)
{ {
if (module->module.SymType == SymDeferred) struct module* xmodule = module_get_debug(pcs, module);
{ if (!xmodule || xmodule != module) continue;
struct module* xmodule = module_get_debug(pcs, module); }
if (!xmodule) continue; hash_table_iter_init(&module->ht_symbols, &hti, Name);
module = xmodule; while ((ptr = hash_table_iter_up(&hti)))
} {
hash_table_iter_init(&module->ht_symbols, &hti, Name); sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
if (!strcmp(sym->hash_elt.name, Name)) if (!strcmp(sym->hash_elt.name, Name))
{ {
symt_fill_sym_info(module, &sym->symt, Symbol); symt_fill_sym_info(module, &sym->symt, Symbol);
return TRUE; return TRUE;
}
} }
} }
module = (name) ? NULL : module->next;
} }
return FALSE; return FALSE;
} }
......
...@@ -361,8 +361,7 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, unsigned long BaseOfDll, ...@@ -361,8 +361,7 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, unsigned long BaseOfDll,
TRACE("(%p %08lx %p %p)\n", TRACE("(%p %08lx %p %p)\n",
hProcess, BaseOfDll, EnumSymbolsCallback, UserContext); hProcess, BaseOfDll, EnumSymbolsCallback, UserContext);
pcs = process_find_by_handle(hProcess); if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
if (!pcs) return FALSE;
module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module))) return FALSE; if (!(module = module_get_debug(pcs, module))) return FALSE;
...@@ -730,13 +729,16 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, unsigned long ModBase, ...@@ -730,13 +729,16 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, unsigned long ModBase,
PVOID pInfo) PVOID pInfo)
{ {
struct process* pcs = process_find_by_handle(hProcess); struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
if (!pcs) return FALSE; if (!pcs) return FALSE;
#if 0
struct module* module;
module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN); module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module))) return FALSE; if (!(module = module_get_debug(pcs, module)))
#endif {
FIXME("Someone didn't properly set ModBase (0x%08lx)\n", ModBase);
return FALSE;
}
return symt_get_info((struct symt*)TypeId, GetType, pInfo); return symt_get_info((struct symt*)TypeId, GetType, pInfo);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment