From e2c97e602fdebde4fb44b63dc8399fa7d740da73 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Fri, 17 Feb 2017 16:15:49 +0000 Subject: [PATCH] [DBGHELP_APITEST] Add tests for pdb and rsym parsing. CORE-12773 svn path=/trunk/; revision=73816 --- rostests/apitests/CMakeLists.txt | 1 + rostests/apitests/dbghelp/CMakeLists.txt | 20 + rostests/apitests/dbghelp/data.c | 277 +++++++++++++ rostests/apitests/dbghelp/pdb.c | 378 ++++++++++++++++++ rostests/apitests/dbghelp/resource.rc | 5 + rostests/apitests/dbghelp/rsym.c | 369 +++++++++++++++++ .../dbghelp/testdata/gcc_uffs.dll.compr | Bin 0 -> 1582 bytes .../dbghelp/testdata/msvc_uffs.dll.compr | Bin 0 -> 1091 bytes .../dbghelp/testdata/msvc_uffs.pdb.compr | Bin 0 -> 9206 bytes rostests/apitests/dbghelp/testlist.c | 13 + 10 files changed, 1063 insertions(+) create mode 100644 rostests/apitests/dbghelp/CMakeLists.txt create mode 100644 rostests/apitests/dbghelp/data.c create mode 100644 rostests/apitests/dbghelp/pdb.c create mode 100644 rostests/apitests/dbghelp/resource.rc create mode 100644 rostests/apitests/dbghelp/rsym.c create mode 100644 rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr create mode 100644 rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr create mode 100644 rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr create mode 100644 rostests/apitests/dbghelp/testlist.c diff --git a/rostests/apitests/CMakeLists.txt b/rostests/apitests/CMakeLists.txt index ff582efdd9e..e43ca4f87d3 100644 --- a/rostests/apitests/CMakeLists.txt +++ b/rostests/apitests/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(atl) add_subdirectory(browseui) add_subdirectory(com) add_subdirectory(crt) +add_subdirectory(dbghelp) add_subdirectory(dciman32) add_subdirectory(dnsapi) add_subdirectory(gdi32) diff --git a/rostests/apitests/dbghelp/CMakeLists.txt b/rostests/apitests/dbghelp/CMakeLists.txt new file mode 100644 index 00000000000..fdc68332709 --- /dev/null +++ b/rostests/apitests/dbghelp/CMakeLists.txt @@ -0,0 +1,20 @@ + +add_definitions(-D__ROS_LONG64__ -DWINETEST_USE_DBGSTR_LONGLONG) + +include_directories( + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib + ${REACTOS_SOURCE_DIR}/sdk/tools/rsym +) + +list(APPEND SOURCE + pdb.c + rsym.c + data.c + testlist.c) + +add_executable(dbghelp_apitest ${SOURCE} resource.rc) +set_module_type(dbghelp_apitest win32cui) +target_link_libraries(dbghelp_apitest zlib) +add_delay_importlibs(dbghelp_apitest dbghelp) +add_importlibs(dbghelp_apitest msvcrt kernel32 ntdll) +add_rostests_file(TARGET dbghelp_apitest) diff --git a/rostests/apitests/dbghelp/data.c b/rostests/apitests/dbghelp/data.c new file mode 100644 index 00000000000..13c823df490 --- /dev/null +++ b/rostests/apitests/dbghelp/data.c @@ -0,0 +1,277 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Support functions for dbghelp api test + * PROGRAMMER: Mark Jansen + */ + +#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_exe(char szFile[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; + + return 1; +} + +void cleanup_msvc_exe() +{ + 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_exe(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_exe() +{ + 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 diff --git a/rostests/apitests/dbghelp/pdb.c b/rostests/apitests/dbghelp/pdb.c new file mode 100644 index 00000000000..64942c1d393 --- /dev/null +++ b/rostests/apitests/dbghelp/pdb.c @@ -0,0 +1,378 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp PDB functions + * PROGRAMMER: Mark Jansen + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + + +// data.c +void create_compressed_files(); +int extract_msvc_exe(char szFile[MAX_PATH]); +void cleanup_msvc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +/* Maybe our dbghelp.dll is too old? */ +static BOOL can_enumerate(HANDLE hProc, DWORD64 BaseAddress) +{ + IMAGEHLP_MODULE64 ModuleInfo; + BOOL Ret; + + memset(&ModuleInfo, 0, sizeof(ModuleInfo)); + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); + Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo); + + return Ret && ModuleInfo.SymType == SymPdb; +} + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_DllMain@12", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_DllMain@12"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsChkdsk@24"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsFormat@24"); + } + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1d); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The padding below the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1e); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* One byte before the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x2f); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot read this symbol!\n"); + } + else + { + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "__imp__DbgPrint"); + } + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; +} test_data[] = { + /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */ + { 0x1070, 36, SymTagFunction, "FfsFormat" }, + { 0x1010, 32, SymTagFunction, "DllMain" }, + { 0x1040, 36, SymTagFunction, "FfsChkdsk" }, + + { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" }, + { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" }, + { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" }, + { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" }, + { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" }, +}; + +static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); + ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str(pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, ctx.BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); + ok_int(Ret, TRUE); + ok_int(ctx.Index, ARRAYSIZE(test_data)); + } + + deinit_sym(); +} + + +START_TEST(pdb) +{ + char szDllName[MAX_PATH]; + //create_compressed_files(); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_msvc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_msvc_exe(); +} diff --git a/rostests/apitests/dbghelp/resource.rc b/rostests/apitests/dbghelp/resource.rc new file mode 100644 index 00000000000..79920a0e64e --- /dev/null +++ b/rostests/apitests/dbghelp/resource.rc @@ -0,0 +1,5 @@ +#include "windef.h" + +msvc_uffs.dll RCDATA testdata/msvc_uffs.dll.compr +msvc_uffs.pdb RCDATA testdata/msvc_uffs.pdb.compr +gcc_uffs.dll RCDATA testdata/gcc_uffs.dll.compr diff --git a/rostests/apitests/dbghelp/rsym.c b/rostests/apitests/dbghelp/rsym.c new file mode 100644 index 00000000000..b471849e4ad --- /dev/null +++ b/rostests/apitests/dbghelp/rsym.c @@ -0,0 +1,369 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp rsym functions + * PROGRAMMER: Mark Jansen + * + * These tests are based on the PDB tests. + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + +#define ok_ulonglong_(file, line, expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok_(file, line)(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + +#define ok_hex_(file, line, expression, result) \ + do { \ + int _value = (expression); \ + ok_(file, line)(_value == (result), "Wrong value for '%s', expected: " #result " (0x%x), got: 0x%x\n", \ + #expression, (int)(result), _value); \ + } while (0) + +#define ok_str_(file, line, x, y) \ + ok_(file, line)(strcmp(x, y) == 0, "Wrong string. Expected '%s', got '%s'\n", y, x) + + +// data.c +void dump_rsym(const char* filename); +int extract_gcc_exe(char szFile[MAX_PATH]); +void cleanup_gcc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +static BOOL supports_rsym(HANDLE hProc, DWORD64 BaseAddress) +{ + IMAGEHLP_MODULE64 ModuleInfo; + BOOL Ret; + + memset(&ModuleInfo, 0, sizeof(ModuleInfo)); + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); + Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo); + + return Ret && + ModuleInfo.SymType == SymDia && + ModuleInfo.CVSig == ('R' | ('S' << 8) | ('Y' << 16) | ('M' << 24)); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + if (supports_rsym(hProc, BaseAddress)) + { + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x100C); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + } + else + { + skip("dbghelp.dll cannot parse rsym\n"); + } + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + if (supports_rsym(hProc, BaseAddress)) + { + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + /* Our dbghelp.dll does not recognize this yet */ + todo_if(!Ret) + { + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + } + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1009, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x9); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103F, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x4000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, SYMFLAG_EXPORT); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x4000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_head_dll_ntdll_libntdll_a"); + } + else + { + skip("dbghelp.dll cannot parse rsym\n"); + } + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; + int Line; +} test_data[] = { + + /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */ + { 0x107c, 0, SymTagPublicSymbol, "__CTOR_LIST__", __LINE__ }, + { 0x2074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST_END__", __LINE__ }, + { 0x1000, 12, SymTagPublicSymbol, "EntryPoint", __LINE__ }, + { 0x100c, 51, SymTagFunction, "FfsFormat", __LINE__ }, + { 0x4030, 0, SymTagPublicSymbol, "_imp__DbgPrint", __LINE__ }, + { 0x1084, 0, SymTagPublicSymbol, "__DTOR_LIST__", __LINE__ }, + { 0x103f, 53, SymTagFunction, "FfsChkdsk", __LINE__ }, + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_end", __LINE__ }, + { 0x103f, 53, SymTagPublicSymbol, "ChkdskEx", __LINE__ }, + { 0x4048, 0, SymTagPublicSymbol, "_dll_ntdll_libntdll_a_iname", __LINE__ }, + + + + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_start", __LINE__ }, + { 0x1000, 12, SymTagFunction, "DllMain", __LINE__ }, + { 0x100c, 0, SymTagPublicSymbol, "FormatEx", __LINE__ }, + { 0x1074, 0, SymTagPublicSymbol, "DbgPrint", __LINE__ }, + { 0x68900000, 0, SymTagPublicSymbol, "__ImageBase", __LINE__ }, + { 0x68902074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST__", __LINE__ }, + { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a", __LINE__ }, +}; + +BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->ModBase, ctx->BaseAddress); + if (test_data[ctx->Index].AddressOffset > 0x100000) + ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address, test_data[ctx->Index].AddressOffset); + else + ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + if (supports_rsym(hProc, ctx.BaseAddress)) + { + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); + ok_int(Ret, TRUE); + ok_int(ctx.Index, ARRAYSIZE(test_data)); + } + else + { + skip("dbghelp.dll cannot parse rsym\n"); + } + + deinit_sym(); +} + + + + +START_TEST(rsym) +{ + char szDllName[MAX_PATH]; + //dump_rsym("R:\\src\\trunk\\reactos\\modules\\rostests\\apitests\\dbghelp\\testdata\\gcc_uffs.dll"); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_gcc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_gcc_exe(); +} diff --git a/rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr b/rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr new file mode 100644 index 0000000000000000000000000000000000000000..f3e38c93232465ca2e399483a1325e77c888ea7d GIT binary patch literal 1582 zcmV+}2GRL=ob6dnY#T)sezwz+v?&Tzs}`tWgHlvgs=X~KwBe_2V~1Kw?9_46f+(A{ zy|$OEcdgw`NT5iS;DW@#2RLvCi4)?$p+e$E<$yT!z?ln|A`S>Hy>KCXGdpX~+E&V` zKayWGJM+!F_vXDfv*S0Lh1c7ZAfgeJ?QNnP6i}M(PS;T$efpb6>FcpulQ&}Xw)ym?fHzJwnMZKEFaw1bx3z zd~$Creu&}#W5Rw$_C^4{)PjB@MaWHbqkhDc8^|zT>65>RQS& z%c+{jpK_JNyMFn6F`vu7I-@8@Jw^BNoH<%maPlwba|?^}*@bMrl+8@;p}Cqj=eSMX zXRX=BTGd;--~JA%pZISt=p{Ay&5Vn33|K`ugK`dM`Z!7!?L7N^0p~ilM6zmG6fA9a zlY-SoV@MAP9ZPrH7t=xBGKkKkqxA%3%JoIpv{_<;KHJAe;G1Dc4;!5j?>~E|S?YE; zNbMv2>|9U>^p7DgyolBn?8qXD4A`Q2dVW zf~SczR0sbStkHoCuDgg@rwVizFoQxF;0+WD5-rYUV@yH*Y;Y+?Z_<;{8QQ=kJZNCH zwZLma(&l_~_+vUlP6cQSygu4ZpapJ^4u6c!OpH#^n52IN#f4N??=(1)bec{;-wM28 zbR3b4@p$;0pXs$EPuCHr8niH~(Ij~1(O>6Wv)tD$?m?Xz+=~7_g-#-}XXy;)J%!kw zq!-ZF8$UTtGu)4Y&|wOjLci=j+mckph$YsAt=l4G9rUjA8FpH?0<2|z>wE>+9*IUf zh}&qN&fe&%J(11uUB3do?tooKG{rAUB|ftaJ(jQ_T&uB>uX=8I_n9VwyW3Ohv+4=; zlKPsus&1(F+o&PkD`Mw;3uonZl)n-|{#TODafV-%Fx$Mp#H09*tPo@0%Lg_l$O%1< z3H)&^I)0}I|49AvAtfYzhbYKN&x!T{35T>_8fUlK=OxSv%WF@I_N0VE%1Yzxifc-k zeZ%sB(~|wyfY;+u{IY~U0RE>3zbDP-D@336;FVYuf0u~jcjfO^X`;_0{VbpRqzB)Y zFw5u0B+PQaO?f@A0J|gK#T5EghSYAP5>fnn#NKw}5=HR=d4C{fOucQ|&z(xK>jZz` zj=A#nZ9cbD(lpZ8*DuZUb=PM| z%ajVm&Y0#~UUv-7mdC$tiB1SxmR4!#E^f(&YkIzkA#i%;JBH@e7*}OYt2oW3>G$`$ zhG)1N1{-MVZ#k~!t(Uzm&o`RdhT(dqV{;oSn0M2XOynJAe}`dL0Xtc^R`w+0cL+i@ zpW%UkFFa}25YwQcYo@I?jjrJhLvKm`1T(jKO=$^JxJu@oX~R3mlif0#dfm{t3(lkPKID;Jyro`c&R^n}rSpmJR7aqc>2JRinIK*Kn@cb;ApxY1f?2P`T_H g8zHhx+X&k=mz@{_c)r`=VgD2u(gRQb0p~s0r#sg$(f|Me literal 0 HcmV?d00001 diff --git a/rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr b/rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr new file mode 100644 index 0000000000000000000000000000000000000000..c02738094ef7b901fbb808052203a76e9e7aabf0 GIT binary patch literal 1091 zcmV-J1ibrrob6UkXd6cqev*GGxwgB97E&7MsKgLLvuqmoC#E!NEvXS$KS=%wMXtS) zR?^0+mDpVc8(J_4v~kr#dq@qXq@hsgp@$xNFoi-$b8JWmoM*(v%9G* z3HJ|TTKvSDnfK;#U@jX2W4cjae;|=_ZS1@~qw{Yx3CG$Pv%StuHR#X#eobrq8b}Dw~(Y zczg2$A&+fti2j6--~0F_Pk&PMIlWZlc79CRIMGaCh(5jYPj|w<#Xebh{;~HLE`Q#F zRc@+KZ0Sb1;NVYYrC{pjId!RSpDz`7v(zjX3&Jf1$!9?{pJ*7 z6E;&Fv{MshhF8E`I+@DO#8dI~Y&;ej`4?-sr{Qm|bwK}w0^-8OfAo5{o`1(mAAK1A z_h&F#juIX2^WHf;Fo|}a^0b6DPC1N{l%X`_B-#YVoW39Y^#S)cM8||Y0r*i{d$xqo<*t2BuC;Qh{GXG%6%b z_|BnMsRZ8{tiW&&YIGiKz@jNoCgvE;3S3>-yiL!*rym2iu;GEn)&y3Er73U;{J2ja z$snx(>tI}mloIi%$VYp)5~mj^+~I#7Y{BXezmq`7^dcRHzj6m!QCWQ}<=YEZj zOk1c^1ztE+@OTZ-4D?ljnijdPi43Y#6H)Z)7@a_6PvJFt9P2BPUWTr_ew}ri5_x1i zAG#NlpO@Jan@nZQ7~a0{eaphO0c}gHu-Cq25G~JJ6+6Js$nI*pbqn?Q?5?iTRoR$0 z{qyi^^*MD!N5n&TR;+BokKsk&?^Ss4o37XSK9S_U$VO^< J{SKd!l~+2ZEL8vi literal 0 HcmV?d00001 diff --git a/rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr b/rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr new file mode 100644 index 0000000000000000000000000000000000000000..2fbd57031a92954c74342750826807f651dca5b5 GIT binary patch literal 9206 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 literal 0 HcmV?d00001 diff --git a/rostests/apitests/dbghelp/testlist.c b/rostests/apitests/dbghelp/testlist.c new file mode 100644 index 00000000000..d4758e4acc8 --- /dev/null +++ b/rostests/apitests/dbghelp/testlist.c @@ -0,0 +1,13 @@ + +#define STANDALONE +#include + +extern void func_pdb(void); +extern void func_rsym(void); + +const struct test winetest_testlist[] = +{ + { "pdb", func_pdb }, + { "rsym", func_rsym }, + { 0, 0 } +};