[PATCH 02/10] dbghelp/msc tools/winedump: better detect whether IPI stream is present

Eric Pouech eric.pouech at gmail.com
Wed Nov 10 09:42:14 CST 2021


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 at 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)
     {




More information about the wine-devel mailing list