mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 05:28:14 +00:00
[DBGHELP_APITEST] Add tests for pdb and rsym parsing. CORE-12773
svn path=/trunk/; revision=73816
This commit is contained in:
parent
17a622f506
commit
e2c97e602f
10 changed files with 1063 additions and 0 deletions
|
@ -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)
|
||||
|
|
20
rostests/apitests/dbghelp/CMakeLists.txt
Normal file
20
rostests/apitests/dbghelp/CMakeLists.txt
Normal file
|
@ -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)
|
277
rostests/apitests/dbghelp/data.c
Normal file
277
rostests/apitests/dbghelp/data.c
Normal file
|
@ -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 <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#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
|
378
rostests/apitests/dbghelp/pdb.c
Normal file
378
rostests/apitests/dbghelp/pdb.c
Normal file
|
@ -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 <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <cvconst.h> // SymTagXXX
|
||||
#include <stdio.h>
|
||||
|
||||
#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();
|
||||
}
|
5
rostests/apitests/dbghelp/resource.rc
Normal file
5
rostests/apitests/dbghelp/resource.rc
Normal file
|
@ -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
|
369
rostests/apitests/dbghelp/rsym.c
Normal file
369
rostests/apitests/dbghelp/rsym.c
Normal file
|
@ -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 <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <cvconst.h> // SymTagXXX
|
||||
#include <stdio.h>
|
||||
|
||||
#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();
|
||||
}
|
BIN
rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr
vendored
Normal file
BIN
rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr
vendored
Normal file
Binary file not shown.
BIN
rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr
vendored
Normal file
BIN
rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr
vendored
Normal file
Binary file not shown.
BIN
rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr
vendored
Normal file
BIN
rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr
vendored
Normal file
Binary file not shown.
13
rostests/apitests/dbghelp/testlist.c
Normal file
13
rostests/apitests/dbghelp/testlist.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
#define STANDALONE
|
||||
#include <wine/test.h>
|
||||
|
||||
extern void func_pdb(void);
|
||||
extern void func_rsym(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "pdb", func_pdb },
|
||||
{ "rsym", func_rsym },
|
||||
{ 0, 0 }
|
||||
};
|
Loading…
Reference in a new issue