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