Old version of PDB files can have a stream #4 which is not an IPI stream Available documentation isn't 100% clear about when IPI has been introduced. So decide that IPI is present when header of stream looks like a type stream header.
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/msc.c | 6 ++++-- tools/winedump/pdb.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index c481c762b1d..4e44655deb5 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3047,6 +3047,7 @@ static BOOL pdb_init_type_parse(const struct msc_debug_info* msc_dbg, break; default: ERR("-Unknown type info version %d\n", types.version); + return FALSE; }
ctp->module = msc_dbg->module; @@ -3324,6 +3325,7 @@ static BOOL pdb_process_internal(const struct process* pcs, BYTE* file; int header_size = 0; PDB_STREAM_INDEXES* psi; + BOOL ipi_ok;
pdb_convert_symbols_header(&symbols, &header_size, symbols_image); switch (symbols.version) @@ -3363,7 +3365,7 @@ static BOOL pdb_process_internal(const struct process* pcs, pdb_process_types(msc_dbg, pdb_file);
ipi_image = pdb_read_file(pdb_file, 4); - pdb_init_type_parse(msc_dbg, &ipi_ctp, ipi_image); + ipi_ok = pdb_init_type_parse(msc_dbg, &ipi_ctp, ipi_image);
/* Read global symbol table */ globalimage = pdb_read_file(pdb_file, symbols.gsym_file); @@ -3387,7 +3389,7 @@ static BOOL pdb_process_internal(const struct process* pcs, modimage = pdb_read_file(pdb_file, sfile.file); if (modimage) { - struct cv_module_snarf cvmod = {&ipi_ctp, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size, + struct cv_module_snarf cvmod = {ipi_ok ? &ipi_ctp : NULL, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size, files_image + 12, files_size}; codeview_snarf(msc_dbg, modimage, sizeof(DWORD), sfile.symbol_size, &cvmod, TRUE); diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index ed4877cd10a..958a13f5e1c 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -54,6 +54,21 @@ struct pdb_reader DWORD file_used[1024]; };
+static inline BOOL has_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + return reader->file_used[file_nr / 32] & (1 << (file_nr % 32)); +} + +static inline void mark_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + reader->file_used[file_nr / 32] |= 1 << (file_nr % 32); +} + +static inline void clear_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + reader->file_used[file_nr / 32] &= ~(1 << (file_nr % 32)); +} + static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list, int size) { int i, nBlocks; @@ -78,7 +93,7 @@ static void* pdb_jg_read_file(struct pdb_reader* reader, DWORD file_nr)
if (!reader->u.jg.toc || file_nr >= reader->u.jg.toc->num_files) return NULL;
- reader->file_used[file_nr / 32] |= 1 << (file_nr % 32); + mark_file_been_read(reader, file_nr); if (reader->u.jg.toc->file[file_nr].size == 0 || reader->u.jg.toc->file[file_nr].size == 0xFFFFFFFF) return NULL; @@ -125,7 +140,7 @@ static void pdb_exit(struct pdb_reader* reader)
for (i = 0; i < pdb_get_num_files(reader); i++) { - if (reader->file_used[i / 32] & (1 << (i % 32))) continue; + if (has_file_been_read(reader, i)) continue;
file = reader->read_file(reader, i); if (!file) continue; @@ -615,7 +630,14 @@ static void pdb_dump_types_hash(struct pdb_reader* reader, unsigned file, const static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const char* strmname) { PDB_TYPES* types = NULL; + BOOL used = has_file_been_read(reader, strmidx);
+ if (pdb_get_file_size(reader, strmidx) < sizeof(*types)) + { + if (strmidx == 2) + printf("-Too small type header\n"); + return; + } types = reader->read_file(reader, strmidx); if (!types) return;
@@ -628,7 +650,12 @@ static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const ch case 20040203: /* VC 8.0 */ break; default: - printf("-Unknown type info version %d\n", types->version); + /* IPI stream is not always present in older PDB files */ + if (strmidx == 2) + printf("-Unknown type info version %d\n", types->version); + free(types); + if (used) clear_file_been_read(reader, strmidx); + return; }
/* Read type table */ @@ -870,7 +897,7 @@ static void* pdb_ds_read_file(struct pdb_reader* reader, DWORD file_number)
if (!reader->u.ds.toc || file_number >= reader->u.ds.toc->num_files) return NULL;
- reader->file_used[file_number / 32] |= 1 << (file_number % 32); + mark_file_been_read(reader, file_number); if (reader->u.ds.toc->file_size[file_number] == 0 || reader->u.ds.toc->file_size[file_number] == 0xFFFFFFFF) return NULL; @@ -932,7 +959,7 @@ static void pdb_ds_dump(void) * - segments * - extended FPO data */ - reader.file_used[0] |= 1; /* mark stream #0 as read */ + mark_file_been_read(&reader, 0); /* mark stream #0 as read */ reader.u.ds.root = reader.read_file(&reader, 1); if (reader.u.ds.root) {