Commit 40f09314 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- 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
parent f349cbb7
......@@ -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)
......
......@@ -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 */
......
......@@ -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 .<digit>+ 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, "<elf>") ||
!strcmp(module->module.ModuleName, "<wine-loader>"))
......@@ -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
......
......@@ -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;
}
......@@ -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 .<digit>+ 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;
}
......@@ -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;
}
......
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