From: Eric Pouech epouech@codeweavers.com
Implement it for PDB. It uses DBI hash for lookup, but still returns a symt ptr. It however forces the full containing compiland load.
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 | 82 +++++++++++++++++++++++++++++++++- dlls/dbghelp/symbol.c | 19 ++++++++ 5 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 3ccd249b97c..cecd7f62607 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -441,6 +441,7 @@ struct module_format_vtable /* index management */ 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);
/* 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 eb4abd9d5e8..634d8332184 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -4303,6 +4303,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 10b1277bac2..2b1ed69ecb5 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -4020,6 +4020,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 457a7e63ab7..eb6da132c37 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -3570,7 +3570,7 @@ static enum pdb_result pdb_reader_init_IPI(struct pdb_reader *pdb) goto invalid_file; if (pdb->ipi_header.hash_value_size > sizeof(unsigned)) { - FIXME("Unexpected hash value size %u\n", pdb->ipi_header.hash_value_size); + PDB_REPORT_UNEXPECTED("IPI hash value size", pdb->ipi_header.hash_value_size); goto invalid_file; } pdb->ipi_walker.offset = pdb->ipi_header.type_offset; @@ -4579,11 +4579,91 @@ static enum method_result pdb_method_lookup_symbol_by_address(struct module_form return pdb_method_result(pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, symref)); }
+static enum pdb_result pdb_reader_dereference_procedure(struct pdb_reader *pdb, unsigned compiland_id, pdbsize_t stream_offset, + unsigned *segment, unsigned *offset) +{ + enum pdb_result result; + struct pdb_reader_walker walker; + union codeview_symbol cv_symbol; + unsigned stream_id; + + if (!compiland_id || compiland_id > pdb->num_compilands) return R_PDB_INVALID_ARGUMENT; + compiland_id--; + stream_id = pdb->compilands[compiland_id].stream_id; + + if ((result = pdb_reader_walker_init(pdb, stream_id, &walker))) return result; + walker.offset = stream_offset; + if ((result = pdb_reader_read_partial_codeview_symbol(pdb, &walker, &cv_symbol))) return result; + switch (cv_symbol.generic.id) + { + case S_GPROC32: + case S_LPROC32: + *segment = cv_symbol.proc_v3.segment; + *offset = cv_symbol.proc_v3.offset; + break; + + default: + PDB_REPORT_UNEXPECTED("codeview symbol-id", cv_symbol.generic.id); + /* fall through */ + case S_OBJNAME: + case S_COMPILE: + case S_COMPILE2: + case S_COMPILE3: + case S_BUILDINFO: + case S_UDT: + case S_UNAMESPACE: + case S_GMANPROC: + case S_LMANPROC: + return R_PDB_NOT_FOUND; + } + + return result; +} + +static enum method_result pdb_method_lookup_symbol_by_name(struct module_format *modfmt, const char *name, symref_t *symref) +{ + enum pdb_result result; + struct pdb_reader *pdb; + union codeview_symbol cv_symbol; + pdbsize_t globals_offset; + unsigned segment; + unsigned offset; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + + if ((result = pdb_reader_read_DBI_codeview_symbol_by_name(pdb, name, &globals_offset, &cv_symbol))) + return pdb_method_result(result); + + switch (cv_symbol.generic.id) + { + case S_GDATA32: + case S_LDATA32: + segment = cv_symbol.data_v3.segment; + offset = cv_symbol.data_v3.offset; + 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 MR_FAILURE; + } + break; + default: + return MR_FAILURE; + } + result = pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, symref); + if (result == R_PDB_SUCCESS) return MR_SUCCESS; + TRACE("No symbol %s found...\n", name); + return MR_NOT_FOUND; +} + 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_find_type, pdb_method_enumerate_types, pdb_method_location_compute, diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 85eb76af15e..9c900344bd7 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1610,6 +1610,7 @@ BOOL WINAPI SymGetSymFromAddr64(HANDLE hProcess, DWORD64 Address, static BOOL find_name(struct process* pcs, struct module* module, const char* name, SYMBOL_INFO* symbol) { + struct module_format_vtable_iterator iter = {}; struct hash_table_iter hti; void* ptr; struct symt_ht* sym = NULL; @@ -1619,6 +1620,24 @@ static BOOL find_name(struct process* pcs, struct module* module, const char* na if (!(pair.requested = module)) return FALSE; if (!module_get_debug(&pair)) return FALSE;
+ while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(lookup_by_name)))) + { + symref_t symref; + enum method_result result = iter.modfmt->vtable->lookup_by_name(iter.modfmt, name, &symref); + if (result == MR_SUCCESS) + { + if (symt_is_symref_ptr(symref)) + { + symt_fill_sym_info(&pair, NULL, SYMT_SYMREF_TO_PTR(symref), symbol); + return TRUE; + } + FIXME("Not expected case\n"); + return FALSE; + } + if (result != MR_NOT_FOUND) return FALSE; + } + hash_table_iter_init(&pair.effective->ht_symbols, &hti, name); while ((ptr = hash_table_iter_up(&hti))) {