This serie finishes the migration of the remaining types from TPI stream (function signature, struct/class/union, enum) to new PDB backend.
And it removes dual allocation of symt_* in old PDB backed.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 257 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 237 insertions(+), 20 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 94430f75b39..1c44b8bcd70 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -79,6 +79,18 @@ struct pdb_type_details struct symt *symt; };
+enum pdb_action_type +{ + action_type_cv_typ_t, /* cv_typ_t or cv_typ16_t (depending on size) */ +}; + +struct pdb_action_entry +{ + enum pdb_action_type action_type : 2; + unsigned action_length : 14; + pdbsize_t stream_offset; +}; + struct pdb_type_hash_entry { cv_typ_t cv_typeid; @@ -113,6 +125,10 @@ struct pdb_reader struct pdb_type_details *tpi_typemap; /* from first to last */ struct pdb_type_hash_entry *tpi_types_hash;
+ /* symbol (and types) management */ + unsigned num_action_entries; + struct pdb_action_entry *action_store; + /* cache PE module sections for mapping... * we should rather use pe_module information */ @@ -253,8 +269,9 @@ static enum pdb_result pdb_reader_read_from_stream(struct pdb_reader *pdb, const
struct symref_code { - enum {symref_code_cv_typeid} kind; + enum {symref_code_cv_typeid, symref_code_action} kind; cv_typ_t cv_typeid; + unsigned action; };
static inline struct symref_code *symref_code_init_from_cv_typeid(struct symref_code *code, cv_typ_t cv_typeid) @@ -264,20 +281,33 @@ static inline struct symref_code *symref_code_init_from_cv_typeid(struct symref_ return code; }
+static inline struct symref_code *symref_code_init_from_action(struct symref_code *code, unsigned action) +{ + code->kind = symref_code_action; + code->action = action; + return code; +} + static enum pdb_result pdb_reader_encode_symref(struct pdb_reader *pdb, const struct symref_code *code, symref_t *symref) { unsigned v; - if (code->kind == symref_code_cv_typeid) + switch (code->kind) { + case symref_code_cv_typeid: if (code->cv_typeid < T_MAXPREDEFINEDTYPE) v = code->cv_typeid; else if (code->cv_typeid >= pdb->tpi_header.first_index && code->cv_typeid < pdb->tpi_header.last_index) v = T_MAXPREDEFINEDTYPE + (code->cv_typeid - pdb->tpi_header.first_index); else return R_PDB_INVALID_ARGUMENT; - *symref = (v << 2) | 1; + break; + case symref_code_action: + v = T_MAXPREDEFINEDTYPE + pdb->tpi_header.last_index - pdb->tpi_header.first_index + code->action; + break; + default: + return R_PDB_INVALID_ARGUMENT; } - else return R_PDB_INVALID_ARGUMENT; + *symref = (v << 2) | 1; return R_PDB_SUCCESS; }
@@ -289,11 +319,34 @@ static enum pdb_result pdb_reader_decode_symref(struct pdb_reader *pdb, symref_t 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; }
+static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_action_type action, pdbsize_t stream_offset, + unsigned id_size, symref_t *symref) +{ + enum pdb_result result; + struct symref_code code; + + if (!(pdb->num_action_entries & (pdb->num_action_entries - 1))) + { + unsigned n = pdb->num_action_entries; + n = n ? n * 2 : 256; + if ((result = pdb_reader_realloc(pdb, (void**)&pdb->action_store, n * sizeof(pdb->action_store[0])))) return result; + } + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, pdb->num_action_entries), symref))) return result; + pdb->action_store[pdb->num_action_entries].action_type = action; + pdb->action_store[pdb->num_action_entries].action_length = id_size; + pdb->action_store[pdb->num_action_entries].stream_offset = stream_offset; + pdb->num_action_entries++; + + return R_PDB_SUCCESS; +} + static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *module, HANDLE file) { enum pdb_result result; @@ -1223,19 +1276,14 @@ static enum pdb_result pdb_reader_read_partial_blob(struct pdb_reader *pdb, stru static enum pdb_result pdb_reader_alloc_and_read_full_blob(struct pdb_reader *pdb, struct pdb_reader_walker *walker, void **blob) { enum pdb_result result; - unsigned short int len; + unsigned short len;
- if ((result = pdb_reader_READ(pdb, walker, &len))) return result; - if ((result = pdb_reader_alloc(pdb, len + sizeof(len), blob))) - { - walker->offset -= sizeof(len); - return result; - } + if ((result = pdb_reader_internal_read_advance(pdb, walker, &len, sizeof(len)))) return result; + if ((result = pdb_reader_alloc(pdb, len + 2, blob))) return result;
if ((result = pdb_reader_internal_read_advance(pdb, walker, (char*)*blob + sizeof(len), len))) { - pdb_reader_free(pdb, *blob); - walker->offset -= sizeof(len); + pdb_reader_free(pdb, blob); return result; } *(unsigned short int*)*blob = len; @@ -1787,6 +1835,20 @@ static enum pdb_result pdb_reader_alloc_and_read_codeview_type_variablepart(stru return result; }
+static enum pdb_result pdb_reader_TPI_read_partial_reftype(struct pdb_reader *pdb, cv_typ_t cv_typeid, union codeview_reftype *cv_reftype, + pdbsize_t *tpi_offset) +{ + struct pdb_reader_walker walker; + enum pdb_result result; + + if ((result = pdb_reader_init_TPI(pdb))) return result; + if ((result = pdb_reader_TPI_offset_from_cv_typeid(pdb, cv_typeid, tpi_offset))) return result; + walker = pdb->tpi_types_walker; + walker.offset = *tpi_offset; + + return pdb_reader_read_partial_blob(pdb, &walker, (void*)cv_reftype, sizeof(*cv_reftype)); +} + static UINT32 codeview_compute_hash(const char* ptr, unsigned len) { const char* last = ptr + len; @@ -2047,7 +2109,7 @@ static enum method_result pdb_reader_TPI_array_request(struct pdb_reader *pdb, c *((DWORD*)data) = SymTagArrayType; return MR_SUCCESS; case TI_GET_COUNT: - if (!pdb_reader_request_cv_typeid(pdb, cv_type->array_v3.elemtype, TI_GET_LENGTH, &element_length)) return MR_FAILURE; + if (!pdb_reader_request_cv_typeid(pdb, cv_type->array_v3.elemtype, TI_GET_LENGTH, &element_length)) return MR_FAILURE; if (codeview_fetch_leaf_as_int(cv_type, cv_type->array_v3.data, &array_size)) return MR_FAILURE; if (!element_length || (array_size % element_length)) WARN("Incorrect array %u %I64u\n", array_size, element_length); @@ -2059,7 +2121,7 @@ static enum method_result pdb_reader_TPI_array_request(struct pdb_reader *pdb, c return MR_SUCCESS; case TI_GET_TYPE: case TI_GET_TYPEID: - return pdb_reader_index_from_cv_typeid(pdb, cv_type->array_v3.elemtype, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + return pdb_reader_index_from_cv_typeid(pdb, cv_type->array_v3.elemtype, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; case TI_GET_ARRAYINDEXTYPEID: return pdb_reader_index_from_cv_typeid(pdb, cv_type->array_v3.idxtype, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; case TI_FINDCHILDREN: @@ -2071,6 +2133,134 @@ static enum method_result pdb_reader_TPI_array_request(struct pdb_reader *pdb, c } }
+static enum pdb_result pdb_reader_TPI_fillin_arglist(struct pdb_reader *pdb, unsigned num_ids, unsigned id_size, pdbsize_t tpi_offset, + DWORD *indexes) +{ + enum pdb_result result; + symref_t symref; + unsigned i; + + for (i = 0; i < num_ids; i++, tpi_offset += id_size) + { + if ((result = pdb_reader_push_action(pdb, action_type_cv_typ_t, tpi_offset, id_size, &symref))) return result; + indexes[i] = symt_symref_to_index(pdb->module, symref); + } + return R_PDB_SUCCESS; +} + +static enum method_result pdb_reader_TPI_procsignature_request(struct pdb_reader *pdb, const union codeview_type *cv_type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum pdb_result result; + cv_typ_t return_cv_typeid, arglist_cv_typeid; + unsigned char call_conv; + unsigned num_args; + + switch (cv_type->generic.id) + { + case LF_PROCEDURE_V2: + return_cv_typeid = cv_type->procedure_v2.rvtype; + arglist_cv_typeid = cv_type->procedure_v2.arglist; + call_conv = cv_type->procedure_v2.callconv; + num_args = cv_type->procedure_v2.params; + break; + /* FIXME: for C++, this is plain wrong, but as we don't use arg types + * nor class information, this would just do for now + */ + case LF_MFUNCTION_V2: + return_cv_typeid = cv_type->mfunction_v2.rvtype; + arglist_cv_typeid = cv_type->mfunction_v2.arglist; + call_conv = cv_type->mfunction_v2.callconv; + num_args = cv_type->mfunction_v2.params; + break; + default: + return MR_FAILURE; + } + + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagFunctionType; + return MR_SUCCESS; + case TI_FINDCHILDREN: + { + TI_FINDCHILDREN_PARAMS *p = data; + union codeview_reftype cv_reftype; + pdbsize_t tpi_arglist_offset; + + /* sigh... the codeview format doesn't have an explicit storage for the arg list item + * so we have to fake one using the 'action' field in storage + */ + if (p->Start != 0) return MR_FAILURE; + if ((result = pdb_reader_TPI_read_partial_reftype(pdb, arglist_cv_typeid, &cv_reftype, &tpi_arglist_offset))) + return MR_FAILURE; + tpi_arglist_offset += offsetof(union codeview_reftype, arglist_v2.args[0]); + if (p->Count != cv_reftype.arglist_v2.num || num_args > cv_reftype.arglist_v2.num) + return MR_FAILURE; + result = pdb_reader_TPI_fillin_arglist(pdb, cv_reftype.arglist_v2.num, sizeof(cv_typ_t), tpi_arglist_offset, p->ChildId); + if (result) return MR_FAILURE; + } + return MR_SUCCESS; + case TI_GET_CHILDRENCOUNT: + case TI_GET_COUNT: /* should evolve when considering methods */ + { + enum pdb_result result; + union codeview_reftype cv_reftype; + pdbsize_t tpi_offset; + + if ((result = pdb_reader_TPI_read_partial_reftype(pdb, arglist_cv_typeid, &cv_reftype, &tpi_offset))) + return MR_FAILURE; + *((DWORD*)data) = cv_reftype.arglist_v2.num; + } + return MR_SUCCESS; + case TI_GET_TYPE: + case TI_GET_TYPEID: + return pdb_reader_index_from_cv_typeid(pdb, return_cv_typeid, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_GET_CALLING_CONVENTION: + *((DWORD*)data) = call_conv; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + return pdb_reader_default_request(pdb, req, data); + + default: + return MR_FAILURE; + } +} + +static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum pdb_result result; + + switch (req) + { + case TI_GET_SYMTAG: + *(DWORD*)data = SymTagFunctionArgType; + return MR_SUCCESS; + case TI_GET_TYPE: + case TI_GET_TYPEID: + { + cv_typ_t cv_typeid; + struct pdb_reader_walker walker = pdb->tpi_types_walker; + walker.offset = entry->stream_offset; + if (entry->action_length == sizeof(cv_typ16_t)) + { + cv_typ16_t cv_typeid16; + result = pdb_reader_READ(pdb, &walker, &cv_typeid16); + cv_typeid = cv_typeid16; + } + else + result = pdb_reader_READ(pdb, &walker, &cv_typeid); + if (result || !cv_typeid) return MR_FAILURE; + return pdb_reader_index_from_cv_typeid(pdb, cv_typeid, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + } + case TI_FINDCHILDREN: + case TI_GET_CHILDRENCOUNT: + case TI_GET_LEXICALPARENT: + return pdb_reader_default_request(pdb, req, data); + default: + return MR_FAILURE; + } +} + static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, struct pdb_type_details *type_details, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result; @@ -2091,6 +2281,11 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, struct case LF_ARRAY_V3: ret = pdb_reader_TPI_array_request(pdb, &cv_type, req, data); break; + + case LF_PROCEDURE_V2: + case LF_MFUNCTION_V2: + return pdb_reader_TPI_procsignature_request(pdb, &cv_type, req, data); + default: FIXME("Unexpected id %x\n", cv_type.generic.id); ret = MR_FAILURE; @@ -2112,11 +2307,31 @@ static enum method_result pdb_method_request_symref_t(struct module_format *modf *((DWORD*)data) = symt_symref_to_index(modfmt->module, symref); return MR_SUCCESS; } + if (pdb_reader_decode_symref(pdb, symref, &code)) return MR_FAILURE; - if (code.cv_typeid < T_MAXPREDEFINEDTYPE) - return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); - if (pdb_reader_get_type_details(pdb, code.cv_typeid, &type_details)) return MR_FAILURE; - return pdb_reader_TPI_request(pdb, type_details, req, data); + switch (code.kind) + { + case symref_code_cv_typeid: + if (code.cv_typeid < T_MAXPREDEFINEDTYPE) + return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); + if (pdb_reader_get_type_details(pdb, code.cv_typeid, &type_details)) return MR_FAILURE; + return pdb_reader_TPI_request(pdb, type_details, req, data); + case symref_code_action: + { + struct pdb_action_entry *entry = &pdb->action_store[code.action]; + + switch (entry->action_type) + { + case action_type_cv_typ_t: + return pdb_reader_TPI_argtype_request(pdb, entry, req, data); + default: + return MR_FAILURE; + } + } + return MR_FAILURE; + default: + return MR_FAILURE; + } }
symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struct symt *symt) @@ -2132,7 +2347,9 @@ symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struc return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; } if (symt_check_tag(symt, SymTagPointerType) || - symt_check_tag(symt, SymTagArrayType)) + symt_check_tag(symt, SymTagArrayType) || + symt_check_tag(symt, SymTagFunctionType) || + symt_check_tag(symt, SymTagFunctionArgType)) { return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 419 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 354 insertions(+), 65 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 1c44b8bcd70..15ae1454ef2 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -82,6 +82,7 @@ struct pdb_type_details 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 */ };
struct pdb_action_entry @@ -89,6 +90,7 @@ struct pdb_action_entry enum pdb_action_type action_type : 2; unsigned action_length : 14; pdbsize_t stream_offset; + symref_t container_symref; };
struct pdb_type_hash_entry @@ -150,6 +152,13 @@ enum pdb_result R_PDB_BUFFER_TOO_SMALL, };
+#define PDB_REPORT_UNEXPECTED(k,i) pdb_reader_report_unexpected(k, __FUNCTION__, (i)) +static enum pdb_result pdb_reader_report_unexpected(const char *kind, const char *function, unsigned id) +{ + WARN("%s: unexpected %s %x\n", function, kind, id); + return R_PDB_INVALID_PDB_FILE; +} + static const unsigned short PDB_STREAM_TPI = 2; static const unsigned short PDB_STREAM_DBI = 3;
@@ -327,7 +336,7 @@ static enum pdb_result pdb_reader_decode_symref(struct pdb_reader *pdb, symref_t }
static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_action_type action, pdbsize_t stream_offset, - unsigned id_size, symref_t *symref) + unsigned id_size, symref_t container_symref, symref_t *symref) { enum pdb_result result; struct symref_code code; @@ -342,6 +351,7 @@ static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_a pdb->action_store[pdb->num_action_entries].action_type = action; pdb->action_store[pdb->num_action_entries].action_length = id_size; pdb->action_store[pdb->num_action_entries].stream_offset = stream_offset; + pdb->action_store[pdb->num_action_entries].container_symref = container_symref; pdb->num_action_entries++;
return R_PDB_SUCCESS; @@ -1140,6 +1150,130 @@ static unsigned codeview_get_leaf_length(unsigned short type) return type < ARRAY_SIZE(codeview_leaf_length) ? codeview_leaf_length[type] : 0; }
+static int codeview_leaf_as_variant(const unsigned char *leaf, VARIANT *v) +{ + unsigned short int type = *(const unsigned short *)leaf; + + if (type < LF_NUMERIC) + { + V_VT(v) = VT_I2; + V_I2(v) = type; + return sizeof(unsigned short); + } + leaf += sizeof(unsigned short); + switch (type) + { + case LF_CHAR: + V_VT(v) = VT_I1; + V_I1(v) = *(const char*)leaf; + break; + case LF_SHORT: + V_VT(v) = VT_I2; + V_I2(v) = *(const short*)leaf; + break; + case LF_USHORT: + V_VT(v) = VT_UI2; + V_UI2(v) = *(const unsigned short*)leaf; + break; + case LF_LONG: + V_VT(v) = VT_I4; + V_I4(v) = *(const int*)leaf; + break; + case LF_ULONG: + V_VT(v) = VT_UI4; + V_UI4(v) = *(const unsigned int*)leaf; + break; + case LF_QUADWORD: + V_VT(v) = VT_I8; + V_I8(v) = *(const long long int*)leaf; + break; + case LF_UQUADWORD: + V_VT(v) = VT_UI8; + V_UI8(v) = *(const long long unsigned int*)leaf; + break; + case LF_REAL32: + V_VT(v) = VT_R4; + V_R4(v) = *(const float*)leaf; + break; + case LF_REAL64: + V_VT(v) = VT_R8; + V_R8(v) = *(const double*)leaf; + break; + + case LF_VARSTRING: + PDB_REPORT_UNEXPECTED("numeric leaf", type); + V_VT(v) = VT_EMPTY; /* FIXME */ + return 2 + *leaf; + + case LF_REAL48: + case LF_REAL80: + case LF_REAL128: + case LF_COMPLEX32: + case LF_COMPLEX64: + case LF_COMPLEX80: + case LF_COMPLEX128: + /* we can't convert them into an int */ + default: + PDB_REPORT_UNEXPECTED("numeric leaf", type); + V_VT(v) = VT_EMPTY; /* FIXME */ + return 0; + } + return sizeof(unsigned short) + codeview_get_leaf_length(type); +} + +/* read a codeview numeric leaf */ +static enum pdb_result pdb_reader_read_leaf_as_variant(struct pdb_reader *pdb, struct pdb_reader_walker *walker, VARIANT *v) +{ + enum pdb_result result; + unsigned short int type; + + if ((result = pdb_reader_READ(pdb, walker, &type))) return result; + + if (type < LF_NUMERIC) + { + V_VT(v) = VT_I2; + V_I2(v) = type; + } + else + { + switch (type) + { + case LF_CHAR: V_VT(v) = VT_I1; return pdb_reader_READ(pdb, walker, &V_I1(v)); + case LF_SHORT: V_VT(v) = VT_I2; return pdb_reader_READ(pdb, walker, &V_I2(v)); + case LF_USHORT: V_VT(v) = VT_UI2; return pdb_reader_READ(pdb, walker, &V_UI2(v)); + case LF_LONG: V_VT(v) = VT_I4; return pdb_reader_READ(pdb, walker, &V_I4(v)); + case LF_ULONG: V_VT(v) = VT_UI4; return pdb_reader_READ(pdb, walker, &V_UI4(v)); + case LF_QUADWORD: V_VT(v) = VT_I8; return pdb_reader_READ(pdb, walker, &V_I8(v)); + case LF_UQUADWORD: V_VT(v) = VT_UI8; return pdb_reader_READ(pdb, walker, &V_UI8(v)); + case LF_REAL32: V_VT(v) = VT_R4; return pdb_reader_READ(pdb, walker, &V_R4(v)); + case LF_REAL64: V_VT(v) = VT_R8; return pdb_reader_READ(pdb, walker, &V_R8(v)); + + /* types that don't simply fit inside VARIANT (would need conversion) */ + + case LF_OCTWORD: + case LF_UOCTWORD: + case LF_REAL48: + case LF_REAL80: + case LF_REAL128: + case LF_COMPLEX32: + case LF_COMPLEX64: + case LF_COMPLEX80: + case LF_COMPLEX128: + + /* case LF_VARSTRING: */ + + /* as we don't know the length... will lead to later issues */ + default: + break; + } + PDB_REPORT_UNEXPECTED("numeric leaf", type); + walker->offset += codeview_get_leaf_length(type); + V_VT(v) = VT_EMPTY; + } + + return R_PDB_SUCCESS; +} + /* read a codeview numeric leaf from a partially loaded codeview type */ static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_type, const unsigned char *data, int *value) { @@ -1185,7 +1319,7 @@ static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_ /* as we don't know the length... will lead to later issues */
default: - FIXME("Unknown numeric leaf type %04x\n", type); + PDB_REPORT_UNEXPECTED("numeric leaf", type); return R_PDB_INVALID_ARGUMENT; } } @@ -1193,61 +1327,15 @@ static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_ return R_PDB_SUCCESS; }
-/* read a codeview numeric leaf */ -static enum pdb_result pdb_reader_read_leaf_as_variant(struct pdb_reader *pdb, struct pdb_reader_walker *walker, VARIANT *v) +static WCHAR *heap_allocate_symname(const char *string) { - enum pdb_result result; - unsigned short int type; - - if ((result = pdb_reader_READ(pdb, walker, &type))) return result; - - if (type < LF_NUMERIC) - { - V_VT(v) = VT_I2; - V_I2(v) = type; - } - else - { - int len = 0; - - switch (type) - { - case LF_CHAR: V_VT(v) = VT_I1; return pdb_reader_READ(pdb, walker, &V_I1(v)); - case LF_SHORT: V_VT(v) = VT_I2; return pdb_reader_READ(pdb, walker, &V_I2(v)); - case LF_USHORT: V_VT(v) = VT_UI2; return pdb_reader_READ(pdb, walker, &V_UI2(v)); - case LF_LONG: V_VT(v) = VT_I4; return pdb_reader_READ(pdb, walker, &V_I4(v)); - case LF_ULONG: V_VT(v) = VT_UI4; return pdb_reader_READ(pdb, walker, &V_UI4(v)); - case LF_QUADWORD: V_VT(v) = VT_I8; return pdb_reader_READ(pdb, walker, &V_I8(v)); - case LF_UQUADWORD: V_VT(v) = VT_UI8; return pdb_reader_READ(pdb, walker, &V_UI8(v)); - case LF_REAL32: V_VT(v) = VT_R4; return pdb_reader_READ(pdb, walker, &V_R4(v)); - case LF_REAL64: V_VT(v) = VT_R8; return pdb_reader_READ(pdb, walker, &V_R8(v)); + unsigned sz = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0); + WCHAR *stringW;
- /* types that don't simply fit inside VARIANT (would need conversion) */ - - case LF_OCTWORD: len = 16; break; - case LF_UOCTWORD: len = 16; break; - case LF_REAL48: len = 6; break; - case LF_REAL80: len = 10; break; - case LF_REAL128: len = 16; break; - - case LF_COMPLEX32: len = 8; break; - case LF_COMPLEX64: len = 16; break; - case LF_COMPLEX80: len = 20; break; - case LF_COMPLEX128:len = 32; break; - - case LF_VARSTRING: - if ((result = pdb_reader_READ(pdb, walker, &len))) return result; - break; - - /* as we don't know the length... will lead to later issues */ - default: len = 0; break; - } - FIXME("Unknown numeric leaf type %04x\n", type); - walker->offset += len; - V_VT(v) = VT_EMPTY; - } - - return R_PDB_SUCCESS; + stringW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)); + if (stringW) + MultiByteToWideChar(CP_ACP, 0, string, -1, stringW, sz); + return stringW; }
#define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */ @@ -1486,7 +1574,7 @@ static enum method_result pdb_reader_basic_request(struct pdb_reader *pdb, unsig
if (!is_basic_supported(basic & T_BASICTYPE_MASK)) { - FIXME("Unsupported basic type %x\n", basic); + PDB_REPORT_UNEXPECTED("basic type", basic); return MR_FAILURE; }
@@ -1849,6 +1937,20 @@ static enum pdb_result pdb_reader_TPI_read_partial_reftype(struct pdb_reader *pd return pdb_reader_read_partial_blob(pdb, &walker, (void*)cv_reftype, sizeof(*cv_reftype)); }
+static enum pdb_result pdb_reader_TPI_alloc_and_read_full_reftype(struct pdb_reader *pdb, cv_typ_t cv_typeid, union codeview_reftype **cv_reftype, + pdbsize_t *tpi_offset) +{ + struct pdb_reader_walker walker; + enum pdb_result result; + + if ((result = pdb_reader_init_TPI(pdb))) return result; + if ((result = pdb_reader_TPI_offset_from_cv_typeid(pdb, cv_typeid, tpi_offset))) return result; + walker = pdb->tpi_types_walker; + walker.offset = *tpi_offset; + + return pdb_reader_alloc_and_read_full_blob(pdb, &walker, (void**)cv_reftype); +} + static UINT32 codeview_compute_hash(const char* ptr, unsigned len) { const char* last = ptr + len; @@ -2142,7 +2244,7 @@ static enum pdb_result pdb_reader_TPI_fillin_arglist(struct pdb_reader *pdb, uns
for (i = 0; i < num_ids; i++, tpi_offset += id_size) { - if ((result = pdb_reader_push_action(pdb, action_type_cv_typ_t, tpi_offset, id_size, &symref))) return result; + if ((result = pdb_reader_push_action(pdb, action_type_cv_typ_t, tpi_offset, id_size, 0, &symref))) return result; indexes[i] = symt_symref_to_index(pdb->module, symref); } return R_PDB_SUCCESS; @@ -2226,7 +2328,115 @@ static enum method_result pdb_reader_TPI_procsignature_request(struct pdb_reader } }
+static enum pdb_result pdb_reader_TPI_fillin_enumlist(struct pdb_reader *pdb, symref_t container_symref, + cv_typ_t enumlist_cv_typeid, unsigned count, DWORD *index) + { + enum pdb_result result; + union codeview_reftype *cv_reftype; + pdbsize_t tpi_offset; + const unsigned char *start, *ptr, *last; + const union codeview_fieldtype *cv_field; + unsigned length; + VARIANT v; + symref_t symref; + + if ((result = pdb_reader_TPI_alloc_and_read_full_reftype(pdb, enumlist_cv_typeid, &cv_reftype, &tpi_offset))) return result; + if (cv_reftype->generic.id != LF_FIELDLIST_V2) return PDB_REPORT_UNEXPECTED("enum list", cv_reftype->generic.id); + start = ptr = (const unsigned char *)cv_reftype->fieldlist.list; + last = (const unsigned char *)cv_reftype + sizeof(cv_reftype->generic.id) + cv_reftype->generic.len; + + tpi_offset += offsetof(union codeview_reftype, fieldlist.list); + + while (ptr < last) + { + if (*ptr >= 0xf0) /* Padding */ + { + ptr += *ptr & 0x0f; + continue; + } + cv_field = (const union codeview_fieldtype *)ptr; + switch (cv_field->generic.id) + { + case LF_ENUMERATE_V3: + if (!count) return R_PDB_INVALID_ARGUMENT; + length = offsetof(union codeview_fieldtype, enumerate_v3.data); + length += codeview_leaf_as_variant(ptr + length, &v); + length += strlen((const char *)ptr + length) + 1; + if ((result = pdb_reader_push_action(pdb, action_type_field, tpi_offset + (ptr - start), length, container_symref, &symref))) + { + pdb_reader_free(pdb, cv_reftype); + return result; + } + *index = symt_symref_to_index(pdb->module, symref); + index++; + count--; + ptr += length; + break; + + case LF_INDEX_V2: + if ((result = pdb_reader_TPI_fillin_enumlist(pdb, container_symref, cv_field->index_v2.ref, count, index))) return result; + ptr += sizeof(cv_field->index_v2); + break; + + default: + pdb_reader_free(pdb, cv_reftype); + return PDB_REPORT_UNEXPECTED("enum field list", cv_field->generic.id); + } + } + pdb_reader_free(pdb, cv_reftype); + return R_PDB_SUCCESS; +} + +static enum method_result pdb_reader_TPI_enum_request(struct pdb_reader *pdb, symref_t symref, const union codeview_type *cv_type, + const struct pdb_reader_walker *walker, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + switch (req) + { + case TI_FINDCHILDREN: + { + TI_FINDCHILDREN_PARAMS *p = data; + if (p->Start != 0 || p->Count != cv_type->enumeration_v3.count) return MR_FAILURE; + if (pdb_reader_TPI_fillin_enumlist(pdb, symref, cv_type->enumeration_v3.fieldlist, cv_type->enumeration_v3.count, p->ChildId)) return MR_FAILURE; + } + return MR_SUCCESS; + case TI_GET_CHILDRENCOUNT: + *(DWORD*)data = cv_type->enumeration_v3.count; + return MR_SUCCESS; + case TI_GET_SYMNAME: + { + VARIANT v; + char *string; + + if (pdb_reader_alloc_and_read_codeview_type_variablepart(pdb, *walker, cv_type, &v, &string, NULL)) + return MR_FAILURE; + *((WCHAR**)data) = heap_allocate_symname(string); + pdb_reader_free(pdb, string); + } + return *((WCHAR**)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_BASETYPE: + case TI_GET_LENGTH: /* forward to base type */ + if (cv_type->enumeration_v3.type >= T_MAXPREDEFINEDTYPE) return MR_FAILURE; + return pdb_reader_basic_request(pdb, cv_type->enumeration_v3.type, req, data); + case TI_GET_NESTED: + *(DWORD*)data = 0; + return MR_SUCCESS; + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagEnum; + return MR_SUCCESS; + case TI_GET_TYPE: + case TI_GET_TYPEID: + return pdb_reader_index_from_cv_typeid(pdb, cv_type->enumeration_v3.type, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_GET_LEXICALPARENT: + return pdb_reader_default_request(pdb, req, data); + 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); + static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) + { enum pdb_result result;
@@ -2261,7 +2471,73 @@ static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, } }
-static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, struct pdb_type_details *type_details, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +static enum method_result pdb_reader_TPI_enumerate_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, const union codeview_fieldtype *cv_field, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + pdbsize_t var; + VARIANT v; + + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagData; + return MR_SUCCESS; + case TI_GET_SYMNAME: + var = offsetof(union codeview_fieldtype, enumerate_v3.data); + var += codeview_leaf_as_variant((const unsigned char *)cv_field + var, &v); + *((WCHAR **)data) = heap_allocate_symname((const char *)cv_field + var); + return *((WCHAR **)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_DATAKIND: + *((DWORD*)data) = DataIsConstant; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + *((DWORD*)data) = symt_symref_to_index(pdb->module, entry->container_symref); + return MR_SUCCESS; + case TI_GET_LENGTH: + case TI_GET_TYPE: + case TI_GET_TYPEID: + /* forward to container type */ + return pdb_reader_request_symref_t(pdb, entry->container_symref, req, data); + case TI_GET_VALUE: + var = offsetof(union codeview_fieldtype, enumerate_v3.data); + return codeview_leaf_as_variant((const unsigned char *)cv_field + var, (VARIANT*)data) != 0 ? MR_SUCCESS : MR_FAILURE; + case TI_FINDCHILDREN: + case TI_GET_CHILDRENCOUNT: + return pdb_reader_default_request(pdb, req, data); + default: + return MR_FAILURE; + } +} + +static enum method_result pdb_reader_TPI_field_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; + union codeview_fieldtype *cv_field; + pdbsize_t num_read; + enum method_result ret = MR_FAILURE; + + walker = pdb->tpi_types_walker; + walker.offset = entry->stream_offset; + if ((result = pdb_reader_alloc(pdb, entry->action_length, (void**)&cv_field))) return MR_FAILURE; + if (!pdb_reader_read_from_stream(pdb, &walker, cv_field, entry->action_length, &num_read) && + num_read == entry->action_length) + { + switch (cv_field->generic.id) + { + case LF_ENUMERATE_V3: + ret = pdb_reader_TPI_enumerate_request(pdb, entry, cv_field, req, data); + break; + default: + PDB_REPORT_UNEXPECTED("field list", cv_field->generic.id); + break; + } + } + pdb_reader_free(pdb, cv_field); + return ret; +} + +static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, symref_t symref, struct pdb_type_details *type_details, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result; struct pdb_reader_walker walker; @@ -2286,8 +2562,11 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, struct case LF_MFUNCTION_V2: return pdb_reader_TPI_procsignature_request(pdb, &cv_type, req, data);
+ case LF_ENUM_V3: + return pdb_reader_TPI_enum_request(pdb, symref, &cv_type, &walker, req, data); + default: - FIXME("Unexpected id %x\n", cv_type.generic.id); + PDB_REPORT_UNEXPECTED("codeview type id", cv_type.generic.id); ret = MR_FAILURE; break; } @@ -2295,16 +2574,14 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, struct return ret; }
-static enum method_result pdb_method_request_symref_t(struct module_format *modfmt, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +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_reader *pdb; struct pdb_type_details *type_details; struct symref_code code;
- if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; if (req == TI_GET_SYMINDEX) { - *((DWORD*)data) = symt_symref_to_index(modfmt->module, symref); + *((DWORD*)data) = symt_symref_to_index(pdb->module, symref); return MR_SUCCESS; }
@@ -2315,7 +2592,7 @@ static enum method_result pdb_method_request_symref_t(struct module_format *modf if (code.cv_typeid < T_MAXPREDEFINEDTYPE) return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); if (pdb_reader_get_type_details(pdb, code.cv_typeid, &type_details)) return MR_FAILURE; - return pdb_reader_TPI_request(pdb, type_details, req, data); + return pdb_reader_TPI_request(pdb, symref, type_details, req, data); case symref_code_action: { struct pdb_action_entry *entry = &pdb->action_store[code.action]; @@ -2324,6 +2601,8 @@ static enum method_result pdb_method_request_symref_t(struct module_format *modf { case action_type_cv_typ_t: return pdb_reader_TPI_argtype_request(pdb, entry, req, data); + case action_type_field: + return pdb_reader_TPI_field_request(pdb, entry, req, data); default: return MR_FAILURE; } @@ -2334,6 +2613,14 @@ static enum method_result pdb_method_request_symref_t(struct module_format *modf } }
+static enum method_result pdb_method_request_symref_t(struct module_format *modfmt, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + struct pdb_reader *pdb; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + return pdb_reader_request_symref_t(pdb, symref, req, data); +} + symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struct symt *symt) { struct symref_code code; @@ -2349,7 +2636,9 @@ symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struc if (symt_check_tag(symt, SymTagPointerType) || symt_check_tag(symt, SymTagArrayType) || symt_check_tag(symt, SymTagFunctionType) || - symt_check_tag(symt, SymTagFunctionArgType)) + symt_check_tag(symt, SymTagFunctionArgType) || + symt_check_tag(symt, SymTagEnum) || + (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagEnum))) { return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 334 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 322 insertions(+), 12 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 15ae1454ef2..5354b97f64f 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -1275,13 +1275,10 @@ static enum pdb_result pdb_reader_read_leaf_as_variant(struct pdb_reader *pdb, s }
/* read a codeview numeric leaf from a partially loaded codeview type */ -static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_type, const unsigned char *data, int *value) +static enum pdb_result codeview_leaf_as_int(const unsigned char *data, int *value) { - unsigned data_len = min(sizeof(*cv_type), sizeof(cv_type->generic.len) + cv_type->generic.len) - (data - (const unsigned char*)cv_type); unsigned short int type;
- if (data_len < sizeof(unsigned short)) return R_PDB_BUFFER_TOO_SMALL; - type = *(unsigned short int*)data; if (type < LF_NUMERIC) { @@ -1289,9 +1286,6 @@ static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_ } else { - if (data_len < codeview_get_leaf_length(type)) - return R_PDB_BUFFER_TOO_SMALL; - switch (type) { case LF_CHAR: *value = *(char*)(data + 2); break; @@ -1327,6 +1321,19 @@ static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_ return R_PDB_SUCCESS; }
+static enum pdb_result codeview_fetch_leaf_as_int(const union codeview_type *cv_type, const unsigned char *data, int *value) +{ + unsigned data_len = min(sizeof(*cv_type), sizeof(cv_type->generic.len) + cv_type->generic.len) - (data - (const unsigned char*)cv_type); + unsigned short int type; + + if (data_len < sizeof(unsigned short)) return R_PDB_BUFFER_TOO_SMALL; + + type = *(unsigned short int*)data; + if (type >= LF_NUMERIC && data_len < codeview_get_leaf_length(type)) + return R_PDB_BUFFER_TOO_SMALL; + return codeview_leaf_as_int(data, value); +} + static WCHAR *heap_allocate_symname(const char *string) { unsigned sz = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0); @@ -2328,6 +2335,35 @@ static enum method_result pdb_reader_TPI_procsignature_request(struct pdb_reader } }
+struct pdb_children_filler +{ + DWORD *indexes; + unsigned count; /* max allowed indexes */ + unsigned actual; /* actual index in indexes when filling */ +}; + +static enum pdb_result pdb_reader_push_children_filler(struct pdb_reader *pdb, struct pdb_children_filler *children, symref_t symref) +{ + if (children->actual >= children->count) return R_PDB_BUFFER_TOO_SMALL; + if (children->indexes) + children->indexes[children->actual] = symt_symref_to_index(pdb->module, symref); + children->actual++; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_push_action_and_filler(struct pdb_reader *pdb, enum pdb_action_type action, pdbsize_t stream_offset, + unsigned id_size, symref_t container_symref, struct pdb_children_filler *children) +{ + enum pdb_result result; + symref_t symref; + + if (!children->indexes) + symref = 0; + else + if ((result = pdb_reader_push_action(pdb, action, stream_offset, id_size, container_symref, &symref))) return result; + return pdb_reader_push_children_filler(pdb, children, symref); +} + static enum pdb_result pdb_reader_TPI_fillin_enumlist(struct pdb_reader *pdb, symref_t container_symref, cv_typ_t enumlist_cv_typeid, unsigned count, DWORD *index) { @@ -2433,10 +2469,214 @@ static enum method_result pdb_reader_TPI_enum_request(struct pdb_reader *pdb, sy } }
+static enum pdb_result pdb_reader_TPI_fillin_UDTlist(struct pdb_reader *pdb, symref_t container_symref, + cv_typ_t udtlist_cv_typeid, struct pdb_children_filler *children) +{ + enum pdb_result result; + union codeview_reftype *cv_reftype; + pdbsize_t tpi_offset; + const unsigned char *start, *ptr, *last; + const union codeview_fieldtype *cv_field; + unsigned length; + VARIANT v; + + if ((result = pdb_reader_TPI_alloc_and_read_full_reftype(pdb, udtlist_cv_typeid, &cv_reftype, &tpi_offset))) return result; + if (cv_reftype->generic.id != LF_FIELDLIST_V2) return PDB_REPORT_UNEXPECTED("list", cv_reftype->generic.id); + start = ptr = (const unsigned char *)cv_reftype->fieldlist.list; + last = (const unsigned char *)cv_reftype + sizeof(cv_reftype->generic.id) + cv_reftype->generic.len; + + tpi_offset += offsetof(union codeview_reftype, fieldlist.list); + + while (ptr < last) + { + if (*ptr >= 0xf0) /* Padding */ + { + ptr += *ptr & 0x0f; + continue; + } + cv_field = (const union codeview_fieldtype *)ptr; + result = R_PDB_SUCCESS; + switch (cv_field->generic.id) + { + case LF_BCLASS_V2: + length = offsetof(union codeview_fieldtype, bclass_v2.data); + length += codeview_leaf_as_variant(ptr + length, &v); + /* FIXME: ignored for now */ + break; + + case LF_VBCLASS_V2: + case LF_IVBCLASS_V2: + length = offsetof(union codeview_fieldtype, vbclass_v2.data); + length += codeview_leaf_as_variant(ptr + length, &v); /* vbpoff */ + length += codeview_leaf_as_variant(ptr + length, &v); /* vboff */ + /* FIXME: ignored for now */ + break; + + case LF_MEMBER_V3: + length = offsetof(union codeview_fieldtype, member_v3.data); + length += codeview_leaf_as_variant(ptr + length, &v); + length += strlen((const char *)ptr + length) + 1; + result = pdb_reader_push_action_and_filler(pdb, action_type_field, tpi_offset + (ptr - start), length, container_symref, children); + break; + + case LF_STMEMBER_V3: + /* FIXME: ignored for now */ + length = offsetof(union codeview_fieldtype, stmember_v3.name) + strlen(cv_field->stmember_v3.name) + 1; + break; + + case LF_METHOD_V3: + /* FIXME: ignored for now */ + length = offsetof(union codeview_fieldtype, method_v3.name) + strlen(cv_field->method_v3.name) + 1; + break; + + case LF_NESTTYPE_V3: + /* FIXME: ignored for now */ + length = offsetof(union codeview_fieldtype, nesttype_v3.name) + strlen(cv_field->nesttype_v3.name) + 1; + break; + + case LF_VFUNCTAB_V2: + /* FIXME: ignored for now */ + length = sizeof(cv_field->vfunctab_v2); + break; + + case LF_ONEMETHOD_V3: + /* FIXME: ignored for now */ + switch ((cv_field->onemethod_v3.attribute >> 2) & 7) + { + case 4: case 6: /* (pure) introducing virtual method */ + length = offsetof(union codeview_fieldtype, onemethod_virt_v3.name); + break; + default: + length = offsetof(union codeview_fieldtype, onemethod_v3.name); + break; + } + length += strlen((const char *)ptr + length) + 1; + break; + + case LF_INDEX_V2: + if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, cv_field->index_v2.ref, children))) return result; + length = sizeof(cv_field->index_v2); + break; + + default: + result = PDB_REPORT_UNEXPECTED("UDT field list", cv_field->generic.id); + } + ptr += length; + if (result) break; + } + + pdb_reader_free(pdb, cv_reftype); + return result; +} + +static enum pdb_result pdb_reader_count_advertized_in_UDT_fieldlist(struct pdb_reader *pdb, symref_t container_symref, + cv_typ_t fieldlist_cv_typeid, DWORD *count) +{ + enum pdb_result result; + struct pdb_children_filler filler = {.actual = 0, .count = ~0u, .indexes = NULL}; + + if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, fieldlist_cv_typeid, &filler))) return result; + *count = filler.actual; + return R_PDB_SUCCESS; +} + +static enum method_result pdb_reader_TPI_UDT_request(struct pdb_reader *pdb, symref_t symref, const union codeview_type *cv_type, + const struct pdb_reader_walker *walker, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum UdtKind kind; + unsigned count; + const unsigned char *var; + cv_typ_t fieldlist_cv_typeid; + cv_property_t property; + + switch (cv_type->generic.id) + { + case LF_CLASS_V3: + case LF_STRUCTURE_V3: + kind = cv_type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct; + count = cv_type->struct_v3.n_element; + fieldlist_cv_typeid = cv_type->struct_v3.fieldlist; + property = cv_type->struct_v3.property; + var = cv_type->struct_v3.data; + break; + case LF_UNION_V3: + kind = UdtUnion; + count = cv_type->union_v3.count; + fieldlist_cv_typeid = cv_type->union_v3.fieldlist; + property = cv_type->union_v3.property; + var = cv_type->union_v3.data; + break; + default: + return MR_FAILURE; + } + /* Note: we can have a forward type here when its declared but not defined. */ + + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagUDT; + return MR_SUCCESS; + case TI_FINDCHILDREN: + { + TI_FINDCHILDREN_PARAMS *p = data; + struct pdb_children_filler filler = {.actual = 0, .count = p->Count, .indexes = p->ChildId}; + + if (p->Start != 0) return MR_FAILURE; + if (property.is_forward_defn && !p->Count) return MR_SUCCESS; + if (pdb_reader_TPI_fillin_UDTlist(pdb, symref, fieldlist_cv_typeid, &filler)) return MR_FAILURE; + if (filler.actual != filler.count) {WARN("Count mismatch %u^%u %u\n", filler.actual, filler.count, count); return MR_FAILURE;} + } + return MR_SUCCESS; + case TI_GET_CHILDRENCOUNT: + if (!property.is_forward_defn) + /* Unfortunately the count field describes the number of entries in the field_list, not + * the count of entries we currently advertize (we drop a bunch of them in the fillin_ helpers). + * Be on the save side and always recompute. + */ + return pdb_reader_count_advertized_in_UDT_fieldlist(pdb, symref, fieldlist_cv_typeid, (DWORD*)data) ? MR_FAILURE : MR_SUCCESS; + *((DWORD*)data) = 0; + return MR_SUCCESS; + case TI_GET_SYMNAME: + { + VARIANT v; + char *string; + + if (pdb_reader_alloc_and_read_codeview_type_variablepart(pdb, *walker, cv_type, &v, &string, NULL)) + return MR_FAILURE; + *((WCHAR**)data) = heap_allocate_symname(string); + pdb_reader_free(pdb, string); + } + return *((WCHAR**)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_LENGTH: + { + int value; + if (codeview_fetch_leaf_as_int(cv_type, var, &value)) return MR_FAILURE; + *((DWORD64*)data) = (unsigned)value; + } + return MR_SUCCESS; + case TI_GET_NESTED: + *((DWORD*)data) = property.is_nested; + return MR_SUCCESS; + case TI_GET_UDTKIND: + *((DWORD*)data) = kind; + return MR_SUCCESS; + case TI_GET_LEXICALPARENT: + *((DWORD*)data) = symt_ptr_to_index(pdb->module, &pdb->module->top->symt); + return MR_SUCCESS; + 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);
-static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +static enum method_result pdb_reader_TPI_modifier_request(struct pdb_reader *pdb, symref_t symref, const union codeview_type *cv_type, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + return pdb_reader_request_cv_typeid(pdb, cv_type->modifier_v2.type, req, data) ? MR_SUCCESS : MR_FAILURE; +}
+static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result;
@@ -2472,7 +2712,7 @@ static enum method_result pdb_reader_TPI_argtype_request(struct pdb_reader *pdb, }
static enum method_result pdb_reader_TPI_enumerate_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, const union codeview_fieldtype *cv_field, - IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { pdbsize_t var; VARIANT v; @@ -2509,6 +2749,61 @@ static enum method_result pdb_reader_TPI_enumerate_request(struct pdb_reader *pd } }
+static enum method_result pdb_reader_TPI_UDT_field_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, const union codeview_fieldtype *cv_field, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + union codeview_reftype cv_reftype; + pdbsize_t tpi_offset; + + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagData; + return MR_SUCCESS; + case TI_GET_SYMNAME: + { + const unsigned char *var; + VARIANT v; + var = cv_field->member_v3.data; + var += codeview_leaf_as_variant(var, &v); + *((WCHAR **)data) = heap_allocate_symname((const char *)var); + } + return *((WCHAR **)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_DATAKIND: + *((DWORD*)data) = DataIsMember; + return MR_SUCCESS; + case TI_GET_OFFSET: + return codeview_leaf_as_int( cv_field->member_v3.data, (int*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_GET_LENGTH: + if (cv_field->member_v3.type < T_FIRSTDEFINABLETYPE || + pdb_reader_TPI_read_partial_reftype(pdb, cv_field->member_v3.type, &cv_reftype, &tpi_offset) || + cv_reftype.generic.id != LF_BITFIELD_V2) + return MR_FAILURE; + *((DWORD64*)data) = cv_reftype.bitfield_v2.nbits; + return MR_SUCCESS; + case TI_GET_BITPOSITION: + if (cv_field->member_v3.type < T_FIRSTDEFINABLETYPE || + pdb_reader_TPI_read_partial_reftype(pdb, cv_field->member_v3.type, &cv_reftype, &tpi_offset) || + cv_reftype.generic.id != LF_BITFIELD_V2) + return MR_FAILURE; + *((DWORD*)data) = cv_reftype.bitfield_v2.bitoff; + return MR_SUCCESS; + case TI_GET_TYPE: + case TI_GET_TYPEID: + if (cv_field->member_v3.type >= T_FIRSTDEFINABLETYPE && + !pdb_reader_TPI_read_partial_reftype(pdb, cv_field->member_v3.type, &cv_reftype, &tpi_offset) && + cv_reftype.generic.id == LF_BITFIELD_V2) + return pdb_reader_index_from_cv_typeid(pdb, cv_reftype.bitfield_v2.type, (DWORD *)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + return pdb_reader_index_from_cv_typeid(pdb, cv_field->member_v3.type, (DWORD *)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_FINDCHILDREN: + case TI_GET_CHILDRENCOUNT: + case TI_GET_LEXICALPARENT: + return pdb_reader_default_request(pdb, req, data); + default: + return MR_FAILURE; + } +} + static enum method_result pdb_reader_TPI_field_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result; @@ -2519,15 +2814,19 @@ static enum method_result pdb_reader_TPI_field_request(struct pdb_reader *pdb, s
walker = pdb->tpi_types_walker; walker.offset = entry->stream_offset; + if ((result = pdb_reader_alloc(pdb, entry->action_length, (void**)&cv_field))) return MR_FAILURE; - if (!pdb_reader_read_from_stream(pdb, &walker, cv_field, entry->action_length, &num_read) && - num_read == entry->action_length) + if ((result = pdb_reader_read_from_stream(pdb, &walker, cv_field, entry->action_length, &num_read))) return MR_FAILURE; + if (num_read == entry->action_length) { switch (cv_field->generic.id) { case LF_ENUMERATE_V3: ret = pdb_reader_TPI_enumerate_request(pdb, entry, cv_field, req, data); break; + case LF_MEMBER_V3: + ret = pdb_reader_TPI_UDT_field_request(pdb, entry, cv_field, req, data); + break; default: PDB_REPORT_UNEXPECTED("field list", cv_field->generic.id); break; @@ -2565,6 +2864,14 @@ static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, symref_ case LF_ENUM_V3: return pdb_reader_TPI_enum_request(pdb, symref, &cv_type, &walker, req, data);
+ case LF_UNION_V3: + case LF_STRUCTURE_V3: + case LF_CLASS_V3: + return pdb_reader_TPI_UDT_request(pdb, symref, &cv_type, &walker, req, data); + + case LF_MODIFIER_V2: + return pdb_reader_TPI_modifier_request(pdb, symref, &cv_type, req, data); + default: PDB_REPORT_UNEXPECTED("codeview type id", cv_type.generic.id); ret = MR_FAILURE; @@ -2638,7 +2945,10 @@ symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struc symt_check_tag(symt, SymTagFunctionType) || symt_check_tag(symt, SymTagFunctionArgType) || symt_check_tag(symt, SymTagEnum) || - (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagEnum))) + (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagEnum)) || + symt_check_tag(symt, SymTagUDT) || + (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagUDT))) + { return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 5 +- dlls/dbghelp/msc.c | 110 +++++++++++++++++---------------- dlls/dbghelp/pdb.c | 77 +++++++++-------------- 3 files changed, 88 insertions(+), 104 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 45239b04fd3..54ea829e21b 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -316,7 +316,7 @@ struct symt_public struct symt symt; struct hash_table_elt hash_elt; struct symt* container; /* compiland */ - BOOL is_function; + BOOL is_function; ULONG_PTR address; ULONG_PTR size; }; @@ -1075,5 +1075,4 @@ struct pdb_reader; extern BOOL pdb_hack_get_main_info(struct module_format *modfmt, struct pdb_reader **pdb, unsigned *fpoext_stream); extern void pdb_reader_dispose(struct pdb_reader *pdb); extern struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections); -extern symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, unsigned typeno, struct symt *symt); -extern struct symt *pdb_hack_advertize_codeview_type(struct pdb_reader *pdb, unsigned typeid, struct symt *symt, unsigned offset); +extern BOOL cv_hack_ptr_to_symref(struct pdb_reader *pdb, unsigned typeno, symref_t *symref); diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 729c860342c..09b36803be8 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -619,8 +619,6 @@ static int codeview_add_type(unsigned int typeno, struct symt* dt, unsigned offs return FALSE; } idx = typeno - cv_current_module->first_type_index; - if (cv_current_module->pdb) - pdb_hack_advertize_codeview_type(cv_current_module->pdb, typeno, dt, offset);
if (cv_current_module->defined_types[idx]) { @@ -668,15 +666,25 @@ static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp,
static symref_t codeview_fetch_symref(struct codeview_type_parse* ctp, unsigned typeno) { - struct symt *symt = codeview_fetch_type(ctp, typeno); - return cv_hack_ptr_to_symref(cv_current_module->pdb, typeno, symt); + symref_t symref; + + if (!cv_hack_ptr_to_symref(ctp->module->format_info[DFI_PDB]->u.pdb_info->pdb_files[0].pdb_reader, typeno, &symref)) + { + symref = symt_ptr_to_symref(codeview_fetch_type(ctp, typeno)); + } + + return symref; }
-static symref_t codeview_get_symref(struct module *module, unsigned typeno, struct symt *symt) +static symref_t codeview_get_symref(struct module *module, unsigned typeno) { - if (!symt) - symt = codeview_get_type(typeno, FALSE); - return cv_hack_ptr_to_symref(module->format_info[DFI_PDB]->u.pdb_info->pdb_files[0].pdb_reader, typeno, symt); + symref_t symref; + + if (!cv_hack_ptr_to_symref(module->format_info[DFI_PDB]->u.pdb_info->pdb_files[0].pdb_reader, typeno, &symref)) + { + symref = symt_ptr_to_symref(codeview_get_type(typeno, TRUE)); + } + return symref; }
static UINT32 codeview_compute_hash(const char* ptr, unsigned len) @@ -1000,7 +1008,7 @@ static void codeview_add_udt_element(struct codeview_type_parse* ctp, { DWORD64 elem_size = 0; symt_get_info(ctp->module, subtype, TI_GET_LENGTH, &elem_size); - symt_add_udt_element(ctp->module, symt, name, codeview_get_symref(ctp->module, type, subtype), + symt_add_udt_element(ctp->module, symt, name, codeview_get_symref(ctp->module, type), value, 0, 0); } } @@ -1837,7 +1845,7 @@ static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg, { if (!is_local || in_tls) WARN("Unsupported construct\n"); symt_add_func_local(msc_dbg->module, func, DataIsStaticLocal, &loc, block, - codeview_get_symref(msc_dbg->module, symtype, NULL), name); + codeview_get_symref(msc_dbg->module, symtype), name); return; } if (!dontcheck && !in_tls) @@ -1870,7 +1878,7 @@ static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg, } if (is_local ^ (compiland != NULL)) FIXME("Unsupported construct\n"); symt_new_global_variable(msc_dbg->module, compiland, name, is_local, loc, 0, - codeview_get_symref(msc_dbg->module, symtype, NULL)); + codeview_get_symref(msc_dbg->module, symtype)); } }
@@ -2205,14 +2213,14 @@ static struct symt_function* codeview_create_inline_site(const struct msc_debug_ case LF_FUNC_ID: inlined = symt_new_inlinesite(msc_dbg->module, top_func, container, cvt->func_id_v3.name, - codeview_get_symref(msc_dbg->module, cvt->func_id_v3.type, NULL), + codeview_get_symref(msc_dbg->module, cvt->func_id_v3.type), num_ranges); break; case LF_MFUNC_ID: /* FIXME we just declare a function, not a method */ inlined = symt_new_inlinesite(msc_dbg->module, top_func, container, cvt->mfunc_id_v3.name, - codeview_get_symref(msc_dbg->module, cvt->mfunc_id_v3.type, NULL), + codeview_get_symref(msc_dbg->module, cvt->mfunc_id_v3.type), num_ranges); break; default: @@ -2327,7 +2335,6 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, { struct symt_function* top_func = NULL; struct symt_function* curr_func = NULL; - struct symt* func_signature; int i, length; struct symt_block* block = NULL; struct symt_compiland* compiland = NULL; @@ -2427,14 +2434,12 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, case S_GPROC32_16t: case S_LPROC32_16t: if (top_func) FIXME("nested function\n"); - func_signature = codeview_get_type(sym->proc_v1.proctype, FALSE); - if (!func_signature || func_signature->tag == SymTagFunctionType) + if ((top_func = symt_new_function(msc_dbg->module, compiland, + terminate_string(&sym->proc_v1.p_name), + codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset), + sym->proc_v1.proc_len, + codeview_get_symref(msc_dbg->module, sym->proc_v1.proctype)))) { - top_func = symt_new_function(msc_dbg->module, compiland, - terminate_string(&sym->proc_v1.p_name), - codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset), - sym->proc_v1.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v1.proctype, func_signature)); curr_func = top_func; loc.kind = loc_absolute; loc.offset = sym->proc_v1.debug_start; @@ -2446,14 +2451,12 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, case S_GPROC32_ST: case S_LPROC32_ST: if (top_func) FIXME("nested function\n"); - func_signature = codeview_get_type(sym->proc_v2.proctype, FALSE); - if (!func_signature || func_signature->tag == SymTagFunctionType) + if ((top_func = symt_new_function(msc_dbg->module, compiland, + terminate_string(&sym->proc_v2.p_name), + codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset), + sym->proc_v2.proc_len, + codeview_get_symref(msc_dbg->module, sym->proc_v2.proctype)))) { - top_func = symt_new_function(msc_dbg->module, compiland, - terminate_string(&sym->proc_v2.p_name), - codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset), - sym->proc_v2.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v2.proctype, func_signature)); curr_func = top_func; loc.kind = loc_absolute; loc.offset = sym->proc_v2.debug_start; @@ -2465,14 +2468,12 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, case S_GPROC32: case S_LPROC32: if (top_func) FIXME("nested function\n"); - func_signature = codeview_get_type(sym->proc_v3.proctype, FALSE); - if (!func_signature || func_signature->tag == SymTagFunctionType) + if ((top_func = symt_new_function(msc_dbg->module, compiland, + sym->proc_v3.name, + codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset), + sym->proc_v3.proc_len, + codeview_get_symref(msc_dbg->module, sym->proc_v3.proctype)))) { - top_func = symt_new_function(msc_dbg->module, compiland, - sym->proc_v3.name, - codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset), - sym->proc_v3.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v3.proctype, func_signature)); curr_func = top_func; loc.kind = loc_absolute; loc.offset = sym->proc_v3.debug_start; @@ -2492,7 +2493,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, symt_add_func_local(msc_dbg->module, curr_func, sym->stack_v1.offset > 0 ? DataIsParam : DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->stack_v1.symtype, NULL), + codeview_get_symref(msc_dbg->module, sym->stack_v1.symtype), terminate_string(&sym->stack_v1.p_name)); break; case S_BPREL32_ST: @@ -2503,7 +2504,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, symt_add_func_local(msc_dbg->module, curr_func, sym->stack_v2.offset > 0 ? DataIsParam : DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->stack_v2.symtype, NULL), + codeview_get_symref(msc_dbg->module, sym->stack_v2.symtype), terminate_string(&sym->stack_v2.p_name)); break; case S_BPREL32: @@ -2516,7 +2517,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, symt_add_func_local(msc_dbg->module, curr_func, sym->stack_v3.offset > 0 ? DataIsParam : DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->stack_v3.symtype, NULL), + codeview_get_symref(msc_dbg->module, sym->stack_v3.symtype), sym->stack_v3.name); break; case S_REGREL32: @@ -2529,7 +2530,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, symt_add_func_local(msc_dbg->module, curr_func, sym->regrel_v3.offset >= top_frame_size ? DataIsParam : DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->regrel_v3.symtype, NULL), + codeview_get_symref(msc_dbg->module, sym->regrel_v3.symtype), sym->regrel_v3.name); break;
@@ -2539,7 +2540,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, loc.offset = 0; symt_add_func_local(msc_dbg->module, curr_func, DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->register_v1.type, NULL), + codeview_get_symref(msc_dbg->module, sym->register_v1.type), terminate_string(&sym->register_v1.p_name)); break; case S_REGISTER_ST: @@ -2548,7 +2549,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, loc.offset = 0; symt_add_func_local(msc_dbg->module, curr_func, DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->register_v2.type, NULL), + codeview_get_symref(msc_dbg->module, sym->register_v2.type), terminate_string(&sym->register_v2.p_name)); break; case S_REGISTER: @@ -2559,7 +2560,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, loc.offset = 0; symt_add_func_local(msc_dbg->module, curr_func, DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->register_v3.type, NULL), + codeview_get_symref(msc_dbg->module, sym->register_v3.type), sym->register_v3.name); break;
@@ -2657,7 +2658,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg,
TRACE("S-Constant-V1 %u %s %x\n", V_INT(&v), terminate_string(name), sym->constant_v1.type); symt_new_constant(msc_dbg->module, compiland, terminate_string(name), - codeview_get_symref(msc_dbg->module, sym->constant_v1.type, NULL), &v); + codeview_get_symref(msc_dbg->module, sym->constant_v1.type), &v); } break; case S_CONSTANT_ST: @@ -2671,7 +2672,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg,
TRACE("S-Constant-V2 %u %s %x\n", V_INT(&v), terminate_string(name), sym->constant_v2.type); symt_new_constant(msc_dbg->module, compiland, terminate_string(name), - codeview_get_symref(msc_dbg->module, sym->constant_v2.type, NULL), &v); + codeview_get_symref(msc_dbg->module, sym->constant_v2.type), &v); } break; case S_CONSTANT: @@ -2686,28 +2687,28 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, TRACE("S-Constant-V3 %u %s %x\n", V_INT(&v), debugstr_a(name), sym->constant_v3.type); /* FIXME: we should add this as a constant value */ symt_new_constant(msc_dbg->module, compiland, name, - codeview_get_symref(msc_dbg->module, sym->constant_v3.type, NULL), &v); + codeview_get_symref(msc_dbg->module, sym->constant_v3.type), &v); } break;
case S_UDT_16t: if (sym->udt_v1.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v1.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v1.type), terminate_string(&sym->udt_v1.p_name)); } break; case S_UDT_ST: if (sym->udt_v2.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v2.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v2.type), terminate_string(&sym->udt_v2.p_name)); } break; case S_UDT: if (sym->udt_v3.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v3.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v3.type), sym->udt_v3.name); } break; @@ -2730,7 +2731,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, symt_add_func_local(msc_dbg->module, curr_func, sym->local_v3.varflags.is_param ? DataIsParam : DataIsLocal, &loc, block, - codeview_get_symref(msc_dbg->module, sym->local_v3.symtype, NULL), + codeview_get_symref(msc_dbg->module, sym->local_v3.symtype), sym->local_v3.name); } else @@ -2990,21 +2991,21 @@ static BOOL pdb_global_feed_types(const struct msc_debug_info* msc_dbg, const un case S_UDT_16t: if (sym->udt_v1.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v1.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v1.type), terminate_string(&sym->udt_v1.p_name)); } break; case S_UDT_ST: if (sym->udt_v2.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v2.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v2.type), terminate_string(&sym->udt_v2.p_name)); } break; case S_UDT: if (sym->udt_v3.type) { - symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v3.type, NULL), + symt_new_typedef(msc_dbg->module, codeview_get_symref(msc_dbg->module, sym->udt_v3.type), sym->udt_v3.name); } break; @@ -3877,7 +3878,10 @@ static BOOL pdb_process_internal(const struct process *pcs,
pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image, pdb_module_info, module_index); - pdb_process_types(msc_dbg, pdb_file); + if (!pdb_file->pdb_reader) + { + pdb_process_types(msc_dbg, pdb_file); + }
ipi_image = pdb_read_stream(pdb_file, 4); ipi_ok = pdb_init_type_parse(msc_dbg, pdb_file, &ipi_ctp, ipi_image); diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 5354b97f64f..b519868ff42 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -76,7 +76,6 @@ struct pdb_type_details { pdbsize_t stream_offset; /* inside TPI stream */ cv_typ_t resolved_cv_typeid; - struct symt *symt; };
enum pdb_action_type @@ -303,6 +302,11 @@ static enum pdb_result pdb_reader_encode_symref(struct pdb_reader *pdb, const st switch (code->kind) { case symref_code_cv_typeid: + if (!code->cv_typeid) + { + *symref = 0; + return R_PDB_SUCCESS; + } if (code->cv_typeid < T_MAXPREDEFINEDTYPE) v = code->cv_typeid; else if (code->cv_typeid >= pdb->tpi_header.first_index && code->cv_typeid < pdb->tpi_header.last_index) @@ -410,6 +414,9 @@ static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *mo } pdb->streams[i].name = NULL; } + /* hack (must be set before loading debug info so it can be used therein) */ + pdb->module->ops_symref_modfmt = module->format_info[DFI_PDB]; + return R_PDB_SUCCESS;
failure: @@ -2025,14 +2032,14 @@ static enum method_result pdb_method_find_type(struct module_format *modfmt, con struct pdb_reader_walker walker; cv_typ_t cv_typeid; union codeview_type cv_type; + struct symref_code code; struct pdb_type_details *type_details;
if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; if ((result = pdb_reader_init_TPI(pdb))) return pdb_method_result(result); if ((result = pdb_reader_read_codeview_type_by_name(pdb, name, &walker, &cv_type, &cv_typeid))) return pdb_method_result(result); if ((result = pdb_reader_get_type_details(pdb, cv_typeid, &type_details))) return pdb_method_result(result); - *ref = cv_hack_ptr_to_symref(pdb, cv_typeid, type_details->symt); - return MR_SUCCESS; + return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; }
static BOOL codeview_type_is_forward(const union codeview_type* cvtype) @@ -2093,15 +2100,21 @@ static enum pdb_result pdb_reader_resolve_cv_typeid(struct pdb_reader *pdb, cv_t { case R_PDB_SUCCESS: type_details->resolved_cv_typeid = other_cv_typeid; + if (!type_details->stream_offset) type_details->stream_offset = other_walker.offset; break; case R_PDB_NOT_FOUND: /* we can have a forward decl without a real implementation */ type_details->resolved_cv_typeid = raw_cv_typeid; + if (!type_details->stream_offset) type_details->stream_offset = tpi_offset; break; default: return result; } } - else type_details->resolved_cv_typeid = raw_cv_typeid; + else + { + type_details->resolved_cv_typeid = raw_cv_typeid; + if (!type_details->stream_offset) type_details->stream_offset = tpi_offset; + }
*cv_typeid = type_details->resolved_cv_typeid; return R_PDB_SUCCESS; @@ -2116,6 +2129,8 @@ static enum method_result pdb_method_enumerate_types(struct module_format *modfm struct pdb_type_details *type_details; struct pdb_type_hash_entry *hash_entry; union codeview_type cv_type; + struct symref_code code; + symref_t symref; char *name; VARIANT v; BOOL ret; @@ -2143,8 +2158,8 @@ static enum method_result pdb_method_enumerate_types(struct module_format *modfm result = pdb_reader_alloc_and_read_codeview_type_variablepart(pdb, walker, &cv_type, &v, &name, NULL); if (!result) { - if (*name) - ret = (*cb)(cv_hack_ptr_to_symref(pdb, hash_entry->cv_typeid, type_details->symt), name, user); + if (*name && pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, hash_entry->cv_typeid), &symref) == R_PDB_SUCCESS) + ret = (*cb)(symref, name, user); else ret = TRUE; pdb_reader_free(pdb, name); @@ -2162,14 +2177,9 @@ static enum pdb_result pdb_reader_index_from_cv_typeid(struct pdb_reader *pdb, c symref_t symref;
if (cv_typeid > T_MAXPREDEFINEDTYPE) - { - struct pdb_type_details *type_details; - if ((result = pdb_reader_resolve_cv_typeid(pdb, cv_typeid, &cv_typeid))) return result; - if ((result = pdb_reader_get_type_details(pdb, cv_typeid, &type_details))) return result; - symref = cv_hack_ptr_to_symref(pdb, cv_typeid, type_details->symt); - } - else if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref))) return result; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref))) return result; + *index = symt_symref_to_index(pdb->module, symref); return R_PDB_SUCCESS; } @@ -2898,6 +2908,7 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy case symref_code_cv_typeid: if (code.cv_typeid < T_MAXPREDEFINEDTYPE) return pdb_reader_basic_request(pdb, code.cv_typeid, req, data); + if (pdb_reader_resolve_cv_typeid(pdb, code.cv_typeid, &code.cv_typeid)) return MR_FAILURE; if (pdb_reader_get_type_details(pdb, code.cv_typeid, &type_details)) return MR_FAILURE; return pdb_reader_TPI_request(pdb, symref, type_details, req, data); case symref_code_action: @@ -2925,47 +2936,17 @@ static enum method_result pdb_method_request_symref_t(struct module_format *modf struct pdb_reader *pdb;
if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + if (pdb_reader_init_TPI(pdb)) return MR_FAILURE; return pdb_reader_request_symref_t(pdb, symref, req, data); }
-symref_t cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, struct symt *symt) +BOOL cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, symref_t *symref) { struct symref_code code; - symref_t symref; - - if (pdb) - { - if (symt_check_tag(symt, SymTagBaseType)) - { - if (cv_typeid < T_MAXPREDEFINEDTYPE) - return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; - } - if (symt_check_tag(symt, SymTagPointerType) || - symt_check_tag(symt, SymTagArrayType) || - symt_check_tag(symt, SymTagFunctionType) || - symt_check_tag(symt, SymTagFunctionArgType) || - symt_check_tag(symt, SymTagEnum) || - (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagEnum)) || - symt_check_tag(symt, SymTagUDT) || - (symt_check_tag(symt, SymTagData) && symt_check_tag(((struct symt_data*)symt)->container, SymTagUDT))) - - { - return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &symref) ? 0 : symref; - } - } - return symt_ptr_to_symref(symt); -} - -struct symt *pdb_hack_advertize_codeview_type(struct pdb_reader *pdb, cv_typ_t cv_typeid, struct symt *symt, unsigned offset) -{ - if (pdb_reader_init_TPI(pdb)) return symt; - if (!pdb->tpi_typemap[cv_typeid - pdb->tpi_header.first_index].symt) - { - pdb->tpi_typemap[cv_typeid - pdb->tpi_header.first_index].symt = symt; - pdb->tpi_typemap[cv_typeid - pdb->tpi_header.first_index].stream_offset = offset; - }
- return symt; + if (!pdb) return FALSE; + if (pdb_reader_init_TPI(pdb)) return FALSE; + return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), symref) == R_PDB_SUCCESS; }
static struct module_format_vtable pdb_module_format_vtable =
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index b519868ff42..95531866959 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -2184,13 +2184,15 @@ static enum pdb_result pdb_reader_index_from_cv_typeid(struct pdb_reader *pdb, c return R_PDB_SUCCESS; }
-/* FIXME: suboptimal implementation until we have moved all types */ +static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data); + static BOOL pdb_reader_request_cv_typeid(struct pdb_reader *pdb, cv_typ_t cv_typeid, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { - DWORD index; + struct symref_code code; + symref_t target_symref;
- if (pdb_reader_index_from_cv_typeid(pdb, cv_typeid, &index)) return FALSE; - return symt_get_info_from_index(pdb->module, index, req, data); + if ((pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), &target_symref))) return MR_FAILURE; + return pdb_reader_request_symref_t(pdb, target_symref, req, data) == MR_SUCCESS; }
static enum method_result pdb_reader_TPI_pointer_request(struct pdb_reader *pdb, const union codeview_type *cv_type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) @@ -2678,8 +2680,6 @@ static enum method_result pdb_reader_TPI_UDT_request(struct pdb_reader *pdb, sym } }
-static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, symref_t symref, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data); - static enum method_result pdb_reader_TPI_modifier_request(struct pdb_reader *pdb, symref_t symref, const union codeview_type *cv_type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) {