From: Eric Pouech epouech@codeweavers.com
Implement it for PDB backend. It ensures containing compiland of every matched symbol is actually loaded.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/dwarf.c | 1 + dlls/dbghelp/msc.c | 1 + dlls/dbghelp/pdb.c | 68 ++++++++++++++++++++++++++++++++++ dlls/dbghelp/symbol.c | 33 +++++++++++++++++ 5 files changed, 104 insertions(+)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index cecd7f62607..21a0112ea89 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -442,6 +442,7 @@ struct module_format_vtable enum method_result (*request_symref_t)(struct module_format *modfmt, symref_t ref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data); enum method_result (*lookup_by_address)(struct module_format *modfmt, DWORD_PTR address, symref_t *symref); enum method_result (*lookup_by_name)(struct module_format *modfmt, const char *name, symref_t *symref); + enum method_result (*enumerate_symbols)(struct module_format *modfmt, const WCHAR *match, BOOL (*cb)(symref_t, const char *, void *), void *user);
/* types management */ enum method_result (*find_type)(struct module_format *modfmt, const char *name, symref_t *ref); diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 634d8332184..163167b596f 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -4304,6 +4304,7 @@ static const struct module_format_vtable dwarf2_module_format_vtable = NULL, NULL, NULL, + NULL, dwarf2_location_compute, };
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 2b1ed69ecb5..c5721720537 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -4021,6 +4021,7 @@ static const struct module_format_vtable old_pdb_module_format_vtable = NULL, NULL, NULL, + NULL, pdb_location_compute, };
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index eb6da132c37..eb4e3202541 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -4658,12 +4658,80 @@ static enum method_result pdb_method_lookup_symbol_by_name(struct module_format return MR_NOT_FOUND; }
+static enum method_result pdb_method_enumerate_symbols(struct module_format *modfmt, const WCHAR *match, BOOL (*cb)(symref_t, const char *, void *), void *user) +{ + enum pdb_result result; + struct pdb_reader *pdb; + struct pdb_reader_walker walker, symbol_walker; + union codeview_symbol cv_symbol; + unsigned segment; + unsigned offset; + char *symbol_name; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + + /* FIXME could be optimized if match doesn't contain wild cards */ + /* this is currently ugly, but basically we just ensure that all the compilands which contain matching symbols + * are actually loaded, and fall back to generic mode... + */ + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return pdb_method_result(result); + while (pdb_reader_read_partial_codeview_symbol(pdb, &walker, &cv_symbol) == R_PDB_SUCCESS) + { + symbol_name = NULL; + symbol_walker = walker; + symbol_walker.offset -= sizeof(cv_symbol.generic.len); + switch (cv_symbol.generic.id) + { + case S_GDATA32: + case S_LDATA32: + segment = cv_symbol.data_v3.segment; + offset = cv_symbol.data_v3.offset; + symbol_walker.offset += offsetof(union codeview_symbol, data_v3.name); + if ((result = pdb_reader_alloc_and_fetch_string(pdb, &symbol_walker, &symbol_name))) return pdb_method_result(result); + break; + case S_PROCREF: + case S_LPROCREF: + if ((result = pdb_reader_dereference_procedure(pdb, cv_symbol.refsym2_v3.imod, cv_symbol.refsym2_v3.ibSym, + &segment, &offset))) + { + return pdb_method_result(result); + } + symbol_walker.offset += offsetof(union codeview_symbol, refsym2_v3.name); + if ((result = pdb_reader_alloc_and_fetch_string(pdb, &symbol_walker, &symbol_name))) return pdb_method_result(result); + break; + case S_UDT: + case S_CONSTANT: + case S_PUB32: + break; + default: + PDB_REPORT_UNEXPECTED("codeview symbol-id", cv_symbol.generic.id); + break; + } + if (symbol_name) + { + BOOL do_continue = TRUE; + symref_t symref; + + if (symt_match_stringAW(symbol_name, match, TRUE) && + pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, &symref) == R_PDB_SUCCESS) + { + do_continue = cb(symref, symbol_name, user); + } + pdb_reader_free(pdb, symbol_name); + if (!do_continue) return MR_SUCCESS; + } + walker.offset += cv_symbol.generic.len; + } + return MR_FAILURE; +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ pdb_method_request_symref_t, pdb_method_lookup_symbol_by_address, pdb_method_lookup_symbol_by_name, + pdb_method_enumerate_symbols, pdb_method_find_type, pdb_method_enumerate_types, pdb_method_location_compute, diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 9c900344bd7..7ab11e2f4eb 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -892,15 +892,48 @@ static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair, return !se->cb(se->sym_info, se->sym_info->Size, se->user); }
+struct symbol_enum_method +{ + struct module_pair *pair; + const struct sym_enum *se; +}; + +static BOOL symbol_enum_method_cb(symref_t symref, const char *name, void *user) +{ + struct symbol_enum_method *sem = user; + + sem->se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); + sem->se->sym_info->MaxNameLen = sizeof(sem->se->buffer) - sizeof(SYMBOL_INFO); + + if (symt_is_symref_ptr(symref)) + { + if (send_symbol(sem->se, sem->pair, NULL, (struct symt*)symref)) return TRUE; + } + else FIXME("No support for this case yet %Ix\n", symref); + return TRUE; +} + static BOOL symt_enum_module(struct module_pair* pair, const WCHAR* match, const struct sym_enum* se) { + struct module_format_vtable_iterator iter = {}; void* ptr; struct symt_ht* sym = NULL; struct hash_table_iter hti; WCHAR* nameW; BOOL ret;
+ while ((module_format_vtable_iterator_next(pair->effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(enumerate_symbols)))) + { + struct symbol_enum_method sem = {pair, se}; + enum method_result result = iter.modfmt->vtable->enumerate_symbols(iter.modfmt, match, symbol_enum_method_cb, &sem); + + if (result == MR_SUCCESS) return TRUE; + if (result == MR_FAILURE) return FALSE; + /* fall back in all the other cases */ + } + hash_table_iter_init(&pair->effective->ht_symbols, &hti, NULL); while ((ptr = hash_table_iter_up(&hti))) {