- 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
This commit is contained in:
parent
f349cbb72b
commit
40f09314e4
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue