From: Eric Pouech epouech@codeweavers.com
Implement it for PDB backend.
Note that we'll merely use this method to ensure that containing compiland is fully loaded, and still return a symt ptr.
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 | 35 ++++++++++++++++++++++++++++++++++ dlls/dbghelp/symbol.c | 29 +++++++++++++++++++++++++++- 5 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 106d84cdde7..3ccd249b97c 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -440,6 +440,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);
/* 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 31ef65f158d..eb4abd9d5e8 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -4302,6 +4302,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 b5ccddadb67..10b1277bac2 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -4019,6 +4019,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 7b8ce182c7e..457a7e63ab7 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -4545,10 +4545,45 @@ static enum pdb_result pdb_reader_ensure_symbols_loaded_from_compiland(struct pd return R_PDB_SUCCESS; }
+static enum pdb_result pdb_reader_lookup_top_symbol_by_segment_offset(struct pdb_reader *pdb, unsigned segment, unsigned offset, symref_t *symref) +{ + enum pdb_result result; + unsigned compiland_index; + DWORD64 in_address; + struct symt_ht *symbol; + + if ((result = pdb_reader_get_segment_address(pdb, segment, offset, &in_address))) return result; + result = pdb_reader_lookup_compiland_by_segment_offset(pdb, segment, offset, &compiland_index); + if (result == R_PDB_SUCCESS) + { + if ((result = pdb_reader_ensure_symbols_loaded_from_compiland(pdb, compiland_index))) + return result; + } + /* don't fail if not found as some symbols are only present in DBI, but not in compiland */ + else if (result != R_PDB_NOT_FOUND) return result; + /* fallback to ptr symbols lookup (as ptr should be loaded by now) */ + symbol = symt_find_symbol_at(pdb->module, in_address); + if (!symbol) return R_PDB_NOT_FOUND; + *symref = symt_ptr_to_symref(&symbol->symt); + return R_PDB_SUCCESS; +} + +static enum method_result pdb_method_lookup_symbol_by_address(struct module_format *modfmt, DWORD_PTR address, symref_t *symref) +{ + enum pdb_result result; + struct pdb_reader *pdb; + unsigned segment, offset; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + if ((result = pdb_reader_get_segment_offset_from_address(pdb, address, &segment, &offset))) return MR_FAILURE; + return pdb_method_result(pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, symref)); +} + 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_find_type, pdb_method_enumerate_types, pdb_method_location_compute, diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 9f8049e3330..85eb76af15e 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1034,7 +1034,7 @@ static int symt_get_best_at(struct module* module, int idx_sorttab) }
/* assume addr is in module */ -struct symt_ht* symt_find_nearest(struct module* module, DWORD_PTR addr) +static struct symt_ht* symt_find_nearest_internal(struct module* module, DWORD_PTR addr) { int mid, high, low; ULONG64 ref_addr, ref_size; @@ -1080,6 +1080,33 @@ struct symt_ht* symt_find_nearest(struct module* module, DWORD_PTR addr) return module->addr_sorttab[low]; }
+struct symt_ht *symt_find_nearest(struct module *module, DWORD_PTR addr) +{ + static int recursive; + struct module_format_vtable_iterator iter = {}; + + /* prevent recursive lookup inside backend */ + if (!recursive++) + { + while ((module_format_vtable_iterator_next(module, &iter, + MODULE_FORMAT_VTABLE_INDEX(lookup_by_address)))) + { + symref_t symref; + enum method_result result = iter.modfmt->vtable->lookup_by_address(iter.modfmt, addr, &symref); + if (result == MR_SUCCESS) + { + recursive--; + if (symt_is_symref_ptr(symref)) return (struct symt_ht*)SYMT_SYMREF_TO_PTR(symref); + FIXME("No support for this case yet\n"); + return NULL; + } + /* fall back in all the other cases */ + } + } + recursive--; + return symt_find_nearest_internal(module, addr); +} + struct symt_ht* symt_find_symbol_at(struct module* module, DWORD_PTR addr) { struct symt_ht* nearest = symt_find_nearest(module, addr);