ReactOS 0.4.16-dev-197-g92996da
dbghelp.c
Go to the documentation of this file.
1/*
2 * Copyright 2018 Zebediah Figura
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "windef.h"
20#include "verrsrc.h"
21#include "dbghelp.h"
22#include "wine/test.h"
23
24#if defined(__i386__) || defined(__x86_64__)
25
26static DWORD CALLBACK stack_walk_thread(void *arg)
27{
29 ok(!count, "got %d\n", count);
30 return 0;
31}
32
33static void test_stack_walk(void)
34{
35 char si_buf[sizeof(SYMBOL_INFO) + 200];
36 SYMBOL_INFO *si = (SYMBOL_INFO *)si_buf;
37 STACKFRAME64 frame = {{0}}, frame0;
38 BOOL found_our_frame = FALSE;
41 DWORD64 disp;
44 BOOL ret;
45
46 thread = CreateThread(NULL, 0, stack_walk_thread, NULL, 0, NULL);
47
48 /* wait for the thread to suspend itself */
49 do
50 {
51 Sleep(50);
54 }
55 while (!count);
56
57 ctx.ContextFlags = CONTEXT_CONTROL;
59 ok(ret, "got error %u\n", ret);
60
61 frame.AddrPC.Mode = AddrModeFlat;
64
65#ifdef __i386__
67
68 frame.AddrPC.Segment = ctx.SegCs;
69 frame.AddrPC.Offset = ctx.Eip;
70 frame.AddrFrame.Segment = ctx.SegSs;
71 frame.AddrFrame.Offset = ctx.Ebp;
72 frame.AddrStack.Segment = ctx.SegSs;
73 frame.AddrStack.Offset = ctx.Esp;
74#elif defined(__x86_64__)
76
77 frame.AddrPC.Segment = ctx.SegCs;
78 frame.AddrPC.Offset = ctx.Rip;
79 frame.AddrFrame.Segment = ctx.SegSs;
80 frame.AddrFrame.Offset = ctx.Rbp;
81 frame.AddrStack.Segment = ctx.SegSs;
82 frame.AddrStack.Offset = ctx.Rsp;
83#endif
84 frame0 = frame;
85
86 /* first invocation just calculates the return address */
89 ok(ret, "StackWalk64() failed: %u\n", GetLastError());
90 ok(frame.AddrPC.Offset == frame0.AddrPC.Offset, "expected %s, got %s\n",
91 wine_dbgstr_longlong(frame0.AddrPC.Offset),
93 ok(frame.AddrStack.Offset == frame0.AddrStack.Offset, "expected %s, got %s\n",
94 wine_dbgstr_longlong(frame0.AddrStack.Offset),
96 ok(frame.AddrReturn.Offset && frame.AddrReturn.Offset != frame.AddrPC.Offset,
97 "got bad return address %s\n", wine_dbgstr_longlong(frame.AddrReturn.Offset));
98
99 while (frame.AddrReturn.Offset)
100 {
101 char *addr;
102
105 ok(ret, "StackWalk64() failed: %u\n", GetLastError());
106
107 addr = (void *)(DWORD_PTR)frame.AddrPC.Offset;
108
109 if (addr > (char *)stack_walk_thread && addr < (char *)stack_walk_thread + 0x100)
110 {
111 found_our_frame = TRUE;
112
113 si->SizeOfStruct = sizeof(SYMBOL_INFO);
114 si->MaxNameLen = 200;
115 if (SymFromAddr(GetCurrentProcess(), frame.AddrPC.Offset, &disp, si))
116 ok(!strcmp(si->Name, "stack_walk_thread"), "got wrong name %s\n", si->Name);
117 }
118 }
119
122 ok(!ret, "StackWalk64() should have failed\n");
123
124 ok(found_our_frame, "didn't find stack_walk_thread frame\n");
125}
126
127#else /* __i386__ || __x86_64__ */
128
129static void test_stack_walk(void)
130{
131}
132
133#endif /* __i386__ || __x86_64__ */
134
135static void test_search_path(void)
136{
137 char search_path[128];
138 BOOL ret;
139
140 /* The default symbol path is ".[;%_NT_SYMBOL_PATH%][;%_NT_ALT_SYMBOL_PATH%]".
141 * We unset both variables earlier so should simply get "." */
142 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
143 ok(ret == TRUE, "ret = %d\n", ret);
144 ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
145
146 /* Set an arbitrary search path */
148 ok(ret == TRUE, "ret = %d\n", ret);
149 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
150 ok(ret == TRUE, "ret = %d\n", ret);
151 ok(!strcmp(search_path, "W:\\"), "Got search path '%s', expected 'W:\\'\n", search_path);
152
153 /* Setting to NULL resets to the default */
155 ok(ret == TRUE, "ret = %d\n", ret);
156 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
157 ok(ret == TRUE, "ret = %d\n", ret);
158 ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
159
160 /* With _NT_SYMBOL_PATH */
161 SetEnvironmentVariableA("_NT_SYMBOL_PATH", "X:\\");
163 ok(ret == TRUE, "ret = %d\n", ret);
164 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
165 ok(ret == TRUE, "ret = %d\n", ret);
166 ok(!strcmp(search_path, ".;X:\\"), "Got search path '%s', expected '.;X:\\'\n", search_path);
167
168 /* With both _NT_SYMBOL_PATH and _NT_ALT_SYMBOL_PATH */
169 SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", "Y:\\");
171 ok(ret == TRUE, "ret = %d\n", ret);
172 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
173 ok(ret == TRUE, "ret = %d\n", ret);
174 ok(!strcmp(search_path, ".;X:\\;Y:\\"), "Got search path '%s', expected '.;X:\\;Y:\\'\n", search_path);
175
176 /* With just _NT_ALT_SYMBOL_PATH */
177 SetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL);
179 ok(ret == TRUE, "ret = %d\n", ret);
180 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
181 ok(ret == TRUE, "ret = %d\n", ret);
182 ok(!strcmp(search_path, ".;Y:\\"), "Got search path '%s', expected '.;Y:\\'\n", search_path);
183
184 /* Restore original search path */
185 SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", NULL);
187 ok(ret == TRUE, "ret = %d\n", ret);
188 ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
189 ok(ret == TRUE, "ret = %d\n", ret);
190 ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
191}
192
194{
195 BOOL ret;
196
197 /* Don't let the user's environment influence our symbol path */
198 SetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL);
199 SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", NULL);
200
202 ok(ret, "got error %u\n", GetLastError());
203
206
208 ok(ret, "got error %u\n", GetLastError());
209}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, PSYMBOL_INFO Symbol)
Definition: symbol.c:1263
PVOID WINAPI SymFunctionTableAccess64(HANDLE, DWORD64)
Definition: module.c:1371
DWORD64 WINAPI SymGetModuleBase64(HANDLE, DWORD64)
Definition: module.c:1313
@ AddrModeFlat
Definition: compat.h:1159
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GetCurrentProcess()
Definition: compat.h:759
struct _SYMBOL_INFO SYMBOL_INFO
#define CALLBACK
Definition: compat.h:35
BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PCSTR searchPath)
Definition: dbghelp.c:263
BOOL WINAPI SymCleanup(HANDLE hProcess)
Definition: dbghelp.c:557
BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:534
BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath, DWORD SearchPathLength)
Definition: dbghelp.c:299
BOOL WINAPI StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 frame, PVOID ctx, PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr)
Definition: stack.c:210
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum const GLvoid * addr
Definition: glext.h:9621
static void test_stack_walk(void)
Definition: dbghelp.c:129
static void test_search_path(void)
Definition: dbghelp.c:135
static const char machine[]
Definition: profile.c:104
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
ADDRESS64 AddrStack
Definition: compat.h:1404
ADDRESS64 AddrFrame
Definition: compat.h:1403
ADDRESS64 AddrPC
Definition: compat.h:1401
ADDRESS64 AddrReturn
Definition: compat.h:1402
WORD Segment
Definition: compat.h:1175
ADDRESS_MODE Mode
Definition: compat.h:1176
DWORD64 Offset
Definition: compat.h:1174
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint64_t DWORD64
Definition: typedefs.h:67
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148