This serie mainly tests and implement support for SymSrvGetFileIndexInfo() on a few more file formats. - .dbg: with test and implementation, - .pdb (JG format): This format has been replaced by the DS format for more than 25 years, so I didn't bother writting tests for generating such files (implementation has been tested manually against some existing samples).
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/tests/path.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 756eb862df9..4092fb5b2ab 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -503,7 +503,7 @@ static void pdb_write(HANDLE hfile, struct pdb_file* pdb) SetEndOfFile(hfile); }
-static BOOL create_test_pdb_ds(const char* pdb_name, const GUID* guid, DWORD age) +static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD age) { struct PDB_DS_ROOT root = { @@ -660,8 +660,8 @@ static BOOL create_test_pdb_ds(const char* pdb_name, const GUID* guid, DWORD age
stream = pdb_add_stream(&pdb, &pddt.sections_stream, &ro_section, sizeof(ro_section));
- hfile = CreateFileA(pdb_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); - ok(hfile != INVALID_HANDLE_VALUE, "failed to create %s err %lu\n", pdb_name, GetLastError()); + 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()); if (hfile == INVALID_HANDLE_VALUE) return FALSE;
pdb_write(hfile, &pdb); @@ -803,8 +803,8 @@ static void test_srvgetindexes_pe(void) static void test_srvgetindexes_pdb(void) { unsigned int i; - char filename[128]; - SYMSRV_INDEX_INFO ssii; + WCHAR filename[128]; + SYMSRV_INDEX_INFOW ssii; BOOL ret;
static struct @@ -822,12 +822,12 @@ static void test_srvgetindexes_pdb(void) winetest_push_context("pdb#%02u", i);
/* create dll */ - snprintf(filename, ARRAYSIZE(filename), "winetest%02u.pdb", i); + swprintf(filename, ARRAY_SIZE(filename), L"winetest%02u.pdb", i); create_test_pdb_ds(filename, indexes[i].guid, 240 + i);
memset(&ssii, 0x45, sizeof(ssii)); ssii.sizeofstruct = sizeof(ssii); - ret = SymSrvGetFileIndexInfo(filename, &ssii, 0); + ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0); ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
ok(ssii.age == 240 + i, "Mismatch in age: %lx\n", ssii.age); @@ -839,11 +839,11 @@ static void test_srvgetindexes_pdb(void) ok(ssii.size == 0, "Mismatch in size: %lx\n", ssii.size); ok(!ssii.stripped, "Mismatch in stripped: %x\n", ssii.stripped); ok(ssii.timestamp == 0, "Mismatch in timestamp: %lx\n", ssii.timestamp); - 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); + ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file); + ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %ls\n", ssii.pdbfile); + ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %ls\n", ssii.dbgfile);
- DeleteFileA(filename); + DeleteFileW(filename); winetest_pop_context(); } }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/tests/path.c | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+)
diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 4092fb5b2ab..e1539bad966 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -671,6 +671,34 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag return TRUE; }
+static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD timestamp, DWORD size) +{ + HANDLE hfile; + + /* minimalistic .dbg made of a header and a DEBUG_DIRECTORY without any data */ + const IMAGE_SEPARATE_DEBUG_HEADER header = {.Signature = 0x4944 /* DI */, + .Flags = 0, .Machine = machine, .Characteristics = 0x010E, .TimeDateStamp = timestamp, + .CheckSum = 0, .ImageBase = 0x00040000, .SizeOfImage = size, .NumberOfSections = 0, + .ExportedNamesSize = 0, .DebugDirectorySize = sizeof(IMAGE_DEBUG_DIRECTORY)}; + const IMAGE_DEBUG_DIRECTORY debug_dir = {.Characteristics = 0, .TimeDateStamp = timestamp + 1, + .MajorVersion = 0, .MinorVersion = 0, .Type = IMAGE_DEBUG_TYPE_CODEVIEW, + .SizeOfData = 0, .AddressOfRawData = 0, + .PointerToRawData = sizeof(header) + header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + + header.DebugDirectorySize}; + + hfile = CreateFileW(dbg_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to create %ls err %lu\n", dbg_name, GetLastError()); + if (hfile == INVALID_HANDLE_VALUE) return FALSE; + + check_write_file(hfile, &header, sizeof(header)); + /* FIXME: 0 sections... as header.NumberOfSections */ + check_write_file(hfile, &debug_dir, sizeof(debug_dir)); + ok(SetFilePointer(hfile, 0, NULL, FILE_CURRENT) == debug_dir.PointerToRawData, "mismatch\n"); + + CloseHandle(hfile); + return TRUE; +} + /* ============================================== * the tests * ============================================== @@ -848,6 +876,58 @@ static void test_srvgetindexes_pdb(void) } }
+static void test_srvgetindexes_dbg(void) +{ + unsigned int i; + WCHAR filename[128]; + SYMSRV_INDEX_INFOW ssii; + BOOL ret; + + static struct + { + /* input parameters */ + WORD machine; + DWORD timestamp; + DWORD imagesize; + } + indexes[] = + { + {IMAGE_FILE_MACHINE_I386, 0x1234, 0x00560000}, + {IMAGE_FILE_MACHINE_AMD64, 0x1235, 0x00570000}, + }; + for (i = 0; i < ARRAY_SIZE(indexes); i++) + { + winetest_push_context("dbg#%02u", i); + + /* create dll */ + swprintf(filename, ARRAY_SIZE(filename), L"winetest%02u.dbg", i); + ret = create_test_dbg(filename, indexes[i].machine, indexes[i].timestamp, indexes[i].imagesize); + ok(ret, "Couldn't create dbg file %ls\n", filename); + + memset(&ssii, 0x45, sizeof(ssii)); + ssii.sizeofstruct = sizeof(ssii); + ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0); + todo_wine + ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError()); + + if (ret){ + ok(ssii.age == 0, "Mismatch in age: %lx\n", ssii.age); + ok(!memcmp(&ssii.guid, &null_guid, sizeof(GUID)), + "Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid)); + + ok(ssii.sig == 0, "Mismatch in sig: %lx\n", ssii.sig); + ok(ssii.size == indexes[i].imagesize, "Mismatch in size: %lx\n", ssii.size); + ok(!ssii.stripped, "Mismatch in stripped: %x\n", ssii.stripped); + ok(ssii.timestamp == indexes[i].timestamp, "Mismatch in timestamp: %lx\n", ssii.timestamp); + ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file); + ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %ls\n", ssii.pdbfile); + ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %ls\n", ssii.dbgfile); + } + DeleteFileW(filename); + winetest_pop_context(); + } +} + START_TEST(path) { /* cleanup env variables that affect dbghelp's behavior */ @@ -856,4 +936,5 @@ START_TEST(path)
test_srvgetindexes_pe(); test_srvgetindexes_pdb(); + test_srvgetindexes_dbg(); }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/msc.c | 33 +++++++++++++++++++++++++++++++++ dlls/dbghelp/path.c | 2 ++ dlls/dbghelp/tests/path.c | 4 +--- 4 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index acba5faca37..4f14433c7c4 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -767,6 +767,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); extern DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info); +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, diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index a62667ea8c3..0440530f6cf 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -4573,3 +4573,36 @@ DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* debug_dir } return info->stripped && !num_misc_records ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS; } + +DWORD dbg_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) +{ + const IMAGE_SEPARATE_DEBUG_HEADER *header; + DWORD num_directories; + + if (size < sizeof(*header)) return ERROR_BAD_EXE_FORMAT; + header = image; + if (header->Signature != 0x4944 /* DI */ || + size < sizeof(*header) + header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + header->ExportedNamesSize + header->DebugDirectorySize) + return ERROR_BAD_EXE_FORMAT; + + /* header is followed by: + * - header->NumberOfSections of IMAGE_SECTION_HEADER + * - header->ExportedNameSize + * - then num_directories of IMAGE_DEBUG_DIRECTORY + */ + num_directories = header->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY); + + if (!num_directories) return ERROR_BAD_EXE_FORMAT; + + info->age = 0; + memset(&info->guid, 0, sizeof(info->guid)); + info->sig = 0; + info->dbgfile[0] = L'\0'; + info->pdbfile[0] = L'\0'; + info->size = header->SizeOfImage; + /* seems to use header's timestamp, not debug_directory one */ + info->timestamp = header->TimeDateStamp; + info->stripped = FALSE; /* FIXME */ + + return ERROR_SUCCESS; +} diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index 2437a7b6131..ec182c969d3 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -860,6 +860,8 @@ BOOL WINAPI SymSrvGetFileIndexInfoW(const WCHAR *file, SYMSRV_INDEX_INFOW* info, ret = pe_get_file_indexinfo(image, fsize, info); if (ret == ERROR_BAD_FORMAT) ret = pdb_get_file_indexinfo(image, fsize, info); + if (ret == ERROR_BAD_FORMAT) + ret = dbg_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 e1539bad966..fb7c103d845 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -907,10 +907,8 @@ static void test_srvgetindexes_dbg(void) memset(&ssii, 0x45, sizeof(ssii)); ssii.sizeofstruct = sizeof(ssii); ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0); - todo_wine ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
- if (ret){ ok(ssii.age == 0, "Mismatch in age: %lx\n", ssii.age); ok(!memcmp(&ssii.guid, &null_guid, sizeof(GUID)), "Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid)); @@ -922,7 +920,7 @@ static void test_srvgetindexes_dbg(void) ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file); ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %ls\n", ssii.pdbfile); ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %ls\n", ssii.dbgfile); - } + DeleteFileW(filename); winetest_pop_context(); }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 0440530f6cf..26e921f7a0f 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3615,8 +3615,47 @@ DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info)
if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT))) { - FIXME("Unsupported for PDB files in JG format\n"); - return ERROR_FILE_CORRUPT; + const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image; + struct PDB_JG_TOC* jg_toc; + struct PDB_JG_ROOT* root; + DWORD ec = ERROR_SUCCESS; + + jg_toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size); + root = pdb_read_jg_stream(pdb, jg_toc, 1); + if (!root) + { + ERR("-Unable to get root from .PDB\n"); + pdb_free(jg_toc); + return ERROR_FILE_CORRUPT; + } + switch (root->Version) + { + case 19950623: /* VC 4.0 */ + case 19950814: + case 19960307: /* VC 5.0 */ + case 19970604: /* VC 6.0 */ + break; + default: + ERR("-Unknown root block version %d\n", root->Version); + ec = ERROR_FILE_CORRUPT; + } + if (ec == ERROR_SUCCESS) + { + info->dbgfile[0] = '\0'; + memset(&info->guid, 0, sizeof(GUID)); + info->guid.Data1 = root->TimeDateStamp; + info->pdbfile[0] = '\0'; + info->age = root->Age; + info->sig = root->TimeDateStamp; + info->size = 0; + info->stripped = FALSE; + info->timestamp = 0; + } + + pdb_free(jg_toc); + pdb_free(root); + + return ec; } if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT))) {