We used to expect a fixed number of DBI substreams (the expected number depended on the DBI header version). Recent MSVC generate a different number as we expected. Implement a more flexible scheme where we allow any number of streams. This lets these recent PDB files to be properly displayed by winedump, and loaded/parsed by dbghelp.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- include/wine/mscvpdb.h | 8 +++++ tools/winedump/pdb.c | 71 ++++++++++++------------------------------ 2 files changed, 28 insertions(+), 51 deletions(-)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index 3502e0faed0..c0f9c70a4e1 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -2568,6 +2568,14 @@ typedef struct _PDB_SYMBOLS unsigned int resvd4; } PDB_SYMBOLS, *PPDB_SYMBOLS;
+/* FIXME other entries are unknown */ +enum PDB_STREAM_INDEX +{ + PDB_SIDX_FPO, + PDB_SIDX_SECTIONS = 5, + PDB_SIDX_FPOEXT = 9 +}; + typedef struct { unsigned short FPO; diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index c028f2df2b6..5e5cc0ab67d 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -489,10 +489,8 @@ static void pdb_dump_symbols(struct pdb_reader* reader) unsigned char* modimage; const char* file; char tcver[32]; - PDB_STREAM_INDEXES sidx; - - sidx.FPO = sidx.unk0 = sidx.unk1 = sidx.unk2 = sidx.unk3 = sidx.sections_stream = - sidx.unk4 = sidx.unk5 = sidx.unk6 = sidx.FPO_EXT = sidx.unk7 = -1; + const unsigned short* sub_streams; + unsigned num_sub_streams = 0;
symbols = reader->read_stream(reader, 3); if (!symbols) return; @@ -736,52 +734,20 @@ static void pdb_dump_symbols(struct pdb_reader* reader) } if (symbols->stream_index_size && globals_dump_sect("image")) { + const char* sub_stream_names[] = {"FPO", NULL, NULL, NULL, NULL, "Sections stream", NULL, NULL, NULL, "FPO-ext"}; + int i; + printf("\t------------stream indexes--------------\n"); - switch (symbols->stream_index_size) + num_sub_streams = symbols->stream_index_size / sizeof(sub_streams[0]); + sub_streams = (const unsigned short*)((const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size + + symbols->sectcontrib_size + symbols->segmap_size + symbols->srcmodule_size + + symbols->pdbimport_size + symbols->unknown2_size); + for (i = 0; i < num_sub_streams; i++) { - case sizeof(PDB_STREAM_INDEXES_OLD): - /* PDB_STREAM_INDEXES is a superset of PDB_STREAM_INDEX_OLD - * FIXME: to be confirmed when all fields are fully understood - */ - memcpy(&sidx, - (const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size + - symbols->sectcontrib_size + symbols->segmap_size + symbols->srcmodule_size + - symbols->pdbimport_size + symbols->unknown2_size, - sizeof(PDB_STREAM_INDEXES_OLD)); - printf("\tFPO: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\tSections stream: %04x\n", - sidx.FPO, sidx.unk0, sidx.unk1, sidx.unk2, sidx.unk3, - sidx.sections_stream); - break; - case sizeof(PDB_STREAM_INDEXES): - case sizeof(PDB_STREAM_INDEXES) + 2: - memcpy(&sidx, - (const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size + - symbols->sectcontrib_size + symbols->segmap_size + symbols->srcmodule_size + - symbols->pdbimport_size + symbols->unknown2_size, - sizeof(sidx)); - printf("\tFPO: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\tSection stream: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\t?: %04x\n" - "\tFPO-ext: %04x\n" - "\t?: %04x\n", - sidx.FPO, sidx.unk0, sidx.unk1, sidx.unk2, sidx.unk3, - sidx.sections_stream, sidx.unk4, sidx.unk5, sidx.unk6, sidx.FPO_EXT, - sidx.unk7); - break; - default: - printf("unexpected size for stream index %d\n", symbols->stream_index_size); - break; + const char* name = "?"; + if (i < ARRAY_SIZE(sub_stream_names) && sub_stream_names[i]) + name = sub_stream_names[i]; + printf("\t%s:%.*s%04x\n", name, (int)(21 - strlen(name)), "", sub_streams[i]); } }
@@ -837,9 +803,12 @@ static void pdb_dump_symbols(struct pdb_reader* reader)
if (globals_dump_sect("image")) { - pdb_dump_fpo(reader, sidx.FPO); - pdb_dump_fpo_ext(reader, sidx.FPO_EXT); - pdb_dump_sections(reader, sidx.sections_stream); + if (PDB_SIDX_FPO < num_sub_streams) + pdb_dump_fpo(reader, sub_streams[PDB_SIDX_FPO]); + if (PDB_SIDX_FPOEXT < num_sub_streams) + pdb_dump_fpo_ext(reader, sub_streams[PDB_SIDX_FPOEXT]); + if (PDB_SIDX_SECTIONS < num_sub_streams) + pdb_dump_sections(reader, sub_streams[PDB_SIDX_SECTIONS]); }
free(symbols);
From: Eric Pouech epouech@codeweavers.com
MSC no longer emits a fixed number of substreams (depending on version of PDB file), but can emit less.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 30 ++++++++++-------------------- dlls/dbghelp/tests/path.c | 6 +++--- include/wine/mscvpdb.h | 25 ------------------------- 3 files changed, 13 insertions(+), 48 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 26e921f7a0f..12ed93380b6 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3823,7 +3823,8 @@ static BOOL pdb_process_internal(const struct process* pcs, struct codeview_type_parse ipi_ctp; BYTE* file; int header_size = 0; - PDB_STREAM_INDEXES* psi; + unsigned num_sub_streams; + const unsigned short* sub_streams; BOOL ipi_ok;
pdb_convert_symbols_header(&symbols, &header_size, symbols_image); @@ -3839,25 +3840,14 @@ static BOOL pdb_process_internal(const struct process* pcs, symbols.version, symbols.version); }
- switch (symbols.stream_index_size) - { - case 0: - case sizeof(PDB_STREAM_INDEXES_OLD): - /* no fpo ext stream in this case */ - break; - case sizeof(PDB_STREAM_INDEXES): - case sizeof(PDB_STREAM_INDEXES) + 2: - psi = (PDB_STREAM_INDEXES*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) + - symbols.module_size + symbols.sectcontrib_size + - symbols.segmap_size + symbols.srcmodule_size + - symbols.pdbimport_size + symbols.unknown2_size); - pdb_file->fpoext_stream = psi->FPO_EXT; - break; - default: - FIXME("Unknown PDB_STREAM_INDEXES size (%u)\n", symbols.stream_index_size); - pdb_free(symbols_image); - return FALSE; - } + num_sub_streams = symbols.stream_index_size / sizeof(sub_streams[0]); + sub_streams = (const unsigned short*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) + + symbols.module_size + symbols.sectcontrib_size + + symbols.segmap_size + symbols.srcmodule_size + + symbols.pdbimport_size + symbols.unknown2_size); + if (PDB_SIDX_FPO < num_sub_streams) + pdb_file->fpoext_stream = sub_streams[PDB_SIDX_FPO]; + files_image = pdb_read_strings(pdb_file);
pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image, diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index fb7c103d845..781df3dd771 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -587,7 +587,7 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag .hash_records_size = 0, .unknown = 0 }; - PDB_STREAM_INDEXES pddt = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, }; + unsigned short dbi_substream[] = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, }; char unknown[] = { 0xfe, 0xef, 0xfe, 0xef, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, @@ -650,7 +650,7 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag DBI.unknown2_size = stream->size - mark;
mark = stream->size; - pdb_append_to_stream(stream, &pddt, sizeof(pddt)); + pdb_append_to_stream(stream, dbi_substream, sizeof(dbi_substream)); DBI.stream_index_size = stream->size - mark;
stream = pdb_add_stream(&pdb, NULL, &IPI, sizeof(IPI)); /* always stream #4 */ @@ -658,7 +658,7 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag stream = pdb_add_stream(&pdb, &DBI.global_hash_stream, &GHASH, sizeof(GHASH)); stream = pdb_add_stream(&pdb, &DBI.gsym_stream, NULL, 0);
- stream = pdb_add_stream(&pdb, &pddt.sections_stream, &ro_section, sizeof(ro_section)); + stream = pdb_add_stream(&pdb, &dbi_substream[PDB_SIDX_SECTIONS], &ro_section, sizeof(ro_section));
hfile = CreateFileW(pdb_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); ok(hfile != INVALID_HANDLE_VALUE, "failed to create %ls err %lu\n", pdb_name, GetLastError()); diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index c0f9c70a4e1..08353f11811 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -2576,31 +2576,6 @@ enum PDB_STREAM_INDEX PDB_SIDX_FPOEXT = 9 };
-typedef struct -{ - unsigned short FPO; - unsigned short unk0; - unsigned short unk1; - unsigned short unk2; - unsigned short unk3; - unsigned short sections_stream; -} PDB_STREAM_INDEXES_OLD; - -typedef struct -{ - unsigned short FPO; - unsigned short unk0; - unsigned short unk1; - unsigned short unk2; - unsigned short unk3; - unsigned short sections_stream; - unsigned short unk4; - unsigned short unk5; - unsigned short unk6; - unsigned short FPO_EXT; - unsigned short unk7; -} PDB_STREAM_INDEXES; - typedef struct _PDB_FPO_DATA { unsigned int start;