From 40f09314e473adb69712be1e58431b24c7a3cc16 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 4 Jul 2004 00:10:54 +0000 Subject: [PATCH] - added support for GCC static local variables - fixed some bugs in SYMOPT_NO_PUBLICS and SYMOPT_PUBLICS_ONLY handling - in stabs parsing, just drop any debug info for a module if stabs parsing fails (instead of assert()'ing) - symbol lookup now allows lookup in pure ELF modules - fixed some bugs in symbol enumeration --- dlls/dbghelp/dbghelp.c | 2 - dlls/dbghelp/dbghelp_private.h | 8 +++- dlls/dbghelp/elf_module.c | 77 +++++++++++++++++++++++----------- dlls/dbghelp/module.c | 45 ++++++++++++++++++-- dlls/dbghelp/stabs.c | 30 ++++++++++--- dlls/dbghelp/symbol.c | 29 ++++++++++--- 6 files changed, 149 insertions(+), 42 deletions(-) diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index e03eec7b34..ce7681b078 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -39,8 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); * 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 * and link it to winedump, and potentially to msvcrt and dbghelp (check best * way not to duplicate code in msvcrt & dbghelp) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 8c7f644003..a9948b3227 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -318,7 +318,13 @@ extern struct module* enum module_type type, unsigned long addr, unsigned long size, unsigned long stamp, unsigned long checksum); - +extern struct module* + module_get_container(const struct process* pcs, + const struct module* inner); +extern struct module* + module_get_containee(const struct process* pcs, + const struct module* inner); +extern void module_reset_debug_info(struct module* module); extern BOOL module_remove(struct process* pcs, struct module* module); /* msc.c */ diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 859ce18151..e90e96d289 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -119,6 +119,7 @@ static void elf_hash_symtab(const struct module* module, struct pool* pool, const char* strp; const char* symname; const char* filename = NULL; + const char* ptr; const Elf32_Sym* symp; struct symtab_elt* ste; @@ -156,8 +157,28 @@ static void elf_hash_symtab(const struct module* module, struct pool* pool, } } if (j < num_areas) continue; + ste = pool_alloc(pool, sizeof(*ste)); + /* GCC seems to emit, in some cases, a .+ suffix. + * This is used for static variable inside functions, so + * that we can have several such variables with same name in + * the same compilation unit + * We simply ignore that suffix when present (we also get rid + * of it in stabs parsing) + */ + ptr = symname + strlen(symname) - 1; ste->ht_elt.name = symname; + if (isdigit(*ptr)) + { + while (*ptr >= '0' && *ptr <= '9' && ptr >= symname) ptr--; + if (ptr > symname && *ptr == '.') + { + char* n = pool_alloc(pool, ptr - symname + 1); + memcpy(n, symname, ptr - symname + 1); + n[ptr - symname] = '\0'; + ste->ht_elt.name = n; + } + } ste->symp = symp; ste->filename = filename; ste->used = 0; @@ -381,10 +402,14 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt 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); + /* if none of symbols has a correct size, we consider they are both markers + * Hence, we can silence this warning + */ + if (xsize || ste->symp->st_size) + 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); } } } @@ -406,7 +431,7 @@ static int elf_new_public_symbols(struct module* module, struct hash_table* symt struct hash_table_iter hti; struct symtab_elt* ste; - if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) return TRUE; + if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE; hash_table_iter_init(symtab, &hti, NULL); while ((ste = hash_table_iter_up(&hti))) @@ -541,27 +566,29 @@ SYM_TYPE elf_load_debug_info(struct module* module) spnt + symtab_sect, spnt + spnt[symtab_sect].sh_link, sizeof(thunks) / sizeof(thunks[0]), thunks); - if (stab_sect != -1 && stabstr_sect != -1 && - !(dbghelp_options & SYMOPT_PUBLICS_ONLY)) + if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - /* OK, now just parse all of the stabs. */ - sym_type = stabs_parse(module, addr, module->elf_info->elf_addr, - spnt[stab_sect].sh_offset, spnt[stab_sect].sh_size, - spnt[stabstr_sect].sh_offset, - spnt[stabstr_sect].sh_size); - if (sym_type == -1) + if (stab_sect != -1 && stabstr_sect != -1) { - WARN("Couldn't read correctly read stabs\n"); - goto leave; + /* OK, now just parse all of the stabs. */ + sym_type = stabs_parse(module, addr, module->elf_info->elf_addr, + spnt[stab_sect].sh_offset, spnt[stab_sect].sh_size, + spnt[stabstr_sect].sh_offset, + spnt[stabstr_sect].sh_size); + if (sym_type == -1) + { + WARN("Couldn't read correctly read stabs\n"); + goto leave; + } + /* and fill in the missing information for stabs */ + elf_finish_stabs_info(module, &ht_symtab); + } + else if (debug_sect != -1) + { + /* Dwarf 2 debug information */ + FIXME("Unsupported Dwarf2 information\n"); + sym_type = SymNone; } - /* and fill in the missing information for stabs */ - elf_finish_stabs_info(module, &ht_symtab); - } - else if (debug_sect != -1) - { - /* Dwarf 2 debug information */ - FIXME("Unsupported Dwarf2 information\n"); - sym_type = SymNone; } if (strstr(module->module.ModuleName, "") || !strcmp(module->module.ModuleName, "")) @@ -571,8 +598,8 @@ SYM_TYPE elf_load_debug_info(struct module* module) elf_new_wine_thunks(module, &ht_symtab, sizeof(thunks) / sizeof(thunks[0]), thunks); /* add the public symbols from symtab - * (only if they haven't been defined yet) - */ + * (only if they haven't been defined yet) + */ elf_new_public_symbols(module, &ht_symtab, FALSE); } else diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index f39d13e891..22167ae995 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -149,11 +149,11 @@ struct module* module_find_by_name(const struct process* pcs, } /*********************************************************************** - * module_has_container + * module_get_container * */ -static struct module* module_get_container(const struct process* pcs, - const struct module* inner) +struct module* module_get_container(const struct process* pcs, + const struct module* inner) { struct module* module; @@ -168,6 +168,26 @@ static struct module* module_get_container(const struct process* pcs, return NULL; } +/*********************************************************************** + * module_get_containee + * + */ +struct module* module_get_containee(const struct process* pcs, + const struct module* outter) +{ + struct module* module; + + for (module = pcs->lmodules; module; module = module->next) + { + if (module != outter && + outter->module.BaseOfImage <= module->module.BaseOfImage && + outter->module.BaseOfImage + outter->module.ImageSize >= + module->module.BaseOfImage + module->module.ImageSize) + return module; + } + return NULL; +} + /****************************************************************** * module_get_debug * @@ -464,3 +484,22 @@ DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) if (!module) return 0; return module->module.BaseOfImage; } + +/****************************************************************** + * module_reset_debug_info + * Removes any debug information linked to a given module. + */ +void module_reset_debug_info(struct module* module) +{ + module->sortlist_valid = TRUE; + module->addr_sorttab = NULL; + hash_table_destroy(&module->ht_symbols); + module->ht_symbols.num_buckets = 0; + module->ht_symbols.buckets = NULL; + hash_table_destroy(&module->ht_types); + module->ht_types.num_buckets = 0; + module->ht_types.buckets = NULL; + hash_table_destroy(&module->ht_symbols); + module->sources_used = module->sources_alloc = 0; + module->sources = NULL; +} diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index 7d6913fb88..c5db79b7ac 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -107,7 +107,20 @@ static void stab_strcpy(char* dest, int sz, const char* source) */ while (*source != '\0' && *source != ':' && sz-- > 0) *dest++ = *source++; - *dest = '\0'; + *dest-- = '\0'; + /* GCC seems to emit, in some cases, a .+ suffix. + * This is used for static variable inside functions, so + * that we can have several such variables with same name in + * the same compilation unit + * We simply ignore that suffix when present (we also get rid + * of it in ELF symtab parsing) + */ + if (isdigit(*dest)) + { + while (isdigit(*dest)) dest--; + if (*dest == '.') *dest = '\0'; + } + assert(sz > 0); } @@ -166,7 +179,7 @@ static int stabs_find_include(const char* file, unsigned long val) static int stabs_add_include(int idx) { - assert(idx >= 0); + if (idx < 0) return -1; cu_include_stk_idx++; /* if this happens, just bump MAX_INCLUDES */ @@ -1088,6 +1101,7 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr, struct pending_loc_var* pending_vars = NULL; unsigned num_pending_vars = 0; unsigned num_allocated_pending_vars = 0; + SYM_TYPE ret = SymDia; nstab = stablen / sizeof(struct stab_nlist); stab_ptr = (const struct stab_nlist*)(addr + staboff); @@ -1403,7 +1417,13 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr, source_idx = incl[--incl_stk]; break; case N_EXCL: - stabs_add_include(stabs_find_include(ptr, stab_ptr->n_value)); + if (stabs_add_include(stabs_find_include(ptr, stab_ptr->n_value)) < 0) + { + ERR("Excluded header not found (%s,%ld)\n", ptr, stab_ptr->n_value); + module_reset_debug_info(module); + ret = SymNone; + goto done; + } break; case N_MAIN: /* Always ignore these. GCC doesn't even generate them. */ @@ -1416,10 +1436,10 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr, TRACE("0x%02x %lx %s\n", stab_ptr->n_type, stab_ptr->n_value, strs + stab_ptr->n_un.n_strx); } - +done: HeapFree(GetProcessHeap(), 0, stabbuff); stabs_free_includes(); if (pending_vars) HeapFree(GetProcessHeap(), 0, pending_vars); - return SymSym; + return ret; } diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 322ef79fb4..395b85fb65 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -560,10 +560,10 @@ static BOOL symt_enum_module(struct module* module, regex_t* regex, sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO); symt_fill_sym_info(module, &sym->symt, sym_info); - if (!cb(sym_info, sym_info->Size, user)) break; + if (!cb(sym_info, sym_info->Size, user)) return TRUE; } } - return sym ? FALSE : TRUE; + return FALSE; } /*********************************************************************** @@ -788,8 +788,26 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask, { if (module->type == DMT_PE && (dbg_module = module_get_debug(pcs, module))) { - if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0) - symt_enum_module(dbg_module, &sym_regex, EnumSymbolsCallback, UserContext); + if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 && + symt_enum_module(dbg_module, &sym_regex, + EnumSymbolsCallback, UserContext)) + break; + } + } + /* not found in PE modules, retry on the ELF ones + */ + if (!module && (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES)) + { + for (module = pcs->lmodules; module; module = module->next) + { + if (module->type == DMT_ELF && + !module_get_containee(pcs, module) && + (dbg_module = module_get_debug(pcs, module))) + { + if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 && + symt_enum_module(dbg_module, &sym_regex, EnumSymbolsCallback, UserContext)) + break; + } } } regfree(&mod_regex); @@ -921,7 +939,7 @@ BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol) else module = pcs->lmodules; /* FIXME: Name could be made out of a regular expression */ - while (module) + for (; module; module = (name) ? NULL : module->next) { if (module->module.SymType == SymNone) continue; if (module->module.SymType == SymDeferred) @@ -940,7 +958,6 @@ BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol) return TRUE; } } - module = (name) ? NULL : module->next; } return FALSE; }