Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/os/windows/windbghelp.cpp
40931 views
1
/*
2
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "utilities/ostream.hpp"
27
#include "windbghelp.hpp"
28
29
#include <windows.h>
30
31
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
32
typedef DWORD (WINAPI *pfn_SymGetOptions)(void);
33
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
34
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
35
typedef DWORD (WINAPI *pfn_UnDecorateSymbolName)(const char*, char*, DWORD, DWORD);
36
typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
37
typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
38
typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,
39
HANDLE hProcess,
40
HANDLE hThread,
41
LPSTACKFRAME64 StackFrame,
42
PVOID ContextRecord,
43
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
44
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
45
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
46
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
47
typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
48
typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);
49
typedef BOOL (WINAPI *pfn_MiniDumpWriteDump) (HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
50
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
51
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
52
PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
53
typedef BOOL (WINAPI *pfn_SymGetLineFromAddr64) (HANDLE hProcess, DWORD64 dwAddr,
54
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);
55
typedef LPAPI_VERSION (WINAPI *pfn_ImagehlpApiVersion)(void);
56
57
// Add functions as needed.
58
#define FOR_ALL_FUNCTIONS(DO) \
59
DO(ImagehlpApiVersion) \
60
DO(SymGetOptions) \
61
DO(SymSetOptions) \
62
DO(SymInitialize) \
63
DO(SymGetSymFromAddr64) \
64
DO(UnDecorateSymbolName) \
65
DO(SymSetSearchPath) \
66
DO(SymGetSearchPath) \
67
DO(StackWalk64) \
68
DO(SymFunctionTableAccess64) \
69
DO(SymGetModuleBase64) \
70
DO(MiniDumpWriteDump) \
71
DO(SymGetLineFromAddr64)
72
73
74
#define DECLARE_FUNCTION_POINTER(functionname) \
75
static pfn_##functionname g_pfn_##functionname;
76
77
FOR_ALL_FUNCTIONS(DECLARE_FUNCTION_POINTER)
78
79
80
static HMODULE g_dll_handle = NULL;
81
static DWORD g_dll_load_error = 0;
82
static API_VERSION g_version = { 0, 0, 0, 0 };
83
84
static enum {
85
state_uninitialized = 0,
86
state_ready = 1,
87
state_error = 2
88
} g_state = state_uninitialized;
89
90
static void initialize() {
91
92
assert(g_state == state_uninitialized, "wrong sequence");
93
g_state = state_error;
94
95
g_dll_handle = ::LoadLibrary("DBGHELP.DLL");
96
if (g_dll_handle == NULL) {
97
g_dll_load_error = ::GetLastError();
98
} else {
99
// Note: We loaded the DLL successfully. From here on we count
100
// initialization as success. We still may fail to load all of the
101
// desired function pointers successfully, but DLL may still be usable
102
// enough for our purposes.
103
g_state = state_ready;
104
105
#define DO_RESOLVE(functionname) \
106
g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);
107
108
FOR_ALL_FUNCTIONS(DO_RESOLVE)
109
110
// Retrieve version information.
111
if (g_pfn_ImagehlpApiVersion) {
112
const API_VERSION* p = g_pfn_ImagehlpApiVersion();
113
memcpy(&g_version, p, sizeof(API_VERSION));
114
}
115
}
116
117
}
118
119
120
///////////////////// External functions //////////////////////////
121
122
// All outside facing functions are synchronized. Also, we run
123
// initialization on first touch.
124
125
static CRITICAL_SECTION g_cs;
126
127
namespace { // Do not export.
128
class WindowsDbgHelpEntry {
129
public:
130
WindowsDbgHelpEntry() {
131
::EnterCriticalSection(&g_cs);
132
if (g_state == state_uninitialized) {
133
initialize();
134
}
135
}
136
~WindowsDbgHelpEntry() {
137
::LeaveCriticalSection(&g_cs);
138
}
139
};
140
}
141
142
// Called at DLL_PROCESS_ATTACH.
143
void WindowsDbgHelp::pre_initialize() {
144
::InitializeCriticalSection(&g_cs);
145
}
146
147
DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {
148
WindowsDbgHelpEntry entry_guard;
149
if (g_pfn_SymSetOptions != NULL) {
150
return g_pfn_SymSetOptions(arg);
151
}
152
return 0;
153
}
154
155
DWORD WindowsDbgHelp::symGetOptions(void) {
156
WindowsDbgHelpEntry entry_guard;
157
if (g_pfn_SymGetOptions != NULL) {
158
return g_pfn_SymGetOptions();
159
}
160
return 0;
161
}
162
163
BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {
164
WindowsDbgHelpEntry entry_guard;
165
if (g_pfn_SymInitialize != NULL) {
166
return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
167
}
168
return FALSE;
169
}
170
171
BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,
172
PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {
173
WindowsDbgHelpEntry entry_guard;
174
if (g_pfn_SymGetSymFromAddr64 != NULL) {
175
return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);
176
}
177
return FALSE;
178
}
179
180
DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,
181
DWORD UndecoratedLength, DWORD Flags) {
182
WindowsDbgHelpEntry entry_guard;
183
if (g_pfn_UnDecorateSymbolName != NULL) {
184
return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);
185
}
186
if (UnDecoratedName != NULL && UndecoratedLength > 0) {
187
UnDecoratedName[0] = '\0';
188
}
189
return 0;
190
}
191
192
BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {
193
WindowsDbgHelpEntry entry_guard;
194
if (g_pfn_SymSetSearchPath != NULL) {
195
return g_pfn_SymSetSearchPath(hProcess, SearchPath);
196
}
197
return FALSE;
198
}
199
200
BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {
201
WindowsDbgHelpEntry entry_guard;
202
if (g_pfn_SymGetSearchPath != NULL) {
203
return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
204
}
205
return FALSE;
206
}
207
208
BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,
209
HANDLE hProcess,
210
HANDLE hThread,
211
LPSTACKFRAME64 StackFrame,
212
PVOID ContextRecord) {
213
WindowsDbgHelpEntry entry_guard;
214
if (g_pfn_StackWalk64 != NULL) {
215
return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,
216
ContextRecord,
217
NULL, // ReadMemoryRoutine
218
g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,
219
g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine
220
NULL // TranslateAddressRoutine
221
);
222
}
223
return FALSE;
224
}
225
226
PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
227
WindowsDbgHelpEntry entry_guard;
228
if (g_pfn_SymFunctionTableAccess64 != NULL) {
229
return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);
230
}
231
return NULL;
232
}
233
234
DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {
235
WindowsDbgHelpEntry entry_guard;
236
if (g_pfn_SymGetModuleBase64 != NULL) {
237
return g_pfn_SymGetModuleBase64(hProcess, dwAddr);
238
}
239
return 0;
240
}
241
242
BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
243
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
244
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
245
PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
246
WindowsDbgHelpEntry entry_guard;
247
if (g_pfn_MiniDumpWriteDump != NULL) {
248
return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,
249
ExceptionParam, UserStreamParam, CallbackParam);
250
}
251
return FALSE;
252
}
253
254
BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
255
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {
256
WindowsDbgHelpEntry entry_guard;
257
if (g_pfn_SymGetLineFromAddr64 != NULL) {
258
return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);
259
}
260
return FALSE;
261
}
262
263
// Print one liner describing state (if library loaded, which functions are
264
// missing - if any, and the dbhelp API version)
265
void WindowsDbgHelp::print_state_on(outputStream* st) {
266
// Note: We should not lock while printing, but this should be
267
// safe to do without lock anyway.
268
st->print("dbghelp: ");
269
270
if (g_state == state_uninitialized) {
271
st->print("uninitialized.");
272
} else if (g_state == state_error) {
273
st->print("loading error: %u", g_dll_load_error);
274
} else {
275
st->print("loaded successfully ");
276
277
// We may want to print dll file name here - which may be interesting for
278
// cases where more than one version exists on the system, e.g. with a
279
// debugging sdk separately installed. But we get the file name in the DLL
280
// section of the hs-err file too, so this may be redundant.
281
282
// Print version.
283
st->print("- version: %u.%u.%u",
284
g_version.MajorVersion, g_version.MinorVersion, g_version.Revision);
285
286
// Print any functions which failed to load.
287
int num_missing = 0;
288
st->print(" - missing functions: ");
289
290
#define CHECK_AND_PRINT_IF_NULL(functionname) \
291
if (g_pfn_##functionname == NULL) { \
292
st->print("%s" #functionname, ((num_missing > 0) ? ", " : "")); \
293
num_missing ++; \
294
}
295
296
FOR_ALL_FUNCTIONS(CHECK_AND_PRINT_IF_NULL)
297
298
if (num_missing == 0) {
299
st->print("none");
300
}
301
}
302
st->cr();
303
}
304
305
306