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