[PATCH 0/6] MR9957: PDB speedup 3
This serie continues the optimization for gaining speed and memory consumption in PDB reader. It mostly consists of refactoring, and preparing the next serie by letting a couple of helpers be compatible with symref\_t descriptors. It also fixes dbghelp to be compatible with native behavior wrt. variables with thread storage. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> Native dbghelp for a variable with thread storage: - fails on ADDRESS and OFFSET requests, - doesn't set the Address field in SYMBOL_INFO, - but succeeds on ADDRESSOFSET request. Let dbghelp and winedbg use the correct requests. Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/symbol.c | 2 +- dlls/dbghelp/type.c | 35 ++++++++++++++++++++++++++++++++--- programs/winedbg/symbol.c | 7 ++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 29a32ad7dcf..a3f323ebea6 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -789,7 +789,7 @@ static BOOL symt_fill_sym_info(struct module_pair* pair, { case loc_tlsrel: sym_info->Flags |= SYMFLAG_TLSREL; - /* fall through */ + break; case loc_absolute: symt_get_address(sym, &sym_info->Address); break; diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index a0529ec37fb..e347f02b8f9 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -141,9 +141,14 @@ BOOL symt_get_address(const struct symt* type, ULONG64* addr) case DataIsGlobal: case DataIsFileStatic: case DataIsStaticLocal: - *addr = ((const struct symt_data*)type)->u.var.offset; - break; - default: return FALSE; + if (((const struct symt_data*)type)->u.var.kind == loc_absolute) + { + *addr = ((const struct symt_data*)type)->u.var.offset; + break; + } + /* fall through */ + default: + return FALSE; } break; case SymTagBlock: @@ -1123,6 +1128,30 @@ BOOL symt_get_info(struct module* module, const struct symt* type, X(DWORD) = symt_ptr_to_index(module, type); break; + case TI_GET_ADDRESSOFFSET: + switch (type->tag) + { + case SymTagData: + switch (((const struct symt_data*)type)->kind) + { + case DataIsGlobal: + case DataIsFileStatic: + case DataIsStaticLocal: + if (((const struct symt_data*)type)->u.var.kind == loc_tlsrel) + { + X(DWORD) = ((const struct symt_data*)type)->u.var.offset; + break; + } + /* fall through */ + default: + return FALSE; + } + break; + default: + return FALSE; + } + break; + /* FIXME: we don't support properly C++ for now */ case TI_GET_VIRTUALBASECLASS: case TI_GET_VIRTUALTABLESHAPEID: diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index 96df020fba5..432b82f36a6 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -68,6 +68,8 @@ static BOOL fetch_tls_lvalue(const SYMBOL_INFO* sym, struct dbg_lvalue* lvalue) struct dbg_lvalue lv_teb_tls, lv_index_addr, lv_module_tls; dbg_lgint_t teb_tls_addr, index_addr, tls_module_addr; char* teb_tls_storage; + struct dbg_type sym_type; + DWORD tls_offset; if (!mod || !mod->tls_index_offset || !dbg_curr_thread) return FALSE; @@ -94,7 +96,10 @@ static BOOL fetch_tls_lvalue(const SYMBOL_INFO* sym, struct dbg_lvalue* lvalue) init_lvalue(&lv_module_tls, TRUE, (void*)(DWORD_PTR)(teb_tls_addr + tlsindex * ADDRSIZE)); if (!memory_fetch_integer(&lv_module_tls, ADDRSIZE, FALSE, &tls_module_addr)) return FALSE; - init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(tls_module_addr + sym->Address)); + sym_type.module = sym->ModBase; + sym_type.id = sym->Index; + if (!types_get_info(&sym_type, TI_GET_ADDRESSOFFSET, &tls_offset)) return FALSE; + init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(tls_module_addr + tls_offset)); return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> Next patches will depend on a number of bits coming from TPI being always available. Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 53 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index bc897c45878..d14fbb79cd6 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -447,6 +447,7 @@ static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_a return R_PDB_SUCCESS; } +static enum pdb_result pdb_reader_read_TPI_header(struct pdb_reader *pdb); static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb); static enum pdb_result pdb_reader_internal_binary_search(size_t num_elt, enum pdb_result (*cmp)(unsigned idx, int *cmp_ressult, void *user), @@ -1853,6 +1854,7 @@ static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) unsigned i; if ((result = pdb_reader_read_DBI_header(pdb, &pdb->dbi_header, &walker))) return result; + if ((result = pdb_reader_read_TPI_header(pdb))) return result; /* count number of compilands */ if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; @@ -2187,6 +2189,36 @@ static enum pdb_result pdb_reader_read_cv_typeid_hash(struct pdb_reader *pdb, cv return R_PDB_SUCCESS; } +static enum pdb_result pdb_reader_read_TPI_header(struct pdb_reader *pdb) +{ + enum pdb_result result; + + if ((result = pdb_reader_walker_init(pdb, PDB_STREAM_TPI, &pdb->tpi_types_walker))) goto invalid_file; + /* assuming stream is always big enough go hold a full PDB_TYPES */ + if ((result = pdb_reader_READ(pdb, &pdb->tpi_types_walker, &pdb->tpi_header))) goto invalid_file; + result = R_PDB_INVALID_PDB_FILE; + if (pdb->tpi_header.version < 19960000 || pdb->tpi_header.type_offset < sizeof(PDB_TYPES)) + { + /* not supported yet... */ + FIXME("Old PDB_TYPES header, skipping\n"); + goto invalid_file; + } + /* validate some bits */ + if (pdb->tpi_header.hash_size != (pdb->tpi_header.last_index - pdb->tpi_header.first_index) * pdb->tpi_header.hash_value_size || + pdb->tpi_header.search_size % sizeof(uint32_t[2])) + goto invalid_file; + if (pdb->tpi_header.hash_value_size > sizeof(unsigned)) + { + FIXME("Unexpected hash value size %u\n", pdb->tpi_header.hash_value_size); + goto invalid_file; + } + pdb->tpi_types_walker.offset = pdb->tpi_header.type_offset; + return R_PDB_SUCCESS; +invalid_file: + pdb->TPI_types_invalid = 1; + return R_PDB_INVALID_PDB_FILE; +} + static enum pdb_result pdb_reader_init_TPI(struct pdb_reader *pdb) { enum pdb_result result; @@ -2195,27 +2227,6 @@ static enum pdb_result pdb_reader_init_TPI(struct pdb_reader *pdb) if (pdb->TPI_types_invalid) return R_PDB_INVALID_PDB_FILE; if (!pdb->tpi_typemap) /* load basic types information and hash table */ { - if ((result = pdb_reader_walker_init(pdb, PDB_STREAM_TPI, &pdb->tpi_types_walker))) goto invalid_file; - /* assuming stream is always big enough go hold a full PDB_TYPES */ - if ((result = pdb_reader_READ(pdb, &pdb->tpi_types_walker, &pdb->tpi_header))) goto invalid_file; - result = R_PDB_INVALID_PDB_FILE; - if (pdb->tpi_header.version < 19960000 || pdb->tpi_header.type_offset < sizeof(PDB_TYPES)) - { - /* not supported yet... */ - FIXME("Old PDB_TYPES header, skipping\n"); - goto invalid_file; - } - /* validate some bits */ - if (pdb->tpi_header.hash_size != (pdb->tpi_header.last_index - pdb->tpi_header.first_index) * pdb->tpi_header.hash_value_size || - pdb->tpi_header.search_size % sizeof(uint32_t[2])) - goto invalid_file; - if (pdb->tpi_header.hash_value_size > sizeof(unsigned)) - { - FIXME("Unexpected hash value size %u\n", pdb->tpi_header.hash_value_size); - goto invalid_file; - } - pdb->tpi_types_walker.offset = pdb->tpi_header.type_offset; - if ((result = pdb_reader_alloc(pdb, (pdb->tpi_header.last_index - pdb->tpi_header.first_index) * sizeof(pdb->tpi_typemap[0]), (void **)&pdb->tpi_typemap))) goto invalid_file; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> For now just a wrapper around the existing symt*. Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 105 +++++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index d14fbb79cd6..30c3042b802 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -81,7 +81,7 @@ enum pdb_action_type { action_type_cv_typ_t, /* cv_typ_t or cv_typ16_t (depending on size) */ action_type_field, /* union codeview_fieldtype */ - action_type_globals, /* union codeview_symbol in DBI's globals stream */ + action_type_globals, /* union codeview_symbol in DBI's globals or a compiland stream */ }; struct pdb_action_entry @@ -363,11 +363,25 @@ static enum pdb_result pdb_reader_read_from_stream(struct pdb_reader *pdb, const struct symref_code { - enum {symref_code_cv_typeid, symref_code_action} kind; + enum {symref_code_top, symref_code_compiland, symref_code_cv_typeid, symref_code_action} kind; + unsigned compiland; cv_typ_t cv_typeid; unsigned action; }; +static inline struct symref_code *symref_code_init_from_top(struct symref_code *code) +{ + code->kind = symref_code_top; + return code; +} + +static inline struct symref_code *symref_code_init_from_compiland(struct symref_code *code, unsigned int compiland) +{ + code->kind = symref_code_compiland; + code->compiland = compiland; + return code; +} + static inline struct symref_code *symref_code_init_from_cv_typeid(struct symref_code *code, cv_typ_t cv_typeid) { code->kind = symref_code_cv_typeid; @@ -387,6 +401,12 @@ static enum pdb_result pdb_reader_encode_symref(struct pdb_reader *pdb, const st unsigned v; switch (code->kind) { + case symref_code_top: + v = 0; + break; + case symref_code_compiland: + v = 1 + code->compiland; + break; case symref_code_cv_typeid: if (!code->cv_typeid) { @@ -399,9 +419,10 @@ static enum pdb_result pdb_reader_encode_symref(struct pdb_reader *pdb, const st v = T_MAXPREDEFINEDTYPE + (code->cv_typeid - pdb->tpi_header.first_index); else return R_PDB_INVALID_ARGUMENT; + v += 1 + pdb->num_compilands; break; case symref_code_action: - v = T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index + code->action; + v = 1 + pdb->num_compilands + T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index + code->action; break; default: return R_PDB_INVALID_ARGUMENT; @@ -414,14 +435,22 @@ static enum pdb_result pdb_reader_decode_symref(struct pdb_reader *pdb, symref_t { if ((ref & 3) != 1) return R_PDB_INVALID_ARGUMENT; ref >>= 2; - if (ref < T_MAXPREDEFINEDTYPE) - symref_code_init_from_cv_typeid(code, ref); - else if (ref < T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index) - symref_code_init_from_cv_typeid(code, pdb->tpi_header.first_index + (ref - T_MAXPREDEFINEDTYPE)); - else if (ref < T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index + pdb->num_action_entries) - symref_code_init_from_action(code, ref - (T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index)); + if (ref == 0) + symref_code_init_from_top(code); + else if (ref < 1 + pdb->num_compilands) + symref_code_init_from_compiland(code, ref - 1); else - return R_PDB_INVALID_ARGUMENT; + { + ref -= 1 + pdb->num_compilands; + if (ref < T_MAXPREDEFINEDTYPE) + symref_code_init_from_cv_typeid(code, ref); + else if (ref < T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index) + symref_code_init_from_cv_typeid(code, pdb->tpi_header.first_index + (ref - T_MAXPREDEFINEDTYPE)); + else if (ref < T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index + pdb->num_action_entries) + symref_code_init_from_action(code, ref - (T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index)); + else + return R_PDB_INVALID_ARGUMENT; + } return R_PDB_SUCCESS; } @@ -1890,11 +1919,13 @@ static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) { struct pdb_dbi_hash_bucket *bucket = &pdb->dbi_symbols_hash_buckets[hash]; DWORD64 address; - symref_t type_symref; + struct symref_code code; + symref_t top_symref, type_symref; unsigned int i, j; BOOL found; if (!bucket->num_entries) continue; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), &top_symref))) return result; for (i = 0; i < bucket->num_entries; i++) { if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[i].dbi_stream_offset, &cv_global_symbol)) @@ -1903,7 +1934,8 @@ static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) { case S_UDT: if ((result = pdb_reader_push_action(pdb, action_type_globals, bucket->entries[i].dbi_stream_offset, - cv_global_symbol->generic.len + sizeof(cv_global_symbol->generic.len), 0, &symref))) return result; + cv_global_symbol->generic.len + sizeof(cv_global_symbol->generic.len), + top_symref, &symref))) return result; break; case S_GDATA32: /* There are cases (incremental linking) where we have several entries of same name, but @@ -3473,29 +3505,42 @@ static enum method_result pdb_reader_DBI_typedef_request(struct pdb_reader *pdb, } } -static enum method_result pdb_reader_DBI_globals_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +static enum method_result pdb_reader_codeview_symbol_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result; struct pdb_reader_walker walker; + struct symref_code code; union codeview_symbol *cv_symbol; - pdbsize_t num_read; enum method_result ret = MR_FAILURE; + unsigned int stream_id; - if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return MR_FAILURE; - walker.offset = entry->stream_offset; - if ((result = pdb_reader_alloc(pdb, entry->action_length, (void**)&cv_symbol))) return MR_FAILURE; - if ((result = pdb_reader_read_from_stream(pdb, &walker, cv_symbol, entry->action_length, &num_read))) return MR_FAILURE; - if (num_read == entry->action_length) + if ((result = pdb_reader_decode_symref(pdb, entry->container_symref, &code))) return MR_FAILURE; + if (code.kind == symref_code_top) + stream_id = pdb->dbi_header.gsym_stream; + else if (code.kind == symref_code_compiland) + stream_id = pdb->compilands[code.compiland].compiland_stream_id; + else { - switch (cv_symbol->generic.id) - { - case S_UDT: + FIXME("Unexpected encoding kind %u\n", code.kind); + return MR_FAILURE; + } + + if ((result = pdb_reader_walker_init(pdb, stream_id, &walker)) || + (result = pdb_reader_walker_narrow(&walker, entry->stream_offset, entry->action_length)) || + (result = pdb_reader_alloc_and_read_full_codeview_symbol(pdb, &walker, &cv_symbol))) + return MR_FAILURE; + + switch (cv_symbol->generic.id) + { + case S_UDT: + if (code.kind == symref_code_top) ret = pdb_reader_DBI_typedef_request(pdb, entry, cv_symbol, req, data); - break; - default: - WARN("Got unexpected %x\n", cv_symbol->generic.id); - break; - } + else + FIXME("Unexpected encoding kind %u\n", code.kind); + break; + default: + WARN("Got unexpected %x\n", cv_symbol->generic.id); + break; } pdb_reader_free(pdb, cv_symbol); return ret; @@ -3560,6 +3605,10 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy if (pdb_reader_decode_symref(pdb, symref, &code)) return MR_FAILURE; switch (code.kind) { + case symref_code_top: + return symt_get_info(pdb->module, &pdb->module->top->symt, req, data) ? MR_SUCCESS : MR_FAILURE; + case symref_code_compiland: + return symt_get_info(pdb->module, &pdb->compilands[code.compiland].compiland->symt, req, data) ? MR_SUCCESS : MR_FAILURE; case symref_code_cv_typeid: if (code.cv_typeid < T_MAXPREDEFINEDTYPE) return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); @@ -3577,7 +3626,7 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy case action_type_field: return pdb_reader_TPI_field_request(pdb, entry, req, data); case action_type_globals: - return pdb_reader_DBI_globals_request(pdb, entry, req, data); + return pdb_reader_codeview_symbol_request(pdb, entry, req, data); default: return MR_FAILURE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 30c3042b802..657ee77d683 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -2596,7 +2596,19 @@ static int my_action_global_cmp(const void *p1, const void *p2) return 0; } -static enum method_result pdb_method_find_type(struct module_format *modfmt, const char *name, symref_t *ref) +static enum pdb_result pdb_reader_DBI_globals_symref(struct pdb_reader *pdb, unsigned globals_offset, symref_t *symref) +{ + struct symref_code code; + struct pdb_action_entry *entry; + + entry = bsearch(&globals_offset, pdb->action_store, pdb->num_action_globals, sizeof(pdb->action_store[0]), + &my_action_global_cmp); + if (entry) + return pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, entry - pdb->action_store), symref); + return R_PDB_NOT_FOUND; +} + +static enum method_result pdb_method_find_type(struct module_format *modfmt, const char *name, symref_t *symref) { struct pdb_reader *pdb; enum pdb_result result; @@ -2614,17 +2626,12 @@ static enum method_result pdb_method_find_type(struct module_format *modfmt, con if ((result = pdb_reader_read_codeview_type_by_name(pdb, name, &walker, &cv_type, &cv_typeid)) == R_PDB_SUCCESS) { if ((result = pdb_reader_get_type_details(pdb, cv_typeid, &type_details))) return MR_FAILURE; - return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), symref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; } /* search in DBI globals' hash table */ if ((result = pdb_reader_read_DBI_codeview_symbol_by_name(pdb, name, &stream_offset, &cv_symbol)) == R_PDB_SUCCESS) { - struct pdb_action_entry *entry; - entry = bsearch(&stream_offset, pdb->action_store, pdb->num_action_globals, sizeof(pdb->action_store[0]), - &my_action_global_cmp); - if (entry) - return pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, entry - pdb->action_store), - ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + return pdb_method_result(pdb_reader_DBI_globals_symref(pdb, stream_offset, symref)); } return MR_FAILURE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/symbol.c | 67 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index a3f323ebea6..a21fc73ce8a 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -871,6 +871,69 @@ static BOOL symt_fill_sym_info(struct module_pair* pair, return TRUE; } +static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, symref_t symref, SYMBOL_INFO* sym_info) +{ + DWORD tag; + DWORD64 size; + WCHAR *name; + + if (!symt_get_info_from_symref(pair->effective, symref, TI_GET_SYMTAG, &tag)) + return FALSE; + + sym_info->Tag = tag; + if (symt_is_symref_ptr(symref)) + return symt_fill_sym_info(pair, NULL, SYMT_SYMREF_TO_PTR(symref), sym_info); + + /* FIXME this isn't optimal; perhaps implement SymGetInfoTypeEx to support multiple + * queries at once! + */ + if (!symt_get_info_from_symref(pair->effective, symref, TI_GET_TYPE, &sym_info->TypeIndex)) + sym_info->TypeIndex = 0; + sym_info->Index = symt_symref_to_index(pair->effective, symref); + sym_info->Reserved[0] = sym_info->Reserved[1] = 0; + if (!symt_get_info_from_symref(pair->effective, symref, TI_GET_ADDRESS, &sym_info->Address)) + sym_info->Address = 0; + if (!symt_get_info_from_symref(pair->effective, symref, TI_GET_LENGTH, &size) && + (!sym_info->TypeIndex || + !symt_get_info_from_index(pair->effective, sym_info->TypeIndex, TI_GET_LENGTH, &size))) + size = 0; + sym_info->Size = (DWORD)size; + sym_info->ModBase = pair->requested->module.BaseOfImage; + sym_info->Flags = 0; + sym_info->Value = 0; + sym_info->Register = 0; + sym_info->Scope = 0; /* FIXME */ + + /* FIXME we're swinging back & forth between ANSI & UNICODE... */ + if (symt_get_info_from_symref(pair->effective, symref, TI_GET_SYMNAME, &name) && name) + { + SIZE_T len = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); + char *buffer; + char *tmp; + + if (sym_info->MaxNameLen && (buffer = malloc(len))) + { + WideCharToMultiByte(CP_ACP, 0, name, -1, buffer, len, NULL, NULL); + if (sym_info->Tag == SymTagPublicSymbol && (dbghelp_options & SYMOPT_UNDNAME) && + (tmp = __unDName(NULL, buffer, 0, malloc, free, UNDNAME_NAME_ONLY)) != NULL) + { + symbol_setname(sym_info, tmp); + free(tmp); + } + else + symbol_setname(sym_info, buffer); + free(buffer); + } + else symbol_setname(sym_info, ""); + LocalFree(name); + } + else symbol_setname(sym_info, ""); + + TRACE_(dbghelp_symt)("%Ix => %s %lu %I64x\n", + symref, debugstr_a(sym_info->Name), sym_info->Size, sym_info->Address); + return TRUE; +} + struct sym_enum { PSYM_ENUMERATESYMBOLS_CALLBACK cb; @@ -2761,9 +2824,7 @@ BOOL WINAPI SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBO if (!module_init_pair(&pair, hProcess, BaseOfDll)) return FALSE; if ((symref = symt_index_to_symref(pair.effective, index)) == 0) return FALSE; - if (!symt_is_symref_ptr(symref)) return FALSE; - symt_fill_sym_info(&pair, NULL, (struct symt*)symref, symbol); - return TRUE; + return symt_fill_sym_info_from_symref(&pair, symref, symbol); } /****************************************************************** -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/dbghelp_private.h | 3 +- dlls/dbghelp/elf_module.c | 2 +- dlls/dbghelp/macho_module.c | 2 +- dlls/dbghelp/symbol.c | 75 ++++++++++++++++++---------------- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 39a12af130f..20892db8cda 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -913,8 +913,7 @@ extern int __cdecl symt_cmp_addr(const void* p1, const void* p2); extern void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si); extern void symbol_setname(SYMBOL_INFO* si, const char* name); extern BOOL symt_match_stringAW(const char *string, const WCHAR *re, BOOL _case); -extern struct symt_ht* - symt_find_nearest(struct module* module, DWORD_PTR addr); +extern symref_t symt_find_nearest(struct module* module, DWORD_PTR addr); extern struct symt_ht* symt_find_symbol_at(struct module* module, DWORD_PTR addr); extern struct symt_module* diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index af6fb916290..81f933c76ef 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -946,7 +946,7 @@ static int elf_new_wine_thunks(struct module* module, const struct hash_table* h ULONG64 ref_addr; struct location loc; - symt = symt_find_nearest(module, addr); + symt = (struct symt_ht*)SYMT_SYMREF_TO_PTR(symt_find_nearest(module, addr)); if (symt && !symt_get_address(&symt->symt, &ref_addr)) ref_addr = addr; if (!symt || addr != ref_addr) diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index 9b24fd48ae0..a8358510caf 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1151,7 +1151,7 @@ static void macho_finish_stabs(struct module* module, struct hash_table* ht_symt if (ste->used) continue; - sym = symt_find_nearest(module, ste->addr); + sym = (struct symt_ht*)SYMT_SYMREF_TO_PTR(symt_find_nearest(module, ste->addr)); if (sym) symt_get_address(&sym->symt, &addr); if (sym && ste->addr == addr) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index a21fc73ce8a..d6b7dba4426 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -264,7 +264,7 @@ struct symt_public* symt_new_public(struct module* module, TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%Ix\n", debugstr_w(module->modulename), debugstr_a(name), address); if ((dbghelp_options & SYMOPT_AUTO_PUBLICS) && - symt_find_nearest(module, address) != NULL) + symt_find_nearest(module, address)) return NULL; if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { @@ -871,7 +871,7 @@ static BOOL symt_fill_sym_info(struct module_pair* pair, return TRUE; } -static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, symref_t symref, SYMBOL_INFO* sym_info) +static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, const struct symt_function* func, symref_t symref, SYMBOL_INFO* sym_info) { DWORD tag; DWORD64 size; @@ -882,7 +882,7 @@ static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, symref_t sy sym_info->Tag = tag; if (symt_is_symref_ptr(symref)) - return symt_fill_sym_info(pair, NULL, SYMT_SYMREF_TO_PTR(symref), sym_info); + return symt_fill_sym_info(pair, func, SYMT_SYMREF_TO_PTR(symref), sym_info); /* FIXME this isn't optimal; perhaps implement SymGetInfoTypeEx to support multiple * queries at once! @@ -946,9 +946,9 @@ struct sym_enum }; static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair, - const struct symt_function* func, const struct symt* sym) + const struct symt_function* func, symref_t symref) { - if (!symt_fill_sym_info(pair, func, sym, se->sym_info)) return FALSE; + if (!symt_fill_sym_info_from_symref(pair, func, symref, se->sym_info)) return FALSE; if (se->index && se->sym_info->Index != se->index) return FALSE; if (se->tag && se->sym_info->Tag != se->tag) return FALSE; if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE; @@ -968,11 +968,7 @@ static BOOL symbol_enum_method_cb(symref_t symref, const char *name, void *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); + send_symbol(sem->se, sem->pair, NULL, symref); return TRUE; } @@ -1008,7 +1004,7 @@ static BOOL symt_enum_module(struct module_pair* pair, const WCHAR* match, { se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO); - if (send_symbol(se, pair, NULL, &sym->symt)) return TRUE; + if (send_symbol(se, pair, NULL, symt_ptr_to_symref(&sym->symt))) return TRUE; } } return FALSE; @@ -1176,7 +1172,7 @@ static struct symt_ht* symt_find_nearest_internal(struct module* module, DWORD_P return module->addr_sorttab[low]; } -struct symt_ht *symt_find_nearest(struct module *module, DWORD_PTR addr) +symref_t symt_find_nearest(struct module *module, DWORD_PTR addr) { static int recursive; struct module_format_vtable_iterator iter = {}; @@ -1192,31 +1188,45 @@ struct symt_ht *symt_find_nearest(struct module *module, DWORD_PTR addr) 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; + if (!symt_is_symref_ptr(symref)) FIXME("No support for this case yet\n"); + return symref; } /* fall back in all the other cases */ } } recursive--; - return symt_find_nearest_internal(module, addr); + return symt_ptr_to_symref(&symt_find_nearest_internal(module, addr)->symt); } -struct symt_ht* symt_find_symbol_at(struct module* module, DWORD_PTR addr) +static symref_t symt_find_symref_at(struct module* module, DWORD_PTR addr) { - struct symt_ht* nearest = symt_find_nearest(module, addr); + symref_t nearest = symt_find_nearest(module, addr); if (nearest) { - ULONG64 symaddr, symsize; - symt_get_address(&nearest->symt, &symaddr); - symt_get_length(module, &nearest->symt, &symsize); + ULONG64 symaddr, symsize; + if (symt_get_info_from_symref(module, nearest, TI_GET_ADDRESS, &symaddr)) + { + /* some symbols are defined without size, so grab size for their type (if any) */ + if (!symt_get_info_from_symref(module, nearest, TI_GET_LENGTH, &symsize) || !symsize) + { + DWORD symtype; + if (!symt_get_info_from_symref(module, nearest, TI_GET_TYPE, &symtype) || + !symt_get_info_from_index(module, symtype, TI_GET_LENGTH, &symsize)) + symsize = 1; + } + } if (addr < symaddr || addr >= symaddr + symsize) - nearest = NULL; + nearest = 0; } return nearest; } +struct symt_ht* symt_find_symbol_at(struct module* module, DWORD_PTR addr) +{ + symref_t nearest = symt_find_symref_at(module, addr); + return (struct symt_ht*)SYMT_SYMREF_TO_PTR(nearest); +} + static BOOL symt_enum_locals_helper(struct module_pair* pair, const WCHAR* match, const struct sym_enum* se, struct symt_function* func, const struct vector* v) @@ -1254,7 +1264,7 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair, HeapFree(GetProcessHeap(), 0, nameW); if (ret) { - if (send_symbol(se, pair, func, lsym)) return FALSE; + if (send_symbol(se, pair, func, symt_ptr_to_symref(lsym))) return FALSE; } break; case SymTagLabel: @@ -1609,16 +1619,16 @@ BOOL WINAPI SymEnumerateSymbols64(HANDLE hProcess, DWORD64 BaseOfDll, * SymFromAddr (DBGHELP.@) * */ -BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, +BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, DWORD64* Displacement, PSYMBOL_INFO Symbol) { struct module_pair pair; - struct symt_ht* sym; + symref_t symref; if (!module_init_pair(&pair, hProcess, Address)) return FALSE; - if ((sym = symt_find_symbol_at(pair.effective, Address)) == NULL) return FALSE; + if (!(symref = symt_find_symref_at(pair.effective, Address))) return FALSE; - symt_fill_sym_info(&pair, NULL, &sym->symt, Symbol); + symt_fill_sym_info_from_symref(&pair, NULL, symref, Symbol); if (Displacement) *Displacement = (Address >= Symbol->Address) ? (Address - Symbol->Address) : (DWORD64)-1; return TRUE; @@ -1725,13 +1735,8 @@ static BOOL find_name(struct process* pcs, struct module* module, const char* na 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; + symt_fill_sym_info_from_symref(&pair, NULL, symref, symbol); + return TRUE; } if (result != MR_NOT_FOUND) return FALSE; } @@ -2824,7 +2829,7 @@ BOOL WINAPI SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBO if (!module_init_pair(&pair, hProcess, BaseOfDll)) return FALSE; if ((symref = symt_index_to_symref(pair.effective, index)) == 0) return FALSE; - return symt_fill_sym_info_from_symref(&pair, symref, symbol); + return symt_fill_sym_info_from_symref(&pair, NULL, symref, symbol); } /****************************************************************** -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9957
participants (2)
-
Eric Pouech -
eric pouech (@epo)