diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index f91e2784b15..1ceefcdbde6 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -772,6 +772,7 @@ struct pdb_cmd_pair { }; extern BOOL pdb_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, union ctx *context, struct pdb_cmd_pair *cpair) DECLSPEC_HIDDEN; +extern DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info); /* path.c */ extern BOOL path_find_symbol_file(const struct process* pcs, const struct module* module, diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index f6b681cb4ae..63c3f530bf5 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3615,6 +3615,76 @@ static BOOL pdb_process_internal(const struct process* pcs, struct pdb_module_info* pdb_module_info, unsigned module_index); +DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) +{ + /* check the file header, and if ok, load the TOC */ + TRACE("PDB: %.40s\n", debugstr_an(image, 40)); + + if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT))) + { + FIXME("Unsupported for PDB files in JG format\n"); + return ERROR_FILE_CORRUPT; + } + if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT))) + { + const struct PDB_DS_HEADER* pdb = (const struct PDB_DS_HEADER*)image; + struct PDB_DS_TOC* ds_toc; + struct PDB_DS_ROOT* root; + DWORD ec = ERROR_SUCCESS; + + ds_toc = pdb_ds_read(pdb, (const UINT*)((const char*)pdb + pdb->toc_block * pdb->block_size), + pdb->toc_size); + root = pdb_read_ds_stream(pdb, ds_toc, 1); + if (!root) + { + pdb_free(ds_toc); + return ERROR_FILE_CORRUPT; + } + switch (root->Version) + { + case 20000404: + break; + default: + ERR("-Unknown root block version %u\n", root->Version); + ec = ERROR_FILE_CORRUPT; + } + /* The age field is present twice (in PDB_ROOT and in PDB_SYMBOLS ), + * It's the one in PDB_SYMBOLS which is reported. + */ + if (ec == ERROR_SUCCESS) + { + PDB_SYMBOLS* symbols = pdb_read_ds_stream(pdb, ds_toc, 3); + + if (symbols && symbols->version == 19990903) + { + info->age = symbols->age; + } + else + { + if (symbols) + ERR("-Unknown symbol info version %u %08x\n", symbols->version, symbols->version); + ec = ERROR_FILE_CORRUPT; + } + pdb_free(symbols); + } + if (ec == ERROR_SUCCESS) + { + info->dbgfile[0] = '\0'; + info->guid = root->guid; + info->pdbfile[0] = '\0'; + info->sig = 0; + info->size = 0; + info->stripped = FALSE; + info->timestamp = 0; + } + + pdb_free(ds_toc); + pdb_free(root); + return ec; + } + return ERROR_BAD_FORMAT; +} + static void pdb_process_symbol_imports(const struct process* pcs, const struct msc_debug_info* msc_dbg, const PDB_SYMBOLS* symbols, diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index 5c53e3f857d..dce700b34e7 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -906,7 +906,8 @@ BOOL WINAPI SymSrvGetFileIndexInfoW(const WCHAR *file, SYMSRV_INDEX_INFOW* info, fsize = GetFileSize(hFile, NULL); /* try PE module first */ ret = pe_get_file_indexinfo(image, fsize, info); - /* handle (ret == ERROR_BAD_FORMAT) with .dbg and .pdb format */ + if (ret == ERROR_BAD_FORMAT) + ret = pdb_get_file_indexinfo(image, fsize, info); } else ret = ERROR_FILE_NOT_FOUND; diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 78e357d812f..54189c7ed5c 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -828,10 +828,8 @@ static void test_srvgetindexes_pdb(void) memset(&ssii, 0x45, sizeof(ssii)); ssii.sizeofstruct = sizeof(ssii); ret = SymSrvGetFileIndexInfo(filename, &ssii, 0); - todo_wine ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError()); - if (ret) { ok(ssii.age == 240 + i, "Mismatch in age: %lx\n", ssii.age); ok(!memcmp(&ssii.guid, indexes[i].guid, sizeof(GUID)), "Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid)); @@ -844,7 +842,6 @@ static void test_srvgetindexes_pdb(void) ok(!strcmp(ssii.file, filename), "Mismatch in file: %s\n", ssii.file); ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %s\n", ssii.pdbfile); ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %s\n", ssii.dbgfile); - } DeleteFileA(filename); winetest_pop_context();