This is the second part of a larger serie of four parts to cover module loading and debug info file lookup in dbghelp. This second part covers:
- new tests about SymLoadModule flags and options - separating PDB file loading from trying to find the PDB file matching the requested lookup parameter
Note: some modifications require new todo marks in the tests, as the full fix will require changing other areas that would make the change too large. The large serie of four parts resolves all the todo:s.
From: Eric Pouech epouech@codeweavers.com
Mainly: - SymLoadModules flags (SLMFLAG_VIRTUAL and SLMFLAG_NO_SYMBOLS), - handling of load details (SymType, ImageName vs LoadedImageName, various instances of module name).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/tests/path.c | 292 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+)
diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 0efe55defd2..92b2bd21c94 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -1627,6 +1627,297 @@ static void test_load_modules_path(void) ok(ret, "Couldn't remove directory\n"); }
+struct module_details +{ + WCHAR* name; + unsigned count; +}; + +static BOOL CALLBACK aggregate_module_details_cb(PCWSTR name, DWORD64 base, PVOID usr) +{ + struct module_details* md = usr; + + if (md->count == 0) md->name = wcsdup(name); + md->count++; + return TRUE; +} + +static BOOL has_mismatch(const char *str, char ch, unsigned *val) +{ + if (str && *str == ch) + { + if (val && (ch == 'D' || ch == 'P' || ch == '!')) + *val = char2index(str[1]); + return TRUE; + } + return FALSE; +} + +static void test_load_modules_details(void) +{ + static const struct debug_info_file + { + const GUID* guid; /* non-NULL means PDB/DS, DBG otherwise */ + DWORD age_or_timestamp; /* age for PDB, timestamp for DBG */ + const WCHAR*module_path; + } + test_files[] = + { + /* 0 */ { &guid1, 0x0030cafe, L"bar.pdb" }, + /* 1 */ { NULL, 0xcafe0030, L"bar.dbg" }, + }; + + static const struct module_details_test + { + /* input parameters */ + DWORD flags; + DWORD options; + const WCHAR *in_image_name; + const WCHAR *in_module_name; + int blob_index; /* only when in_image_name is bar.dll */ + const char *test_files; /* various test_files to be created */ + /* output parameters */ + SYM_TYPE sym_type; + const char *mismatch_in; /* 'PN'=PDB, 'DN'=DBG, NULL (N index of expected found file) */ + } + module_details_tests[] = + { +/* 0*/ {SLMFLAG_VIRTUAL, 0, NULL, NULL, -1, "", SymVirtual}, + {SLMFLAG_VIRTUAL, 0, NULL, L"foo_bar", -1, "", SymVirtual}, + {SLMFLAG_VIRTUAL, 0, L"foo.dll", L"foo_bar", -1, "", SymVirtual}, + {SLMFLAG_VIRTUAL, SYMOPT_DEFERRED_LOADS, L"foo.dll", L"foo_bar", -1, "", SymDeferred}, + + {SLMFLAG_NO_SYMBOLS, 0, L"bar.dll", L"foo_bar", -1, "0", SymNone}, +/* 5*/ {SLMFLAG_NO_SYMBOLS, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", -1, "0", SymDeferred}, + + {0, 0, L"bar.dll", L"foo_bar", -1, "0", SymPdb, "!0"}, + {0, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", -1, "0", SymDeferred}, + + {SLMFLAG_NO_SYMBOLS, 0, L"bar.dll", L"foo_bar", 0, "0", SymNone}, + {SLMFLAG_NO_SYMBOLS, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", 0, "0", SymDeferred}, + +/*10*/ {0, 0, L"bar.dll", L"foo_bar", 0, "0", SymPdb}, + {0, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", 0, "0", SymDeferred}, + + {SLMFLAG_NO_SYMBOLS, 0, L"bar.dll", L"foo_bar", 1, "0", SymNone, "P0"}, + {SLMFLAG_NO_SYMBOLS, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", 1, "0", SymDeferred}, + + {0, 0, L"bar.dll", L"foo_bar", 1, "0", SymNone, "P0"}, +/*15*/ {0, SYMOPT_DEFERRED_LOADS, L"bar.dll", L"foo_bar", 1, "0", SymDeferred}, + + /* FIXME add lookup path, exact symbol, .DBG files */ + }; + + unsigned i; + HANDLE dummy = (HANDLE)(ULONG_PTR)0xc4fef00d; + DWORD old_options; + IMAGEHLP_MODULEW64 im; + BOOL ret; + DWORD64 base; + struct module_details md; + WCHAR topdir[MAX_PATH]; + WCHAR filename[MAX_PATH]; + const WCHAR* loaded_img_name; + WCHAR expected_module_name[32]; + WCHAR sym_name[128]; + char buffer[512]; + SYMBOL_INFOW* sym = (void*)buffer; + DWORD len; + + union nt_header h; + struct debug_directory_blob* blob_refs[2]; + + old_options = SymGetOptions(); + im.SizeOfStruct = sizeof(im); + + len = GetTempPathW(ARRAY_SIZE(topdir), topdir); + ok(len && len < ARRAY_SIZE(topdir), "Unexpected length\n"); + wcscat(topdir, L"dh.tmp\"); + ret = CreateDirectoryW(topdir, NULL); + ok(ret, "Couldn't create directory\n"); + + init_headers64(&h.nt_header64, 12324, 3242, 0); + blob_refs[0] = make_pdb_ds_blob(12324, &guid1, 0x0030cafe, "bar.pdb"); + blob_refs[1] = make_pdb_ds_blob(12324, &guid1, 0x0030caff, "bar.pdb"); /* shall generate a mismatch */ + + for (i = 0; i < ARRAY_SIZE(module_details_tests); i++) + { + const struct module_details_test *test = module_details_tests + i; + const char* ptr; + + winetest_push_context("module_test %d", i); + + /* setup debug info files */ + for (ptr = test->test_files; *ptr; ptr++) + { + unsigned val = char2index(*ptr); + if (val < ARRAY_SIZE(test_files)) + { + make_path(filename, topdir, NULL, test_files[val].module_path); + if (test_files[val].guid) + create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp); + else + create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000); + } + else ok(0, "Unrecognized file reference %c\n", *ptr); + } + + /* set up image files (when needed) */ + if (test->in_image_name && !wcscmp(test->in_image_name, L"bar.dll")) + { + make_path(filename, topdir, NULL, test->in_image_name); + if (test->blob_index >= 0) + { + ok(test->blob_index < ARRAY_SIZE(blob_refs), "Out of bounds blob %d\n", test->blob_index); + create_test_dll(&h, sizeof(h.nt_header64), &blob_refs[test->blob_index], 1, filename); + } + else + create_test_dll(&h, sizeof(h.nt_header64), NULL, 0, filename); + } + + ret = SymInitializeW(dummy, topdir, FALSE); + ok(ret, "SymInitialize failed: %lu\n", GetLastError()); + SymSetOptions((SymGetOptions() & ~SYMOPT_DEFERRED_LOADS) | test->options); + base = SymLoadModuleExW(dummy, NULL, + test->in_image_name, test->in_module_name, + 0x4000, 0x6666, NULL, test->flags); + todo_wine_if(i == 0 || i == 1) + ok(base == 0x4000, "SymLoadModuleExW failed: %lu\n", GetLastError()); + ret = SymGetModuleInfoW64(dummy, base, &im); + todo_wine_if(i == 0 || i == 1) + ok(ret, "SymGetModuleInfow64 failed: %lu\n", GetLastError()); + if (!ret) goto temp_bail_out; + if (test->in_image_name) + { + WCHAR *dot; + wcscpy_s(expected_module_name, ARRAY_SIZE(expected_module_name), test->in_image_name); + dot = wcsrchr(expected_module_name, L'.'); + if (dot) *dot = L'\0'; + } + else + expected_module_name[0] = L'\0'; + todo_wine_if(i >= 2) + ok(!wcsicmp(im.ModuleName, expected_module_name), "Unexpected module name '%ls'\n", im.ModuleName); + ok(!wcsicmp(im.ImageName, test->in_image_name ? test->in_image_name : L""), "Unexpected image name '%ls'\n", im.ImageName); + if ((test->options & SYMOPT_DEFERRED_LOADS) || !test->in_image_name) + loaded_img_name = L""; + else if (!wcscmp(test->in_image_name, L"bar.dll")) + { + make_path(filename, topdir, NULL, L"bar.dll"); + loaded_img_name = filename; + } + else + loaded_img_name = test->in_image_name; + todo_wine_if(test->options & SYMOPT_DEFERRED_LOADS) + ok(!wcsicmp(im.LoadedImageName, (test->options & SYMOPT_DEFERRED_LOADS) ? L"" : loaded_img_name), + "Unexpected loaded image name '%ls' (%ls)\n", im.LoadedImageName, loaded_img_name); + todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8 || i == 10 || i == 12 || i == 14) + ok(im.SymType == test->sym_type, "Unexpected module type %u\n", im.SymType); + todo_wine_if(i == 8) + ok(!im.TypeInfo, "No type info present\n"); + if (test->mismatch_in) + { + unsigned val; + if (has_mismatch(test->mismatch_in, '!', &val)) + { + make_path(filename, topdir, NULL, L"bar.pdb"); + todo_wine + ok(!wcscmp(filename, im.LoadedPdbName), "Unexpected value '%ls\n", im.LoadedPdbName); + todo_wine + ok(im.PdbUnmatched, "Unexpected value\n"); + todo_wine + ok(im.PdbUnmatched, "Unexpected value\n"); + ok(!im.DbgUnmatched, "Unexpected value\n"); + todo_wine + ok(IsEqualGUID(&im.PdbSig70, test_files[val].guid), "Unexpected value %s %s\n", + wine_dbgstr_guid(&im.PdbSig70), wine_dbgstr_guid(test_files[val].guid)); + todo_wine + ok(im.PdbAge == test_files[val].age_or_timestamp, "Unexpected value\n"); + } + else if (has_mismatch(test->mismatch_in, 'P', &val)) + { + ok(val < ARRAY_SIZE(test_files), "Incorrect index\n"); + ok(!im.PdbUnmatched, "Unexpected value\n"); + ok(!im.DbgUnmatched, "Unexpected value\n"); + todo_wine + ok(IsEqualGUID(&im.PdbSig70, test_files[val].guid), "Unexpected value %s %s\n", + wine_dbgstr_guid(&im.PdbSig70), wine_dbgstr_guid(test_files[val].guid)); + todo_wine + ok(im.PdbAge == test_files[val].age_or_timestamp + 1, "Unexpected value\n"); + } + else if (has_mismatch(test->mismatch_in, 'D', &val)) + { + ok(val < ARRAY_SIZE(test_files), "Incorrect index\n"); + ok(!im.PdbUnmatched, "Unexpected value\n"); + ok(!im.DbgUnmatched, "Unexpected value\n"); + } + } + else + { + ok(!im.PdbUnmatched, "Unexpected value\n"); + ok(!im.DbgUnmatched, "Unexpected value\n"); + } + ok(im.ImageSize == 0x6666, "Unexpected image size\n"); + memset(&md, 0, sizeof(md)); + ret = SymEnumerateModulesW64(dummy, aggregate_module_details_cb, &md); + ok(ret, "SymEnumerateModules64 failed: %lu\n", GetLastError()); + ok(md.count == 1, "Unexpected module count %u\n", md.count); + todo_wine_if(i >= 2) + ok(!wcscmp(md.name, expected_module_name), "Unexpected module name %ls\n", md.name); + free(md.name); + /* native will fail loading symbol in deferred state, so force loading of debug symbols */ + if (im.SymType == SymDeferred) + { + memset(sym, 0, sizeof(*sym)); + sym->SizeOfStruct = sizeof(*sym); + sym->MaxNameLen = (sizeof(buffer) - sizeof(*sym)) / sizeof(WCHAR); + SymFromNameW(dummy, L"foo", sym); + } + ret = SymAddSymbol(dummy, base, "winetest_symbol_virtual", base + 4242, 13, 0); + ok(ret, "Failed to add symbol\n"); + memset(sym, 0, sizeof(*sym)); + sym->SizeOfStruct = sizeof(*sym); + sym->MaxNameLen = (sizeof(buffer) - sizeof(*sym)) / sizeof(WCHAR); + + swprintf(sym_name, ARRAY_SIZE(sym_name), L"%ls!%s", im.ModuleName, L"winetest_symbol_virtual"); + ret = SymFromNameW(dummy, sym_name, (void*)sym); + ok(ret, "Couldn't find symbol %ls\n", sym_name); + if (test->in_module_name) + { + swprintf(sym_name, ARRAY_SIZE(sym_name), L"%ls!%s", test->in_module_name, L"winetest_symbol_virtual"); + ret = SymFromNameW(dummy, sym_name, (void*)sym); + ok(ret, "Couldn't find symbol %ls\n", sym_name); + } + + ret = SymCleanup(dummy); + ok(ret, "SymCleanup failed: %lu\n", GetLastError()); + for (ptr = test->test_files; *ptr; ptr++) + { + unsigned val = char2index(*ptr); + if (val < ARRAY_SIZE(test_files)) + { + make_path(filename, topdir, NULL, test_files[val].module_path); + ret = DeleteFileW(filename); + ok(ret, "Couldn't delete file %c %ls\n", *ptr, filename); + } + else ok(0, "Unrecognized file reference %c\n", *ptr); + } + temp_bail_out: + if (test->in_image_name && !wcscmp(test->in_image_name, L"bar.dll")) + { + make_path(filename, topdir, NULL, test->in_image_name); + ret = DeleteFileW(filename); + ok(ret, "Couldn't delete file %c %ls\n", *ptr, filename); + } + + winetest_pop_context(); + } + SymSetOptions(old_options); + for (i = 0; i < ARRAY_SIZE(blob_refs); i++) free(blob_refs[i]); + ret = RemoveDirectoryW(topdir); + ok(ret, "Couldn't remove directory\n"); +} + static BOOL skip_too_old_dbghelp(void) { IMAGEHLP_MODULEW64 im64 = {sizeof(im64)}; @@ -1663,5 +1954,6 @@ START_TEST(path) else { test_load_modules_path(); + test_load_modules_details(); } }
From: Eric Pouech epouech@codeweavers.com
This will help separate debug info files lookup from their actual loading once found and correctly matched.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 1 - dlls/dbghelp/msc.c | 28 -------------- dlls/dbghelp/path.c | 68 ++++------------------------------ dlls/dbghelp/tests/path.c | 3 +- 4 files changed, 9 insertions(+), 91 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 4f14433c7c4..382d2d1ce5e 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -759,7 +759,6 @@ extern BOOL pe_load_debug_directory(const struct process* pcs, const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg); extern DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* dbgdir, DWORD size, SYMSRV_INDEX_INFOW* info); -extern BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched); struct pdb_cmd_pair { const char* name; DWORD* pvalue; diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 12ed93380b6..b495d4c24f2 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3996,34 +3996,6 @@ static BOOL pdb_process_file(const struct process* pcs, return ret; }
-BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched) -{ - HANDLE hFile, hMap = NULL; - char* image = NULL; - BOOL ret; - struct pdb_file_info pdb_file; - - if ((hFile = CreateFileA(pdb_lookup->filename, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE || - ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) || - ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL)) - { - WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename); - ret = FALSE; - } - else - { - ret = pdb_init(pdb_lookup, &pdb_file, image, matched); - pdb_free_file(&pdb_file); - } - - if (image) UnmapViewOfFile(image); - if (hMap) CloseHandle(hMap); - if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); - - return ret; -} - /*======================================================================== * FPO unwinding code */ diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index f45807c634f..dd2587db99e 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -477,67 +477,15 @@ struct module_find static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) { struct module_find* mf = user; - DWORD timestamp; unsigned matched = 0; + SYMSRV_INDEX_INFOW info;
- /* the matching weights: - * +1 if a file with same name is found and is a decent file of expected type - * +1 if first parameter and second parameter match - */ - - if (mf->is_pdb) - { - struct pdb_lookup pdb_lookup; - char fn[MAX_PATH]; - - WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); - pdb_lookup.filename = fn; - - if (mf->guid) - { - pdb_lookup.kind = PDB_DS; - pdb_lookup.timestamp = 0; - pdb_lookup.guid = *mf->guid; - } - else - { - pdb_lookup.kind = PDB_JG; - pdb_lookup.timestamp = mf->dw1; - /* pdb_loopkup.guid = */ - } - pdb_lookup.age = mf->dw2; - - if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; - } - else - { - HANDLE hFile, hMap; - void* mapping; - - timestamp = ~mf->dw1; - hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return FALSE; - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) - { - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) - { - const IMAGE_SEPARATE_DEBUG_HEADER* hdr; - hdr = mapping; - - if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) - { - matched++; - timestamp = hdr->TimeDateStamp; - } - UnmapViewOfFile(mapping); - } - CloseHandle(hMap); - } - CloseHandle(hFile); - if (timestamp == mf->dw1) matched++; - else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); - } + info.sizeofstruct = sizeof(info); + if (!SymSrvGetFileIndexInfoW(buffer, &info, 0)) + return FALSE; + if (!memcmp(&info.guid, mf->guid, sizeof(GUID))) matched++; + if (info.timestamp == mf->dw1) matched++; + if (info.age == mf->dw2) matched++;
if (matched > mf->matched) { @@ -547,7 +495,7 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite * convention to stop/continue enumeration. sigh. */ - return mf->matched == 2; + return mf->matched == 3; }
BOOL path_find_symbol_file(const struct process* pcs, const struct module* module, diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 92b2bd21c94..1a7ea1faa18 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -1592,7 +1592,7 @@ static void test_load_modules_path(void) todo_wine ok(im.PdbAge == test_files[test->found_file].age_or_timestamp, "Expected %lx as pdb-age, got %lx instead\n", test_files[test->found_file].age_or_timestamp, im.PdbAge); - todo_wine_if(i == 11 || i == 16 || i == 17) + todo_wine_if(i == 11) ok(im.PdbUnmatched == !(test_files[test->found_file].age_or_timestamp == 0x0030cafe), "Expecting matched PDB\n"); } todo_wine @@ -1813,7 +1813,6 @@ static void test_load_modules_details(void) "Unexpected loaded image name '%ls' (%ls)\n", im.LoadedImageName, loaded_img_name); todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8 || i == 10 || i == 12 || i == 14) ok(im.SymType == test->sym_type, "Unexpected module type %u\n", im.SymType); - todo_wine_if(i == 8) ok(!im.TypeInfo, "No type info present\n"); if (test->mismatch_in) {
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index b495d4c24f2..ead0aec41d0 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3141,21 +3141,22 @@ static void pdb_free_file(struct pdb_file_info* pdb_file) HeapFree(GetProcessHeap(), 0, pdb_file->stream_dict); }
-static BOOL pdb_load_stream_name_table(struct pdb_file_info* pdb_file, const char* str, unsigned cb) +static struct pdb_stream_name* pdb_load_stream_name_table(const char* str, unsigned cb) { - DWORD* pdw; - DWORD* ok_bits; - DWORD count, numok; - unsigned i, j; - char* cpstr; + struct pdb_stream_name* stream_dict; + DWORD* pdw; + DWORD* ok_bits; + DWORD count, numok; + unsigned i, j; + char* cpstr;
pdw = (DWORD*)(str + cb); numok = *pdw++; count = *pdw++;
- pdb_file->stream_dict = HeapAlloc(GetProcessHeap(), 0, (numok + 1) * sizeof(struct pdb_stream_name) + cb); - if (!pdb_file->stream_dict) return FALSE; - cpstr = (char*)(pdb_file->stream_dict + numok + 1); + stream_dict = HeapAlloc(GetProcessHeap(), 0, (numok + 1) * sizeof(struct pdb_stream_name) + cb); + if (!stream_dict) return NULL; + cpstr = (char*)(stream_dict + numok + 1); memcpy(cpstr, str, cb);
/* bitfield: first dword is len (in dword), then data */ @@ -3168,15 +3169,14 @@ static BOOL pdb_load_stream_name_table(struct pdb_file_info* pdb_file, const cha if (ok_bits[i / 32] & (1 << (i % 32))) { if (j >= numok) break; - pdb_file->stream_dict[j].name = &cpstr[*pdw++]; - pdb_file->stream_dict[j].index = *pdw++; + stream_dict[j].name = &cpstr[*pdw++]; + stream_dict[j].index = *pdw++; j++; } } /* add sentinel */ - pdb_file->stream_dict[numok].name = NULL; - pdb_file->fpoext_stream = -1; - return TRUE; + stream_dict[numok].name = NULL; + return stream_dict; }
static unsigned pdb_get_stream_by_name(const struct pdb_file_info* pdb_file, const char* name) @@ -3494,8 +3494,6 @@ static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0"; static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_file, const char* image, unsigned* matched) { - BOOL ret = TRUE; - /* check the file header, and if ok, load the TOC */ TRACE("PDB(%s): %.40s\n", pdb_lookup->filename, debugstr_an(image, 40));
@@ -3539,7 +3537,8 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_lookup->filename, root->Age, pdb_lookup->age); TRACE("found JG for %s: age=%x timestamp=%x\n", pdb_lookup->filename, root->Age, root->TimeDateStamp); - ret = pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames); + pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); + pdb_file->fpoext_stream = -1; pdb_free(root); } else if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT))) @@ -3575,7 +3574,8 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_lookup->filename, root->Age, pdb_lookup->age); TRACE("found DS for %s: age=%x guid=%s\n", pdb_lookup->filename, root->Age, debugstr_guid(&root->guid)); - ret = pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames); + pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); + pdb_file->fpoext_stream = -1;
pdb_free(root); } @@ -3599,7 +3599,7 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_free(x); } } - return ret; + return pdb_file->stream_dict != NULL; }
static BOOL pdb_process_internal(const struct process* pcs,
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 11 --- dlls/dbghelp/msc.c | 141 ++++++++++----------------------- dlls/dbghelp/tests/path.c | 7 +- 3 files changed, 45 insertions(+), 114 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 382d2d1ce5e..99fe4c64a1f 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -548,17 +548,6 @@ struct module_pair struct module* effective; /* out: module with debug info */ };
-enum pdb_kind {PDB_JG, PDB_DS}; - -struct pdb_lookup -{ - const char* filename; - enum pdb_kind kind; - unsigned int age; - unsigned int timestamp; - GUID guid; -}; - struct cpu_stack_walk { HANDLE hProcess; diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index ead0aec41d0..38ca0e59391 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -55,6 +55,8 @@ struct pdb_stream_name unsigned index; };
+enum pdb_kind {PDB_JG, PDB_DS}; + struct pdb_file_info { enum pdb_kind kind; @@ -3305,27 +3307,18 @@ static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols, }
static HANDLE map_pdb_file(const struct process* pcs, - const struct pdb_lookup* lookup, + const char *filename, const GUID *guid, DWORD timestamp, DWORD age, struct module* module) { HANDLE hFile, hMap = NULL; WCHAR dbg_file_path[MAX_PATH]; BOOL ret = FALSE;
- switch (lookup->kind) - { - case PDB_JG: - ret = path_find_symbol_file(pcs, module, lookup->filename, TRUE, NULL, lookup->timestamp, - lookup->age, dbg_file_path, &module->module.PdbUnmatched); - break; - case PDB_DS: - ret = path_find_symbol_file(pcs, module, lookup->filename, TRUE, &lookup->guid, 0, - lookup->age, dbg_file_path, &module->module.PdbUnmatched); - break; - } + ret = path_find_symbol_file(pcs, module, filename, TRUE, guid, timestamp, age, + dbg_file_path, &module->module.PdbUnmatched); if (!ret) { - WARN("\tCouldn't find %s\n", lookup->filename); + WARN("\tCouldn't find %s\n", filename); return NULL; } if ((hFile = CreateFileW(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL, @@ -3491,13 +3484,12 @@ static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0"; * - timestamp or guid depending on kind counts for one * a wrong kind of file returns FALSE (FIXME ?) */ -static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_file, - const char* image, unsigned* matched) +static BOOL pdb_init(struct pdb_file_info* pdb_file, + const char* image) { /* check the file header, and if ok, load the TOC */ - TRACE("PDB(%s): %.40s\n", pdb_lookup->filename, debugstr_an(image, 40)); + TRACE("PDB: %.40s\n", debugstr_an(image, 40));
- *matched = 0; if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT))) { const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image; @@ -3507,7 +3499,7 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* root = pdb_read_jg_stream(pdb, pdb_file->u.jg.toc, 1); if (!root) { - ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename); + ERR("-Unable to get root from .PDB\n"); return FALSE; } switch (root->Version) @@ -3520,23 +3512,10 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* default: ERR("-Unknown root block version %d\n", root->Version); } - if (pdb_lookup->kind != PDB_JG) - { - WARN("Found %s, but wrong PDB kind\n", pdb_lookup->filename); - pdb_free(root); - return FALSE; - } pdb_file->kind = PDB_JG; pdb_file->u.jg.timestamp = root->TimeDateStamp; pdb_file->age = root->Age; - if (root->TimeDateStamp == pdb_lookup->timestamp) (*matched)++; - else WARN("Found %s, but wrong signature: %08x %08x\n", - pdb_lookup->filename, root->TimeDateStamp, pdb_lookup->timestamp); - if (root->Age == pdb_lookup->age) (*matched)++; - else WARN("Found %s, but wrong age: %08x %08x\n", - pdb_lookup->filename, root->Age, pdb_lookup->age); - TRACE("found JG for %s: age=%x timestamp=%x\n", - pdb_lookup->filename, root->Age, root->TimeDateStamp); + TRACE("found JG: age=%x timestamp=%x\n", root->Age, root->TimeDateStamp); pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); pdb_file->fpoext_stream = -1; pdb_free(root); @@ -3552,7 +3531,7 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* root = pdb_read_ds_stream(pdb, pdb_file->u.ds.toc, 1); if (!root) { - ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename); + ERR("-Unable to get root from .PDB\n"); return FALSE; } switch (root->Version) @@ -3565,15 +3544,7 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_file->kind = PDB_DS; pdb_file->u.ds.guid = root->guid; pdb_file->age = root->Age; - if (!memcmp(&root->guid, &pdb_lookup->guid, sizeof(GUID))) (*matched)++; - else WARN("Found %s, but wrong GUID: %s %s\n", - pdb_lookup->filename, debugstr_guid(&root->guid), - debugstr_guid(&pdb_lookup->guid)); - if (root->Age == pdb_lookup->age) (*matched)++; - else WARN("Found %s, but wrong age: %08x %08x\n", - pdb_lookup->filename, root->Age, pdb_lookup->age); - TRACE("found DS for %s: age=%x guid=%s\n", - pdb_lookup->filename, root->Age, debugstr_guid(&root->guid)); + TRACE("found DS: age=%x guid=%s\n", root->Age, debugstr_guid(&root->guid)); pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); pdb_file->fpoext_stream = -1;
@@ -3602,9 +3573,9 @@ static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* return pdb_file->stream_dict != NULL; }
-static BOOL pdb_process_internal(const struct process* pcs, +static BOOL pdb_process_internal(const struct process *pcs, const struct msc_debug_info* msc_dbg, - const struct pdb_lookup* pdb_lookup, + const char *filename, const GUID *guid, DWORD timestamp, DWORD age, struct pdb_module_info* pdb_module_info, unsigned module_index);
@@ -3717,13 +3688,12 @@ DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) 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, - const void* symbols_image, - const char* image, - const struct pdb_lookup* pdb_lookup, - struct pdb_module_info* pdb_module_info, +static void pdb_process_symbol_imports(const struct process *pcs, + const struct msc_debug_info *msc_dbg, + const PDB_SYMBOLS *symbols, + const void *symbols_image, + const char *image, + struct pdb_module_info *pdb_module_info, unsigned module_index) { if (module_index == -1 && symbols && symbols->pdbimport_size) @@ -3733,7 +3703,6 @@ static void pdb_process_symbol_imports(const struct process* pcs, const void* last; const char* ptr; int i = 0; - struct pdb_file_info sf0 = pdb_module_info->pdb_files[0];
imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) + symbols->module_size + symbols->sectcontrib_size + @@ -3744,27 +3713,9 @@ static void pdb_process_symbol_imports(const struct process* pcs, { ptr = (const char*)imp + sizeof(*imp) + strlen(imp->filename); if (i >= CV_MAX_MODULES) FIXME("Out of bounds!!!\n"); - if (!stricmp(pdb_lookup->filename, imp->filename)) - { - if (module_index != -1) FIXME("Twice the entry\n"); - else module_index = i; - pdb_module_info->pdb_files[i] = sf0; - } - else - { - struct pdb_lookup imp_pdb_lookup; - - /* FIXME: this is an import of a JG PDB file - * how's a DS PDB handled ? - */ - imp_pdb_lookup.filename = imp->filename; - imp_pdb_lookup.kind = PDB_JG; - imp_pdb_lookup.timestamp = imp->TimeDateStamp; - imp_pdb_lookup.age = imp->Age; - TRACE("got for %s: age=%u ts=%x\n", - imp->filename, imp->Age, imp->TimeDateStamp); - pdb_process_internal(pcs, msc_dbg, &imp_pdb_lookup, pdb_module_info, i); - } + TRACE("got for %s: age=%u ts=%x\n", + imp->filename, imp->Age, imp->TimeDateStamp); + pdb_process_internal(pcs, msc_dbg, imp->filename, NULL, imp->TimeDateStamp, imp->Age, pdb_module_info, i); i++; imp = (const PDB_SYMBOL_IMPORT*)((const char*)first + ((ptr - (const char*)first + strlen(ptr) + 1 + 3) & ~3)); } @@ -3780,31 +3731,30 @@ static void pdb_process_symbol_imports(const struct process* pcs, cv_current_module->allowed = TRUE; }
-static BOOL pdb_process_internal(const struct process* pcs, - const struct msc_debug_info* msc_dbg, - const struct pdb_lookup* pdb_lookup, - struct pdb_module_info* pdb_module_info, +static BOOL pdb_process_internal(const struct process *pcs, + const struct msc_debug_info *msc_dbg, + const char *filename, const GUID *guid, DWORD timestamp, DWORD age, + struct pdb_module_info *pdb_module_info, unsigned module_index) { HANDLE hMap = NULL; char* image = NULL; BYTE* symbols_image = NULL; PDB_STRING_TABLE* files_image = NULL; - unsigned matched; struct pdb_file_info* pdb_file;
- TRACE("Processing PDB file %s\n", pdb_lookup->filename); + TRACE("Processing PDB file %s\n", filename);
pdb_file = &pdb_module_info->pdb_files[module_index == -1 ? 0 : module_index]; /* Open and map() .PDB file */ - if ((hMap = map_pdb_file(pcs, pdb_lookup, msc_dbg->module)) == NULL || + if ((hMap = map_pdb_file(pcs, filename, guid, timestamp, age, msc_dbg->module)) == NULL || ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL)) { - WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename); + WARN("Unable to open .PDB file: %s\n", filename); CloseHandle(hMap); return FALSE; } - if (!pdb_init(pdb_lookup, pdb_file, image, &matched) || matched != 2) + if (!pdb_init(pdb_file, image)) { CloseHandle(hMap); UnmapViewOfFile(image); @@ -3851,7 +3801,7 @@ static BOOL pdb_process_internal(const struct process* pcs, files_image = pdb_read_strings(pdb_file);
pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image, - pdb_lookup, pdb_module_info, module_index); + pdb_module_info, module_index); pdb_process_types(msc_dbg, pdb_file);
ipi_image = pdb_read_stream(pdb_file, 4); @@ -3937,7 +3887,7 @@ static BOOL pdb_process_internal(const struct process* pcs, } else pdb_process_symbol_imports(pcs, msc_dbg, NULL, NULL, image, - pdb_lookup, pdb_module_info, module_index); + pdb_module_info, module_index);
pdb_free(symbols_image); pdb_free(files_image); @@ -3945,9 +3895,9 @@ static BOOL pdb_process_internal(const struct process* pcs, return TRUE; }
-static BOOL pdb_process_file(const struct process* pcs, - const struct msc_debug_info* msc_dbg, - struct pdb_lookup* pdb_lookup) +static BOOL pdb_process_file(const struct process *pcs, + const struct msc_debug_info *msc_dbg, + const char *filename, const GUID *guid, DWORD timestamp, DWORD age) { BOOL ret; struct module_format* modfmt; @@ -3966,7 +3916,7 @@ static BOOL pdb_process_file(const struct process* pcs,
memset(cv_zmodules, 0, sizeof(cv_zmodules)); codeview_init_basic_types(msc_dbg->module); - ret = pdb_process_internal(pcs, msc_dbg, pdb_lookup, + ret = pdb_process_internal(pcs, msc_dbg, filename, guid, timestamp, age, msc_dbg->module->format_info[DFI_PDB]->u.pdb_info, -1); codeview_clear_type_table(); if (ret) @@ -3978,7 +3928,7 @@ static BOOL pdb_process_file(const struct process* pcs, else msc_dbg->module->module.PdbSig70 = pdb_info->pdb_files[0].u.ds.guid; msc_dbg->module->module.PdbAge = pdb_info->pdb_files[0].age; - MultiByteToWideChar(CP_ACP, 0, pdb_lookup->filename, -1, + MultiByteToWideChar(CP_ACP, 0, filename, -1, msc_dbg->module->module.LoadedPdbName, ARRAY_SIZE(msc_dbg->module->module.LoadedPdbName)); /* FIXME: we could have a finer grain here */ @@ -4317,7 +4267,6 @@ static BOOL codeview_process_info(const struct process* pcs, { const DWORD* signature = (const DWORD*)msc_dbg->root; BOOL ret = FALSE; - struct pdb_lookup pdb_lookup;
TRACE("Processing signature %.4s\n", (const char*)signature);
@@ -4405,11 +4354,7 @@ static BOOL codeview_process_info(const struct process* pcs, case CODEVIEW_NB10_SIG: { const CODEVIEW_PDB_DATA* pdb = (const CODEVIEW_PDB_DATA*)msc_dbg->root; - pdb_lookup.filename = pdb->name; - pdb_lookup.kind = PDB_JG; - pdb_lookup.timestamp = pdb->timestamp; - pdb_lookup.age = pdb->age; - ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup); + ret = pdb_process_file(pcs, msc_dbg, pdb->name, NULL, pdb->timestamp, pdb->age); break; } case CODEVIEW_RSDS_SIG: @@ -4418,11 +4363,7 @@ static BOOL codeview_process_info(const struct process* pcs,
TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n", wine_dbgstr_guid(&rsds->guid), rsds->age, rsds->name); - pdb_lookup.filename = rsds->name; - pdb_lookup.kind = PDB_DS; - pdb_lookup.guid = rsds->guid; - pdb_lookup.age = rsds->age; - ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup); + ret = pdb_process_file(pcs, msc_dbg, rsds->name, &rsds->guid, 0, rsds->age); break; } default: diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 1a7ea1faa18..01902696a75 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -1583,7 +1583,7 @@ static void test_load_modules_path(void) } else { - todo_wine + todo_wine_if(i == 4 || i == 5 || i == 7 || i == 8 || i == 11) ok(im.SymType == SymPdb, "Unexpected symtype %x\n", im.SymType); make_path(filename, topdir, NULL, test_files[test->found_file].module_path); todo_wine @@ -1595,7 +1595,7 @@ static void test_load_modules_path(void) todo_wine_if(i == 11) ok(im.PdbUnmatched == !(test_files[test->found_file].age_or_timestamp == 0x0030cafe), "Expecting matched PDB\n"); } - todo_wine + todo_wine_if(i == 4 || i == 5 || i == 7 || i == 8 || i == 9 || i == 10 || i == 11 || i == 13 || i == 18 || i == 19) ok(IsEqualGUID(&im.PdbSig70, &guid1), "Unexpected PDB GUID\n"); ret = SymCleanup(dummy); ok(ret, "SymCleanup failed: %lu\n", GetLastError()); @@ -1811,8 +1811,9 @@ static void test_load_modules_details(void) todo_wine_if(test->options & SYMOPT_DEFERRED_LOADS) ok(!wcsicmp(im.LoadedImageName, (test->options & SYMOPT_DEFERRED_LOADS) ? L"" : loaded_img_name), "Unexpected loaded image name '%ls' (%ls)\n", im.LoadedImageName, loaded_img_name); - todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8 || i == 10 || i == 12 || i == 14) + todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8 || i == 12 || i == 14) ok(im.SymType == test->sym_type, "Unexpected module type %u\n", im.SymType); + todo_wine_if(i == 8 || i == 10) ok(!im.TypeInfo, "No type info present\n"); if (test->mismatch_in) {
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 4 +- dlls/dbghelp/msc.c | 179 ++++++++++++++++----------------- dlls/dbghelp/path.c | 60 ++++++----- dlls/dbghelp/pe_module.c | 8 +- dlls/dbghelp/tests/path.c | 14 +-- 5 files changed, 132 insertions(+), 133 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 99fe4c64a1f..b3a073ff41f 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -758,9 +758,9 @@ extern DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* extern DWORD dbg_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, +extern BOOL path_find_symbol_file(const struct process *pcs, const struct module *module, PCSTR full_path, BOOL is_pdb, const GUID* guid, DWORD dw1, DWORD dw2, - WCHAR *buffer, BOOL* is_unmatched); + SYMSRV_INDEX_INFOW *info, BOOL *unmatched); extern WCHAR *get_dos_file_name(const WCHAR *filename) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC; extern BOOL search_dll_path(const struct process* process, const WCHAR *name, WORD machine, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param); diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 38ca0e59391..4d310cd0f21 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -60,7 +60,6 @@ enum pdb_kind {PDB_JG, PDB_DS}; struct pdb_file_info { enum pdb_kind kind; - DWORD age; HANDLE hMap; const char* image; struct pdb_stream_name* stream_dict; @@ -69,12 +68,10 @@ struct pdb_file_info { struct { - DWORD timestamp; struct PDB_JG_TOC* toc; } jg; struct { - GUID guid; struct PDB_DS_TOC* toc; } ds; } u; @@ -3306,30 +3303,6 @@ static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols, } }
-static HANDLE map_pdb_file(const struct process* pcs, - const char *filename, const GUID *guid, DWORD timestamp, DWORD age, - struct module* module) -{ - HANDLE hFile, hMap = NULL; - WCHAR dbg_file_path[MAX_PATH]; - BOOL ret = FALSE; - - ret = path_find_symbol_file(pcs, module, filename, TRUE, guid, timestamp, age, - dbg_file_path, &module->module.PdbUnmatched); - if (!ret) - { - WARN("\tCouldn't find %s\n", filename); - return NULL; - } - if ((hFile = CreateFileW(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) - { - hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - } - return hMap; -} - static void pdb_dispose_type_parse(struct codeview_type_parse* ctp) { pdb_free(ctp->hash_stream); @@ -3479,13 +3452,8 @@ static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0"; * pdb_init * * Tries to load a pdb file - * 'matched' is filled with the number of correct matches for this file: - * - age counts for one - * - timestamp or guid depending on kind counts for one - * a wrong kind of file returns FALSE (FIXME ?) */ -static BOOL pdb_init(struct pdb_file_info* pdb_file, - const char* image) +static BOOL pdb_init(struct pdb_file_info* pdb_file, const char* image) { /* check the file header, and if ok, load the TOC */ TRACE("PDB: %.40s\n", debugstr_an(image, 40)); @@ -3494,12 +3462,19 @@ static BOOL pdb_init(struct pdb_file_info* pdb_file, { const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image; struct PDB_JG_ROOT* root; + struct PDB_JG_TOC* jg_toc;
- pdb_file->u.jg.toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size); - root = pdb_read_jg_stream(pdb, pdb_file->u.jg.toc, 1); + jg_toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size); + if (!jg_toc) + { + ERR("-Unable to get TOC from .PDB\n"); + return FALSE; + } + root = pdb_read_jg_stream(pdb, jg_toc, 1); if (!root) { ERR("-Unable to get root from .PDB\n"); + pdb_free(jg_toc); return FALSE; } switch (root->Version) @@ -3513,25 +3488,31 @@ static BOOL pdb_init(struct pdb_file_info* pdb_file, ERR("-Unknown root block version %d\n", root->Version); } pdb_file->kind = PDB_JG; - pdb_file->u.jg.timestamp = root->TimeDateStamp; - pdb_file->age = root->Age; + pdb_file->u.jg.toc = jg_toc; TRACE("found JG: age=%x timestamp=%x\n", root->Age, root->TimeDateStamp); pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); pdb_file->fpoext_stream = -1; + pdb_free(root); } else 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_ROOT* root; + struct PDB_DS_TOC* ds_toc;
- pdb_file->u.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, pdb_file->u.ds.toc, 1); + ds_toc = pdb_ds_read(pdb, (const UINT*)((const char*)pdb + pdb->toc_block * pdb->block_size), + pdb->toc_size); + if (!ds_toc) + { + ERR("-Unable to get TOC from .PDB\n"); + return FALSE; + } + root = pdb_read_ds_stream(pdb, ds_toc, 1); if (!root) { ERR("-Unable to get root from .PDB\n"); + pdb_free(ds_toc); return FALSE; } switch (root->Version) @@ -3542,9 +3523,8 @@ static BOOL pdb_init(struct pdb_file_info* pdb_file, ERR("-Unknown root block version %u\n", root->Version); } pdb_file->kind = PDB_DS; - pdb_file->u.ds.guid = root->guid; - pdb_file->age = root->Age; - TRACE("found DS: age=%x guid=%s\n", root->Age, debugstr_guid(&root->guid)); + pdb_file->u.ds.toc = ds_toc; + TRACE("found DS for: age=%x guid=%s\n", root->Age, debugstr_guid(&root->guid)); pdb_file->stream_dict = pdb_load_stream_name_table(&root->names[0], root->cbNames); pdb_file->fpoext_stream = -1;
@@ -3574,9 +3554,9 @@ static BOOL pdb_init(struct pdb_file_info* pdb_file, }
static BOOL pdb_process_internal(const struct process *pcs, - const struct msc_debug_info* msc_dbg, - const char *filename, const GUID *guid, DWORD timestamp, DWORD age, - struct pdb_module_info* pdb_module_info, + const struct msc_debug_info *msc_dbg, + const WCHAR *filename, + struct pdb_module_info *pdb_module_info, unsigned module_index);
DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) @@ -3711,11 +3691,15 @@ static void pdb_process_symbol_imports(const struct process *pcs, last = (const char*)imp + symbols->pdbimport_size; while (imp < (const PDB_SYMBOL_IMPORT*)last) { + SYMSRV_INDEX_INFOW info; + ptr = (const char*)imp + sizeof(*imp) + strlen(imp->filename); if (i >= CV_MAX_MODULES) FIXME("Out of bounds!!!\n"); TRACE("got for %s: age=%u ts=%x\n", imp->filename, imp->Age, imp->TimeDateStamp); - pdb_process_internal(pcs, msc_dbg, imp->filename, NULL, imp->TimeDateStamp, imp->Age, pdb_module_info, i); + if (path_find_symbol_file(pcs, msc_dbg->module, imp->filename, TRUE, NULL, imp->TimeDateStamp, imp->Age, &info, + &msc_dbg->module->module.PdbUnmatched)) + pdb_process_internal(pcs, msc_dbg, info.pdbfile, pdb_module_info, i); i++; imp = (const PDB_SYMBOL_IMPORT*)((const char*)first + ((ptr - (const char*)first + strlen(ptr) + 1 + 3) & ~3)); } @@ -3733,27 +3717,31 @@ static void pdb_process_symbol_imports(const struct process *pcs,
static BOOL pdb_process_internal(const struct process *pcs, const struct msc_debug_info *msc_dbg, - const char *filename, const GUID *guid, DWORD timestamp, DWORD age, + const WCHAR *filename, struct pdb_module_info *pdb_module_info, unsigned module_index) { - HANDLE hMap = NULL; + HANDLE hFile = NULL, hMap = NULL; char* image = NULL; BYTE* symbols_image = NULL; PDB_STRING_TABLE* files_image = NULL; struct pdb_file_info* pdb_file;
- TRACE("Processing PDB file %s\n", filename); + TRACE("Processing PDB file %ls\n", filename);
pdb_file = &pdb_module_info->pdb_files[module_index == -1 ? 0 : module_index]; /* Open and map() .PDB file */ - if ((hMap = map_pdb_file(pcs, filename, guid, timestamp, age, msc_dbg->module)) == NULL || - ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL)) + if ((hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE || + (hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL || + (image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL) { - WARN("Unable to open .PDB file: %s\n", filename); + WARN("Unable to open .PDB file: %ls\n", filename); CloseHandle(hMap); + CloseHandle(hFile); return FALSE; } + CloseHandle(hFile); if (!pdb_init(pdb_file, image)) { CloseHandle(hMap); @@ -3902,48 +3890,53 @@ static BOOL pdb_process_file(const struct process *pcs, BOOL ret; struct module_format* modfmt; struct pdb_module_info* pdb_module_info; + SYMSRV_INDEX_INFOW info; + BOOL unmatched;
- modfmt = HeapAlloc(GetProcessHeap(), 0, - sizeof(struct module_format) + sizeof(struct pdb_module_info)); - if (!modfmt) return FALSE; - - pdb_module_info = (void*)(modfmt + 1); - msc_dbg->module->format_info[DFI_PDB] = modfmt; - modfmt->module = msc_dbg->module; - modfmt->remove = pdb_module_remove; - modfmt->loc_compute = pdb_location_compute; - modfmt->u.pdb_info = pdb_module_info; - - memset(cv_zmodules, 0, sizeof(cv_zmodules)); - codeview_init_basic_types(msc_dbg->module); - ret = pdb_process_internal(pcs, msc_dbg, filename, guid, timestamp, age, - msc_dbg->module->format_info[DFI_PDB]->u.pdb_info, -1); - codeview_clear_type_table(); - if (ret) - { - struct pdb_module_info* pdb_info = msc_dbg->module->format_info[DFI_PDB]->u.pdb_info; - msc_dbg->module->module.SymType = SymPdb; - if (pdb_info->pdb_files[0].kind == PDB_JG) - msc_dbg->module->module.PdbSig = pdb_info->pdb_files[0].u.jg.timestamp; - else - msc_dbg->module->module.PdbSig70 = pdb_info->pdb_files[0].u.ds.guid; - msc_dbg->module->module.PdbAge = pdb_info->pdb_files[0].age; - MultiByteToWideChar(CP_ACP, 0, filename, -1, - msc_dbg->module->module.LoadedPdbName, - ARRAY_SIZE(msc_dbg->module->module.LoadedPdbName)); - /* FIXME: we could have a finer grain here */ - msc_dbg->module->module.LineNumbers = TRUE; - msc_dbg->module->module.GlobalSymbols = TRUE; - msc_dbg->module->module.TypeInfo = TRUE; - msc_dbg->module->module.SourceIndexed = TRUE; - msc_dbg->module->module.Publics = TRUE; - } - else + if (path_find_symbol_file(pcs, msc_dbg->module, filename, TRUE, guid, timestamp, age, &info, &unmatched) && + (modfmt = HeapAlloc(GetProcessHeap(), 0, + sizeof(struct module_format) + sizeof(struct pdb_module_info)))) { + pdb_module_info = (void*)(modfmt + 1); + msc_dbg->module->format_info[DFI_PDB] = modfmt; + modfmt->module = msc_dbg->module; + modfmt->remove = pdb_module_remove; + modfmt->loc_compute = pdb_location_compute; + modfmt->u.pdb_info = pdb_module_info; + + memset(cv_zmodules, 0, sizeof(cv_zmodules)); + codeview_init_basic_types(msc_dbg->module); + ret = pdb_process_internal(pcs, msc_dbg, info.pdbfile, + msc_dbg->module->format_info[DFI_PDB]->u.pdb_info, -1); + codeview_clear_type_table(); + if (ret) + { + msc_dbg->module->module.SymType = SymPdb; + msc_dbg->module->module.PdbSig = info.sig; + msc_dbg->module->module.PdbAge = info.age; + msc_dbg->module->module.PdbSig70 = info.guid; + msc_dbg->module->module.PdbUnmatched = unmatched; + wcscpy(msc_dbg->module->module.LoadedPdbName, info.pdbfile); + + /* FIXME: we could have a finer grain here */ + msc_dbg->module->module.LineNumbers = TRUE; + msc_dbg->module->module.GlobalSymbols = TRUE; + msc_dbg->module->module.TypeInfo = TRUE; + msc_dbg->module->module.SourceIndexed = TRUE; + msc_dbg->module->module.Publics = TRUE; + return TRUE; + } msc_dbg->module->format_info[DFI_PDB] = NULL; HeapFree(GetProcessHeap(), 0, modfmt); } - return ret; + msc_dbg->module->module.SymType = SymNone; + if (guid) + msc_dbg->module->module.PdbSig70 = *guid; + else + memset(&msc_dbg->module->module.PdbSig70, 0, sizeof(GUID)); + msc_dbg->module->module.PdbSig = timestamp; + msc_dbg->module->module.PdbAge = age; + return FALSE; }
/*======================================================================== @@ -4262,8 +4255,8 @@ BOOL pdb_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, #define CODEVIEW_NB11_SIG MAKESIG('N','B','1','1') #define CODEVIEW_RSDS_SIG MAKESIG('R','S','D','S')
-static BOOL codeview_process_info(const struct process* pcs, - const struct msc_debug_info* msc_dbg) +static BOOL codeview_process_info(const struct process *pcs, + const struct msc_debug_info *msc_dbg) { const DWORD* signature = (const DWORD*)msc_dbg->root; BOOL ret = FALSE; diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index dd2587db99e..0565442bb8b 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -455,7 +455,7 @@ BOOL WINAPI SymFindFileInPath(HANDLE hProcess, PCSTR searchPath, PCSTR full_path
struct module_find { - BOOL is_pdb; + BOOL is_pdb; /* pdb: guid PDB guid (if DS PDB file) * or dw1 PDB timestamp (if JG PDB file) * dw2 PDB age @@ -465,7 +465,8 @@ struct module_find const GUID* guid; DWORD dw1; DWORD dw2; - WCHAR filename[MAX_PATH]; + SYMSRV_INDEX_INFOW *info; + WCHAR *buffer; /* MAX_PATH + 1 */ unsigned matched; };
@@ -483,48 +484,56 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) info.sizeofstruct = sizeof(info); if (!SymSrvGetFileIndexInfoW(buffer, &info, 0)) return FALSE; + matched++; if (!memcmp(&info.guid, mf->guid, sizeof(GUID))) matched++; if (info.timestamp == mf->dw1) matched++; if (info.age == mf->dw2) matched++;
if (matched > mf->matched) { - lstrcpyW(mf->filename, buffer); + size_t len = min(wcslen(buffer), MAX_PATH); + memcpy(mf->buffer, buffer, len * sizeof(WCHAR)); + mf->buffer[len] = L'\0'; mf->matched = matched; + mf->info->guid = info.guid; + mf->info->timestamp = info.timestamp; + mf->info->age = info.age; } /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite * convention to stop/continue enumeration. sigh. */ - return mf->matched == 3; + return mf->matched == 4; }
BOOL path_find_symbol_file(const struct process* pcs, const struct module* module, PCSTR full_path, BOOL is_pdb, const GUID* guid, DWORD dw1, DWORD dw2, - WCHAR *buffer, BOOL* is_unmatched) + SYMSRV_INDEX_INFOW *info, BOOL* is_unmatched) { struct module_find mf; - WCHAR full_pathW[MAX_PATH]; - WCHAR* ptr; + WCHAR *ptr; const WCHAR* filename; - WCHAR* searchPath = pcs->search_path; + WCHAR *searchPath = pcs->search_path; + WCHAR buffer[MAX_PATH];
- TRACE("(pcs = %p, full_path = %s, guid = %s, dw1 = 0x%08lx, dw2 = 0x%08lx, buffer = %p)\n", - pcs, debugstr_a(full_path), debugstr_guid(guid), dw1, dw2, buffer); + TRACE("(pcs = %p, full_path = %s, guid = %s, dw1 = 0x%08lx, dw2 = 0x%08lx)\n", + pcs, debugstr_a(full_path), debugstr_guid(guid), dw1, dw2);
+ mf.info = info; mf.guid = guid; mf.dw1 = dw1; mf.dw2 = dw2; mf.matched = 0; + mf.buffer = is_pdb ? info->pdbfile : info->dbgfile;
- MultiByteToWideChar(CP_ACP, 0, full_path, -1, full_pathW, MAX_PATH); - filename = file_name(full_pathW); + MultiByteToWideChar(CP_ACP, 0, full_path, -1, info->file, MAX_PATH); + filename = file_name(info->file); mf.is_pdb = is_pdb; *is_unmatched = FALSE;
/* first check full path to file */ - if (module_find_cb(full_pathW, &mf)) + if (is_pdb && module_find_cb(info->file, &mf)) { - lstrcpyW( buffer, full_pathW ); + wcscpy( info->pdbfile, info->file ); return TRUE; }
@@ -548,28 +557,29 @@ BOOL path_find_symbol_file(const struct process* pcs, const struct module* modul
while (searchPath) { + size_t len; + ptr = wcschr(searchPath, ';'); - if (ptr) + len = (ptr) ? ptr - searchPath : wcslen(searchPath); + + if (len < ARRAY_SIZE(buffer)) { - memcpy(buffer, searchPath, (ptr - searchPath) * sizeof(WCHAR)); - buffer[ptr - searchPath] = '\0'; - searchPath = ptr + 1; + memcpy(buffer, searchPath, len * sizeof(WCHAR)); + buffer[len] = '\0'; + /* return first fully matched file */ + if (do_searchW(filename, buffer, FALSE, module_find_cb, &mf)) return TRUE; } else - { - lstrcpyW(buffer, searchPath); - searchPath = NULL; - } - /* return first fully matched file */ - if (do_searchW(filename, buffer, FALSE, module_find_cb, &mf)) return TRUE; + ERR("Too long search element %ls\n", searchPath); + searchPath = ptr ? ptr + 1 : NULL; } /* if no fully matching file is found, return the best matching file if any */ if ((dbghelp_options & SYMOPT_LOAD_ANYTHING) && mf.matched) { - lstrcpyW( buffer, mf.filename ); *is_unmatched = TRUE; return TRUE; } + mf.buffer[0] = L'\0'; return FALSE; }
diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 06e70c35037..8d713450386 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -542,15 +542,15 @@ static BOOL pe_load_dwarf(struct module* module) static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module, const char* dbg_name, DWORD timestamp) { - WCHAR tmp[MAX_PATH]; HANDLE hFile = INVALID_HANDLE_VALUE, hMap = 0; const BYTE* dbg_mapping = NULL; BOOL ret = FALSE; + SYMSRV_INDEX_INFOW info;
TRACE("Processing DBG file %s\n", debugstr_a(dbg_name));
- if (path_find_symbol_file(pcs, module, dbg_name, FALSE, NULL, timestamp, 0, tmp, &module->module.DbgUnmatched) && - (hFile = CreateFileW(tmp, GENERIC_READ, FILE_SHARE_READ, NULL, + if (path_find_symbol_file(pcs, module, dbg_name, FALSE, NULL, timestamp, 0, &info, &module->module.DbgUnmatched) && + (hFile = CreateFileW(info.dbgfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE && ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) && ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)) @@ -573,7 +573,7 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module, hdr->DebugDirectorySize / sizeof(*dbg)); } else - ERR("Couldn't find .DBG file %s (%s)\n", debugstr_a(dbg_name), debugstr_w(tmp)); + ERR("Couldn't find .DBG file %s (%s)\n", debugstr_a(dbg_name), debugstr_w(info.dbgfile));
if (dbg_mapping) UnmapViewOfFile(dbg_mapping); if (hMap) CloseHandle(hMap); diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 01902696a75..f45cfd29b58 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -1574,10 +1574,8 @@ static void test_load_modules_path(void) "Expected %ls as loaded image file, got '%ls' instead\n", L"bar.dll", im.LoadedImageName); if (test->found_file == -1) { - todo_wine ok(im.SymType == SymNone, "Unexpected symtype %x\n", im.SymType); ok(!im.LoadedPdbName[0], "Expected empty loaded pdb file, got '%ls' instead\n", im.LoadedPdbName); - todo_wine ok(im.PdbAge == 0x0030cafe, "Expected %x as pdb-age, got %lx instead\n", 0x0030cafe, im.PdbAge); ok(!im.PdbUnmatched, "Expecting matched PDB\n"); } @@ -1586,16 +1584,15 @@ static void test_load_modules_path(void) todo_wine_if(i == 4 || i == 5 || i == 7 || i == 8 || i == 11) ok(im.SymType == SymPdb, "Unexpected symtype %x\n", im.SymType); make_path(filename, topdir, NULL, test_files[test->found_file].module_path); - todo_wine + todo_wine_if(i == 2 || i == 4 || i == 5 || i == 7 || i == 8 || i == 11 || i == 21) ok(!wcscmp(im.LoadedPdbName, filename), "Expected %ls as loaded pdb file, got '%ls' instead\n", test_files[test->found_file].module_path, im.LoadedPdbName); - todo_wine + todo_wine_if(i == 11 || i == 21) ok(im.PdbAge == test_files[test->found_file].age_or_timestamp, "Expected %lx as pdb-age, got %lx instead\n", test_files[test->found_file].age_or_timestamp, im.PdbAge); todo_wine_if(i == 11) ok(im.PdbUnmatched == !(test_files[test->found_file].age_or_timestamp == 0x0030cafe), "Expecting matched PDB\n"); } - todo_wine_if(i == 4 || i == 5 || i == 7 || i == 8 || i == 9 || i == 10 || i == 11 || i == 13 || i == 18 || i == 19) ok(IsEqualGUID(&im.PdbSig70, &guid1), "Unexpected PDB GUID\n"); ret = SymCleanup(dummy); ok(ret, "SymCleanup failed: %lu\n", GetLastError()); @@ -1811,7 +1808,7 @@ static void test_load_modules_details(void) todo_wine_if(test->options & SYMOPT_DEFERRED_LOADS) ok(!wcsicmp(im.LoadedImageName, (test->options & SYMOPT_DEFERRED_LOADS) ? L"" : loaded_img_name), "Unexpected loaded image name '%ls' (%ls)\n", im.LoadedImageName, loaded_img_name); - todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8 || i == 12 || i == 14) + todo_wine_if(i == 3 || i == 4 || i == 6 || i == 8) ok(im.SymType == test->sym_type, "Unexpected module type %u\n", im.SymType); todo_wine_if(i == 8 || i == 10) ok(!im.TypeInfo, "No type info present\n"); @@ -1839,10 +1836,8 @@ static void test_load_modules_details(void) ok(val < ARRAY_SIZE(test_files), "Incorrect index\n"); ok(!im.PdbUnmatched, "Unexpected value\n"); ok(!im.DbgUnmatched, "Unexpected value\n"); - todo_wine ok(IsEqualGUID(&im.PdbSig70, test_files[val].guid), "Unexpected value %s %s\n", wine_dbgstr_guid(&im.PdbSig70), wine_dbgstr_guid(test_files[val].guid)); - todo_wine ok(im.PdbAge == test_files[val].age_or_timestamp + 1, "Unexpected value\n"); } else if (has_mismatch(test->mismatch_in, 'D', &val)) @@ -1874,6 +1869,7 @@ static void test_load_modules_details(void) SymFromNameW(dummy, L"foo", sym); } ret = SymAddSymbol(dummy, base, "winetest_symbol_virtual", base + 4242, 13, 0); + todo_wine_if(i >= 12 && i <= 15) { /* temp */ ok(ret, "Failed to add symbol\n"); memset(sym, 0, sizeof(*sym)); sym->SizeOfStruct = sizeof(*sym); @@ -1888,7 +1884,7 @@ static void test_load_modules_details(void) ret = SymFromNameW(dummy, sym_name, (void*)sym); ok(ret, "Couldn't find symbol %ls\n", sym_name); } - + } /* temp */ ret = SymCleanup(dummy); ok(ret, "SymCleanup failed: %lu\n", GetLastError()); for (ptr = test->test_files; *ptr; ptr++)