From b8a1a612b2d428a31a89d2f72b31000563c93c30 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Wed, 27 Mar 2019 23:09:36 +0100 Subject: [PATCH] [DBGHELP_APITEST] Add rsym+pdb tests on loaded modules Also reorder some stuff to make the tests more alike --- modules/rostests/apitests/dbghelp/data.c | 17 +-- modules/rostests/apitests/dbghelp/pdb.c | 139 +++++++++--------- modules/rostests/apitests/dbghelp/rsym.c | 172 +++++++++++------------ 3 files changed, 167 insertions(+), 161 deletions(-) diff --git a/modules/rostests/apitests/dbghelp/data.c b/modules/rostests/apitests/dbghelp/data.c index 13c823df490..48985517700 100644 --- a/modules/rostests/apitests/dbghelp/data.c +++ b/modules/rostests/apitests/dbghelp/data.c @@ -1,8 +1,8 @@ /* - * PROJECT: ReactOS api tests - * LICENSE: GPLv2+ - See COPYING in the top level directory - * PURPOSE: Support functions for dbghelp api test - * PROGRAMMER: Mark Jansen + * 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 @@ -69,7 +69,7 @@ static int extract_one(const char* filename, const char* resid) } -int extract_msvc_exe(char szFile[MAX_PATH]) +int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]) { const char* dir = tmpdir(); BOOL ret = CreateDirectoryA(dir, NULL); @@ -83,10 +83,11 @@ int extract_msvc_exe(char szFile[MAX_PATH]) if (!extract_one(szFile, "msvc_uffs.dll")) return 0; + strcpy(szPath, dir); return 1; } -void cleanup_msvc_exe() +void cleanup_msvc_dll() { char szFile[MAX_PATH]; BOOL ret; @@ -103,7 +104,7 @@ void cleanup_msvc_exe() ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); } -int extract_gcc_exe(char szFile[MAX_PATH]) +int extract_gcc_dll(char szFile[MAX_PATH]) { const char* dir = tmpdir(); BOOL ret = CreateDirectoryA(dir, NULL); @@ -116,7 +117,7 @@ int extract_gcc_exe(char szFile[MAX_PATH]) return 1; } -void cleanup_gcc_exe() +void cleanup_gcc_dll() { char szFile[MAX_PATH]; BOOL ret; diff --git a/modules/rostests/apitests/dbghelp/pdb.c b/modules/rostests/apitests/dbghelp/pdb.c index 8f4988ac0c7..dc56ae74b08 100644 --- a/modules/rostests/apitests/dbghelp/pdb.c +++ b/modules/rostests/apitests/dbghelp/pdb.c @@ -1,8 +1,8 @@ /* - * PROJECT: ReactOS api tests - * LICENSE: GPLv2+ - See COPYING in the top level directory - * PURPOSE: Test for dbghelp PDB functions - * PROGRAMMER: Mark Jansen + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Test for dbghelp PDB functions + * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) */ #include @@ -26,17 +26,17 @@ // data.c void create_compressed_files(); -int extract_msvc_exe(char szFile[MAX_PATH]); -void cleanup_msvc_exe(); +int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]); +void cleanup_msvc_dll(); static HANDLE proc() { return GetCurrentProcess(); } -static BOOL init_sym_imp(const char* file, int line) +static BOOL init_sym_imp(BOOL fInvadeProcess, const char* file, int line) { - if (!SymInitialize(proc(), NULL, FALSE)) + if (!SymInitialize(proc(), NULL, fInvadeProcess)) { DWORD err = GetLastError(); ok_(file, line)(0, "Failed to init: 0x%x\n", err); @@ -50,7 +50,7 @@ static void deinit_sym() SymCleanup(proc()); } -#define init_sym() init_sym_imp(__FILE__, __LINE__) +#define init_sym(fInvadeProcess) init_sym_imp(fInvadeProcess, __FILE__, __LINE__) #define INIT_PSYM(buff) do { \ memset((buff), 0, sizeof((buff))); \ @@ -222,7 +222,7 @@ PfnDliHook __pfnDliFailureHook2 = DliFailHook; /* Maybe our dbghelp.dll is too old? */ -static BOOL can_enumerate(HANDLE hProc, DWORD64 BaseAddress) +static BOOL supports_pdb(HANDLE hProc, DWORD64 BaseAddress) { IMAGEHLP_MODULE64 ModuleInfo; BOOL Ret; @@ -235,26 +235,13 @@ static BOOL can_enumerate(HANDLE hProc, DWORD64 BaseAddress) } -static void test_SymFromName(HANDLE hProc, const char* szModuleName) +static void test_SymFromName(HANDLE hProc, DWORD64 BaseAddress) { 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)) + if (!supports_pdb(hProc, BaseAddress)) { skip("dbghelp.dll too old or cannot enumerate symbols!\n"); } @@ -314,29 +301,17 @@ static void test_SymFromName(HANDLE hProc, const char* szModuleName) ok_hex(pSymbol->Tag, SymTagPublicSymbol); ok_str(pSymbol->Name, "_FfsFormat@24"); } - - deinit_sym(); } -static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +static void test_SymFromAddr(HANDLE hProc, DWORD64 BaseAddress) { BOOL Ret; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; - DWORD64 BaseAddress, Displacement; + DWORD64 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); @@ -417,7 +392,7 @@ static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) ok_hex(pSymbol->Tag, SymTagFunction); ok_str(pSymbol->Name, "FfsChkdsk"); - if (!can_enumerate(hProc, BaseAddress)) + if (!supports_pdb(hProc, BaseAddress)) { skip("dbghelp.dll too old or cannot read this symbol!\n"); } @@ -435,8 +410,6 @@ static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) ok_hex(pSymbol->Tag, SymTagPublicSymbol); ok_str(pSymbol->Name, "__imp__DbgPrint"); } - - deinit_sym(); } typedef struct _test_context @@ -484,25 +457,15 @@ static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID return TRUE; } -static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress) { 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); + ctx.BaseAddress = BaseAddress; - if (!can_enumerate(hProc, ctx.BaseAddress)) + if (!supports_pdb(hProc, ctx.BaseAddress)) { skip("dbghelp.dll too old or cannot enumerate symbols!\n"); } @@ -512,8 +475,6 @@ static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) ok_int(Ret, TRUE); ok_int(ctx.Index, ARRAYSIZE(test_data)); } - - deinit_sym(); } typedef struct _symregcallback_context @@ -524,7 +485,6 @@ typedef struct _symregcallback_context static struct _symregcallback_test_data { ULONG ActionCode; - const char* Name; } symregcallback_test_data[] = { { CBA_DEFERRED_SYMBOL_LOAD_CANCEL }, { CBA_DEFERRED_SYMBOL_LOAD_START }, @@ -567,7 +527,7 @@ static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL tes ctx.idx = 0; ctx.isANSI = testANSI; - if (!init_sym()) + if (!init_sym(FALSE)) return; if (testANSI) @@ -604,14 +564,19 @@ static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL tes START_TEST(pdb) { char szDllName[MAX_PATH]; - //create_compressed_files(); + char szDllPath[MAX_PATH], szOldDir[MAX_PATH]; +#ifdef _M_IX86 + HMODULE hMod; +#endif + DWORD64 BaseAddress; + DWORD dwErr, Options; - DWORD Options = SymGetOptions(); + Options = SymGetOptions(); Options &= ~(SYMOPT_UNDNAME); //Options |= SYMOPT_DEBUG; SymSetOptions(Options); - if (!extract_msvc_exe(szDllName)) + if (!extract_msvc_dll(szDllName, szDllPath)) { ok(0, "Failed extracting files\n"); return; @@ -619,12 +584,54 @@ START_TEST(pdb) init_dbghelp_version(); - test_SymFromName(proc(), szDllName); - test_SymFromAddr(proc(), szDllName); - test_SymEnumSymbols(proc(), szDllName); + if (init_sym(FALSE)) + { + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(proc(), NULL, szDllName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (BaseAddress == 0x600000) + { + trace("Module loaded by SymLoadModule64\n"); + test_SymFromName(proc(), BaseAddress); + test_SymFromAddr(proc(), BaseAddress); + test_SymEnumSymbols(proc(), BaseAddress); + } + + deinit_sym(); + } + + /* This needs to load the module by itself */ test_SymRegCallback(proc(), szDllName, TRUE); test_SymRegCallback(proc(), szDllName, FALSE); - cleanup_msvc_exe(); +#ifdef _M_IX86 + hMod = LoadLibraryA(szDllName); + if (hMod) + { + BaseAddress = (DWORD64)(DWORD_PTR)hMod; + /* Make sure we can find the pdb */ + GetCurrentDirectoryA(_countof(szOldDir), szOldDir); + SetCurrentDirectoryA(szDllPath); + /* Invade process */ + if (init_sym(TRUE)) + { + trace("Module loaded by LoadLibraryA\n"); + test_SymFromName(proc(), BaseAddress); + test_SymFromAddr(proc(), BaseAddress); + test_SymEnumSymbols(proc(), BaseAddress); + + deinit_sym(); + } + /* Restore working dir */ + SetCurrentDirectoryA(szOldDir); + + FreeLibrary(hMod); + } +#endif + cleanup_msvc_dll(); } diff --git a/modules/rostests/apitests/dbghelp/rsym.c b/modules/rostests/apitests/dbghelp/rsym.c index b471849e4ad..16b759c9418 100644 --- a/modules/rostests/apitests/dbghelp/rsym.c +++ b/modules/rostests/apitests/dbghelp/rsym.c @@ -1,10 +1,10 @@ /* - * 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. + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Test for dbghelp rsym functions + * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) + * + * These tests are based on the PDB tests. */ #include @@ -45,17 +45,17 @@ // data.c void dump_rsym(const char* filename); -int extract_gcc_exe(char szFile[MAX_PATH]); -void cleanup_gcc_exe(); +int extract_gcc_dll(char szFile[MAX_PATH]); +void cleanup_gcc_dll(); static HANDLE proc() { return GetCurrentProcess(); } -static BOOL init_sym_imp(const char* file, int line) +static BOOL init_sym_imp(BOOL fInvadeProcess, const char* file, int line) { - if (!SymInitialize(proc(), NULL, FALSE)) + if (!SymInitialize(proc(), NULL, fInvadeProcess)) { DWORD err = GetLastError(); ok_(file, line)(0, "Failed to init: 0x%x\n", err); @@ -69,6 +69,14 @@ static void deinit_sym() SymCleanup(proc()); } +#define init_sym(fInvadeProcess) init_sym_imp(fInvadeProcess, __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 BOOL supports_rsym(HANDLE hProc, DWORD64 BaseAddress) { IMAGEHLP_MODULE64 ModuleInfo; @@ -83,36 +91,19 @@ static BOOL supports_rsym(HANDLE hProc, DWORD64 BaseAddress) 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) +static void test_SymFromName(HANDLE hProc, DWORD64 BaseAddress) { 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)) + if (!supports_rsym(hProc, BaseAddress)) + { + skip("dbghelp.dll cannot parse rsym\n"); + } + else { - ok_ulonglong(BaseAddress, 0x600000); - ok_hex(dwErr, ERROR_SUCCESS); - INIT_PSYM(buffer); Ret = SymFromName(hProc, "DllMain", pSymbol); ok_int(Ret, TRUE); @@ -140,35 +131,23 @@ static void test_SymFromName(HANDLE hProc, const char* szModuleName) 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) +static void test_SymFromAddr(HANDLE hProc, DWORD64 BaseAddress) { BOOL Ret; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; - DWORD64 BaseAddress, Displacement; + DWORD64 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)) + if (!supports_rsym(hProc, BaseAddress)) + { + skip("dbghelp.dll cannot parse rsym\n"); + } + else { - ok_ulonglong(BaseAddress, 0x600000); - ok_hex(dwErr, ERROR_SUCCESS); - /* No address found before load address of module */ Displacement = 0; INIT_PSYM(buffer); @@ -241,12 +220,6 @@ static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) 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 @@ -286,7 +259,7 @@ static struct _test_data { { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a", __LINE__ }, }; -BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) { test_context* ctx = UserContext; @@ -310,60 +283,85 @@ BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserCon return TRUE; } -static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress) { 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(); + ctx.BaseAddress = BaseAddress; - if (supports_rsym(hProc, ctx.BaseAddress)) + 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)); + skip("dbghelp.dll cannot parse rsym\n"); } else { - skip("dbghelp.dll cannot parse rsym\n"); + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); + ok_int(Ret, TRUE); + ok_int(ctx.Index, ARRAYSIZE(test_data)); } - - deinit_sym(); } - - START_TEST(rsym) { char szDllName[MAX_PATH]; - //dump_rsym("R:\\src\\trunk\\reactos\\modules\\rostests\\apitests\\dbghelp\\testdata\\gcc_uffs.dll"); +#ifdef _M_IX86 + HMODULE hMod; +#endif + DWORD64 BaseAddress; + DWORD dwErr, Options; - DWORD Options = SymGetOptions(); + Options = SymGetOptions(); Options &= ~(SYMOPT_UNDNAME); //Options |= SYMOPT_DEBUG; SymSetOptions(Options); - if (!extract_gcc_exe(szDllName)) + if (!extract_gcc_dll(szDllName)) { ok(0, "Failed extracting files\n"); return; } - test_SymFromName(proc(), szDllName); - test_SymFromAddr(proc(), szDllName); - test_SymEnumSymbols(proc(), szDllName); + if (init_sym(FALSE)) + { + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(proc(), NULL, szDllName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (BaseAddress == 0x600000) + { + trace("Module loaded by SymLoadModule64\n"); + test_SymFromName(proc(), BaseAddress); + test_SymFromAddr(proc(), BaseAddress); + test_SymEnumSymbols(proc(), BaseAddress); + } + + deinit_sym(); + } + +#ifdef _M_IX86 + hMod = LoadLibraryA(szDllName); + if (hMod) + { + BaseAddress = (DWORD64)(DWORD_PTR)hMod; + /* Invade process */ + if (init_sym(TRUE)) + { + trace("Module loaded by LoadLibraryA\n"); + test_SymFromName(proc(), BaseAddress); + test_SymFromAddr(proc(), BaseAddress); + test_SymEnumSymbols(proc(), BaseAddress); - cleanup_gcc_exe(); + deinit_sym(); + } + + FreeLibrary(hMod); + } +#endif + cleanup_gcc_dll(); } -- 2.17.1