Fri, 25 Jan 2013 16:50:33 -0800
6518907: cleanup IA64 specific code in Hotspot
Summary: removed unused IA64 specific code
Reviewed-by: twisti, kvn, dholmes
1 /*
2 * Copyright (c) 2002, 2007, 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. We are not intending to use this for full-fledged
376 ProcessControl implementation to be used with BugSpotAgent.
378 Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
379 In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
380 actually debugging at all. We can safely 'detach' from the process anytime
381 we want and debuggee process is left as is on all Windows variants.
383 This also makes JDI-on-SA installation/usage simpler because with this we would
384 not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.
386 ***********************************************************************************/
389 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
390 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
391 }
393 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
394 ptrIDebugControl_ID);
395 CHECK_EXCEPTION_(false);
396 if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
397 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
398 }
400 return true;
401 }
404 static bool addLoadObjects(JNIEnv* env, jobject obj) {
405 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
406 ptrIDebugSymbols_ID);
407 CHECK_EXCEPTION_(false);
408 ULONG loaded = 0, unloaded = 0;
409 if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) {
410 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false);
411 }
413 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
415 if (params.asPtr() == 0) {
416 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
417 }
419 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
420 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
421 }
423 for (int u = 0; u < (int)loaded; u++) {
424 TCHAR imageName[MAX_PATH];
425 if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base,
426 imageName, MAX_PATH, NULL, NULL,
427 0, NULL, NULL, 0, NULL) != S_OK) {
428 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false);
429 }
431 jstring strName = env->NewStringUTF(imageName);
432 CHECK_EXCEPTION_(false);
433 env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size,
434 (jlong) params.asPtr()[u].Base);
435 CHECK_EXCEPTION_(false);
436 }
438 return true;
439 }
441 static bool addThreads(JNIEnv* env, jobject obj) {
442 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
443 ptrIDebugSystemObjects_ID);
444 CHECK_EXCEPTION_(false);
446 ULONG numThreads = 0;
447 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
448 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
449 }
451 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
453 if (ptrSysThreadIds.asPtr() == 0) {
454 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
455 }
457 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
459 if (ptrThreadIds.asPtr() == 0) {
460 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
461 }
463 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
464 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
465 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
466 }
469 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
470 ptrIDebugAdvanced_ID);
471 CHECK_EXCEPTION_(false);
473 // for each thread, get register context and save it.
474 for (ULONG t = 0; t < numThreads; t++) {
475 if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) {
476 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false);
477 }
479 jlongArray regs = env->NewLongArray(NPRGREG);
480 CHECK_EXCEPTION_(false);
482 jboolean isCopy = JNI_FALSE;
483 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
484 CHECK_EXCEPTION_(false);
486 // copy register values from the CONTEXT struct
487 CONTEXT context;
488 memset(&context, 0, sizeof(CONTEXT));
490 #undef REG_INDEX
491 #ifdef _M_IX86
492 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
494 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
495 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
497 ptrRegs[REG_INDEX(GS)] = context.SegGs;
498 ptrRegs[REG_INDEX(FS)] = context.SegFs;
499 ptrRegs[REG_INDEX(ES)] = context.SegEs;
500 ptrRegs[REG_INDEX(DS)] = context.SegDs;
502 ptrRegs[REG_INDEX(EDI)] = context.Edi;
503 ptrRegs[REG_INDEX(ESI)] = context.Esi;
504 ptrRegs[REG_INDEX(EBX)] = context.Ebx;
505 ptrRegs[REG_INDEX(EDX)] = context.Edx;
506 ptrRegs[REG_INDEX(ECX)] = context.Ecx;
507 ptrRegs[REG_INDEX(EAX)] = context.Eax;
509 ptrRegs[REG_INDEX(FP)] = context.Ebp;
510 ptrRegs[REG_INDEX(PC)] = context.Eip;
511 ptrRegs[REG_INDEX(CS)] = context.SegCs;
512 ptrRegs[REG_INDEX(EFL)] = context.EFlags;
513 ptrRegs[REG_INDEX(SP)] = context.Esp;
514 ptrRegs[REG_INDEX(SS)] = context.SegSs;
516 ptrRegs[REG_INDEX(DR0)] = context.Dr0;
517 ptrRegs[REG_INDEX(DR1)] = context.Dr1;
518 ptrRegs[REG_INDEX(DR2)] = context.Dr2;
519 ptrRegs[REG_INDEX(DR3)] = context.Dr3;
520 ptrRegs[REG_INDEX(DR6)] = context.Dr6;
521 ptrRegs[REG_INDEX(DR7)] = context.Dr7;
523 #elif _M_AMD64
524 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
526 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
527 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
529 // Segment Registers and processor flags
530 ptrRegs[REG_INDEX(CS)] = context.SegCs;
531 ptrRegs[REG_INDEX(DS)] = context.SegDs;
532 ptrRegs[REG_INDEX(ES)] = context.SegEs;
533 ptrRegs[REG_INDEX(FS)] = context.SegFs;
534 ptrRegs[REG_INDEX(GS)] = context.SegGs;
535 ptrRegs[REG_INDEX(SS)] = context.SegSs;
536 ptrRegs[REG_INDEX(RFL)] = context.EFlags;
538 // Integer registers
539 ptrRegs[REG_INDEX(RDI)] = context.Rdi;
540 ptrRegs[REG_INDEX(RSI)] = context.Rsi;
541 ptrRegs[REG_INDEX(RAX)] = context.Rax;
542 ptrRegs[REG_INDEX(RCX)] = context.Rcx;
543 ptrRegs[REG_INDEX(RDX)] = context.Rdx;
544 ptrRegs[REG_INDEX(RBX)] = context.Rbx;
545 ptrRegs[REG_INDEX(RBP)] = context.Rbp;
546 ptrRegs[REG_INDEX(RSP)] = context.Rsp;
548 ptrRegs[REG_INDEX(R8)] = context.R8;
549 ptrRegs[REG_INDEX(R9)] = context.R9;
550 ptrRegs[REG_INDEX(R10)] = context.R10;
551 ptrRegs[REG_INDEX(R11)] = context.R11;
552 ptrRegs[REG_INDEX(R12)] = context.R12;
553 ptrRegs[REG_INDEX(R13)] = context.R13;
554 ptrRegs[REG_INDEX(R14)] = context.R14;
555 ptrRegs[REG_INDEX(R15)] = context.R15;
557 // Program counter
558 ptrRegs[REG_INDEX(RIP)] = context.Rip;
559 #endif
561 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
562 CHECK_EXCEPTION_(false);
564 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
565 (jlong) ptrThreadIds.asPtr()[t], regs);
566 CHECK_EXCEPTION_(false);
568 ULONG sysId;
569 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
570 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
571 }
573 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
574 CHECK_EXCEPTION_(false);
575 }
577 return true;
578 }
580 /*
581 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
582 * Method: attach0
583 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
584 */
585 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
586 (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {
588 if (getWindbgInterfaces(env, obj) == false) {
589 return;
590 }
592 if (openDumpFile(env, obj, coreFileName) == false) {
593 return;
594 }
596 if (addLoadObjects(env, obj) == false) {
597 return;
598 }
600 if (addThreads(env, obj) == false) {
601 return;
602 }
603 }
605 /*
606 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
607 * Method: attach0
608 * Signature: (I)V
609 */
610 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I
611 (JNIEnv *env, jobject obj, jint pid) {
613 if (getWindbgInterfaces(env, obj) == false) {
614 return;
615 }
617 if (attachToProcess(env, obj, pid) == false) {
618 return;
619 }
621 if (addLoadObjects(env, obj) == false) {
622 return;
623 }
625 if (addThreads(env, obj) == false) {
626 return;
627 }
628 }
631 static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {
632 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
633 ptrIDebugDataSpaces_ID);
634 CHECK_EXCEPTION_(false);
635 if (ptrIDebugDataSpaces != 0) {
636 ptrIDebugDataSpaces->Release();
637 }
639 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
640 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
641 CHECK_EXCEPTION_(false);
642 if (ptrIDebugOutputCallbacks != 0) {
643 ptrIDebugOutputCallbacks->Release();
644 }
646 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
647 ptrIDebugAdvanced_ID);
648 CHECK_EXCEPTION_(false);
650 if (ptrIDebugAdvanced != 0) {
651 ptrIDebugAdvanced->Release();
652 }
654 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
655 ptrIDebugSymbols_ID);
656 CHECK_EXCEPTION_(false);
657 if (ptrIDebugSymbols != 0) {
658 ptrIDebugSymbols->Release();
659 }
661 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
662 ptrIDebugSystemObjects_ID);
663 CHECK_EXCEPTION_(false);
664 if (ptrIDebugSystemObjects != 0) {
665 ptrIDebugSystemObjects->Release();
666 }
668 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
669 ptrIDebugControl_ID);
670 CHECK_EXCEPTION_(false);
671 if (ptrIDebugControl != 0) {
672 ptrIDebugControl->Release();
673 }
675 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
676 ptrIDebugClient_ID);
677 CHECK_EXCEPTION_(false);
678 if (ptrIDebugClient != 0) {
679 ptrIDebugClient->Release();
680 }
682 return true;
683 }
685 /*
686 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
687 * Method: detach0
688 * Signature: ()V
689 */
690 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0
691 (JNIEnv *env, jobject obj) {
692 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
693 ptrIDebugClient_ID);
694 CHECK_EXCEPTION;
695 ptrIDebugClient->DetachProcesses();
696 releaseWindbgInterfaces(env, obj);
697 }
700 /*
701 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
702 * Method: readBytesFromProcess0
703 * Signature: (JJ)[B
704 */
705 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0
706 (JNIEnv *env, jobject obj, jlong address, jlong numBytes) {
707 jbyteArray byteArray = env->NewByteArray((long) numBytes);
708 CHECK_EXCEPTION_(0);
710 jboolean isCopy = JNI_FALSE;
711 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
712 CHECK_EXCEPTION_(0);
714 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
715 ptrIDebugDataSpaces_ID);
716 CHECK_EXCEPTION_(0);
718 ULONG bytesRead;
719 if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr,
720 (ULONG)numBytes, &bytesRead) != S_OK) {
721 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0);
722 }
724 if (bytesRead != numBytes) {
725 return 0;
726 }
728 env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
729 CHECK_EXCEPTION_(0);
731 return byteArray;
732 }
734 /*
735 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
736 * Method: getThreadIdFromSysId0
737 * Signature: (J)J
738 */
739 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0
740 (JNIEnv *env, jobject obj, jlong sysId) {
741 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
742 ptrIDebugSystemObjects_ID);
743 CHECK_EXCEPTION_(0);
745 ULONG id = 0;
746 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
747 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
748 }
750 return (jlong) id;
751 }
753 // manage COM 'auto' pointers (to avoid multiple Release
754 // calls at every early (exception) returns). Similar to AutoArrayPtr.
756 template <class T>
757 class AutoCOMPtr {
758 T* m_ptr;
760 public:
761 AutoCOMPtr(T* ptr) : m_ptr(ptr) {
762 }
764 ~AutoCOMPtr() {
765 if (m_ptr) {
766 m_ptr->Release();
767 }
768 }
770 T* operator->() {
771 return m_ptr;
772 }
773 };
775 /*
776 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
777 * Method: consoleExecuteCommand0
778 * Signature: (Ljava/lang/String;)Ljava/lang/String;
779 */
780 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0
781 (JNIEnv *env, jobject obj, jstring cmd) {
782 jboolean isCopy = JNI_FALSE;
783 const char* buf = env->GetStringUTFChars(cmd, &isCopy);
784 CHECK_EXCEPTION_(0);
785 AutoJavaString command(env, cmd, buf);
787 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
788 CHECK_EXCEPTION_(0);
790 IDebugClient* tmpClientPtr = 0;
791 if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) {
792 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0);
793 }
794 AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);
796 IDebugControl* tmpControlPtr = 0;
797 if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) {
798 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0);
799 }
800 AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);
802 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
803 ptrIDebugOutputCallbacks_ID);
804 CHECK_EXCEPTION_(0);
806 saOutputCallbacks->clearBuffer();
808 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
809 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
810 }
812 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
814 const char* output = saOutputCallbacks->getBuffer();
815 if (output == 0) {
816 output = "";
817 }
819 jstring res = env->NewStringUTF(output);
820 saOutputCallbacks->clearBuffer();
821 return res;
822 }
824 /*
825 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
826 * Method: lookupByName0
827 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
828 */
830 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0
831 (JNIEnv *env, jobject obj, jstring objName, jstring sym) {
832 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
833 ptrIDebugSymbols_ID);
834 CHECK_EXCEPTION_(0);
836 jboolean isCopy;
837 const char* buf = env->GetStringUTFChars(sym, &isCopy);
838 CHECK_EXCEPTION_(0);
839 AutoJavaString name(env, sym, buf);
841 ULONG64 offset = 0L;
842 if (strstr(name, "::") != 0) {
843 ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);
844 } else {
845 ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);
846 }
847 if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
848 return (jlong) 0;
849 }
850 return (jlong) offset;
851 }
853 #define SYMBOL_BUFSIZE 512
854 /*
855 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
856 * Method: lookupByAddress0
857 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
858 */
859 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0
860 (JNIEnv *env, jobject obj, jlong address) {
861 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
862 ptrIDebugSymbols_ID);
863 CHECK_EXCEPTION_(0);
865 ULONG64 disp = 0L;
866 char buf[SYMBOL_BUFSIZE];
867 memset(buf, 0, sizeof(buf));
869 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
870 != S_OK) {
871 return 0;
872 }
874 jstring sym = env->NewStringUTF(buf);
875 CHECK_EXCEPTION_(0);
876 jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);
877 CHECK_EXCEPTION_(0);
878 return res;
879 }