2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for dbghelp PDB functions
5 * PROGRAMMER: Mark Jansen
9 #define WIN32_NO_STATUS
12 #include <cvconst.h> // SymTagXXX
15 #include "wine/test.h"
17 #define ok_ulonglong(expression, result) \
19 ULONG64 _value = (expression); \
20 ULONG64 _result = (result); \
21 ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \
22 #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \
27 void create_compressed_files();
28 int extract_msvc_exe(char szFile
[MAX_PATH
]);
29 void cleanup_msvc_exe();
33 return GetCurrentProcess();
36 static BOOL
init_sym_imp(const char* file
, int line
)
38 if (!SymInitialize(proc(), NULL
, FALSE
))
40 DWORD err
= GetLastError();
41 ok_(file
, line
)(0, "Failed to init: 0x%x\n", err
);
47 static void deinit_sym()
52 #define init_sym() init_sym_imp(__FILE__, __LINE__)
54 #define INIT_PSYM(buff) do { \
55 memset((buff), 0, sizeof((buff))); \
56 ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \
57 ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \
61 /* Maybe our dbghelp.dll is too old? */
62 static BOOL
can_enumerate(HANDLE hProc
, DWORD64 BaseAddress
)
64 IMAGEHLP_MODULE64 ModuleInfo
;
67 memset(&ModuleInfo
, 0, sizeof(ModuleInfo
));
68 ModuleInfo
.SizeOfStruct
= sizeof(ModuleInfo
);
69 Ret
= SymGetModuleInfo64(hProc
, BaseAddress
, &ModuleInfo
);
71 return Ret
&& ModuleInfo
.SymType
== SymPdb
;
75 static void test_SymFromName(HANDLE hProc
, const char* szModuleName
)
78 char buffer
[sizeof(SYMBOL_INFO
) + MAX_SYM_NAME
* sizeof(TCHAR
)];
79 PSYMBOL_INFO pSymbol
= (PSYMBOL_INFO
)buffer
;
87 SetLastError(ERROR_SUCCESS
);
88 BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
89 dwErr
= GetLastError();
91 ok_ulonglong(BaseAddress
, 0x600000);
92 ok_hex(dwErr
, ERROR_SUCCESS
);
94 if (!can_enumerate(hProc
, BaseAddress
))
96 skip("dbghelp.dll too old or cannot enumerate symbols!\n");
101 Ret
= SymFromName(hProc
, "DllMain", pSymbol
);
103 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
104 ok_hex(pSymbol
->Flags
, 0);
105 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
106 ok_hex(pSymbol
->Tag
, SymTagFunction
);
107 ok_str(pSymbol
->Name
, "DllMain");
110 Ret
= SymFromName(hProc
, "_DllMain@12", pSymbol
);
112 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
113 ok_hex(pSymbol
->Flags
, 0x400000); // ??
114 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
115 ok_hex(pSymbol
->Tag
, SymTagPublicSymbol
);
116 ok_str(pSymbol
->Name
, "_DllMain@12");
119 Ret
= SymFromName(hProc
, "FfsChkdsk", pSymbol
);
121 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
122 ok_hex(pSymbol
->Flags
, 0);
123 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1040);
124 ok_hex(pSymbol
->Tag
, SymTagFunction
);
125 ok_str(pSymbol
->Name
, "FfsChkdsk");
128 Ret
= SymFromName(hProc
, "_FfsChkdsk@24", pSymbol
);
130 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
131 ok_hex(pSymbol
->Flags
, 0x400000); // ??
132 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1040);
133 ok_hex(pSymbol
->Tag
, SymTagPublicSymbol
);
134 ok_str(pSymbol
->Name
, "_FfsChkdsk@24");
137 Ret
= SymFromName(hProc
, "FfsFormat", pSymbol
);
139 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
140 ok_hex(pSymbol
->Flags
, 0);
141 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1070);
142 ok_hex(pSymbol
->Tag
, SymTagFunction
);
143 ok_str(pSymbol
->Name
, "FfsFormat");
146 Ret
= SymFromName(hProc
, "_FfsFormat@24", pSymbol
);
148 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
149 ok_hex(pSymbol
->Flags
, 0x400000); // ??
150 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1070);
151 ok_hex(pSymbol
->Tag
, SymTagPublicSymbol
);
152 ok_str(pSymbol
->Name
, "_FfsFormat@24");
158 static void test_SymFromAddr(HANDLE hProc
, const char* szModuleName
)
161 char buffer
[sizeof(SYMBOL_INFO
) + MAX_SYM_NAME
* sizeof(TCHAR
)];
162 PSYMBOL_INFO pSymbol
= (PSYMBOL_INFO
)buffer
;
164 DWORD64 BaseAddress
, Displacement
;
170 SetLastError(ERROR_SUCCESS
);
171 BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
172 dwErr
= GetLastError();
174 ok_ulonglong(BaseAddress
, 0x600000);
175 ok_hex(dwErr
, ERROR_SUCCESS
);
177 /* No address found before load address of module */
180 Ret
= SymFromAddr(hProc
, BaseAddress
-1, &Displacement
, pSymbol
);
181 dwErr
= GetLastError();
183 ok_hex(dwErr
, ERROR_MOD_NOT_FOUND
);
185 /* Right at the start of the module is recognized as the first symbol found */
188 Ret
= SymFromAddr(hProc
, BaseAddress
, &Displacement
, pSymbol
);
190 ok_ulonglong(Displacement
, 0xffffffffffffffff);
191 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
192 ok_hex(pSymbol
->Flags
, 0);
193 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
194 ok_hex(pSymbol
->Tag
, SymTagFunction
);
195 ok_str(pSymbol
->Name
, "DllMain");
197 /* The actual first instruction of the function */
200 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x1010, &Displacement
, pSymbol
);
202 ok_ulonglong(Displacement
, 0);
203 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
204 ok_hex(pSymbol
->Flags
, 0);
205 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
206 ok_hex(pSymbol
->Tag
, SymTagFunction
);
207 ok_str(pSymbol
->Name
, "DllMain");
209 /* The last instruction in the function */
212 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x102D, &Displacement
, pSymbol
);
214 ok_ulonglong(Displacement
, 0x1d);
215 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
216 ok_hex(pSymbol
->Flags
, 0);
217 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
218 ok_hex(pSymbol
->Tag
, SymTagFunction
);
219 ok_str(pSymbol
->Name
, "DllMain");
221 /* The padding below the function */
224 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x102E, &Displacement
, pSymbol
);
226 ok_ulonglong(Displacement
, 0x1e);
227 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
228 ok_hex(pSymbol
->Flags
, 0);
229 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
230 ok_hex(pSymbol
->Tag
, SymTagFunction
);
231 ok_str(pSymbol
->Name
, "DllMain");
233 /* One byte before the next function */
236 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x103f, &Displacement
, pSymbol
);
238 ok_ulonglong(Displacement
, 0x2f);
239 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
240 ok_hex(pSymbol
->Flags
, 0);
241 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1010);
242 ok_hex(pSymbol
->Tag
, SymTagFunction
);
243 ok_str(pSymbol
->Name
, "DllMain");
245 /* First byte of the next function */
248 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x1040, &Displacement
, pSymbol
);
250 ok_ulonglong(Displacement
, 0);
251 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
252 ok_hex(pSymbol
->Flags
, 0);
253 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1040);
254 ok_hex(pSymbol
->Tag
, SymTagFunction
);
255 ok_str(pSymbol
->Name
, "FfsChkdsk");
257 if (!can_enumerate(hProc
, BaseAddress
))
259 skip("dbghelp.dll too old or cannot read this symbol!\n");
266 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x2000, &Displacement
, pSymbol
);
268 ok_ulonglong(Displacement
, 0);
269 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
270 ok_hex(pSymbol
->Flags
, 0);
271 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x2000);
272 ok_hex(pSymbol
->Tag
, SymTagPublicSymbol
);
273 ok_str(pSymbol
->Name
, "__imp__DbgPrint");
279 typedef struct _test_context
285 static struct _test_data
{
286 DWORD64 AddressOffset
;
291 /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */
292 { 0x1070, 36, SymTagFunction
, "FfsFormat" },
293 { 0x1010, 32, SymTagFunction
, "DllMain" },
294 { 0x1040, 36, SymTagFunction
, "FfsChkdsk" },
296 { 0x2100, 0, SymTagPublicSymbol
, "__IMPORT_DESCRIPTOR_ntdll" },
297 { 0x109a, 0, SymTagPublicSymbol
, "_DbgPrint" },
298 { 0x2004, 0, SymTagPublicSymbol
, "\x7fntdll_NULL_THUNK_DATA" },
299 { 0x2000, 0, SymTagPublicSymbol
, "__imp__DbgPrint" },
300 { 0x2114, 0, SymTagPublicSymbol
, "__NULL_IMPORT_DESCRIPTOR" },
303 static BOOL CALLBACK
EnumSymProc(PSYMBOL_INFO pSymInfo
, ULONG SymbolSize
, PVOID UserContext
)
305 test_context
* ctx
= UserContext
;
307 if (ctx
->Index
< ARRAYSIZE(test_data
))
309 ok_ulonglong(pSymInfo
->ModBase
, ctx
->BaseAddress
);
310 ok_ulonglong(pSymInfo
->Address
, ctx
->BaseAddress
+ test_data
[ctx
->Index
].AddressOffset
);
311 ok_hex(pSymInfo
->Tag
, test_data
[ctx
->Index
].Tag
);
312 ok_str(pSymInfo
->Name
, test_data
[ctx
->Index
].Name
);
318 ok(0, "Out of bounds (%lu), max is: %i!\n", ctx
->Index
, ARRAYSIZE(test_data
));
324 static void test_SymEnumSymbols(HANDLE hProc
, const char* szModuleName
)
335 SetLastError(ERROR_SUCCESS
);
336 ctx
.BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
337 dwErr
= GetLastError();
339 ok_ulonglong(ctx
.BaseAddress
, 0x600000);
340 ok_hex(dwErr
, ERROR_SUCCESS
);
342 if (!can_enumerate(hProc
, ctx
.BaseAddress
))
344 skip("dbghelp.dll too old or cannot enumerate symbols!\n");
348 Ret
= SymEnumSymbols(hProc
, ctx
.BaseAddress
, NULL
, EnumSymProc
, &ctx
);
350 ok_int(ctx
.Index
, ARRAYSIZE(test_data
));
359 char szDllName
[MAX_PATH
];
360 //create_compressed_files();
362 DWORD Options
= SymGetOptions();
363 Options
&= ~(SYMOPT_UNDNAME
);
364 //Options |= SYMOPT_DEBUG;
365 SymSetOptions(Options
);
367 if (!extract_msvc_exe(szDllName
))
369 ok(0, "Failed extracting files\n");
373 test_SymFromName(proc(), szDllName
);
374 test_SymFromAddr(proc(), szDllName
);
375 test_SymEnumSymbols(proc(), szDllName
);