Some various bits before tackling the symbols part: - some speed ups in loading with implementing a cache, - no longer fail on some managed symbols information in PDB, - a fix for children request.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 56 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index ba09f8e37ba..dc503b79dc9 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -62,7 +62,7 @@ typedef uint64_t pdboff_t; /* offset in whole PDB file (64bit) */ typedef uint32_t pdbsize_t; /* size inside a stream (including offset from beg of stream) (2G max) */
struct pdb_reader; -typedef enum pdb_result (*pdb_reader_fetch_t)(struct pdb_reader *pdb, void *buffer, pdboff_t offset, pdbsize_t size); +typedef enum pdb_result (*pdb_reader_fetch_block_t)(struct pdb_reader *pdb, unsigned block_no, void **block_buffer);
struct pdb_reader_walker { @@ -145,7 +145,10 @@ struct pdb_reader const IMAGE_SECTION_HEADER *sections; unsigned num_sections;
- pdb_reader_fetch_t fetch; + /* PDB file access */ + pdb_reader_fetch_block_t fetch; + struct {unsigned block_no; unsigned age;} cache[4*4]; + char *fetch_cache_blocks; };
enum pdb_result @@ -170,7 +173,7 @@ static enum pdb_result pdb_reader_report_unexpected(const char *kind, const char static const unsigned short PDB_STREAM_TPI = 2; static const unsigned short PDB_STREAM_DBI = 3;
-static enum pdb_result pdb_reader_fetch_file(struct pdb_reader *pdb, void *buffer, pdboff_t offset, pdbsize_t size) +static enum pdb_result pdb_reader_fetch_file_no_cache(struct pdb_reader *pdb, void *buffer, pdboff_t offset, pdbsize_t size) { OVERLAPPED ov = {.Offset = offset, .OffsetHigh = offset >> 32, .hEvent = (HANDLE)(DWORD_PTR)1}; DWORD num_read; @@ -178,6 +181,36 @@ static enum pdb_result pdb_reader_fetch_file(struct pdb_reader *pdb, void *buffe return ReadFile(pdb->file, buffer, size, &num_read, &ov) && num_read == size ? R_PDB_SUCCESS : R_PDB_IOERROR; }
+static enum pdb_result pdb_reader_fetch_block_from_file(struct pdb_reader *pdb, unsigned block_no, void **buffer) +{ + enum pdb_result result; + unsigned i; + unsigned lru = ARRAY_SIZE(pdb->cache), found = ARRAY_SIZE(pdb->cache); + + for (i = 0; i < ARRAY_SIZE(pdb->cache); i++) + { + if (pdb->cache[i].block_no == block_no) + found = i; + else + { + pdb->cache[i].age++; + if (lru == ARRAY_SIZE(pdb->cache) || pdb->cache[lru].age < pdb->cache[i].age) + lru = i; + } + } + if (found == ARRAY_SIZE(pdb->cache)) + { + if ((result = pdb_reader_fetch_file_no_cache(pdb, pdb->fetch_cache_blocks + lru * pdb->block_size, + (pdboff_t)block_no * pdb->block_size, pdb->block_size))) return result; + pdb->cache[lru].block_no = block_no; + found = lru; + } + + pdb->cache[found].age = 0; + *buffer = pdb->fetch_cache_blocks + found * pdb->block_size; + return R_PDB_SUCCESS; +} + static const char PDB_JG_IDENT[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0"; static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
@@ -242,13 +275,14 @@ static enum pdb_result pdb_reader_internal_read_from_blocks(struct pdb_reader *p enum pdb_result result; pdbsize_t initial_size = size; pdbsize_t toread; + void *block_buffer;
while (size) { toread = min(pdb->block_size - delta, size);
- if ((result = (*pdb->fetch)(pdb, buffer, (pdboff_t)*blocks * pdb->block_size + delta, toread))) - return result; + if ((result = (pdb->fetch)(pdb, *blocks, &block_buffer))) return result; + memcpy(buffer, (char *)block_buffer + delta, toread); size -= toread; blocks++; buffer = (char*)buffer + toread; @@ -406,9 +440,8 @@ static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *mo pdb->module = module; pdb->file = file; pool_init(&pdb->pool, 65536); - pdb->fetch = &pdb_reader_fetch_file;
- if ((result = (*pdb->fetch)(pdb, &hdr, 0, sizeof(hdr)))) return result; + if ((result = pdb_reader_fetch_file_no_cache(pdb, &hdr, 0, sizeof(hdr)))) return result; if (!memcmp(hdr.signature, PDB_JG_IDENT, sizeof(PDB_JG_IDENT))) { FIXME("PDB reader doesn't support old PDB JG file format\n"); @@ -420,9 +453,16 @@ static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *mo return R_PDB_INVALID_PDB_FILE; } pdb->block_size = hdr.block_size; + if ((result = pdb_reader_alloc(pdb, pdb->block_size * ARRAY_SIZE(pdb->cache), (void **)&pdb->fetch_cache_blocks))) goto failure; + for (i = 0; i < ARRAY_SIZE(pdb->cache); i++) + { + pdb->cache[i].block_no = 0; /* block where PDB header is, so should never be matched by a read operation */ + pdb->cache[i].age = i; + } + pdb->fetch = &pdb_reader_fetch_block_from_file; toc_blocks_size = pdb_reader_num_blocks(pdb, hdr.toc_size) * sizeof(uint32_t); if ((result = pdb_reader_alloc(pdb, toc_blocks_size, (void**)&toc_blocks)) || - (result = (*pdb->fetch)(pdb, toc_blocks, (pdboff_t)hdr.toc_block * hdr.block_size, toc_blocks_size)) || + (result = pdb_reader_fetch_file_no_cache(pdb, toc_blocks, (pdboff_t)hdr.toc_block * hdr.block_size, toc_blocks_size)) || (result = pdb_reader_alloc(pdb, hdr.toc_size, (void**)&toc)) || (result = pdb_reader_internal_read_from_blocks(pdb, toc_blocks, 0, toc, hdr.toc_size, NULL)) || (result = pdb_reader_alloc(pdb, toc->num_streams * sizeof(pdb->streams[0]), (void**)&pdb->streams)))
From: Eric Pouech epouech@codeweavers.com
Adding some missing definitions to include/wine/mscvpdb.h
Signed-off-by: Eric Pouech epouech@codeweavers.com --- include/wine/mscvpdb.h | 38 ++++++++++++++++++++++++++++++++++++++ tools/winedump/msc.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index bc45027d36c..34752d9526b 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -2090,6 +2090,43 @@ union codeview_symbol unsigned numInstrs; unsigned staInstLive; } pogoinfo_v3; + + struct + { + unsigned short int len; + unsigned short int id; + unsigned int pparent; + unsigned int pend; + unsigned int pnext; + unsigned int proc_len; + unsigned int debug_start; + unsigned int debug_end; + unsigned int token; + unsigned int off; + unsigned short sect; + unsigned char flags; + unsigned short ret_reg; + unsigned char name[]; + } managed_proc_v3; + + struct + { + unsigned short len; + unsigned short id; + unsigned int islot; + cv_typ_t typeid; + struct cv_local_varflag attr; + unsigned char name[]; + } managed_slot_v3; + + struct + { + unsigned short len; + unsigned short id; + GUID idOEM; + cv_typ_t typeid; + unsigned int rgl[]; + } oem_v3; };
enum BinaryAnnotationOpcode @@ -2145,6 +2182,7 @@ enum BinaryAnnotationOpcode #define S_DATAREF_ST 0x0401 #define S_ALIGN 0x0402 #define S_LPROCREF_ST 0x0403 +#define S_OEM 0x0404
#define S_REGISTER_ST 0x1001 /* Variants with new 32-bit type indices */ #define S_CONSTANT_ST 0x1002 diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 7c61ba128a4..ff8d7b4ff1a 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1429,9 +1429,11 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long case S_DATAREF: case S_PROCREF: case S_LPROCREF: + case S_TOKENREF: printf("%sref V3 '%s' %04x:%08x name:%08x\n", sym->generic.id == S_DATAREF ? "Data" : - (sym->generic.id == S_PROCREF ? "Proc" : "Lproc"), + (sym->generic.id == S_PROCREF ? "Proc" : + (sym->generic.id == S_LPROCREF ? "Lproc" : "Token")), get_symbol_str(sym->refsym2_v3.name), sym->refsym2_v3.imod, sym->refsym2_v3.ibSym, sym->refsym2_v3.sumName); break; @@ -1958,6 +1960,40 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->pogoinfo_v3.numInstrs, sym->pogoinfo_v3.staInstLive); break;
+ case S_GMANPROC: + case S_LMANPROC: + printf("%s Managed Procedure V3: '%s' (%04x:%08x#%x) attr:%x\n", + sym->generic.id == S_GMANPROC ? "Global" : "Local", + sym->managed_proc_v3.name, + sym->managed_proc_v3.sect, sym->managed_proc_v3.off, sym->managed_proc_v3.proc_len, + sym->managed_proc_v3.flags); + printf("%*s\- Debug: start=%08x end=%08x\n", + indent, "", sym->managed_proc_v3.debug_start, sym->managed_proc_v3.debug_end); + printf("%*s\- parent:<%x> end:<%x> next<%x>\n", + indent, "", sym->managed_proc_v3.pparent, sym->managed_proc_v3.pend, sym->managed_proc_v3.pnext); + printf("%*s\- token:%x retReg:%x\n", + indent, "", sym->managed_proc_v3.token, sym->managed_proc_v3.ret_reg); + push_symbol_dumper(&sd, sym, sym->managed_proc_v3.pend); + break; + + case S_MANSLOT: + printf("Managed slot V3: '%s' type:%x attr:%s slot:%u\n", + sym->managed_slot_v3.name, sym->managed_slot_v3.typeid, + get_varflags(sym->managed_slot_v3.attr), sym->managed_slot_v3.islot); + break; + + case S_OEM: + printf("OEM symbol V3 guid=%s type=%x\n", + get_guid_str(&sym->oem_v3.idOEM), sym->oem_v3.typeid); + { + const unsigned int *from = (const void*)sym->oem_v3.rgl; + const unsigned int *last = (unsigned int*)((unsigned char*)sym + 2 + sym->generic.len); + printf("%*s\- rgl: [", indent, ""); + for (; from < last; from++) printf("%08x%s", *from, (from + 1) < last ? " " : ""); + printf("]\n"); + } + break; + default: printf("\n\t\t>>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2); dump_data((const void*)sym, sym->generic.len + 2, " ");
From: Eric Pouech epouech@codeweavers.com
A step towards a full fix of:
Wine-Bug-Id: https://bugs.winehq.org/show_bug.cgi?id=34990
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index d65b7707921..2078881d8f2 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2848,6 +2848,19 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, FIXME("Unexpected S_FRAMEPROC %d (%p %p) %x\n", top_frame_size, top_func, curr_func, i); break;
+ case S_GMANPROC: + case S_LMANPROC: + /* skip whole record and sub-records */ + i = sym->managed_proc_v3.pend; + sym = (const union codeview_symbol*)(root + i); + if (i + sizeof(sym->generic) > size || sym->generic.id != S_END) + { + FIXME("Wrong relocation after managed proc, aborting\n"); + return FALSE; + } + length = 2 + sym->generic.len; + break; + /* the symbols we can safely ignore for now */ case S_SKIP: case S_TRAMPOLINE: @@ -2857,6 +2870,9 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, case S_EXPORT: case S_CALLSITEINFO: case S_ARMSWITCHTABLE: + case S_TOKENREF: + case S_OEM: + case S_MANSLOT: /* even if S_LOCAL groks all the S_DEFRANGE* records following itself, * those kinds of records can also be present after a S_FILESTATIC record * so silence them until (at least) S_FILESTATIC is supported
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 2078881d8f2..788c6bc585d 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2977,11 +2977,13 @@ static BOOL codeview_snarf_sym_hashtable(const struct msc_debug_info* msc_dbg, c if (hashsize < sizeof(DBI_HASH_HEADER) || hash_hdr->signature != 0xFFFFFFFF || hash_hdr->version != 0xeffe0000 + 19990810 || + !hash_hdr->hash_records_size || (hash_hdr->hash_records_size % sizeof(DBI_HASH_RECORD)) != 0 || sizeof(DBI_HASH_HEADER) + hash_hdr->hash_records_size + DBI_BITMAP_HASH_SIZE > hashsize || (hashsize - (sizeof(DBI_HASH_HEADER) + hash_hdr->hash_records_size + DBI_BITMAP_HASH_SIZE)) % sizeof(unsigned)) { - FIXME("Incorrect hash structure\n"); + if (hash_hdr->hash_records_size) + FIXME("Incorrect hash structure\n"); return FALSE; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 111 +++++++++++++++++++++++--------------------- dlls/dbghelp/type.c | 2 +- 2 files changed, 58 insertions(+), 55 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index dc503b79dc9..349fe8be087 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -2635,7 +2635,7 @@ 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) + TI_FINDCHILDREN_PARAMS *tfp) { enum pdb_result result; symref_t symref; @@ -2643,8 +2643,12 @@ 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, 0, &symref))) return result; - indexes[i] = symt_symref_to_index(pdb->module, symref); + if (i >= tfp->Start + tfp->Count) return R_PDB_BUFFER_TOO_SMALL; + if (i >= tfp->Start) + { + if ((result = pdb_reader_push_action(pdb, action_type_cv_typ_t, tpi_offset, id_size, 0, &symref))) return result; + tfp->ChildId[i] = symt_symref_to_index(pdb->module, symref); + } } return R_PDB_SUCCESS; } @@ -2691,14 +2695,14 @@ static enum method_result pdb_reader_TPI_procsignature_request(struct pdb_reader /* 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) + if (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; + result = pdb_reader_TPI_fillin_arglist(pdb, cv_reftype.arglist_v2.num, sizeof(cv_typ_t), tpi_arglist_offset, p); + if (result && result != R_PDB_BUFFER_TOO_SMALL) return MR_FAILURE; + if (p->Start + p->Count > cv_reftype.arglist_v2.num) return MR_FAILURE; } return MR_SUCCESS; case TI_GET_CHILDRENCOUNT: @@ -2727,37 +2731,28 @@ 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) + unsigned id_size, symref_t container_symref, unsigned *where, TI_FINDCHILDREN_PARAMS *tfp) { 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); + if (tfp) + { + if (*where >= tfp->Start + tfp->Count) return R_PDB_BUFFER_TOO_SMALL; + if (*where >= tfp->Start) + { + if ((result = pdb_reader_push_action(pdb, action, stream_offset, id_size, container_symref, &symref))) return result; + tfp->ChildId[*where] = symt_symref_to_index(pdb->module, symref); + } + } + (*where)++; + return R_PDB_SUCCESS; }
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) + cv_typ_t enumlist_cv_typeid, unsigned *where, + TI_FINDCHILDREN_PARAMS *tfp) { enum pdb_result result; union codeview_reftype *cv_reftype; @@ -2786,23 +2781,30 @@ static enum pdb_result pdb_reader_TPI_fillin_enumlist(struct pdb_reader *pdb, sy 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))) + if (*where >= tfp->Start + tfp->Count) { pdb_reader_free(pdb, cv_reftype); - return result; + return R_PDB_BUFFER_TOO_SMALL; } - *index = symt_symref_to_index(pdb->module, symref); - index++; - count--; + if (*where >= tfp->Start) + { + 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; + } + tfp->ChildId[*where] = symt_symref_to_index(pdb->module, symref); + } + (*where)++; 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; + if ((result = pdb_reader_TPI_fillin_enumlist(pdb, container_symref, cv_field->index_v2.ref, + where, tfp))) return result; ptr += sizeof(cv_field->index_v2); break;
@@ -2823,8 +2825,11 @@ static enum method_result pdb_reader_TPI_enum_request(struct pdb_reader *pdb, sy 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; + unsigned where = 0; + enum pdb_result result; + result = pdb_reader_TPI_fillin_enumlist(pdb, symref, cv_type->enumeration_v3.fieldlist, &where, p); + if (result && result != R_PDB_BUFFER_TOO_SMALL) return MR_FAILURE; + if (p->Start + p->Count > where) return MR_FAILURE; } return MR_SUCCESS; case TI_GET_CHILDRENCOUNT: @@ -2862,7 +2867,7 @@ 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) + cv_typ_t udtlist_cv_typeid, unsigned *where, TI_FINDCHILDREN_PARAMS *tfp) { enum pdb_result result; union codeview_reftype *cv_reftype; @@ -2908,7 +2913,7 @@ static enum pdb_result pdb_reader_TPI_fillin_UDTlist(struct pdb_reader *pdb, sym 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); + result = pdb_reader_push_action_and_filler(pdb, action_type_field, tpi_offset + (ptr - start), length, container_symref, where, tfp); break;
case LF_STMEMBER_V3: @@ -2946,7 +2951,7 @@ static enum pdb_result pdb_reader_TPI_fillin_UDTlist(struct pdb_reader *pdb, sym break;
case LF_INDEX_V2: - if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, cv_field->index_v2.ref, children))) return result; + if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, cv_field->index_v2.ref, where, tfp))) return result; length = sizeof(cv_field->index_v2); break;
@@ -2965,10 +2970,10 @@ static enum pdb_result pdb_reader_count_advertized_in_UDT_fieldlist(struct pdb_r cv_typ_t fieldlist_cv_typeid, DWORD *count) { enum pdb_result result; - struct pdb_children_filler filler = {.actual = 0, .count = ~0u, .indexes = NULL}; + unsigned where = 0;
- if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, fieldlist_cv_typeid, &filler))) return result; - *count = filler.actual; + if ((result = pdb_reader_TPI_fillin_UDTlist(pdb, container_symref, fieldlist_cv_typeid, &where, NULL))) return result; + *count = where; return R_PDB_SUCCESS; }
@@ -2976,24 +2981,22 @@ static enum method_result pdb_reader_TPI_UDT_request(struct pdb_reader *pdb, sym 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; + enum pdb_result result;
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; @@ -3010,13 +3013,13 @@ static enum method_result pdb_reader_TPI_UDT_request(struct pdb_reader *pdb, sym return MR_SUCCESS; case TI_FINDCHILDREN: { - TI_FINDCHILDREN_PARAMS *p = data; - struct pdb_children_filler filler = {.actual = 0, .count = p->Count, .indexes = p->ChildId}; + TI_FINDCHILDREN_PARAMS *tfp = data; + unsigned where = 0;
- 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;} + if (property.is_forward_defn) return !tfp->Count ? MR_SUCCESS : MR_FAILURE; + result = pdb_reader_TPI_fillin_UDTlist(pdb, symref, fieldlist_cv_typeid, &where, tfp); + if (result && result != R_PDB_BUFFER_TOO_SMALL) return MR_FAILURE; + if (tfp->Start + tfp->Count > where) return MR_FAILURE; } return MR_SUCCESS; case TI_GET_CHILDRENCOUNT: diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index f0469845277..a0529ec37fb 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -708,7 +708,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, for (i = 0; i < tifp->Count; i++) { if (!(symref = (symref_t *)vector_at(v, tifp->Start + i))) return FALSE; - tifp->ChildId[i] = symt_symref_to_index(module, *symref); + tifp->ChildId[tifp->Start + i] = symt_symref_to_index(module, *symref); } } break;