Tue, 24 Dec 2013 11:48:39 -0800
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
Summary: Copyright year updated for files modified during 2013
Reviewed-by: twisti, iveresov
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 */
25 // this is source code windbg based SA debugger agent to debug
26 // Dr. Watson dump files and process snapshots.
28 #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"
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
40 #include <limits.h>
41 #include <windows.h>
43 #ifndef STDMETHODV
44 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
45 #endif
47 #define DEBUG_NO_IMPLEMENTATION
48 #include <dbgeng.h>
49 #include <dbghelp.h>
51 // simple template to manage array delete across early (error) returns
53 template <class T>
54 class AutoArrayPtr {
55 T* m_ptr;
56 public:
57 AutoArrayPtr(T* ptr) : m_ptr(ptr) {
58 }
60 ~AutoArrayPtr() {
61 delete [] m_ptr;
62 }
64 T* asPtr() {
65 return m_ptr;
66 }
67 };
69 class AutoJavaString {
70 JNIEnv* m_env;
71 jstring m_str;
72 const char* m_buf;
74 public:
75 AutoJavaString(JNIEnv* env, jstring str, const char* buf)
76 : m_env(env), m_str(str), m_buf(buf) {
77 }
79 ~AutoJavaString() {
80 m_env->ReleaseStringUTFChars(m_str, m_buf);
81 }
83 operator const char* () {
84 return m_buf;
85 }
86 };
88 // field and method IDs we want here
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;
100 static jmethodID addLoadObject_ID = 0;
101 static jmethodID addThread_ID = 0;
102 static jmethodID createClosestSymbol_ID = 0;
103 static jmethodID setThreadIntegerRegisterSet_ID = 0;
105 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
106 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
108 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
109 throwNewDebuggerException(env, str); return value; }
111 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \
112 return;}
114 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
115 env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
116 }
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;
128 symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
129 CHECK_EXCEPTION;
131 ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
132 CHECK_EXCEPTION;
134 ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
135 CHECK_EXCEPTION;
137 ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
138 CHECK_EXCEPTION;
140 ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz,
141 "ptrIDebugOutputCallbacks", "J");
142 CHECK_EXCEPTION;
144 ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
145 CHECK_EXCEPTION;
147 ptrIDebugSymbols_ID = env->GetFieldID(clazz,
148 "ptrIDebugSymbols", "J");
149 CHECK_EXCEPTION;
151 ptrIDebugSystemObjects_ID = env->GetFieldID(clazz,
152 "ptrIDebugSystemObjects", "J");
153 CHECK_EXCEPTION;
155 addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject",
156 "(Ljava/lang/String;JJ)V");
157 CHECK_EXCEPTION;
159 addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
160 CHECK_EXCEPTION;
162 createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
163 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
164 CHECK_EXCEPTION;
166 setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
167 "setThreadIntegerRegisterSet", "(J[J)V");
168 CHECK_EXCEPTION;
170 }
172 // class for IDebugOutputCallbacks
174 class SAOutputCallbacks : public IDebugOutputCallbacks {
175 LONG m_refCount;
176 char* m_msgBuffer;
178 public:
179 SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) {
180 }
182 ~SAOutputCallbacks() {
183 clearBuffer();
184 }
186 const char* getBuffer() const {
187 return m_msgBuffer;
188 }
190 void clearBuffer() {
191 if (m_msgBuffer) {
192 free(m_msgBuffer);
193 m_msgBuffer = 0;
194 }
195 }
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 };
207 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
208 InterlockedIncrement(&m_refCount);
209 return m_refCount;
210 }
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 }
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 }
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 }
258 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
259 // get windbg interfaces ..
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);
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);
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);
281 SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
282 ptrIDebugOutputCallbacks->AddRef();
283 env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
284 CHECK_EXCEPTION_(false);
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);
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);
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);
307 return true;
308 }
310 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
311 jboolean isCopy;
312 jclass clazz = env->GetObjectClass(obj);
313 jstring path;
314 const char* buf;
316 path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
317 buf = env->GetStringUTFChars(path, &isCopy);
318 CHECK_EXCEPTION_(false);
319 AutoJavaString imagePath(env, path, buf);
321 path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
322 buf = env->GetStringUTFChars(path, &isCopy);
323 CHECK_EXCEPTION_(false);
324 AutoJavaString symbolPath(env, path, buf);
326 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
327 ptrIDebugSymbols_ID);
328 CHECK_EXCEPTION_(false);
330 ptrIDebugSymbols->SetImagePath(imagePath);
331 ptrIDebugSymbols->SetSymbolPath(symbolPath);
332 return true;
333 }
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 }
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 }
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 }
359 return true;
360 }
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);
371 /***********************************************************************************
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.
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.
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.
385 ***********************************************************************************/
388 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
389 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
390 }
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 }
399 return true;
400 }
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 }
412 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
414 if (params.asPtr() == 0) {
415 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
416 }
418 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
419 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
420 }
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 }
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 }
437 return true;
438 }
440 static bool addThreads(JNIEnv* env, jobject obj) {
441 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
442 ptrIDebugSystemObjects_ID);
443 CHECK_EXCEPTION_(false);
445 ULONG numThreads = 0;
446 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
447 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
448 }
450 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
452 if (ptrSysThreadIds.asPtr() == 0) {
453 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
454 }
456 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
458 if (ptrThreadIds.asPtr() == 0) {
459 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
460 }
462 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
463 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
464 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
465 }
468 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
469 ptrIDebugAdvanced_ID);
470 CHECK_EXCEPTION_(false);
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 }
478 jlongArray regs = env->NewLongArray(NPRGREG);
479 CHECK_EXCEPTION_(false);
481 jboolean isCopy = JNI_FALSE;
482 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
483 CHECK_EXCEPTION_(false);
485 // copy register values from the CONTEXT struct
486 CONTEXT context;
487 memset(&context, 0, sizeof(CONTEXT));
489 #undef REG_INDEX
490 #ifdef _M_IX86
491 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
493 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
494 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
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;
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;
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;
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;
522 #elif _M_AMD64
523 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
525 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
526 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
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;
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;
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;
556 // Program counter
557 ptrRegs[REG_INDEX(RIP)] = context.Rip;
558 #endif
560 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
561 CHECK_EXCEPTION_(false);
563 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
564 (jlong) ptrThreadIds.asPtr()[t], regs);
565 CHECK_EXCEPTION_(false);
567 ULONG sysId;
568 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
569 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
570 }
572 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
573 CHECK_EXCEPTION_(false);
574 }
576 return true;
577 }
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) {
587 if (getWindbgInterfaces(env, obj) == false) {
588 return;
589 }
591 if (openDumpFile(env, obj, coreFileName) == false) {
592 return;
593 }
595 if (addLoadObjects(env, obj) == false) {
596 return;
597 }
599 if (addThreads(env, obj) == false) {
600 return;
601 }
602 }
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) {
612 if (getWindbgInterfaces(env, obj) == false) {
613 return;
614 }
616 if (attachToProcess(env, obj, pid) == false) {
617 return;
618 }
620 if (addLoadObjects(env, obj) == false) {
621 return;
622 }
624 if (addThreads(env, obj) == false) {
625 return;
626 }
627 }
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 }
638 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
639 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
640 CHECK_EXCEPTION_(false);
641 if (ptrIDebugOutputCallbacks != 0) {
642 ptrIDebugOutputCallbacks->Release();
643 }
645 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
646 ptrIDebugAdvanced_ID);
647 CHECK_EXCEPTION_(false);
649 if (ptrIDebugAdvanced != 0) {
650 ptrIDebugAdvanced->Release();
651 }
653 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
654 ptrIDebugSymbols_ID);
655 CHECK_EXCEPTION_(false);
656 if (ptrIDebugSymbols != 0) {
657 ptrIDebugSymbols->Release();
658 }
660 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
661 ptrIDebugSystemObjects_ID);
662 CHECK_EXCEPTION_(false);
663 if (ptrIDebugSystemObjects != 0) {
664 ptrIDebugSystemObjects->Release();
665 }
667 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
668 ptrIDebugControl_ID);
669 CHECK_EXCEPTION_(false);
670 if (ptrIDebugControl != 0) {
671 ptrIDebugControl->Release();
672 }
674 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
675 ptrIDebugClient_ID);
676 CHECK_EXCEPTION_(false);
677 if (ptrIDebugClient != 0) {
678 ptrIDebugClient->Release();
679 }
681 return true;
682 }
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 }
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);
709 jboolean isCopy = JNI_FALSE;
710 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
711 CHECK_EXCEPTION_(0);
713 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
714 ptrIDebugDataSpaces_ID);
715 CHECK_EXCEPTION_(0);
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 }
723 if (bytesRead != numBytes) {
724 return 0;
725 }
727 env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
728 CHECK_EXCEPTION_(0);
730 return byteArray;
731 }
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);
744 ULONG id = 0;
745 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
746 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
747 }
749 return (jlong) id;
750 }
752 // manage COM 'auto' pointers (to avoid multiple Release
753 // calls at every early (exception) returns). Similar to AutoArrayPtr.
755 template <class T>
756 class AutoCOMPtr {
757 T* m_ptr;
759 public:
760 AutoCOMPtr(T* ptr) : m_ptr(ptr) {
761 }
763 ~AutoCOMPtr() {
764 if (m_ptr) {
765 m_ptr->Release();
766 }
767 }
769 T* operator->() {
770 return m_ptr;
771 }
772 };
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);
786 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
787 CHECK_EXCEPTION_(0);
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);
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);
801 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
802 ptrIDebugOutputCallbacks_ID);
803 CHECK_EXCEPTION_(0);
805 saOutputCallbacks->clearBuffer();
807 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
808 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
809 }
811 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
813 const char* output = saOutputCallbacks->getBuffer();
814 if (output == 0) {
815 output = "";
816 }
818 jstring res = env->NewStringUTF(output);
819 saOutputCallbacks->clearBuffer();
820 return res;
821 }
823 /*
824 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
825 * Method: lookupByName0
826 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
827 */
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);
835 jboolean isCopy;
836 const char* buf = env->GetStringUTFChars(sym, &isCopy);
837 CHECK_EXCEPTION_(0);
838 AutoJavaString name(env, sym, buf);
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 }
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);
864 ULONG64 disp = 0L;
865 char buf[SYMBOL_BUFSIZE];
866 memset(buf, 0, sizeof(buf));
868 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
869 != S_OK) {
870 return 0;
871 }
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 }