ReactOS  0.4.14-dev-1331-g167fa2c
rsym.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Test for dbghelp rsym functions
5  * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
6  *
7  * These tests are based on the PDB tests.
8  */
9 
10 #include <ntstatus.h>
11 #define WIN32_NO_STATUS
12 #include <windows.h>
13 #include <dbghelp.h>
14 #include <cvconst.h> // SymTagXXX
15 #include <stdio.h>
16 
17 #include "wine/test.h"
18 
19 #define ok_ulonglong(expression, result) \
20  do { \
21  ULONG64 _value = (expression); \
22  ULONG64 _result = (result); \
23  ok(_value == _result, "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \
24  #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \
25  } while (0)
26 
27 #define ok_ulonglong_(file, line, expression, result) \
28  do { \
29  ULONG64 _value = (expression); \
30  ULONG64 _result = (result); \
31  ok_(file, line)(_value == _result, "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \
32  #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \
33  } while (0)
34 
35 
36 // data.c
37 void dump_rsym(const char* filename);
38 int extract_gcc_dll(char szFile[MAX_PATH]);
39 void cleanup_gcc_dll();
40 
41 static HANDLE proc()
42 {
43  return GetCurrentProcess();
44 }
45 
46 static BOOL init_sym_imp(BOOL fInvadeProcess, const char* file, int line)
47 {
48  if (!SymInitialize(proc(), NULL, fInvadeProcess))
49  {
51  ok_(file, line)(0, "Failed to init: 0x%x\n", err);
52  return FALSE;
53  }
54  return TRUE;
55 }
56 
57 static void deinit_sym()
58 {
59  SymCleanup(proc());
60 }
61 
62 #define init_sym(fInvadeProcess) init_sym_imp(fInvadeProcess, __FILE__, __LINE__)
63 
64 #define INIT_PSYM(buff) do { \
65  memset((buff), 0, sizeof((buff))); \
66  ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \
67  ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \
68 } while (0)
69 
71 {
72  IMAGEHLP_MODULE64 ModuleInfo;
73  BOOL Ret;
74 
75  memset(&ModuleInfo, 0, sizeof(ModuleInfo));
76  ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
77  Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo);
78 
79  return Ret &&
80  ModuleInfo.SymType == SymDia &&
81  ModuleInfo.CVSig == ('R' | ('S' << 8) | ('Y' << 16) | ('M' << 24));
82 }
83 
84 
86 {
87  BOOL Ret;
88  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
89  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
90 
91  if (!supports_rsym(hProc, BaseAddress))
92  {
93  skip("dbghelp.dll cannot parse rsym\n");
94  }
95  else
96  {
98  Ret = SymFromName(hProc, "DllMain", pSymbol);
99  ok_int(Ret, TRUE);
100  ok_ulonglong(pSymbol->ModBase, BaseAddress);
101  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
102  ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000);
103  ok_hex(pSymbol->Tag, SymTagFunction);
104  ok_str(pSymbol->Name, "DllMain");
105 
106  INIT_PSYM(buffer);
107  Ret = SymFromName(hProc, "FfsChkdsk", pSymbol);
108  ok_int(Ret, TRUE);
109  ok_ulonglong(pSymbol->ModBase, BaseAddress);
110  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
111  ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F);
112  ok_hex(pSymbol->Tag, SymTagFunction);
113  ok_str(pSymbol->Name, "FfsChkdsk");
114 
115  INIT_PSYM(buffer);
116  Ret = SymFromName(hProc, "FfsFormat", pSymbol);
117  ok_int(Ret, TRUE);
118  ok_ulonglong(pSymbol->ModBase, BaseAddress);
119  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
120  ok_ulonglong(pSymbol->Address, BaseAddress + 0x100C);
121  ok_hex(pSymbol->Tag, SymTagFunction);
122  ok_str(pSymbol->Name, "FfsFormat");
123  }
124 }
125 
127 {
128  BOOL Ret;
129  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
130  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
131 
132  DWORD64 Displacement;
133  DWORD dwErr;
134 
135  if (!supports_rsym(hProc, BaseAddress))
136  {
137  skip("dbghelp.dll cannot parse rsym\n");
138  }
139  else
140  {
141  /* No address found before load address of module */
142  Displacement = 0;
143  INIT_PSYM(buffer);
144  Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol);
145  dwErr = GetLastError();
146  ok_int(Ret, FALSE);
148 
149  /* Right at the start of the module is recognized as the first symbol found */
150  Displacement = 0;
151  INIT_PSYM(buffer);
152  Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol);
153  /* Our dbghelp.dll does not recognize this yet */
154  todo_if(!Ret)
155  {
156  ok_int(Ret, TRUE);
157  ok_ulonglong(Displacement, 0xffffffffffffffff);
158  ok_ulonglong(pSymbol->ModBase, BaseAddress);
159  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
160  ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000);
161  ok_hex(pSymbol->Tag, SymTagFunction);
162  ok_str(pSymbol->Name, "DllMain");
163  }
164 
165  /* The actual first instruction of the function */
166  Displacement = 0;
167  INIT_PSYM(buffer);
168  Ret = SymFromAddr(hProc, BaseAddress + 0x1000, &Displacement, pSymbol);
169  ok_int(Ret, TRUE);
170  ok_ulonglong(Displacement, 0);
171  ok_ulonglong(pSymbol->ModBase, BaseAddress);
172  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
173  ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000);
174  ok_hex(pSymbol->Tag, SymTagFunction);
175  ok_str(pSymbol->Name, "DllMain");
176 
177  /* The last instruction in the function */
178  Displacement = 0;
179  INIT_PSYM(buffer);
180  Ret = SymFromAddr(hProc, BaseAddress + 0x1009, &Displacement, pSymbol);
181  ok_int(Ret, TRUE);
182  ok_ulonglong(Displacement, 0x9);
183  ok_ulonglong(pSymbol->ModBase, BaseAddress);
184  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
185  ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000);
186  ok_hex(pSymbol->Tag, SymTagFunction);
187  ok_str(pSymbol->Name, "DllMain");
188 
189  /* First byte of the next function */
190  Displacement = 0;
191  INIT_PSYM(buffer);
192  Ret = SymFromAddr(hProc, BaseAddress + 0x103F, &Displacement, pSymbol);
193  ok_int(Ret, TRUE);
194  ok_ulonglong(Displacement, 0);
195  ok_ulonglong(pSymbol->ModBase, BaseAddress);
196  ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
197  ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F);
198  ok_hex(pSymbol->Tag, SymTagFunction);
199  ok_str(pSymbol->Name, "FfsChkdsk");
200 
201  /* .idata */
202  Displacement = 0;
203  INIT_PSYM(buffer);
204  Ret = SymFromAddr(hProc, BaseAddress + 0x4000, &Displacement, pSymbol);
205  ok_int(Ret, TRUE);
206  ok_ulonglong(Displacement, 0);
207  ok_ulonglong(pSymbol->ModBase, BaseAddress);
208  ok_hex(pSymbol->Flags, SYMFLAG_EXPORT);
209  ok_ulonglong(pSymbol->Address, BaseAddress + 0x4000);
210  ok_hex(pSymbol->Tag, SymTagPublicSymbol);
211  ok_str(pSymbol->Name, "_head_dll_ntdll_libntdll_a");
212  }
213 }
214 
215 typedef struct _test_context
216 {
218  SIZE_T Index;
219 } test_context;
220 
221 static struct _test_data {
223  ULONG Size;
224  ULONG Tag;
225  const char* Name;
226  int Line;
227 } test_data[] = {
228 
229  /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */
230  { 0x107c, 0, SymTagPublicSymbol, "__CTOR_LIST__", __LINE__ },
231  { 0x2074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST_END__", __LINE__ },
232  { 0x1000, 12, SymTagPublicSymbol, "EntryPoint", __LINE__ },
233  { 0x100c, 51, SymTagFunction, "FfsFormat", __LINE__ },
234  { 0x4030, 0, SymTagPublicSymbol, "_imp__DbgPrint", __LINE__ },
235  { 0x1084, 0, SymTagPublicSymbol, "__DTOR_LIST__", __LINE__ },
236  { 0x103f, 53, SymTagFunction, "FfsChkdsk", __LINE__ },
237  { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_end", __LINE__ },
238  { 0x103f, 53, SymTagPublicSymbol, "ChkdskEx", __LINE__ },
239  { 0x4048, 0, SymTagPublicSymbol, "_dll_ntdll_libntdll_a_iname", __LINE__ },
240 
241 
242 
243  { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_start", __LINE__ },
244  { 0x1000, 12, SymTagFunction, "DllMain", __LINE__ },
245  { 0x100c, 0, SymTagPublicSymbol, "FormatEx", __LINE__ },
246  { 0x1074, 0, SymTagPublicSymbol, "DbgPrint", __LINE__ },
247  { 0x68900000, 0, SymTagPublicSymbol, "__ImageBase", __LINE__ },
248  { 0x68902074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST__", __LINE__ },
249  { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a", __LINE__ },
250 };
251 
252 static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
253 {
254  test_context* ctx = UserContext;
255 
256  if (ctx->Index < ARRAYSIZE(test_data))
257  {
258  ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->ModBase, ctx->BaseAddress);
259  if (test_data[ctx->Index].AddressOffset > 0x100000)
260  ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address, test_data[ctx->Index].AddressOffset);
261  else
262  ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset);
263  ok_hex_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Tag, test_data[ctx->Index].Tag);
264  ok_str_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Name, test_data[ctx->Index].Name);
265 
266  ctx->Index++;
267  }
268  else
269  {
270  ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data));
271  }
272 
273  return TRUE;
274 }
275 
277 {
278  BOOL Ret;
279  test_context ctx;
280 
281  ctx.Index = 0;
282  ctx.BaseAddress = BaseAddress;
283 
284  if (!supports_rsym(hProc, ctx.BaseAddress))
285  {
286  skip("dbghelp.dll cannot parse rsym\n");
287  }
288  else
289  {
290  Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx);
291  ok_int(Ret, TRUE);
292  ok_int(ctx.Index, ARRAYSIZE(test_data));
293  }
294 }
295 
296 
298 {
299  char szDllName[MAX_PATH];
300 #ifdef _M_IX86
301  HMODULE hMod;
302 #endif
305 
307  Options &= ~(SYMOPT_UNDNAME);
308  //Options |= SYMOPT_DEBUG;
310 
312  {
313  ok(0, "Failed extracting files\n");
314  return;
315  }
316 
317  if (init_sym(FALSE))
318  {
320  BaseAddress = SymLoadModule64(proc(), NULL, szDllName, NULL, 0x600000, 0);
321  dwErr = GetLastError();
322 
323  ok_ulonglong(BaseAddress, 0x600000);
325 
326  if (BaseAddress == 0x600000)
327  {
328  trace("Module loaded by SymLoadModule64\n");
332  }
333 
334  deinit_sym();
335  }
336 
337 #ifdef _M_IX86
338  hMod = LoadLibraryA(szDllName);
339  if (hMod)
340  {
341  BaseAddress = (DWORD64)(DWORD_PTR)hMod;
342  /* Invade process */
343  if (init_sym(TRUE))
344  {
345  trace("Module loaded by LoadLibraryA\n");
349 
350  deinit_sym();
351  }
352 
353  FreeLibrary(hMod);
354  }
355 #endif
356  cleanup_gcc_dll();
357 }
BOOL WINAPI SymCleanup(HANDLE hProcess)
Definition: dbghelp.c:416
ULONG Tag
Definition: compat.h:706
SYM_TYPE SymType
Definition: compat.h:893
CHAR Name[1]
Definition: compat.h:709
#define TRUE
Definition: types.h:120
#define ok_ulonglong(expression, result)
Definition: rsym.c:19
Definition: compat.h:720
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ok_str(x, y)
Definition: atltest.h:127
static BOOL init_sym_imp(BOOL fInvadeProcess, const char *file, int line)
Definition: rsym.c:46
static const WCHAR szDllName[]
Definition: sip.c:61
DWORD WINAPI SymSetOptions(DWORD opts)
Definition: dbghelp.c:443
#define ok_hex_(expression, result)
static void test_SymFromAddr(HANDLE hProc, DWORD64 BaseAddress)
Definition: rsym.c:126
#define MAX_SYM_NAME
Definition: rsym.c:34
#define CALLBACK
Definition: compat.h:27
ULONG Flags
Definition: compat.h:701
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
ULONG64 Address
Definition: compat.h:703
#define INIT_PSYM(buff)
Definition: rsym.c:64
const char * filename
Definition: ioapi.h:135
enum OPTION_FLAGS Options
Definition: stats.c:44
#define ok_hex(expression, result)
Definition: atltest.h:94
static void deinit_sym()
Definition: rsym.c:57
struct _SYMBOL_INFO * PSYMBOL_INFO
unsigned int BOOL
Definition: ntddk_ex.h:94
static BOOL supports_rsym(HANDLE hProc, DWORD64 BaseAddress)
Definition: rsym.c:70
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
int Line
Definition: rsym.c:226
#define ok_ulonglong_(file, line, expression, result)
Definition: rsym.c:27
ULONG64 ModBase
Definition: compat.h:700
smooth NULL
Definition: ftsmooth.c:416
BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:393
#define ok_int(expression, result)
Definition: atltest.h:134
Definition: parser.c:48
DWORD SizeOfStruct
Definition: compat.h:887
void cleanup_gcc_dll()
Definition: data.c:120
START_TEST(rsym)
Definition: rsym.c:297
DWORD dwErr
Definition: service.c:36
DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
Definition: module.c:673
int extract_gcc_dll(char szFile[MAX_PATH])
Definition: data.c:107
char TCHAR
Definition: xmlstorage.h:189
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define FreeLibrary(x)
Definition: compat.h:413
ULONG Tag
Definition: pdb.c:424
#define trace
Definition: atltest.h:70
#define init_sym(fInvadeProcess)
Definition: rsym.c:62
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1138
#define todo_if(is_todo)
Definition: test.h:152
struct _SYMBOL_INFO SYMBOL_INFO
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:417
void dump_rsym(const char *filename)
#define SYMOPT_UNDNAME
Definition: compat.h:645
#define MAX_PATH
Definition: rsym.c:33
struct _test_context test_context
DWORD64 AddressOffset
Definition: pdb.c:422
#define ok_str_(file, line, x, y)
Definition: test.h:866
static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
Definition: rsym.c:252
#define err(...)
uint32_t DWORD_PTR
Definition: typedefs.h:64
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, PSYMBOL_INFO Symbol)
Definition: symbol.c:1271
#define SYMFLAG_FUNCTION
Definition: compat.h:661
ULONG_PTR SIZE_T
Definition: typedefs.h:79
uint64_t DWORD64
Definition: typedefs.h:66
const char * Name
Definition: pdb.c:425
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, PVOID UserContext)
Definition: symbol.c:1155
#define ok(value,...)
Definition: atltest.h:57
#define SYMFLAG_EXPORT
Definition: compat.h:659
static void test_SymFromName(HANDLE hProc, DWORD64 BaseAddress)
Definition: rsym.c:85
DWORD WINAPI SymGetOptions(void)
Definition: dbghelp.c:458
#define skip(...)
Definition: atltest.h:64
DWORD64 BaseAddress
Definition: pdb.c:417
static HANDLE proc()
Definition: rsym.c:41
#define ERROR_MOD_NOT_FOUND
Definition: compat.h:94
unsigned int ULONG
Definition: retypes.h:1
BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
Definition: symbol.c:1400
static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress)
Definition: rsym.c:276
#define memset(x, y, z)
Definition: compat.h:39
ULONG Size
Definition: pdb.c:423
BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, PIMAGEHLP_MODULE64 ModuleInfo)
Definition: module.c:1013
#define ok_(x1, x2)
Definition: atltest.h:61
SIZE_T Index
Definition: pdb.c:418
Definition: fci.c:126