[PATCH 0/5] MR10018: PDB speedup 4
This MR continues improving PDB support: - by no longer creating symt for global and file static variables (the function static are still created as symt), - starting implementing some direct access for top module and compiland objects - it incidentaly fixes support for thread storage variables. This reduces memory footprint and optimizes initial debug info load time (up to a couple of seconds on large PDB files). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 367 ++++++++++++++++++++++++++++++++---------- dlls/dbghelp/symbol.c | 44 ++++- 2 files changed, 325 insertions(+), 86 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 657ee77d683..d8fddbef155 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -120,6 +120,12 @@ struct pdb_compiland struct symt_compiland* compiland; }; +struct pdb_global +{ + unsigned rva; + symref_t symref; +}; + struct pdb_reader { struct module *module; @@ -170,6 +176,10 @@ struct pdb_reader const IMAGE_SECTION_HEADER *sections; unsigned num_sections; + /* global symbols map */ + struct pdb_global *globals; + unsigned num_globals; + /* PDB file access */ pdb_reader_fetch_block_t fetch; struct {unsigned block_no; unsigned age;} cache[4*4]; @@ -1840,16 +1850,6 @@ static enum pdb_result pdb_reader_whole_stream_access_codeview_symbol(struct pdb return R_PDB_SUCCESS; } -static int my_action_global_obj_cmp(const void *p1, const void *p2) -{ - pdbsize_t o1 = ((const struct pdb_action_entry *)p1)->stream_offset; - pdbsize_t o2 = ((const struct pdb_action_entry *)p2)->stream_offset; - - if (o1 < o2) return -1; - if (o1 > o2) return +1; - return 0; -} - static enum pdb_result pdb_reader_init_DBI_substreams(struct pdb_reader *pdb) { enum pdb_result result; @@ -1871,14 +1871,23 @@ static enum pdb_result pdb_reader_init_DBI_substreams(struct pdb_reader *pdb) return R_PDB_SUCCESS; } +static int pdb_global_cmp(const void *p1, const void *p2) +{ + const struct pdb_global *g1 = p1; + const struct pdb_global *g2 = p2; + if (g1->rva < g2->rva) return -1; + if (g1->rva > g2->rva) return +1; + return 0; +} + static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) { enum pdb_result result; struct pdb_reader_compiland_iterator compiland_iter; struct pdb_reader_walker walker; - struct pdb_reader_whole_stream whole; - const union codeview_symbol *cv_global_symbol, *cv_global_symbol2; - unsigned hash; + union codeview_symbol cv_symbol; + struct symref_code code; + symref_t top_symref; symref_t symref; unsigned i; @@ -1913,65 +1922,46 @@ static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) } if ((result = pdb_reader_load_DBI_hash_table(pdb))) return result; - if ((result = pdb_reader_alloc_and_load_whole_stream(pdb, pdb->dbi_header.gsym_stream, &whole))) return result; + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return result; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), &top_symref))) return result; - for (hash = 0; hash < DBI_MAX_HASH; hash++) + pdb->num_globals = 0; + pdb->globals = NULL; + while (!(result = pdb_reader_read_partial_codeview_symbol(pdb, &walker, &cv_symbol))) { - struct pdb_dbi_hash_bucket *bucket = &pdb->dbi_symbols_hash_buckets[hash]; - DWORD64 address; - 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++) + DWORD64 addr; + switch (cv_symbol.generic.id) { - if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[i].dbi_stream_offset, &cv_global_symbol)) + case S_GDATA32: + case S_LDATA32: + case S_GTHREAD32: + case S_LTHREAD32: + case S_UDT: + if ((result = pdb_reader_push_action(pdb, action_type_globals, walker.offset - sizeof(cv_symbol.generic.len), + cv_symbol.generic.len + sizeof(cv_symbol.generic.len), + top_symref, &symref))) return result; + if (cv_symbol.generic.id == S_GDATA32 || cv_symbol.generic.id == S_LDATA32) { - switch (cv_global_symbol->generic.id) + if (!pdb_reader_get_segment_address(pdb, cv_symbol.data_v3.segment, cv_symbol.data_v3.offset, &addr)) { - 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), - top_symref, &symref))) return result; - break; - case S_GDATA32: - /* There are cases (incremental linking) where we have several entries of same name, but - * only one is valid. - * We discriminate valid with: - * - there's no other entry with same name before this entry in hash bucket, - * - the address is valid - * - the typeid is valid - * Note: checking address map doesn't bring nothing as the invalid entries are also listed - * there. - */ - found = FALSE; - for (j = 0; !found && j < i; j++) + if (!(pdb->num_globals & (pdb->num_globals - 1))) { - if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[j].dbi_stream_offset, &cv_global_symbol2)) - found = !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); + unsigned sz = pdb->num_globals ? pdb->num_globals * 2 : 1; + if ((result = pdb_reader_realloc(pdb, (void **)&pdb->globals, sz * sizeof(pdb->globals[0])))) + return result; } - if (!found && - !pdb_reader_get_segment_address(pdb, cv_global_symbol->data_v3.segment, cv_global_symbol->data_v3.offset, &address) && - !pdb_reader_symref_from_cv_typeid(pdb, cv_global_symbol->data_v3.symtype, &type_symref)) - { - struct location loc = {.kind = loc_absolute, .reg = 0, .offset = address}; - symt_new_global_variable(pdb->module, 0, cv_global_symbol->data_v3.name, - FALSE, loc, 0, type_symref); - } - break; + pdb->globals[pdb->num_globals].rva = addr - pdb->module->module.BaseOfImage; + pdb->globals[pdb->num_globals].symref = symref; + pdb->num_globals++; } } + break; } + walker.offset += cv_symbol.generic.len; } - if ((result = pdb_reader_dispose_whole_stream(pdb, &whole))) return result; pdb->num_action_globals = pdb->num_action_entries; - /* as we walked the DBI stream according to hash order, resort by stream_offset */ - qsort(pdb->action_store, pdb->num_action_globals, sizeof(pdb->action_store[0]), - &my_action_global_obj_cmp); - + /* Note: rva is not unique */ + qsort(pdb->globals, pdb->num_globals, sizeof(*pdb->globals), &pdb_global_cmp); if ((result = pdb_reader_init_DBI_substreams(pdb))) return result; return R_PDB_SUCCESS; @@ -2778,28 +2768,21 @@ static enum method_result pdb_method_enumerate_types(struct module_format *modfm struct pdb_reader_walker walker; union codeview_symbol *cv_symbol; struct pdb_action_entry *entry; - pdbsize_t num_read; entry = &pdb->action_store[i]; 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 ((result = pdb_reader_alloc_and_read_full_codeview_symbol(pdb, &walker, &cv_symbol))) return MR_FAILURE; if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, i), &symref))) return MR_FAILURE; - if (num_read == entry->action_length) + switch (cv_symbol->generic.id) { - switch (cv_symbol->generic.id) - { - case S_UDT: - ret = (*cb)(symref, cv_symbol->udt_v3.name, user); - break; - default: - WARN("Got unexpected %x\n", cv_symbol->generic.id); - ret = FALSE; - break; - } + case S_UDT: + ret = (*cb)(symref, cv_symbol->udt_v3.name, user); + break; + default: + ret = TRUE; + break; } - else ret = TRUE; pdb_reader_free(pdb, cv_symbol); if (!ret) break; } @@ -3512,6 +3495,65 @@ static enum method_result pdb_reader_DBI_typedef_request(struct pdb_reader *pdb, } } +static enum method_result pdb_reader_symbol_data_request(struct pdb_reader *pdb, union codeview_symbol *cv_symbol, symref_t parent_symref, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagData; + return MR_SUCCESS; + case TI_GET_SYMNAME: + *((WCHAR **)data) = heap_allocate_symname(cv_symbol->data_v3.name); + return *((WCHAR **)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_DATAKIND: + *((DWORD*)data) = cv_symbol->generic.id == S_GDATA32 ? DataIsGlobal : DataIsFileStatic; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + *((DWORD*)data) = symt_symref_to_index(pdb->module, parent_symref); + return MR_SUCCESS; + case TI_GET_ADDRESS: + return pdb_method_result(pdb_reader_get_segment_address(pdb, cv_symbol->data_v3.segment, cv_symbol->data_v3.offset, data)); + case TI_GET_LENGTH: + return pdb_reader_request_cv_typeid(pdb, cv_symbol->data_v3.symtype, req, data); + case TI_GET_TYPE: + case TI_GET_TYPEID: + return pdb_reader_index_from_cv_typeid(pdb, cv_symbol->data_v3.symtype, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + default: + return MR_FAILURE; + } +} + +static enum method_result pdb_reader_symbol_tls_request(struct pdb_reader *pdb, union codeview_symbol *cv_symbol, symref_t parent_symref, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagData; + return MR_SUCCESS; + case TI_GET_SYMNAME: + *((WCHAR **)data) = heap_allocate_symname(cv_symbol->thread_v3.name); + return *((WCHAR **)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_DATAKIND: + *((DWORD*)data) = cv_symbol->generic.id == S_GTHREAD32 ? DataIsGlobal : DataIsFileStatic; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + *((DWORD*)data) = symt_symref_to_index(pdb->module, parent_symref); + return MR_SUCCESS; + case TI_GET_ADDRESSOFFSET: + *((DWORD*)data) = cv_symbol->thread_v3.offset; + return MR_SUCCESS; + case TI_GET_LENGTH: + return pdb_reader_request_cv_typeid(pdb, cv_symbol->thread_v3.symtype, req, data); + case TI_GET_TYPE: + case TI_GET_TYPEID: + return pdb_reader_index_from_cv_typeid(pdb, cv_symbol->thread_v3.symtype, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + default: + return MR_FAILURE; + } +} + 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; @@ -3545,6 +3587,12 @@ static enum method_result pdb_reader_codeview_symbol_request(struct pdb_reader * else FIXME("Unexpected encoding kind %u\n", code.kind); break; + case S_GDATA32: + case S_LDATA32: + return pdb_reader_symbol_data_request(pdb, cv_symbol, entry->container_symref, req, data); + case S_GTHREAD32: + case S_LTHREAD32: + return pdb_reader_symbol_tls_request(pdb, cv_symbol, entry->container_symref, req, data); default: WARN("Got unexpected %x\n", cv_symbol->generic.id); break; @@ -3598,6 +3646,121 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, symref_ return ret; } +static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, unsigned *count, DWORD *ids, unsigned first, unsigned last) +{ + struct pdb_reader_whole_stream whole; + struct symref_code code; + symref_t top_symref; + enum pdb_result result = R_PDB_SUCCESS; + unsigned int hash; + + if ((result = pdb_reader_alloc_and_load_whole_stream(pdb, pdb->dbi_header.gsym_stream, &whole))) return result; + *count = 0; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), &top_symref))) return result; + for (hash = 0; hash < DBI_MAX_HASH && !result; hash++) + { + struct pdb_dbi_hash_bucket *bucket = &pdb->dbi_symbols_hash_buckets[hash]; + const union codeview_symbol *cv_global_symbol, *cv_global_symbol2; + symref_t symref; + unsigned int i, j; + BOOL found; + + if (!bucket->num_entries) continue; + for (i = 0; i < bucket->num_entries && !result; i++) + { + if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[i].dbi_stream_offset, &cv_global_symbol)) + { + symref = 0; + found = FALSE; + switch (cv_global_symbol->generic.id) + { + case S_UDT: + found = TRUE; + break; + case S_GDATA32: + /* There are cases (incremental linking) where we have several entries of same name, but + * only one is valid. + * We discriminate valid with: + * - there's no other entry with same name before this entry in hash bucket, + * - the address is valid + * - the typeid is valid + * Note: checking address map doesn't bring nothing as the invalid entries are also listed + * there. + */ + for (j = 0; !found && j < i; j++) + { + if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[j].dbi_stream_offset, &cv_global_symbol2)) + found = !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); + } + found = !found; + break; + default: + break; + } + if (found) + { + if (ids) + { + if (*count >= last) + result = R_PDB_BUFFER_TOO_SMALL; + if (*count >= first) + { + 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), + top_symref, &symref))) + ids[*count] = symt_symref_to_index(pdb->module, symref); + } + } + (*count)++; + } + } + } + } + (void)pdb_reader_dispose_whole_stream(pdb, &whole); + return result; +} + +static enum method_result pdb_reader_top_request(struct pdb_reader *pdb, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum pdb_result result; + + switch (req) + { + case TI_GET_SYMTAG: + *(DWORD*)data = SymTagExe; + return MR_SUCCESS; + case TI_GET_CHILDRENCOUNT: + { + unsigned count; + if (!symt_get_info(pdb->module, &pdb->module->top->symt, req, data) || + pdb_reader_top_fill_in(pdb, &count, NULL, 0, 0)) return MR_FAILURE; + *(DWORD*)data += count; + return MR_SUCCESS; + } + case TI_FINDCHILDREN: + { + TI_FINDCHILDREN_PARAMS *p = data; + TI_FINDCHILDREN_PARAMS *alt; + unsigned int count; + + if (pdb_reader_top_fill_in(pdb, &count, p->ChildId, p->Start, p->Count)) return MR_FAILURE; + if (!(alt = malloc(offsetof(TI_FINDCHILDREN_PARAMS, ChildId[p->Count - count])))) return MR_FAILURE; + alt->Start = 0; + alt->Count = p->Count - count; + result = symt_get_info(pdb->module, &pdb->module->top->symt, TI_FINDCHILDREN, alt); + if (result == R_PDB_SUCCESS) + memcpy(&p->ChildId[count], alt->ChildId, (p->Count - count) * sizeof(p->ChildId[0])); + free(alt); + return pdb_method_result(result); + } + case TI_GET_SYMNAME: + return symt_get_info(pdb->module, &pdb->module->top->symt, req, data) ? MR_SUCCESS : MR_FAILURE; + default: + return MR_FAILURE; + } +} + static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { struct pdb_type_details *type_details; @@ -3613,7 +3776,7 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy switch (code.kind) { case symref_code_top: - return symt_get_info(pdb->module, &pdb->module->top->symt, req, data) ? MR_SUCCESS : MR_FAILURE; + return pdb_reader_top_request(pdb, symref, req, data); 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: @@ -3809,6 +3972,8 @@ static enum pdb_result pdb_reader_search_codeview_symbol_by_address(struct pdb_r case S_BUILDINFO: case S_UDT: case S_UNAMESPACE: + case S_GTHREAD32: + case S_LTHREAD32: segment = 0; offset = 0; pend = 0; @@ -4302,7 +4467,7 @@ static enum pdb_result pdb_reader_create_variable(struct pdb_reader *pdb, } if (is_local ^ (compiland != 0)) FIXME("Unsupported construct\n"); - symt_new_global_variable(pdb->module, compiland, name, is_local, *loc, 0, symref); + symt_new_global_variable(pdb->module, (is_local && loc->kind == loc_tlsrel) ? 0 : compiland, name, is_local, *loc, 0, symref); } return R_PDB_SUCCESS; } @@ -4359,7 +4524,6 @@ static enum pdb_result pdb_reader_load_compiland_symbols(struct pdb_reader *pdb, break; /* variables with thread storage */ - case S_GTHREAD32: case S_LTHREAD32: loc.kind = loc_tlsrel; loc.reg = 0; @@ -4625,6 +4789,7 @@ static enum pdb_result pdb_reader_load_compiland_symbols(struct pdb_reader *pdb, case S_LPROCREF: case S_TOKENREF: case S_GDATA32: + case S_GTHREAD32: case S_UDT: PDB_REPORT_UNEXPECTED("(compiland stream) symbol id", cv_symbol->generic.id); break; @@ -4727,9 +4892,30 @@ static enum method_result pdb_method_lookup_symbol_by_address(struct module_form enum pdb_result result; struct pdb_reader *pdb; unsigned segment, offset; + struct pdb_global key, *found; pdb = pdb_get_current_reader(modfmt); - if ((result = pdb_reader_get_segment_offset_from_address(pdb, address, &segment, &offset))) return MR_FAILURE; + if ((result = pdb_reader_get_segment_offset_from_address(pdb, address, &segment, &offset))) + { + struct symref_code code; + if (address == pdb->module->module.BaseOfImage && !pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), symref)) + return MR_SUCCESS; + return MR_FAILURE; + } + key.rva = address - pdb->module->module.BaseOfImage; + found = bsearch(&key, pdb->globals, pdb->num_globals, sizeof(*pdb->globals), &pdb_global_cmp); + if (found && found->rva == key.rva) + { + /* Note: we can have several names for the same address. + * For now, we return one of the entries, no clear way of choosing one or another + */ + if (found > pdb->globals && (found - 1)->rva == key.rva) + WARN("Duplicate found before\n"); + if (found + 1 < pdb->globals + pdb->num_globals && (found + 1)->rva == key.rva) + WARN("Duplicate found after\n"); + *symref = found->symref; + return MR_SUCCESS; + } return pdb_method_result(pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, symref)); } @@ -4791,10 +4977,16 @@ static enum method_result pdb_method_lookup_symbol_by_name(struct module_format switch (cv_symbol.generic.id) { case S_GDATA32: + case S_GTHREAD32: + return pdb_method_result(pdb_reader_DBI_globals_symref(pdb, globals_offset, symref)); case S_LDATA32: segment = cv_symbol.data_v3.segment; offset = cv_symbol.data_v3.offset; break; + case S_LTHREAD32: + segment = cv_symbol.thread_v3.segment; + offset = cv_symbol.thread_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, @@ -4864,12 +5056,21 @@ static enum method_result pdb_method_enumerate_symbols(struct module_format *mod 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) + if (symt_match_stringAW(symbol_name, match, TRUE)) { - do_continue = cb(symref, symbol_name, user); + symref_t symref; + switch (cv_symbol.generic.id) + { + case S_GDATA32: + result = pdb_reader_DBI_globals_symref(pdb, walker.offset - sizeof(cv_symbol.generic.len), &symref); + break; + default: + result = pdb_reader_lookup_top_symbol_by_segment_offset(pdb, segment, offset, &symref); + break; + } + if (result == R_PDB_SUCCESS) + do_continue = cb(symref, symbol_name, user); } pdb_reader_free(pdb, symbol_name); if (!do_continue) return MR_SUCCESS; diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index d6b7dba4426..e786dc61e66 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -876,6 +876,7 @@ static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, const struc DWORD tag; DWORD64 size; WCHAR *name; + DWORD data_kind, offset; if (!symt_get_info_from_symref(pair->effective, symref, TI_GET_SYMTAG, &tag)) return FALSE; @@ -911,7 +912,7 @@ static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, const struc char *buffer; char *tmp; - if (sym_info->MaxNameLen && (buffer = malloc(len))) + if (len && (buffer = malloc(len))) { WideCharToMultiByte(CP_ACP, 0, name, -1, buffer, len, NULL, NULL); if (sym_info->Tag == SymTagPublicSymbol && (dbghelp_options & SYMOPT_UNDNAME) && @@ -929,6 +930,41 @@ static BOOL symt_fill_sym_info_from_symref(struct module_pair* pair, const struc } else symbol_setname(sym_info, ""); + switch (sym_info->Tag) + { + case SymTagData: + if (symt_get_info_from_symref(pair->effective, symref, TI_GET_DATAKIND, &data_kind)) + switch (data_kind) + { + case DataIsGlobal: + case DataIsFileStatic: + case DataIsStaticLocal: + if (symt_get_info_from_symref(pair->effective, symref, TI_GET_ADDRESSOFFSET, &offset)) + sym_info->Flags |= SYMFLAG_TLSREL; + break; + case DataIsConstant: + if (symt_get_info_from_symref(pair->effective, symref, TI_GET_VALUE, &sym_info->Value)) + sym_info->Flags |= SYMFLAG_VALUEPRESENT; + break; + default: + FIXME("Unhandled kind (%lu) in sym data\n", data_kind); + break; + } + else WARN("Couldn't get data kind\n"); + break; + case SymTagUDT: + case SymTagEnum: + case SymTagFunctionType: + case SymTagPointerType: + case SymTagArrayType: + case SymTagBaseType: + case SymTagTypedef: + break; + default: + FIXME("%Ix => %lu %s %lu %I64x\n", + symref, sym_info->Tag, debugstr_a(sym_info->Name), sym_info->Size, sym_info->Address); + } + TRACE_(dbghelp_symt)("%Ix => %s %lu %I64x\n", symref, debugstr_a(sym_info->Name), sym_info->Size, sym_info->Address); return TRUE; @@ -1188,7 +1224,6 @@ symref_t symt_find_nearest(struct module *module, DWORD_PTR addr) if (result == MR_SUCCESS) { recursive--; - if (!symt_is_symref_ptr(symref)) FIXME("No support for this case yet\n"); return symref; } /* fall back in all the other cases */ @@ -1221,10 +1256,13 @@ static symref_t symt_find_symref_at(struct module* module, DWORD_PTR addr) return nearest; } +/* callers really expect a symt ptr from here, so fail when found + * symbol is a symref + */ 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); + return (symt_is_symref_ptr(nearest)) ? (struct symt_ht*)SYMT_SYMREF_TO_PTR(nearest) : NULL; } static BOOL symt_enum_locals_helper(struct module_pair* pair, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
From: Eric Pouech <epouech@codeweavers.com> (static variables inside functions are still created with a symt*). Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index d8fddbef155..18bfa538665 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -415,6 +415,7 @@ static enum pdb_result pdb_reader_encode_symref(struct pdb_reader *pdb, const st v = 0; break; case symref_code_compiland: + if (code->compiland >= pdb->num_compilands) return R_PDB_INVALID_ARGUMENT; v = 1 + code->compiland; break; case symref_code_cv_typeid: @@ -3510,6 +3511,15 @@ static enum method_result pdb_reader_symbol_data_request(struct pdb_reader *pdb, *((DWORD*)data) = cv_symbol->generic.id == S_GDATA32 ? DataIsGlobal : DataIsFileStatic; return MR_SUCCESS; case TI_GET_LEXICALPARENT: + if (cv_symbol->generic.id == S_LDATA32) + { + struct symref_code code; + unsigned compiland; + + if (pdb_reader_lookup_compiland_by_segment_offset(pdb, cv_symbol->data_v3.segment, cv_symbol->data_v3.offset, &compiland) || + pdb_reader_encode_symref(pdb, symref_code_init_from_compiland(&code, compiland), &parent_symref)) + return MR_FAILURE; + } *((DWORD*)data) = symt_symref_to_index(pdb->module, parent_symref); return MR_SUCCESS; case TI_GET_ADDRESS: @@ -3675,13 +3685,16 @@ static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, unsigned * switch (cv_global_symbol->generic.id) { case S_UDT: + case S_LDATA32: + case S_GTHREAD32: + case S_LTHREAD32: found = TRUE; break; case S_GDATA32: /* There are cases (incremental linking) where we have several entries of same name, but * only one is valid. * We discriminate valid with: - * - there's no other entry with same name before this entry in hash bucket, + * - there's no other entry at global scope with same name before this entry in hash bucket, * - the address is valid * - the typeid is valid * Note: checking address map doesn't bring nothing as the invalid entries are also listed @@ -3690,7 +3703,7 @@ static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, unsigned * for (j = 0; !found && j < i; j++) { if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[j].dbi_stream_offset, &cv_global_symbol2)) - found = !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); + found = cv_global_symbol2->generic.id == S_GDATA32 && !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); } found = !found; break; @@ -4513,6 +4526,8 @@ static enum pdb_result pdb_reader_load_compiland_symbols(struct pdb_reader *pdb, switch (cv_symbol->generic.id) { case S_LDATA32: + if (curr_func) + { loc.kind = loc_absolute; loc.reg = 0; if ((result = pdb_reader_get_segment_address(pdb, cv_symbol->data_v3.segment, cv_symbol->data_v3.offset, &address))) @@ -4521,10 +4536,13 @@ static enum pdb_result pdb_reader_load_compiland_symbols(struct pdb_reader *pdb, if ((result = pdb_reader_create_variable(pdb, compiland, curr_func, block, cv_symbol->data_v3.name, &loc, cv_symbol->data_v3.symtype, TRUE))) goto failure; + } break; /* variables with thread storage */ case S_LTHREAD32: + if (curr_func) + { loc.kind = loc_tlsrel; loc.reg = 0; loc.offset = cv_symbol->thread_v3.offset; @@ -4532,6 +4550,7 @@ static enum pdb_result pdb_reader_load_compiland_symbols(struct pdb_reader *pdb, if ((result = pdb_reader_create_variable(pdb, compiland, curr_func, block, cv_symbol->thread_v3.name, &loc, cv_symbol->thread_v3.symtype, cv_symbol->generic.id == S_LTHREAD32))) goto failure; + } break; case S_THUNK32: @@ -4977,16 +4996,10 @@ static enum method_result pdb_method_lookup_symbol_by_name(struct module_format switch (cv_symbol.generic.id) { case S_GDATA32: - case S_GTHREAD32: - return pdb_method_result(pdb_reader_DBI_globals_symref(pdb, globals_offset, symref)); case S_LDATA32: - segment = cv_symbol.data_v3.segment; - offset = cv_symbol.data_v3.offset; - break; + case S_GTHREAD32: case S_LTHREAD32: - segment = cv_symbol.thread_v3.segment; - offset = cv_symbol.thread_v3.offset; - break; + return pdb_method_result(pdb_reader_DBI_globals_symref(pdb, globals_offset, symref)); case S_PROCREF: case S_LPROCREF: if ((result = pdb_reader_dereference_procedure(pdb, cv_symbol.refsym2_v3.imod, cv_symbol.refsym2_v3.ibSym, @@ -5035,6 +5048,13 @@ static enum method_result pdb_method_enumerate_symbols(struct module_format *mod 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_GTHREAD32: + case S_LTHREAD32: + segment = cv_symbol.thread_v3.segment; + offset = cv_symbol.thread_v3.offset; + symbol_walker.offset += offsetof(union codeview_symbol, thread_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, @@ -5063,6 +5083,9 @@ static enum method_result pdb_method_enumerate_symbols(struct module_format *mod switch (cv_symbol.generic.id) { case S_GDATA32: + case S_LDATA32: + case S_GTHREAD32: + case S_LTHREAD32: result = pdb_reader_DBI_globals_symref(pdb, walker.offset - sizeof(cv_symbol.generic.len), &symref); break; default: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/module.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 6428c539420..4751647605b 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -1032,20 +1032,12 @@ BOOL module_remove(struct process* pcs, struct module* module) /* remove local scope if symbol is from this module */ if (pcs->localscope_symt) { - struct symt* locsym = pcs->localscope_symt; - if (symt_check_tag(locsym, SymTagInlineSite)) - locsym = &symt_get_function_from_inlined((struct symt_function*)locsym)->symt; - if (symt_check_tag(locsym, SymTagFunction)) + struct module_pair pair; + if (module_init_pair(&pair, pcs->handle, pcs->localscope_pc) && + (module == pair.effective || module == pair.requested)) { - struct symt_compiland *compiland = (struct symt_compiland*)SYMT_SYMREF_TO_PTR(((struct symt_function*)locsym)->container); - if (symt_check_tag(&compiland->symt, SymTagCompiland)) - { - if (module == ((struct symt_module*)SYMT_SYMREF_TO_PTR(compiland->container))->module) - { - pcs->localscope_pc = 0; - pcs->localscope_symt = NULL; - } - } + pcs->localscope_pc = 0; + pcs->localscope_symt = NULL; } } while (module_format_vtable_iterator_next(module, &iter, MODULE_FORMAT_VTABLE_INDEX(remove))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
From: Eric Pouech <epouech@codeweavers.com> Only storing the compiland in top's children when this symref is a symt ptr. Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/coff.c | 2 +- dlls/dbghelp/dbghelp_private.h | 2 +- dlls/dbghelp/dwarf.c | 2 +- dlls/dbghelp/elf_module.c | 2 +- dlls/dbghelp/msc.c | 2 +- dlls/dbghelp/pdb.c | 2 +- dlls/dbghelp/pe_module.c | 2 +- dlls/dbghelp/stabs.c | 2 +- dlls/dbghelp/symbol.c | 12 ++++++++---- 9 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dlls/dbghelp/coff.c b/dlls/dbghelp/coff.c index d4d804d935e..855d17342f4 100644 --- a/dlls/dbghelp/coff.c +++ b/dlls/dbghelp/coff.c @@ -114,7 +114,7 @@ static int coff_add_file(struct CoffFileSet* coff_files, struct module* module, file = coff_files->files + coff_files->nfiles; file->startaddr = 0xffffffff; file->endaddr = 0; - file->compiland = symt_new_compiland(module, filename); + file->compiland = symt_new_compiland(module, symt_ptr_to_symref(&module->top->symt), filename); file->linetab_offset = -1; file->linecnt = 0; file->entries = NULL; diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 20892db8cda..00ddc77c51e 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -919,7 +919,7 @@ extern struct symt_ht* extern struct symt_module* symt_new_module(struct module* module); extern struct symt_compiland* - symt_new_compiland(struct module* module, const char *filename); + symt_new_compiland(struct module* module, symref_t parent, const char *filename); extern struct symt_public* symt_new_public(struct module* module, struct symt_compiland* parent, diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 4f1908aff09..faf05564345 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -3063,7 +3063,7 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx) ctx->language = language.u.uvalue; tmp = source_build_path(comp_dir.u.string, name.u.string); - ctx->compiland = symt_new_compiland(ctx->module_ctx->module, tmp); + ctx->compiland = symt_new_compiland(ctx->module_ctx->module, symt_ptr_to_symref(&ctx->module_ctx->module->top->symt), tmp); HeapFree(GetProcessHeap(), 0, tmp); ctx->compiland->address = ctx->module_ctx->load_offset + low_pc.u.uvalue; dwarf2_cache_cuhead(ctx->module_ctx->module, ctx->module_ctx->module->format_info[DFI_DWARF]->u.dwarf2_info, ctx->compiland, &ctx->head); diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 81f933c76ef..2a7d9bde8d5 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -698,7 +698,7 @@ static void elf_hash_symtab(struct module* module, struct pool* pool, { case ELF_STT_FILE: if (symname) - compiland = symt_new_compiland(module, symname); + compiland = symt_new_compiland(module, symt_ptr_to_symref(&module->top->symt), symname); else compiland = NULL; continue; diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 1a75dab70ac..135ffbe8c83 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2295,7 +2295,7 @@ static struct symt_compiland* codeview_new_compiland(const struct msc_debug_info if (symt_check_tag(&p->symt, SymTagCompiland) && !strcmp(p->filename, objname)) return p; } - return symt_new_compiland(msc_dbg->module, objname); + return symt_new_compiland(msc_dbg->module, symt_ptr_to_symref(&msc_dbg->module->top->symt), objname); } static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 18bfa538665..7cfe922849e 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -4871,7 +4871,7 @@ static enum pdb_result pdb_reader_ensure_symbols_loaded_from_compiland(struct pd if ((result = pdb_reader_walker_init(pdb, PDB_STREAM_DBI, &walker))) return result; walker.offset = compiland->stream_offset; if ((result = pdb_reader_alloc_and_fetch_string(pdb, &walker, &obj_name))) return result; - compiland->compiland = symt_new_compiland(pdb->module, obj_name); + compiland->compiland = symt_new_compiland(pdb->module, symt_ptr_to_symref(&pdb->module->top->symt), obj_name); pdb_reader_free(pdb, obj_name); if ((result = pdb_reader_walker_init(pdb, compiland->compiland_stream_id, &walker))) return result; diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 44122d385cb..7c30fa2f9f3 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -522,7 +522,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module) if (name[0] == '_') name++; if (!compiland && lastfilename) - compiland = symt_new_compiland(module, lastfilename); + compiland = symt_new_compiland(module, symt_ptr_to_symref(&module->top->symt), lastfilename); if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) symt_new_public(module, compiland, name, FALSE, diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index 8aa9907449c..1a2ddb7fb60 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1587,7 +1587,7 @@ BOOL stabs_parse(struct module* module, ULONG_PTR load_offset, { stabs_reset_includes(); source_idx = source_new(module, srcpath, ptr); - compiland = symt_new_compiland(module, source_get(module, source_idx)); + compiland = symt_new_compiland(module, symt_ptr_to_symref(&module->top->symt), source_get(module, source_idx)); } else { diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index e786dc61e66..8c7dd280d01 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -231,7 +231,7 @@ struct symt_module* symt_new_module(struct module* module) return sym; } -struct symt_compiland* symt_new_compiland(struct module* module, const char *filename) +struct symt_compiland* symt_new_compiland(struct module* module, symref_t parent, const char *filename) { struct symt_compiland* sym; symref_t* p; @@ -241,13 +241,17 @@ struct symt_compiland* symt_new_compiland(struct module* module, const char *fil if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { sym->symt.tag = SymTagCompiland; - sym->container = symt_ptr_to_symref(&module->top->symt); + sym->container = parent; sym->address = 0; sym->filename = pool_strdup(&module->pool, filename); vector_init(&sym->vchildren, sizeof(symref_t), 0); sym->user = NULL; - p = vector_add(&module->top->vchildren, &module->pool); - if (p) *p = symt_ptr_to_symref(&sym->symt); + if (symt_is_symref_ptr(parent)) + { + if (parent != symt_ptr_to_symref(&module->top->symt)) FIXME("Unexpected parent\n"); + p = vector_add(&module->top->vchildren, &module->pool); + if (p) *p = symt_ptr_to_symref(&sym->symt); + } } return sym; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/dbghelp/pdb.c | 149 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 34 deletions(-) diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 7cfe922849e..f72628e8e21 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -3656,13 +3656,14 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, symref_ return ret; } -static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, unsigned *count, DWORD *ids, unsigned first, unsigned last) +static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, struct pdb_compiland *compiland, + unsigned *count, DWORD *ids, unsigned first, unsigned last) { struct pdb_reader_whole_stream whole; struct symref_code code; symref_t top_symref; enum pdb_result result = R_PDB_SUCCESS; - unsigned int hash; + unsigned int hash, compiland_id; if ((result = pdb_reader_alloc_and_load_whole_stream(pdb, pdb->dbi_header.gsym_stream, &whole))) return result; *count = 0; @@ -3684,28 +3685,35 @@ static enum pdb_result pdb_reader_top_fill_in(struct pdb_reader *pdb, unsigned * found = FALSE; switch (cv_global_symbol->generic.id) { + case S_GTHREAD32: case S_UDT: + found = compiland == NULL; + break; case S_LDATA32: - case S_GTHREAD32: case S_LTHREAD32: - found = TRUE; + found = compiland && + !pdb_reader_lookup_compiland_by_segment_offset(pdb, cv_global_symbol->data_v3.segment, cv_global_symbol->data_v3.offset, &compiland_id) && + compiland == &pdb->compilands[compiland_id]; break; case S_GDATA32: - /* There are cases (incremental linking) where we have several entries of same name, but - * only one is valid. - * We discriminate valid with: - * - there's no other entry at global scope with same name before this entry in hash bucket, - * - the address is valid - * - the typeid is valid - * Note: checking address map doesn't bring nothing as the invalid entries are also listed - * there. - */ - for (j = 0; !found && j < i; j++) + if (!compiland) { - if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[j].dbi_stream_offset, &cv_global_symbol2)) - found = cv_global_symbol2->generic.id == S_GDATA32 && !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); + /* There are cases (incremental linking) where we have several entries of same name, but + * only one is valid. + * We discriminate valid with: + * - there's no other entry at global scope with same name before this entry in hash bucket, + * - the address is valid + * - the typeid is valid + * Note: checking address map doesn't bring nothing as the invalid entries are also listed + * there. + */ + for (j = 0; !found && j < i; j++) + { + if (!pdb_reader_whole_stream_access_codeview_symbol(pdb, &whole, bucket->entries[j].dbi_stream_offset, &cv_global_symbol2)) + found = cv_global_symbol2->generic.id == S_GDATA32 && !strcmp(cv_global_symbol->data_v3.name, cv_global_symbol2->data_v3.name); + } + found = !found; } - found = !found; break; default: break; @@ -3746,25 +3754,36 @@ static enum method_result pdb_reader_top_request(struct pdb_reader *pdb, symref_ case TI_GET_CHILDRENCOUNT: { unsigned count; - if (!symt_get_info(pdb->module, &pdb->module->top->symt, req, data) || - pdb_reader_top_fill_in(pdb, &count, NULL, 0, 0)) return MR_FAILURE; - *(DWORD*)data += count; + if (pdb_reader_top_fill_in(pdb, NULL,&count, NULL, 0, 0)) return MR_FAILURE; + *(DWORD*)data = count + pdb->num_compilands; return MR_SUCCESS; } case TI_FINDCHILDREN: { - TI_FINDCHILDREN_PARAMS *p = data; - TI_FINDCHILDREN_PARAMS *alt; - unsigned int count; - - if (pdb_reader_top_fill_in(pdb, &count, p->ChildId, p->Start, p->Count)) return MR_FAILURE; - if (!(alt = malloc(offsetof(TI_FINDCHILDREN_PARAMS, ChildId[p->Count - count])))) return MR_FAILURE; - alt->Start = 0; - alt->Count = p->Count - count; - result = symt_get_info(pdb->module, &pdb->module->top->symt, TI_FINDCHILDREN, alt); - if (result == R_PDB_SUCCESS) - memcpy(&p->ChildId[count], alt->ChildId, (p->Count - count) * sizeof(p->ChildId[0])); - free(alt); + TI_FINDCHILDREN_PARAMS *ti_params = data; + unsigned int count, i; + + if ((result = pdb_reader_top_fill_in(pdb, NULL, &count, ti_params->ChildId, ti_params->Start, ti_params->Count)) == R_PDB_SUCCESS) + { + for (i = 0; i < pdb->num_compilands; i++) + { + if (count + i >= ti_params->Count) + { + result = R_PDB_BUFFER_TOO_SMALL; + break; + } + if (count + i >= ti_params->Start) + { + symref_t symref; + struct symref_code code; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_compiland(&code, i), &symref))) + break; + ti_params->ChildId[count + i] = symt_symref_to_index(pdb->module, symref); + } + } + if (result == R_PDB_SUCCESS && count + pdb->num_compilands != ti_params->Count) + return MR_FAILURE; + } return pdb_method_result(result); } case TI_GET_SYMNAME: @@ -3774,6 +3793,65 @@ static enum method_result pdb_reader_top_request(struct pdb_reader *pdb, symref_ } } +static enum method_result pdb_reader_compiland_request(struct pdb_reader *pdb, symref_t symref, struct pdb_compiland *compiland, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum pdb_result result; + + switch (req) + { + case TI_GET_SYMTAG: + *(DWORD*)data = SymTagCompiland; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + { + symref_t symref; + struct symref_code code; + if (pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), &symref)) return MR_FAILURE; + *(DWORD *)data = symt_symref_to_index(pdb->module, symref); + return MR_SUCCESS; + } + case TI_GET_CHILDRENCOUNT: + { + unsigned count; + if (!symt_get_info(pdb->module, &compiland->compiland->symt, req, data)) return MR_FAILURE; + if (pdb_reader_top_fill_in(pdb, compiland,&count, NULL, 0, 0)) return MR_FAILURE; + *(DWORD*)data += count; + return MR_SUCCESS; + } + return MR_SUCCESS; + case TI_FINDCHILDREN: + { + TI_FINDCHILDREN_PARAMS *ti_params = data; + DWORD symt_count; + unsigned symref_count; + + if (!symt_get_info(pdb->module, &compiland->compiland->symt, TI_GET_CHILDRENCOUNT, &symt_count)) return MR_FAILURE; + if (ti_params->Start < symt_count) + { + DWORD old_count = ti_params->Count; + BOOL ret; + ti_params->Count = symt_count; + ret = symt_get_info(pdb->module, &compiland->compiland->symt, TI_FINDCHILDREN, ti_params); + ti_params->Count = old_count; + if (!ret) return MR_FAILURE; + } + if (ti_params->Count >= symt_count) + result = pdb_reader_top_fill_in(pdb, compiland, &symref_count, &ti_params->ChildId[symt_count], + max(ti_params->Start, symt_count) - symt_count, ti_params->Count - symt_count); + else + result = R_PDB_BUFFER_TOO_SMALL; + if (result == R_PDB_SUCCESS && symt_count + symref_count != ti_params->Count) + return MR_FAILURE; + return pdb_method_result(result); + } + case TI_GET_SYMNAME: + return symt_get_info(pdb->module, &compiland->compiland->symt, req, data) ? MR_SUCCESS : MR_FAILURE; + default: + return MR_FAILURE; + } +} + static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { struct pdb_type_details *type_details; @@ -3791,7 +3869,7 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy case symref_code_top: return pdb_reader_top_request(pdb, symref, req, data); case symref_code_compiland: - return symt_get_info(pdb->module, &pdb->compilands[code.compiland].compiland->symt, req, data) ? MR_SUCCESS : MR_FAILURE; + return pdb_reader_compiland_request(pdb, symref, &pdb->compilands[code.compiland], req, data); case symref_code_cv_typeid: if (code.cv_typeid < T_MAXPREDEFINEDTYPE) return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); @@ -4866,12 +4944,15 @@ static enum pdb_result pdb_reader_ensure_symbols_loaded_from_compiland(struct pd if (!compiland->are_symbols_loaded) { struct pdb_reader_walker walker; + struct symref_code code; + symref_t parent_symref; char *obj_name; if ((result = pdb_reader_walker_init(pdb, PDB_STREAM_DBI, &walker))) return result; walker.offset = compiland->stream_offset; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_top(&code), &parent_symref))) return result; if ((result = pdb_reader_alloc_and_fetch_string(pdb, &walker, &obj_name))) return result; - compiland->compiland = symt_new_compiland(pdb->module, symt_ptr_to_symref(&pdb->module->top->symt), obj_name); + compiland->compiland = symt_new_compiland(pdb->module, parent_symref, obj_name); pdb_reader_free(pdb, obj_name); if ((result = pdb_reader_walker_init(pdb, compiland->compiland_stream_id, &walker))) return result; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10018
participants (2)
-
Eric Pouech -
eric pouech (@epo)