Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
41149 views
1
/*
2
* Copyright (c) 2002, 2021, 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
// Disable CRT security warning against strcpy/strcat
26
#pragma warning(disable: 4996)
27
28
// this is source code windbg based SA debugger agent to debug
29
// Dr. Watson dump files and process snapshots.
30
31
#include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"
32
33
#ifdef _M_IX86
34
#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
35
#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
36
#elif _M_AMD64
37
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
38
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
39
#elif _M_ARM64
40
#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
41
#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
42
#else
43
#error "SA windbg back-end is not supported for your cpu!"
44
#endif
45
46
#include <limits.h>
47
#include <windows.h>
48
#include <inttypes.h>
49
50
#define DEBUG_NO_IMPLEMENTATION
51
#include <dbgeng.h>
52
#include <dbghelp.h>
53
54
55
// Wrappers to simplify cleanup on errors.
56
namespace {
57
58
template <class T>
59
class AutoArrayPtr {
60
T* m_ptr;
61
public:
62
AutoArrayPtr(T* ptr) : m_ptr(ptr) {
63
}
64
65
~AutoArrayPtr() {
66
delete [] m_ptr;
67
}
68
69
operator T* () const {
70
return m_ptr;
71
}
72
};
73
74
// Manage COM 'auto' pointers to avoid multiple Release
75
// calls at every early (exception) returns.
76
77
template <class T>
78
class AutoCOMPtr {
79
T* m_ptr;
80
81
public:
82
AutoCOMPtr(T* ptr) : m_ptr(ptr) {
83
}
84
85
~AutoCOMPtr() {
86
if (m_ptr) {
87
m_ptr->Release();
88
}
89
}
90
91
T* operator->() const {
92
return m_ptr;
93
}
94
};
95
96
class AutoJavaString {
97
JNIEnv* m_env;
98
jstring m_str;
99
const char* m_buf;
100
101
public:
102
// check env->ExceptionOccurred() after ctor
103
AutoJavaString(JNIEnv* env, jstring str)
104
: m_env(env), m_str(str), m_buf(str == nullptr ? nullptr : env->GetStringUTFChars(str, nullptr)) {
105
}
106
107
~AutoJavaString() {
108
if (m_buf) {
109
m_env->ReleaseStringUTFChars(m_str, m_buf);
110
}
111
}
112
113
operator const char* () const {
114
return m_buf;
115
}
116
};
117
118
class AutoJavaByteArray {
119
JNIEnv* env;
120
jbyteArray byteArray;
121
jbyte* bytePtr;
122
jint releaseMode;
123
124
public:
125
// check env->ExceptionOccurred() after ctor
126
AutoJavaByteArray(JNIEnv* env, jbyteArray byteArray, jint releaseMode = JNI_ABORT)
127
: env(env), byteArray(byteArray), releaseMode(releaseMode),
128
bytePtr(env->GetByteArrayElements(byteArray, nullptr)) {
129
}
130
131
~AutoJavaByteArray() {
132
if (bytePtr) {
133
env->ReleaseByteArrayElements(byteArray, bytePtr, releaseMode);
134
}
135
}
136
137
void setReleaseMode(jint mode) {
138
releaseMode = mode;
139
}
140
141
operator jbyte* () const {
142
return bytePtr;
143
}
144
};
145
146
} // unnamed namespace
147
148
149
// field and method IDs we want here
150
151
static jfieldID imagePath_ID = 0;
152
static jfieldID symbolPath_ID = 0;
153
static jfieldID ptrIDebugClient_ID = 0;
154
static jfieldID ptrIDebugControl_ID = 0;
155
static jfieldID ptrIDebugDataSpaces_ID = 0;
156
static jfieldID ptrIDebugOutputCallbacks_ID = 0;
157
static jfieldID ptrIDebugAdvanced_ID = 0;
158
static jfieldID ptrIDebugSymbols_ID = 0;
159
static jfieldID ptrIDebugSystemObjects_ID = 0;
160
161
static jmethodID addLoadObject_ID = 0;
162
static jmethodID addThread_ID = 0;
163
static jmethodID createClosestSymbol_ID = 0;
164
static jmethodID setThreadIntegerRegisterSet_ID = 0;
165
166
#define CHECK_EXCEPTION_(value) if (env->ExceptionOccurred()) { return value; }
167
#define CHECK_EXCEPTION if (env->ExceptionOccurred()) { return; }
168
169
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
170
throwNewDebuggerException(env, str); return value; }
171
172
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { \
173
throwNewDebuggerException(env, str); return; }
174
175
static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
176
jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
177
CHECK_EXCEPTION;
178
env->ThrowNew(clazz, errMsg);
179
}
180
181
// Verifies COM call result is S_OK, throws DebuggerException and exits otherwise.
182
// Note: other success results (like S_FALSE) are considered errors.
183
#define COM_VERIFY_OK_(v, str, retValue) \
184
do { \
185
const HRESULT hr = (v); \
186
if (hr != S_OK) { \
187
AutoArrayPtr<char> errmsg(new char[strlen(str) + 32]); \
188
if (errmsg == nullptr) { \
189
THROW_NEW_DEBUGGER_EXCEPTION_(str, retValue); \
190
} else { \
191
sprintf(errmsg, "%s (hr: 0x%08X)", str, hr); \
192
THROW_NEW_DEBUGGER_EXCEPTION_(errmsg, retValue); \
193
} \
194
} \
195
} while (false)
196
197
/*
198
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
199
* Method: initIDs
200
* Signature: ()V
201
*/
202
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs
203
(JNIEnv *env, jclass clazz) {
204
imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;");
205
CHECK_EXCEPTION;
206
207
symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
208
CHECK_EXCEPTION;
209
210
ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
211
CHECK_EXCEPTION;
212
213
ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
214
CHECK_EXCEPTION;
215
216
ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
217
CHECK_EXCEPTION;
218
219
ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz, "ptrIDebugOutputCallbacks", "J");
220
CHECK_EXCEPTION;
221
222
ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
223
CHECK_EXCEPTION;
224
225
ptrIDebugSymbols_ID = env->GetFieldID(clazz, "ptrIDebugSymbols", "J");
226
CHECK_EXCEPTION;
227
228
ptrIDebugSystemObjects_ID = env->GetFieldID(clazz, "ptrIDebugSystemObjects", "J");
229
CHECK_EXCEPTION;
230
231
addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject", "(Ljava/lang/String;JJ)V");
232
CHECK_EXCEPTION;
233
234
addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
235
CHECK_EXCEPTION;
236
237
createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
238
"(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
239
CHECK_EXCEPTION;
240
241
setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
242
"setThreadIntegerRegisterSet", "(J[J)V");
243
CHECK_EXCEPTION;
244
}
245
246
// class for IDebugOutputCallbacks
247
248
class SAOutputCallbacks : public IDebugOutputCallbacks {
249
LONG m_refCount;
250
char* m_msgBuffer;
251
252
public:
253
SAOutputCallbacks() : m_refCount(1), m_msgBuffer(nullptr) {
254
}
255
256
~SAOutputCallbacks() {
257
clearBuffer();
258
}
259
260
const char* getBuffer() const {
261
return m_msgBuffer;
262
}
263
264
void clearBuffer() {
265
if (m_msgBuffer) {
266
free(m_msgBuffer);
267
m_msgBuffer = 0;
268
}
269
}
270
271
STDMETHOD_(ULONG, AddRef)(THIS);
272
STDMETHOD_(ULONG, Release)(THIS);
273
STDMETHOD(QueryInterface)(THIS_
274
IN REFIID interfaceId,
275
OUT PVOID* ppInterface);
276
STDMETHOD(Output)(THIS_
277
IN ULONG mask,
278
IN PCSTR msg);
279
};
280
281
STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
282
return InterlockedIncrement(&m_refCount);
283
}
284
285
STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) {
286
LONG retVal = InterlockedDecrement(&m_refCount);
287
if (retVal == 0) {
288
delete this;
289
}
290
return retVal;
291
}
292
293
STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_
294
IN REFIID interfaceId,
295
OUT PVOID* ppInterface) {
296
*ppInterface = nullptr;
297
if (IsEqualIID(interfaceId, __uuidof(IUnknown)) ||
298
IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) {
299
*ppInterface = static_cast<IDebugOutputCallbacks*>(this);
300
} else {
301
return E_NOINTERFACE;
302
}
303
AddRef();
304
return S_OK;
305
}
306
307
STDMETHODIMP SAOutputCallbacks::Output(THIS_
308
IN ULONG mask,
309
IN PCSTR msg) {
310
size_t len = strlen(msg) + 1;
311
if (m_msgBuffer == 0) {
312
m_msgBuffer = (char*) malloc(len);
313
if (m_msgBuffer == 0) {
314
fprintf(stderr, "out of memory debugger output!\n");
315
return S_FALSE;
316
}
317
strcpy(m_msgBuffer, msg);
318
} else {
319
char* newBuffer = (char*)realloc(m_msgBuffer, len + strlen(m_msgBuffer));
320
if (newBuffer == nullptr) {
321
// old m_msgBuffer buffer is still valid
322
fprintf(stderr, "out of memory debugger output!\n");
323
return S_FALSE;
324
}
325
m_msgBuffer = newBuffer;
326
strcat(m_msgBuffer, msg);
327
}
328
return S_OK;
329
}
330
331
static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
332
// get windbg interfaces ..
333
334
IDebugClient* ptrIDebugClient = 0;
335
COM_VERIFY_OK_(DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient),
336
"Windbg Error: not able to create IDebugClient object!", false);
337
env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient);
338
339
IDebugControl* ptrIDebugControl = 0;
340
COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(
341
__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl),
342
"Windbg Error: not able to get IDebugControl", false);
343
env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl);
344
345
IDebugDataSpaces* ptrIDebugDataSpaces = 0;
346
COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(
347
__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces),
348
"Windbg Error: not able to get IDebugDataSpaces object!", false);
349
env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces);
350
351
SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
352
env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
353
CHECK_EXCEPTION_(false);
354
355
IDebugAdvanced* ptrIDebugAdvanced = 0;
356
COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(
357
__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced),
358
"Windbg Error: not able to get IDebugAdvanced object!", false);
359
env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced);
360
361
IDebugSymbols* ptrIDebugSymbols = 0;
362
COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(
363
__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols),
364
"Windbg Error: not able to get IDebugSymbols object!", false);
365
env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols);
366
367
IDebugSystemObjects* ptrIDebugSystemObjects = 0;
368
COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(
369
__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects),
370
"Windbg Error: not able to get IDebugSystemObjects object!", false);
371
env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects);
372
373
return true;
374
}
375
376
static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
377
jclass clazz = env->GetObjectClass(obj);
378
CHECK_EXCEPTION_(false);
379
jstring path;
380
381
path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
382
CHECK_EXCEPTION_(false);
383
if (path == nullptr) {
384
THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get imagePath field ID!", false);
385
}
386
AutoJavaString imagePath(env, path);
387
CHECK_EXCEPTION_(false);
388
389
path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
390
CHECK_EXCEPTION_(false);
391
if (path == nullptr) {
392
THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get symbolPath field ID!", false);
393
}
394
AutoJavaString symbolPath(env, path);
395
CHECK_EXCEPTION_(false);
396
397
IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*)env->GetLongField(obj, ptrIDebugSymbols_ID);
398
CHECK_EXCEPTION_(false);
399
400
ptrIDebugSymbols->SetImagePath(imagePath);
401
ptrIDebugSymbols->SetSymbolPath(symbolPath);
402
return true;
403
}
404
405
static HRESULT WaitForEvent(IDebugControl *ptrIDebugControl) {
406
HRESULT hr = ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
407
// see JDK-8204994: sometimes WaitForEvent fails with E_ACCESSDENIED,
408
// but succeeds on 2nd call.
409
// To minimize possible noise retry 3 times.
410
for (int i = 0; hr == E_ACCESSDENIED && i < 3; i++) {
411
// yield current thread use of a processor (short delay).
412
SwitchToThread();
413
hr = ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
414
}
415
return hr;
416
}
417
418
static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) {
419
// open the dump file
420
AutoJavaString coreFile(env, coreFileName);
421
CHECK_EXCEPTION_(false);
422
if (!setImageAndSymbolPath(env, obj)) {
423
return false;
424
}
425
426
IDebugClient* ptrIDebugClient = (IDebugClient*)env->GetLongField(obj, ptrIDebugClient_ID);
427
CHECK_EXCEPTION_(false);
428
COM_VERIFY_OK_(ptrIDebugClient->OpenDumpFile(coreFile),
429
"Windbg Error: OpenDumpFile failed!", false);
430
431
IDebugControl* ptrIDebugControl = (IDebugControl*)env->GetLongField(obj, ptrIDebugControl_ID);
432
CHECK_EXCEPTION_(false);
433
COM_VERIFY_OK_(WaitForEvent(ptrIDebugControl),
434
"Windbg Error: WaitForEvent failed!", false);
435
436
return true;
437
}
438
439
440
static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) {
441
if (!setImageAndSymbolPath(env, obj)) {
442
return false;
443
}
444
IDebugClient* ptrIDebugClient = (IDebugClient*)env->GetLongField(obj, ptrIDebugClient_ID);
445
CHECK_EXCEPTION_(false);
446
447
/***********************************************************************************
448
449
We are attaching to a process in 'read-only' mode. i.e., we do not want to
450
put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
451
usage this should suffice.
452
453
Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
454
In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
455
actually debugging at all. We can safely 'detach' from the process anytime
456
we want and debuggee process is left as is on all Windows variants.
457
458
This also makes JDI-on-SA installation/usage simpler because with this we would
459
not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.
460
461
***********************************************************************************/
462
463
464
COM_VERIFY_OK_(ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE),
465
"Windbg Error: AttachProcess failed!", false);
466
467
IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
468
ptrIDebugControl_ID);
469
CHECK_EXCEPTION_(false);
470
COM_VERIFY_OK_(WaitForEvent(ptrIDebugControl),
471
"Windbg Error: WaitForEvent failed!", false);
472
473
return true;
474
}
475
476
477
static bool addLoadObjects(JNIEnv* env, jobject obj) {
478
IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
479
ptrIDebugSymbols_ID);
480
CHECK_EXCEPTION_(false);
481
ULONG loaded = 0, unloaded = 0;
482
COM_VERIFY_OK_(ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded),
483
"Windbg Error: GetNumberModules failed!", false);
484
485
AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
486
487
if (params == nullptr) {
488
THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
489
}
490
491
COM_VERIFY_OK_(ptrIDebugSymbols->GetModuleParameters(loaded, nullptr, 0, params),
492
"Windbg Error: GetModuleParameters failed!", false);
493
494
for (int u = 0; u < (int)loaded; u++) {
495
TCHAR imageName[MAX_PATH];
496
COM_VERIFY_OK_(ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params[u].Base,
497
imageName, MAX_PATH, nullptr, nullptr,
498
0, nullptr, nullptr, 0, nullptr),
499
"Windbg Error: GetModuleNames failed!", false);
500
501
jstring strName = env->NewStringUTF(imageName);
502
CHECK_EXCEPTION_(false);
503
env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params[u].Size,
504
(jlong) params[u].Base);
505
CHECK_EXCEPTION_(false);
506
env->DeleteLocalRef(strName);
507
}
508
509
return true;
510
}
511
512
static bool addThreads(JNIEnv* env, jobject obj) {
513
IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
514
ptrIDebugSystemObjects_ID);
515
CHECK_EXCEPTION_(false);
516
517
ULONG numThreads = 0;
518
COM_VERIFY_OK_(ptrIDebugSystemObjects->GetNumberThreads(&numThreads),
519
"Windbg Error: GetNumberThreads failed!", false);
520
521
AutoArrayPtr<ULONG> ptrSysThreadIds(new ULONG[numThreads]);
522
523
if (ptrSysThreadIds == nullptr) {
524
THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
525
}
526
527
AutoArrayPtr<ULONG> ptrThreadIds(new ULONG[numThreads]);
528
529
if (ptrThreadIds == nullptr) {
530
THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
531
}
532
533
COM_VERIFY_OK_(ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
534
ptrThreadIds, ptrSysThreadIds),
535
"Windbg Error: GetThreadIdsByIndex failed!", false);
536
537
538
IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
539
ptrIDebugAdvanced_ID);
540
CHECK_EXCEPTION_(false);
541
542
// for each thread, get register context and save it.
543
for (ULONG t = 0; t < numThreads; t++) {
544
COM_VERIFY_OK_(ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds[t]),
545
"Windbg Error: SetCurrentThread failed!", false);
546
547
jlongArray regs = env->NewLongArray(NPRGREG);
548
CHECK_EXCEPTION_(false);
549
550
jlong* ptrRegs = env->GetLongArrayElements(regs, nullptr);
551
CHECK_EXCEPTION_(false);
552
553
// copy register values from the CONTEXT struct
554
CONTEXT context;
555
memset(&context, 0, sizeof(CONTEXT));
556
557
#undef REG_INDEX
558
#ifdef _M_IX86
559
#define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
560
561
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
562
ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
563
564
ptrRegs[REG_INDEX(GS)] = context.SegGs;
565
ptrRegs[REG_INDEX(FS)] = context.SegFs;
566
ptrRegs[REG_INDEX(ES)] = context.SegEs;
567
ptrRegs[REG_INDEX(DS)] = context.SegDs;
568
569
ptrRegs[REG_INDEX(EDI)] = context.Edi;
570
ptrRegs[REG_INDEX(ESI)] = context.Esi;
571
ptrRegs[REG_INDEX(EBX)] = context.Ebx;
572
ptrRegs[REG_INDEX(EDX)] = context.Edx;
573
ptrRegs[REG_INDEX(ECX)] = context.Ecx;
574
ptrRegs[REG_INDEX(EAX)] = context.Eax;
575
576
ptrRegs[REG_INDEX(FP)] = context.Ebp;
577
ptrRegs[REG_INDEX(PC)] = context.Eip;
578
ptrRegs[REG_INDEX(CS)] = context.SegCs;
579
ptrRegs[REG_INDEX(EFL)] = context.EFlags;
580
ptrRegs[REG_INDEX(SP)] = context.Esp;
581
ptrRegs[REG_INDEX(SS)] = context.SegSs;
582
583
ptrRegs[REG_INDEX(DR0)] = context.Dr0;
584
ptrRegs[REG_INDEX(DR1)] = context.Dr1;
585
ptrRegs[REG_INDEX(DR2)] = context.Dr2;
586
ptrRegs[REG_INDEX(DR3)] = context.Dr3;
587
ptrRegs[REG_INDEX(DR6)] = context.Dr6;
588
ptrRegs[REG_INDEX(DR7)] = context.Dr7;
589
590
#elif _M_AMD64
591
#define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
592
593
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
594
ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
595
596
// Segment Registers and processor flags
597
ptrRegs[REG_INDEX(CS)] = context.SegCs;
598
ptrRegs[REG_INDEX(DS)] = context.SegDs;
599
ptrRegs[REG_INDEX(ES)] = context.SegEs;
600
ptrRegs[REG_INDEX(FS)] = context.SegFs;
601
ptrRegs[REG_INDEX(GS)] = context.SegGs;
602
ptrRegs[REG_INDEX(SS)] = context.SegSs;
603
ptrRegs[REG_INDEX(RFL)] = context.EFlags;
604
605
// Integer registers
606
ptrRegs[REG_INDEX(RDI)] = context.Rdi;
607
ptrRegs[REG_INDEX(RSI)] = context.Rsi;
608
ptrRegs[REG_INDEX(RAX)] = context.Rax;
609
ptrRegs[REG_INDEX(RCX)] = context.Rcx;
610
ptrRegs[REG_INDEX(RDX)] = context.Rdx;
611
ptrRegs[REG_INDEX(RBX)] = context.Rbx;
612
ptrRegs[REG_INDEX(RBP)] = context.Rbp;
613
ptrRegs[REG_INDEX(RSP)] = context.Rsp;
614
615
ptrRegs[REG_INDEX(R8)] = context.R8;
616
ptrRegs[REG_INDEX(R9)] = context.R9;
617
ptrRegs[REG_INDEX(R10)] = context.R10;
618
ptrRegs[REG_INDEX(R11)] = context.R11;
619
ptrRegs[REG_INDEX(R12)] = context.R12;
620
ptrRegs[REG_INDEX(R13)] = context.R13;
621
ptrRegs[REG_INDEX(R14)] = context.R14;
622
ptrRegs[REG_INDEX(R15)] = context.R15;
623
624
// Program counter
625
ptrRegs[REG_INDEX(RIP)] = context.Rip;
626
#endif
627
628
env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
629
CHECK_EXCEPTION_(false);
630
631
env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, (jlong)ptrThreadIds[t], regs);
632
CHECK_EXCEPTION_(false);
633
env->DeleteLocalRef(regs);
634
635
ULONG sysId;
636
COM_VERIFY_OK_(ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId),
637
"Windbg Error: GetCurrentThreadSystemId failed!", false);
638
639
env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
640
CHECK_EXCEPTION_(false);
641
}
642
643
return true;
644
}
645
646
/*
647
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
648
* Method: attach0
649
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
650
*/
651
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
652
(JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {
653
654
if (!getWindbgInterfaces(env, obj)) {
655
return;
656
}
657
658
if (!openDumpFile(env, obj, coreFileName)) {
659
return;
660
}
661
662
if (!addLoadObjects(env, obj)) {
663
return;
664
}
665
666
if (!addThreads(env, obj)) {
667
return;
668
}
669
}
670
671
/*
672
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
673
* Method: attach0
674
* Signature: (I)V
675
*/
676
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I
677
(JNIEnv *env, jobject obj, jint pid) {
678
679
if (!getWindbgInterfaces(env, obj)) {
680
return;
681
}
682
683
if (!attachToProcess(env, obj, pid)) {
684
return;
685
}
686
687
if (!addLoadObjects(env, obj)) {
688
return;
689
}
690
691
if (!addThreads(env, obj)) {
692
return;
693
}
694
}
695
696
697
#define RELEASE(fieldID) \
698
do { \
699
IUnknown* ptr = (IUnknown*)env->GetLongField(obj, fieldID); \
700
CHECK_EXCEPTION_(false); \
701
if (ptr) { \
702
ptr->Release(); \
703
} \
704
} while (false)
705
706
static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {
707
RELEASE(ptrIDebugDataSpaces_ID);
708
RELEASE(ptrIDebugOutputCallbacks_ID);
709
RELEASE(ptrIDebugAdvanced_ID);
710
RELEASE(ptrIDebugSymbols_ID);
711
RELEASE(ptrIDebugSystemObjects_ID);
712
RELEASE(ptrIDebugControl_ID);
713
RELEASE(ptrIDebugClient_ID);
714
715
return true;
716
}
717
718
/*
719
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
720
* Method: detach0
721
* Signature: ()V
722
*/
723
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0
724
(JNIEnv *env, jobject obj) {
725
IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
726
CHECK_EXCEPTION;
727
ptrIDebugClient->DetachProcesses();
728
releaseWindbgInterfaces(env, obj);
729
}
730
731
732
/*
733
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
734
* Method: readBytesFromProcess0
735
* Signature: (JJ)[B
736
*/
737
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0
738
(JNIEnv *env, jobject obj, jlong address, jlong numBytes) {
739
jbyteArray byteArray = env->NewByteArray((jsize)numBytes);
740
CHECK_EXCEPTION_(0);
741
742
AutoJavaByteArray arrayBytes(env, byteArray);
743
CHECK_EXCEPTION_(0);
744
745
IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
746
ptrIDebugDataSpaces_ID);
747
CHECK_EXCEPTION_(0);
748
749
ULONG bytesRead;
750
const HRESULT hr = ptrIDebugDataSpaces->ReadVirtual((ULONG64)address, arrayBytes,
751
(ULONG)numBytes, &bytesRead);
752
if (hr != S_OK || bytesRead != numBytes) {
753
return 0;
754
}
755
756
arrayBytes.setReleaseMode(0);
757
758
return byteArray;
759
}
760
761
/*
762
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
763
* Method: getThreadIdFromSysId0
764
* Signature: (J)J
765
*/
766
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0
767
(JNIEnv *env, jobject obj, jlong sysId) {
768
IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
769
ptrIDebugSystemObjects_ID);
770
CHECK_EXCEPTION_(0);
771
772
ULONG id = 0;
773
HRESULT hr = ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id);
774
if (hr != S_OK) {
775
// This is not considered fatal and does happen on occassion, usually with an
776
// 0x80004002 "No such interface supported". The root cause is not fully understood,
777
// but by ignoring this error and returning NULL, stacking walking code will get
778
// null registers and fallback to using the "last java frame" if setup.
779
printf("WARNING: GetThreadIdBySystemId failed with 0x%x for sysId (%" PRIu64 ")\n",
780
hr, sysId);
781
return -1;
782
}
783
return (jlong) id;
784
}
785
786
/*
787
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
788
* Method: consoleExecuteCommand0
789
* Signature: (Ljava/lang/String;)Ljava/lang/String;
790
*/
791
JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0
792
(JNIEnv *env, jobject obj, jstring cmd) {
793
AutoJavaString command(env, cmd);
794
CHECK_EXCEPTION_(0);
795
796
IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
797
CHECK_EXCEPTION_(0);
798
799
IDebugClient* tmpClientPtr = 0;
800
COM_VERIFY_OK_(ptrIDebugClient->CreateClient(&tmpClientPtr),
801
"Windbg Error: CreateClient failed!", 0);
802
AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);
803
804
IDebugControl* tmpControlPtr = 0;
805
COM_VERIFY_OK_(tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr),
806
"Windbg Error: QueryInterface (IDebugControl) failed", 0);
807
AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);
808
809
SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
810
ptrIDebugOutputCallbacks_ID);
811
CHECK_EXCEPTION_(0);
812
813
saOutputCallbacks->clearBuffer();
814
815
COM_VERIFY_OK_(tmpClient->SetOutputCallbacks(saOutputCallbacks),
816
"Windbg Error: SetOutputCallbacks failed!", 0);
817
818
tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
819
820
const char* output = saOutputCallbacks->getBuffer();
821
if (output == 0) {
822
output = "";
823
}
824
825
jstring res = env->NewStringUTF(output);
826
saOutputCallbacks->clearBuffer();
827
return res;
828
}
829
830
/*
831
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
832
* Method: lookupByName0
833
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
834
*/
835
836
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0
837
(JNIEnv *env, jobject obj, jstring objName, jstring sym) {
838
IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*)env->GetLongField(obj, ptrIDebugSymbols_ID);
839
CHECK_EXCEPTION_(0);
840
841
AutoJavaString name(env, sym);
842
CHECK_EXCEPTION_(0);
843
844
ULONG64 offset = 0L;
845
if (strstr(name, "::") != 0) {
846
ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);
847
} else {
848
ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);
849
}
850
if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
851
return (jlong) 0;
852
}
853
return (jlong) offset;
854
}
855
856
#define SYMBOL_BUFSIZE 512
857
/*
858
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
859
* Method: lookupByAddress0
860
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
861
*/
862
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0
863
(JNIEnv *env, jobject obj, jlong address) {
864
IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, ptrIDebugSymbols_ID);
865
CHECK_EXCEPTION_(0);
866
867
ULONG64 disp = 0L;
868
char buf[SYMBOL_BUFSIZE];
869
memset(buf, 0, sizeof(buf));
870
871
if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf), 0, &disp) != S_OK) {
872
return 0;
873
}
874
875
jstring sym = env->NewStringUTF(buf);
876
CHECK_EXCEPTION_(0);
877
jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);
878
CHECK_EXCEPTION_(0);
879
return res;
880
}
881
882