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