2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for dbghelp rsym functions
5 * PROGRAMMER: Mark Jansen
7 * These tests are based on the PDB tests.
11 #define WIN32_NO_STATUS
14 #include <cvconst.h> // SymTagXXX
17 #include "wine/test.h"
19 #define ok_ulonglong(expression, result) \
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)); \
27 #define ok_ulonglong_(file, line, expression, result) \
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)); \
35 #define ok_hex_(file, line, expression, result) \
37 int _value = (expression); \
38 ok_(file, line)(_value == (result), "Wrong value for '%s', expected: " #result " (0x%x), got: 0x%x\n", \
39 #expression, (int)(result), _value); \
42 #define ok_str_(file, line, x, y) \
43 ok_(file, line)(strcmp(x, y) == 0, "Wrong string. Expected '%s', got '%s'\n", y, x)
47 void dump_rsym(const char* filename
);
48 int extract_gcc_exe(char szFile
[MAX_PATH
]);
49 void cleanup_gcc_exe();
53 return GetCurrentProcess();
56 static BOOL
init_sym_imp(const char* file
, int line
)
58 if (!SymInitialize(proc(), NULL
, FALSE
))
60 DWORD err
= GetLastError();
61 ok_(file
, line
)(0, "Failed to init: 0x%x\n", err
);
67 static void deinit_sym()
72 static BOOL
supports_rsym(HANDLE hProc
, DWORD64 BaseAddress
)
74 IMAGEHLP_MODULE64 ModuleInfo
;
77 memset(&ModuleInfo
, 0, sizeof(ModuleInfo
));
78 ModuleInfo
.SizeOfStruct
= sizeof(ModuleInfo
);
79 Ret
= SymGetModuleInfo64(hProc
, BaseAddress
, &ModuleInfo
);
82 ModuleInfo
.SymType
== SymDia
&&
83 ModuleInfo
.CVSig
== ('R' | ('S' << 8) | ('Y' << 16) | ('M' << 24));
86 #define init_sym() init_sym_imp(__FILE__, __LINE__)
88 #define INIT_PSYM(buff) do { \
89 memset((buff), 0, sizeof((buff))); \
90 ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \
91 ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \
95 static void test_SymFromName(HANDLE hProc
, const char* szModuleName
)
98 char buffer
[sizeof(SYMBOL_INFO
) + MAX_SYM_NAME
* sizeof(TCHAR
)];
99 PSYMBOL_INFO pSymbol
= (PSYMBOL_INFO
)buffer
;
107 SetLastError(ERROR_SUCCESS
);
108 BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
109 dwErr
= GetLastError();
111 if (supports_rsym(hProc
, BaseAddress
))
113 ok_ulonglong(BaseAddress
, 0x600000);
114 ok_hex(dwErr
, ERROR_SUCCESS
);
117 Ret
= SymFromName(hProc
, "DllMain", pSymbol
);
119 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
120 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
121 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1000);
122 ok_hex(pSymbol
->Tag
, SymTagFunction
);
123 ok_str(pSymbol
->Name
, "DllMain");
126 Ret
= SymFromName(hProc
, "FfsChkdsk", pSymbol
);
128 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
129 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
130 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x103F);
131 ok_hex(pSymbol
->Tag
, SymTagFunction
);
132 ok_str(pSymbol
->Name
, "FfsChkdsk");
135 Ret
= SymFromName(hProc
, "FfsFormat", pSymbol
);
137 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
138 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
139 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x100C);
140 ok_hex(pSymbol
->Tag
, SymTagFunction
);
141 ok_str(pSymbol
->Name
, "FfsFormat");
145 skip("dbghelp.dll cannot parse rsym\n");
151 static void test_SymFromAddr(HANDLE hProc
, const char* szModuleName
)
154 char buffer
[sizeof(SYMBOL_INFO
) + MAX_SYM_NAME
* sizeof(TCHAR
)];
155 PSYMBOL_INFO pSymbol
= (PSYMBOL_INFO
)buffer
;
157 DWORD64 BaseAddress
, Displacement
;
163 SetLastError(ERROR_SUCCESS
);
164 BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
165 dwErr
= GetLastError();
167 if (supports_rsym(hProc
, BaseAddress
))
169 ok_ulonglong(BaseAddress
, 0x600000);
170 ok_hex(dwErr
, ERROR_SUCCESS
);
172 /* No address found before load address of module */
175 Ret
= SymFromAddr(hProc
, BaseAddress
-1, &Displacement
, pSymbol
);
176 dwErr
= GetLastError();
178 ok_hex(dwErr
, ERROR_MOD_NOT_FOUND
);
180 /* Right at the start of the module is recognized as the first symbol found */
183 Ret
= SymFromAddr(hProc
, BaseAddress
, &Displacement
, pSymbol
);
184 /* Our dbghelp.dll does not recognize this yet */
188 ok_ulonglong(Displacement
, 0xffffffffffffffff);
189 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
190 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
191 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1000);
192 ok_hex(pSymbol
->Tag
, SymTagFunction
);
193 ok_str(pSymbol
->Name
, "DllMain");
196 /* The actual first instruction of the function */
199 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x1000, &Displacement
, pSymbol
);
201 ok_ulonglong(Displacement
, 0);
202 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
203 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
204 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1000);
205 ok_hex(pSymbol
->Tag
, SymTagFunction
);
206 ok_str(pSymbol
->Name
, "DllMain");
208 /* The last instruction in the function */
211 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x1009, &Displacement
, pSymbol
);
213 ok_ulonglong(Displacement
, 0x9);
214 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
215 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
216 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x1000);
217 ok_hex(pSymbol
->Tag
, SymTagFunction
);
218 ok_str(pSymbol
->Name
, "DllMain");
220 /* First byte of the next function */
223 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x103F, &Displacement
, pSymbol
);
225 ok_ulonglong(Displacement
, 0);
226 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
227 ok_hex(pSymbol
->Flags
, SYMFLAG_FUNCTION
);
228 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x103F);
229 ok_hex(pSymbol
->Tag
, SymTagFunction
);
230 ok_str(pSymbol
->Name
, "FfsChkdsk");
235 Ret
= SymFromAddr(hProc
, BaseAddress
+ 0x4000, &Displacement
, pSymbol
);
237 ok_ulonglong(Displacement
, 0);
238 ok_ulonglong(pSymbol
->ModBase
, BaseAddress
);
239 ok_hex(pSymbol
->Flags
, SYMFLAG_EXPORT
);
240 ok_ulonglong(pSymbol
->Address
, BaseAddress
+ 0x4000);
241 ok_hex(pSymbol
->Tag
, SymTagPublicSymbol
);
242 ok_str(pSymbol
->Name
, "_head_dll_ntdll_libntdll_a");
246 skip("dbghelp.dll cannot parse rsym\n");
252 typedef struct _test_context
258 static struct _test_data
{
259 DWORD64 AddressOffset
;
266 /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */
267 { 0x107c, 0, SymTagPublicSymbol
, "__CTOR_LIST__", __LINE__
},
268 { 0x2074, 0, SymTagPublicSymbol
, "__RUNTIME_PSEUDO_RELOC_LIST_END__", __LINE__
},
269 { 0x1000, 12, SymTagPublicSymbol
, "EntryPoint", __LINE__
},
270 { 0x100c, 51, SymTagFunction
, "FfsFormat", __LINE__
},
271 { 0x4030, 0, SymTagPublicSymbol
, "_imp__DbgPrint", __LINE__
},
272 { 0x1084, 0, SymTagPublicSymbol
, "__DTOR_LIST__", __LINE__
},
273 { 0x103f, 53, SymTagFunction
, "FfsChkdsk", __LINE__
},
274 { 0x2074, 0, SymTagPublicSymbol
, "_rt_psrelocs_end", __LINE__
},
275 { 0x103f, 53, SymTagPublicSymbol
, "ChkdskEx", __LINE__
},
276 { 0x4048, 0, SymTagPublicSymbol
, "_dll_ntdll_libntdll_a_iname", __LINE__
},
280 { 0x2074, 0, SymTagPublicSymbol
, "_rt_psrelocs_start", __LINE__
},
281 { 0x1000, 12, SymTagFunction
, "DllMain", __LINE__
},
282 { 0x100c, 0, SymTagPublicSymbol
, "FormatEx", __LINE__
},
283 { 0x1074, 0, SymTagPublicSymbol
, "DbgPrint", __LINE__
},
284 { 0x68900000, 0, SymTagPublicSymbol
, "__ImageBase", __LINE__
},
285 { 0x68902074, 0, SymTagPublicSymbol
, "__RUNTIME_PSEUDO_RELOC_LIST__", __LINE__
},
286 { 0x4000, 0, SymTagPublicSymbol
, "_head_dll_ntdll_libntdll_a", __LINE__
},
289 BOOL CALLBACK
EnumSymProc(PSYMBOL_INFO pSymInfo
, ULONG SymbolSize
, PVOID UserContext
)
291 test_context
* ctx
= UserContext
;
293 if (ctx
->Index
< ARRAYSIZE(test_data
))
295 ok_ulonglong_(__FILE__
, test_data
[ctx
->Index
].Line
, pSymInfo
->ModBase
, ctx
->BaseAddress
);
296 if (test_data
[ctx
->Index
].AddressOffset
> 0x100000)
297 ok_ulonglong_(__FILE__
, test_data
[ctx
->Index
].Line
, pSymInfo
->Address
, test_data
[ctx
->Index
].AddressOffset
);
299 ok_ulonglong_(__FILE__
, test_data
[ctx
->Index
].Line
, pSymInfo
->Address
, ctx
->BaseAddress
+ test_data
[ctx
->Index
].AddressOffset
);
300 ok_hex_(__FILE__
, test_data
[ctx
->Index
].Line
, pSymInfo
->Tag
, test_data
[ctx
->Index
].Tag
);
301 ok_str_(__FILE__
, test_data
[ctx
->Index
].Line
, pSymInfo
->Name
, test_data
[ctx
->Index
].Name
);
307 ok(0, "Out of bounds (%lu), max is: %i!\n", ctx
->Index
, ARRAYSIZE(test_data
));
313 static void test_SymEnumSymbols(HANDLE hProc
, const char* szModuleName
)
324 SetLastError(ERROR_SUCCESS
);
325 ctx
.BaseAddress
= SymLoadModule64(hProc
, NULL
, szModuleName
, NULL
, 0x600000, 0);
326 dwErr
= GetLastError();
328 if (supports_rsym(hProc
, ctx
.BaseAddress
))
330 ok_ulonglong(ctx
.BaseAddress
, 0x600000);
331 ok_hex(dwErr
, ERROR_SUCCESS
);
333 Ret
= SymEnumSymbols(hProc
, ctx
.BaseAddress
, NULL
, EnumSymProc
, &ctx
);
335 ok_int(ctx
.Index
, ARRAYSIZE(test_data
));
339 skip("dbghelp.dll cannot parse rsym\n");
350 char szDllName
[MAX_PATH
];
351 //dump_rsym("R:\\src\\trunk\\reactos\\modules\\rostests\\apitests\\dbghelp\\testdata\\gcc_uffs.dll");
353 DWORD Options
= SymGetOptions();
354 Options
&= ~(SYMOPT_UNDNAME
);
355 //Options |= SYMOPT_DEBUG;
356 SymSetOptions(Options
);
358 if (!extract_gcc_exe(szDllName
))
360 ok(0, "Failed extracting files\n");
364 test_SymFromName(proc(), szDllName
);
365 test_SymFromAddr(proc(), szDllName
);
366 test_SymEnumSymbols(proc(), szDllName
);