From 5efe29edc0c72251b020e085f6a728eb2321b831 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Tue, 20 Jun 2023 17:01:18 +0200 Subject: [PATCH] dbghelp: Implement SymSrvGetFileIndexInfo for PE modules. Signed-off-by: Eric Pouech --- dlls/dbghelp/dbghelp_private.h | 5 ++++- dlls/dbghelp/msc.c | 44 ++++++++++++++++++++++++++++++++++++++++++ dlls/dbghelp/path.c | 33 ++++++++++++++++++++++++++++--- dlls/dbghelp/pe_module.c | 27 ++++++++++++++++++++++++++ dlls/dbghelp/tests/path.c | 3 +-- 5 files changed, 106 insertions(+), 6 deletions(-) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 7ba10447771..f91e2784b15 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -759,10 +759,12 @@ extern WCHAR* get_wine_loader_name(struct process *pcs) __WINE_DEALLOC(Hea /* msc.c */ extern BOOL pe_load_debug_directory(const struct process* pcs, - struct module* module, + struct module* module, const BYTE* mapping, const IMAGE_SECTION_HEADER* sectp, DWORD nsect, const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg) DECLSPEC_HIDDEN; +extern DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* dbgdir, DWORD size, + SYMSRV_INDEX_INFOW* info) DECLSPEC_HIDDEN; extern BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched) DECLSPEC_HIDDEN; struct pdb_cmd_pair { const char* name; @@ -793,6 +795,7 @@ extern struct module* extern BOOL pe_load_debug_info(const struct process* pcs, struct module* module) DECLSPEC_HIDDEN; extern const char* pe_map_directory(struct module* module, int dirno, DWORD* size) DECLSPEC_HIDDEN; +extern DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) DECLSPEC_HIDDEN; /* source.c */ extern unsigned source_new(struct module* module, const char* basedir, const char* source) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index c6dca22883a..f6b681cb4ae 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -4465,3 +4465,47 @@ typedef struct _FPO_DATA __ENDTRY return ret; } + +DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* debug_dir, DWORD num_dir, SYMSRV_INDEX_INFOW* info) +{ + DWORD i; + unsigned num_misc_records = 0; + + info->age = 0; + memset(&info->guid, 0, sizeof(info->guid)); + info->sig = 0; + info->dbgfile[0] = L'\0'; + info->pdbfile[0] = L'\0'; + + for (i = 0; i < num_dir; i++) + { + if (debug_dir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW) + { + const CODEVIEW_PDB_DATA* data = (const CODEVIEW_PDB_DATA*)((char*)image + debug_dir[i].PointerToRawData); + const OMFSignatureRSDS* rsds_data = (const OMFSignatureRSDS*)data; + if (!memcmp(data->Signature, "NB10", 4)) + { + info->age = data->age; + info->sig = data->timestamp; + MultiByteToWideChar(CP_ACP, 0, data->name, -1, info->pdbfile, ARRAY_SIZE(info->pdbfile)); + } + if (!memcmp(rsds_data->Signature, "RSDS", 4)) + { + info->age = rsds_data->age; + info->guid = rsds_data->guid; + MultiByteToWideChar(CP_ACP, 0, rsds_data->name, -1, info->pdbfile, ARRAY_SIZE(info->pdbfile)); + } + } + else if (debug_dir[i].Type == IMAGE_DEBUG_TYPE_MISC && info->stripped) + { + const IMAGE_DEBUG_MISC* misc = (const IMAGE_DEBUG_MISC*) + ((const char*)image + debug_dir[i].PointerToRawData); + if (misc->Unicode) + wcscpy(info->dbgfile, (WCHAR*)misc->Data); + else + MultiByteToWideChar(CP_ACP, 0, (const char*)misc->Data, -1, info->dbgfile, ARRAY_SIZE(info->dbgfile)); + num_misc_records++; + } + } + return info->stripped && !num_misc_records ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS; +} diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index 7c356e3a6ea..5c53e3f857d 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -881,15 +881,42 @@ BOOL WINAPI SymSrvGetFileIndexInfo(const char *file, SYMSRV_INDEX_INFO* info, DW */ BOOL WINAPI SymSrvGetFileIndexInfoW(const WCHAR *file, SYMSRV_INDEX_INFOW* info, DWORD flags) { - FIXME("(%s, %p, 0x%08lx): stub!\n", debugstr_w(file), info, flags); + HANDLE hFile, hMap = NULL; + void* image = NULL; + DWORD fsize, ret; + + TRACE("(%s, %p, 0x%08lx)\n", debugstr_w(file), info, flags); if (info->sizeofstruct < sizeof(*info)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + + if ((hFile = CreateFileW(file, 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)) + { + /* must handle PE, or .dbg or .pdb files. So each helper will return: + * - ERROR_SUCCESS: if the file format is recognized and index info filled, + * - ERROR_BAD_FORMAT: if the file doesn't match the expected format, + * - any other error: if the file has expected format, but internal errors + */ + 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 */ + } + else ret = ERROR_FILE_NOT_FOUND; + + if (image) UnmapViewOfFile(image); + if (hMap) CloseHandle(hMap); + if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); + + if (ret == ERROR_SUCCESS) wcscpy(info->file, file_name(file)); /* overflow? */ + SetLastError(ret); + return ret == ERROR_SUCCESS; } /****************************************************************** diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 7aeb1cf8901..3364498e0c7 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -962,3 +962,30 @@ PVOID WINAPI ImageDirectoryEntryToData( PVOID base, BOOLEAN image, USHORT dir, P { return ImageDirectoryEntryToDataEx( base, image, dir, size, NULL ); } + +DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) +{ + const IMAGE_NT_HEADERS* nthdr; + const IMAGE_DEBUG_DIRECTORY* dbg; + ULONG dirsize; + + if (!(nthdr = RtlImageNtHeader(image))) return ERROR_BAD_FORMAT; + + dbg = RtlImageDirectoryEntryToData(image, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dirsize); + if (!dbg || dirsize < sizeof(dbg)) return ERROR_BAD_EXE_FORMAT; + + /* fill in information from NT header */ + info->timestamp = nthdr->FileHeader.TimeDateStamp; + info->stripped = (nthdr->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0; + if (nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + const IMAGE_NT_HEADERS64* nthdr64 = (const IMAGE_NT_HEADERS64*)nthdr; + info->size = nthdr64->OptionalHeader.SizeOfImage; + } + else if (nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + const IMAGE_NT_HEADERS32* nthdr32 = (const IMAGE_NT_HEADERS32*)nthdr; + info->size = nthdr32->OptionalHeader.SizeOfImage; + } + return msc_get_file_indexinfo(image, dbg, dirsize / sizeof(*dbg), info); +} diff --git a/dlls/dbghelp/tests/path.c b/dlls/dbghelp/tests/path.c index 1e76886a70e..7ba8ef52e0b 100644 --- a/dlls/dbghelp/tests/path.c +++ b/dlls/dbghelp/tests/path.c @@ -442,10 +442,9 @@ static void test_srvgetindexes(void) if (indexes[i].in_error) { ok(!ret, "SymSrvGetFileIndexInfo should have failed\n"); - todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Mismatch in GetLastError: %lu\n", GetLastError()); } - else todo_wine + else { ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError()); -- 2.11.4.GIT