/* * PROJECT: ReactOS api tests * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Support functions for dbghelp api test * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) */ #include #include #include #include "wine/test.h" extern IMAGE_DOS_HEADER __ImageBase; static char szTempPath[MAX_PATH]; static const char* tmpdir() { if (szTempPath[0] == '\0') { GetTempPathA(MAX_PATH, szTempPath); lstrcatA(szTempPath, "dbghelp_tst"); } return szTempPath; } static int extract_one(const char* filename, const char* resid) { HMODULE mod = (HMODULE)&__ImageBase; HGLOBAL glob; PVOID data, decompressed; uLongf size, dstsize; DWORD gccSize, dwErr; HANDLE file; int ret; HRSRC rsrc = FindResourceA(mod, resid, MAKEINTRESOURCEA(RT_RCDATA)); ok(rsrc != 0, "Failed finding '%s' res\n", resid); if (!rsrc) return 0; size = SizeofResource(mod, rsrc); glob = LoadResource(mod, rsrc); ok(glob != NULL, "Failed loading '%s' res\n", resid); if (!glob) return 0; data = LockResource(glob); dstsize = 1024 * 256; decompressed = malloc(dstsize); if (uncompress(decompressed, &dstsize, data, size) != Z_OK) { ok(0, "uncompress failed for %s\n", resid); free(decompressed); return 0; } file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); gccSize = size; ret = WriteFile(file, decompressed, dstsize, &gccSize, NULL); dwErr = GetLastError(); CloseHandle(file); free(decompressed); ok(ret, "WriteFile failed (%d)\n", dwErr); return ret && dstsize == gccSize; } int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]) { const char* dir = tmpdir(); BOOL ret = CreateDirectoryA(dir, NULL); ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); sprintf(szFile, "%s\\uffs.pdb", dir); if (!extract_one(szFile, "msvc_uffs.pdb")) return 0; sprintf(szFile, "%s\\uffs.dll", dir); if (!extract_one(szFile, "msvc_uffs.dll")) return 0; strcpy(szPath, dir); return 1; } void cleanup_msvc_dll() { char szFile[MAX_PATH]; BOOL ret; const char* dir = tmpdir(); sprintf(szFile, "%s\\uffs.pdb", dir); ret = DeleteFileA(szFile); ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); sprintf(szFile, "%s\\uffs.dll", dir); ret = DeleteFileA(szFile); ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); ret = RemoveDirectoryA(dir); ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); } int extract_gcc_dll(char szFile[MAX_PATH]) { const char* dir = tmpdir(); BOOL ret = CreateDirectoryA(dir, NULL); ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); sprintf(szFile, "%s\\uffs.dll", dir); if (!extract_one(szFile, "gcc_uffs.dll")) return 0; return 1; } void cleanup_gcc_dll() { char szFile[MAX_PATH]; BOOL ret; const char* dir = tmpdir(); sprintf(szFile, "%s\\uffs.dll", dir); ret = DeleteFileA(szFile); ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); ret = RemoveDirectoryA(dir); ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); } #if 0 static int compress_one(const char* src, const char* dest) { DWORD size, size2, res; FILE* file = fopen(src, "rb"); fseek(file, 0, SEEK_END); size = ftell(file); fseek(file, 0, SEEK_SET); Bytef* buffer, *buffer2; DWORD dwErr = GetLastError(); buffer = malloc(size); res = fread(buffer, 1, size, file); fclose(file); if (res != size) { printf("Could not read file: 0x%x\n", dwErr); free(buffer); CloseHandle(file); return 0; } size2 = size *2; buffer2 = malloc(size2); res = compress(buffer2, &size2, buffer, size); free(buffer); if (Z_OK != res) { free(buffer2); return 0; } file = fopen(dest, "wb"); res = fwrite(buffer2, 1, size2, file); fclose(file); free(buffer2); return size2 == res; } void create_compressed_files() { SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp"); if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr")) printf("msvc_uffs.dll failed\n"); if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr")) printf("msvc_uffs.pdb failed\n"); if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr")) printf("gcc_uffs.dll failed\n"); } #endif #if 0 typedef struct _SYMBOLFILE_HEADER { ULONG SymbolsOffset; ULONG SymbolsLength; ULONG StringsOffset; ULONG StringsLength; } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; typedef struct _ROSSYM_ENTRY { ULONG Address; ULONG FunctionOffset; ULONG FileOffset; ULONG SourceLine; } ROSSYM_ENTRY, *PROSSYM_ENTRY; static int is_metadata(const char* name) { size_t len = name ? strlen(name) : 0; return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; }; static void dump_rsym_internal(void* data) { PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset); size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); size_t i; char *Strings = (char *)data + RosSymHeader->StringsOffset; for (i = 0; i < symbols; i++) { PROSSYM_ENTRY Entry = Entries + i; if (!Entry->FileOffset) { if (Entry->SourceLine) printf("ERR: SOURCELINE (%D) ", Entry->SourceLine); if (is_metadata(Strings + Entry->FunctionOffset)) printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address); else printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset); } else { printf("0x%x: %s (%s:%u)\n", Entry->Address, Strings + Entry->FunctionOffset, Strings + Entry->FileOffset, Entry->SourceLine); } } } void dump_rsym(const char* filename) { char* data; long size, res; PIMAGE_FILE_HEADER PEFileHeader; PIMAGE_OPTIONAL_HEADER PEOptHeader; PIMAGE_SECTION_HEADER PESectionHeaders; WORD i; FILE* f = fopen(filename, "rb"); fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); data = malloc(size); res = fread(data, 1, size, f); fclose(f); PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG)); PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader); for (i = 0; i < PEFileHeader->NumberOfSections; i++) { if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym")) { dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData); break; } } free(data); } #endif