Thu, 27 May 2010 19:08:38 -0700
6941466: Oracle rebranding changes for Hotspot repositories
Summary: Change all the Sun copyrights to Oracle copyright
Reviewed-by: ohair
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_IA64
31 #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h"
32 #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG
33 #elif _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
43 #include <limits.h>
44 #include <windows.h>
46 #ifndef STDMETHODV
47 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
48 #endif
50 #define DEBUG_NO_IMPLEMENTATION
51 #include <dbgeng.h>
52 #include <dbghelp.h>
54 // simple template to manage array delete across early (error) returns
56 template <class T>
57 class AutoArrayPtr {
58 T* m_ptr;
59 public:
60 AutoArrayPtr(T* ptr) : m_ptr(ptr) {
61 }
63 ~AutoArrayPtr() {
64 delete [] m_ptr;
65 }
67 T* asPtr() {
68 return m_ptr;
69 }
70 };
72 class AutoJavaString {
73 JNIEnv* m_env;
74 jstring m_str;
75 const char* m_buf;
77 public:
78 AutoJavaString(JNIEnv* env, jstring str, const char* buf)
79 : m_env(env), m_str(str), m_buf(buf) {
80 }
82 ~AutoJavaString() {
83 m_env->ReleaseStringUTFChars(m_str, m_buf);
84 }
86 operator const char* () {
87 return m_buf;
88 }
89 };
91 // field and method IDs we want here
93 static jfieldID imagePath_ID = 0;
94 static jfieldID symbolPath_ID = 0;
95 static jfieldID ptrIDebugClient_ID = 0;
96 static jfieldID ptrIDebugControl_ID = 0;
97 static jfieldID ptrIDebugDataSpaces_ID = 0;
98 static jfieldID ptrIDebugOutputCallbacks_ID = 0;
99 static jfieldID ptrIDebugAdvanced_ID = 0;
100 static jfieldID ptrIDebugSymbols_ID = 0;
101 static jfieldID ptrIDebugSystemObjects_ID = 0;
103 static jmethodID addLoadObject_ID = 0;
104 static jmethodID addThread_ID = 0;
105 static jmethodID createClosestSymbol_ID = 0;
106 static jmethodID setThreadIntegerRegisterSet_ID = 0;
108 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
109 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
111 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
112 throwNewDebuggerException(env, str); return value; }
114 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \
115 return;}
117 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
118 env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
119 }
121 /*
122 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
123 * Method: initIDs
124 * Signature: ()V
125 */
126 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs
127 (JNIEnv *env, jclass clazz) {
128 imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;");
129 CHECK_EXCEPTION;
131 symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
132 CHECK_EXCEPTION;
134 ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
135 CHECK_EXCEPTION;
137 ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
138 CHECK_EXCEPTION;
140 ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
141 CHECK_EXCEPTION;
143 ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz,
144 "ptrIDebugOutputCallbacks", "J");
145 CHECK_EXCEPTION;
147 ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
148 CHECK_EXCEPTION;
150 ptrIDebugSymbols_ID = env->GetFieldID(clazz,
151 "ptrIDebugSymbols", "J");
152 CHECK_EXCEPTION;
154 ptrIDebugSystemObjects_ID = env->GetFieldID(clazz,
155 "ptrIDebugSystemObjects", "J");
156 CHECK_EXCEPTION;
158 addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject",
159 "(Ljava/lang/String;JJ)V");
160 CHECK_EXCEPTION;
162 addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
163 CHECK_EXCEPTION;
165 createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
166 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
167 CHECK_EXCEPTION;
169 setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
170 "setThreadIntegerRegisterSet", "(J[J)V");
171 CHECK_EXCEPTION;
173 }
175 // class for IDebugOutputCallbacks
177 class SAOutputCallbacks : public IDebugOutputCallbacks {
178 LONG m_refCount;
179 char* m_msgBuffer;
181 public:
182 SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) {
183 }
185 ~SAOutputCallbacks() {
186 clearBuffer();
187 }
189 const char* getBuffer() const {
190 return m_msgBuffer;
191 }
193 void clearBuffer() {
194 if (m_msgBuffer) {
195 free(m_msgBuffer);
196 m_msgBuffer = 0;
197 }
198 }
200 STDMETHOD_(ULONG, AddRef)(THIS);
201 STDMETHOD_(ULONG, Release)(THIS);
202 STDMETHOD(QueryInterface)(THIS_
203 IN REFIID interfaceId,
204 OUT PVOID* ppInterface);
205 STDMETHOD(Output)(THIS_
206 IN ULONG mask,
207 IN PCSTR msg);
208 };
210 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
211 InterlockedIncrement(&m_refCount);
212 return m_refCount;
213 }
215 STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) {
216 LONG retVal;
217 InterlockedDecrement(&m_refCount);
218 retVal = m_refCount;
219 if (retVal == 0) {
220 delete this;
221 }
222 return retVal;
223 }
225 STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_
226 IN REFIID interfaceId,
227 OUT PVOID* ppInterface) {
228 *ppInterface = 0;
229 HRESULT res = E_NOINTERFACE;
230 if (TRUE == IsEqualIID(interfaceId, __uuidof(IUnknown)) ||
231 TRUE == IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) {
232 *ppInterface = (IDebugOutputCallbacks*) this;
233 AddRef();
234 res = S_OK;
235 }
236 return res;
237 }
239 STDMETHODIMP SAOutputCallbacks::Output(THIS_
240 IN ULONG mask,
241 IN PCSTR msg) {
242 int len = (int) (strlen(msg) + 1);
243 if (m_msgBuffer == 0) {
244 m_msgBuffer = (char*) malloc(len);
245 if (m_msgBuffer == 0) {
246 fprintf(stderr, "out of memory debugger output!\n");
247 return S_FALSE;
248 }
249 strcpy(m_msgBuffer, msg);
250 } else {
251 m_msgBuffer = (char*) realloc(m_msgBuffer, len + strlen(m_msgBuffer));
252 if (m_msgBuffer == 0) {
253 fprintf(stderr, "out of memory debugger output!\n");
254 return S_FALSE;
255 }
256 strcat(m_msgBuffer, msg);
257 }
258 return S_OK;
259 }
261 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
262 // get windbg interfaces ..
264 IDebugClient* ptrIDebugClient = 0;
265 if (DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient) != S_OK) {
266 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to create IDebugClient object!", false);
267 }
268 env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient);
270 IDebugControl* ptrIDebugControl = 0;
271 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl)
272 != S_OK) {
273 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugControl", false);
274 }
275 env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl);
277 IDebugDataSpaces* ptrIDebugDataSpaces = 0;
278 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces)
279 != S_OK) {
280 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugDataSpaces object!", false);
281 }
282 env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces);
284 SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
285 ptrIDebugOutputCallbacks->AddRef();
286 env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
287 CHECK_EXCEPTION_(false);
289 IDebugAdvanced* ptrIDebugAdvanced = 0;
290 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced)
291 != S_OK) {
292 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugAdvanced object!", false);
293 }
294 env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced);
296 IDebugSymbols* ptrIDebugSymbols = 0;
297 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols)
298 != S_OK) {
299 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSymbols object!", false);
300 }
301 env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols);
303 IDebugSystemObjects* ptrIDebugSystemObjects = 0;
304 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects)
305 != S_OK) {
306 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSystemObjects object!", false);
307 }
308 env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects);
310 return true;
311 }
313 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
314 jboolean isCopy;
315 jclass clazz = env->GetObjectClass(obj);
316 jstring path;
317 const char* buf;
319 path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
320 buf = env->GetStringUTFChars(path, &isCopy);
321 CHECK_EXCEPTION_(false);
322 AutoJavaString imagePath(env, path, buf);
324 path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
325 buf = env->GetStringUTFChars(path, &isCopy);
326 CHECK_EXCEPTION_(false);
327 AutoJavaString symbolPath(env, path, buf);
329 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
330 ptrIDebugSymbols_ID);
331 CHECK_EXCEPTION_(false);
333 ptrIDebugSymbols->SetImagePath(imagePath);
334 ptrIDebugSymbols->SetSymbolPath(symbolPath);
335 return true;
336 }
338 static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) {
339 // open the dump file
340 jboolean isCopy;
341 const char* buf = env->GetStringUTFChars(coreFileName, &isCopy);
342 CHECK_EXCEPTION_(false);
343 AutoJavaString coreFile(env, coreFileName, buf);
344 if (setImageAndSymbolPath(env, obj) == false) {
345 return false;
346 }
348 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
349 ptrIDebugClient_ID);
350 CHECK_EXCEPTION_(false);
351 if (ptrIDebugClient->OpenDumpFile(coreFile) != S_OK) {
352 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: OpenDumpFile failed!", false);
353 }
355 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
356 ptrIDebugControl_ID);
357 CHECK_EXCEPTION_(false);
358 if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
359 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
360 }
362 return true;
363 }
366 static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) {
367 if (setImageAndSymbolPath(env, obj) == false) {
368 return false;
369 }
370 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
371 ptrIDebugClient_ID);
372 CHECK_EXCEPTION_(false);
374 /***********************************************************************************
376 We are attaching to a process in 'read-only' mode. i.e., we do not want to
377 put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
378 usage this should suffice. We are not intending to use this for full-fledged
379 ProcessControl implementation to be used with BugSpotAgent.
381 Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
382 In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
383 actually debugging at all. We can safely 'detach' from the process anytime
384 we want and debuggee process is left as is on all Windows variants.
386 This also makes JDI-on-SA installation/usage simpler because with this we would
387 not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.
389 ***********************************************************************************/
392 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
393 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
394 }
396 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
397 ptrIDebugControl_ID);
398 CHECK_EXCEPTION_(false);
399 if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
400 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
401 }
403 return true;
404 }
407 static bool addLoadObjects(JNIEnv* env, jobject obj) {
408 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
409 ptrIDebugSymbols_ID);
410 CHECK_EXCEPTION_(false);
411 ULONG loaded = 0, unloaded = 0;
412 if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) {
413 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false);
414 }
416 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
418 if (params.asPtr() == 0) {
419 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
420 }
422 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
423 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
424 }
426 for (int u = 0; u < (int)loaded; u++) {
427 TCHAR imageName[MAX_PATH];
428 if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base,
429 imageName, MAX_PATH, NULL, NULL,
430 0, NULL, NULL, 0, NULL) != S_OK) {
431 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false);
432 }
434 jstring strName = env->NewStringUTF(imageName);
435 CHECK_EXCEPTION_(false);
436 env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size,
437 (jlong) params.asPtr()[u].Base);
438 CHECK_EXCEPTION_(false);
439 }
441 return true;
442 }
444 static bool addThreads(JNIEnv* env, jobject obj) {
445 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
446 ptrIDebugSystemObjects_ID);
447 CHECK_EXCEPTION_(false);
449 ULONG numThreads = 0;
450 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
451 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
452 }
454 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
456 if (ptrSysThreadIds.asPtr() == 0) {
457 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
458 }
460 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
462 if (ptrThreadIds.asPtr() == 0) {
463 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
464 }
466 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
467 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
468 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
469 }
472 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
473 ptrIDebugAdvanced_ID);
474 CHECK_EXCEPTION_(false);
476 // for each thread, get register context and save it.
477 for (ULONG t = 0; t < numThreads; t++) {
478 if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) {
479 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false);
480 }
482 jlongArray regs = env->NewLongArray(NPRGREG);
483 CHECK_EXCEPTION_(false);
485 jboolean isCopy = JNI_FALSE;
486 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
487 CHECK_EXCEPTION_(false);
489 // copy register values from the CONTEXT struct
490 CONTEXT context;
491 memset(&context, 0, sizeof(CONTEXT));
493 #undef REG_INDEX
494 #ifdef _M_IA64
495 #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x
497 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG;
498 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
500 ptrRegs[REG_INDEX(GR0)] = 0; // always 0
501 ptrRegs[REG_INDEX(GR1)] = context.IntGp; // r1
502 ptrRegs[REG_INDEX(GR2)] = context.IntT0; // r2-r3
503 ptrRegs[REG_INDEX(GR3)] = context.IntT1;
504 ptrRegs[REG_INDEX(GR4)] = context.IntS0; // r4-r7
505 ptrRegs[REG_INDEX(GR5)] = context.IntS1;
506 ptrRegs[REG_INDEX(GR6)] = context.IntS2;
507 ptrRegs[REG_INDEX(GR7)] = context.IntS3;
508 ptrRegs[REG_INDEX(GR8)] = context.IntV0; // r8
509 ptrRegs[REG_INDEX(GR9)] = context.IntT2; // r9-r11
510 ptrRegs[REG_INDEX(GR10)] = context.IntT3;
511 ptrRegs[REG_INDEX(GR11)] = context.IntT4;
512 ptrRegs[REG_INDEX(GR12)] = context.IntSp; // r12 stack pointer
513 ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb
514 ptrRegs[REG_INDEX(GR14)] = context.IntT5; // r14-r31
515 ptrRegs[REG_INDEX(GR15)] = context.IntT6;
516 ptrRegs[REG_INDEX(GR16)] = context.IntT7;
517 ptrRegs[REG_INDEX(GR17)] = context.IntT8;
518 ptrRegs[REG_INDEX(GR18)] = context.IntT9;
519 ptrRegs[REG_INDEX(GR19)] = context.IntT10;
520 ptrRegs[REG_INDEX(GR20)] = context.IntT11;
521 ptrRegs[REG_INDEX(GR21)] = context.IntT12;
522 ptrRegs[REG_INDEX(GR22)] = context.IntT13;
523 ptrRegs[REG_INDEX(GR23)] = context.IntT14;
524 ptrRegs[REG_INDEX(GR24)] = context.IntT15;
525 ptrRegs[REG_INDEX(GR25)] = context.IntT16;
526 ptrRegs[REG_INDEX(GR26)] = context.IntT17;
527 ptrRegs[REG_INDEX(GR27)] = context.IntT18;
528 ptrRegs[REG_INDEX(GR28)] = context.IntT19;
529 ptrRegs[REG_INDEX(GR29)] = context.IntT20;
530 ptrRegs[REG_INDEX(GR30)] = context.IntT21;
531 ptrRegs[REG_INDEX(GR31)] = context.IntT22;
533 ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats;
534 ptrRegs[REG_INDEX(PREDS)] = context.Preds;
536 ptrRegs[REG_INDEX(BR_RP)] = context.BrRp;
537 ptrRegs[REG_INDEX(BR1)] = context.BrS0; // b1-b5
538 ptrRegs[REG_INDEX(BR2)] = context.BrS1;
539 ptrRegs[REG_INDEX(BR3)] = context.BrS2;
540 ptrRegs[REG_INDEX(BR4)] = context.BrS3;
541 ptrRegs[REG_INDEX(BR5)] = context.BrS4;
542 ptrRegs[REG_INDEX(BR6)] = context.BrT0; // b6-b7
543 ptrRegs[REG_INDEX(BR7)] = context.BrT1;
545 ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT;
546 ptrRegs[REG_INDEX(AP_LC)] = context.ApLC;
547 ptrRegs[REG_INDEX(AP_EC)] = context.ApEC;
548 ptrRegs[REG_INDEX(AP_CCV)] = context.ApCCV;
549 ptrRegs[REG_INDEX(AP_DCR)] = context.ApDCR;
551 ptrRegs[REG_INDEX(RS_PFS)] = context.RsPFS;
552 ptrRegs[REG_INDEX(RS_BSP)] = context.RsBSP;
553 ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE;
554 ptrRegs[REG_INDEX(RS_RSC)] = context.RsRSC;
555 ptrRegs[REG_INDEX(RS_RNAT)] = context.RsRNAT;
557 ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR;
558 ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP;
559 ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS;
561 ptrRegs[REG_INDEX(DB_I0)] = context.DbI0;
562 ptrRegs[REG_INDEX(DB_I1)] = context.DbI1;
563 ptrRegs[REG_INDEX(DB_I2)] = context.DbI2;
564 ptrRegs[REG_INDEX(DB_I3)] = context.DbI3;
565 ptrRegs[REG_INDEX(DB_I4)] = context.DbI4;
566 ptrRegs[REG_INDEX(DB_I5)] = context.DbI5;
567 ptrRegs[REG_INDEX(DB_I6)] = context.DbI6;
568 ptrRegs[REG_INDEX(DB_I7)] = context.DbI7;
570 ptrRegs[REG_INDEX(DB_D0)] = context.DbD0;
571 ptrRegs[REG_INDEX(DB_D1)] = context.DbD1;
572 ptrRegs[REG_INDEX(DB_D2)] = context.DbD2;
573 ptrRegs[REG_INDEX(DB_D3)] = context.DbD3;
574 ptrRegs[REG_INDEX(DB_D4)] = context.DbD4;
575 ptrRegs[REG_INDEX(DB_D5)] = context.DbD5;
576 ptrRegs[REG_INDEX(DB_D6)] = context.DbD6;
577 ptrRegs[REG_INDEX(DB_D7)] = context.DbD7;
579 #elif _M_IX86
580 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
582 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
583 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
585 ptrRegs[REG_INDEX(GS)] = context.SegGs;
586 ptrRegs[REG_INDEX(FS)] = context.SegFs;
587 ptrRegs[REG_INDEX(ES)] = context.SegEs;
588 ptrRegs[REG_INDEX(DS)] = context.SegDs;
590 ptrRegs[REG_INDEX(EDI)] = context.Edi;
591 ptrRegs[REG_INDEX(ESI)] = context.Esi;
592 ptrRegs[REG_INDEX(EBX)] = context.Ebx;
593 ptrRegs[REG_INDEX(EDX)] = context.Edx;
594 ptrRegs[REG_INDEX(ECX)] = context.Ecx;
595 ptrRegs[REG_INDEX(EAX)] = context.Eax;
597 ptrRegs[REG_INDEX(FP)] = context.Ebp;
598 ptrRegs[REG_INDEX(PC)] = context.Eip;
599 ptrRegs[REG_INDEX(CS)] = context.SegCs;
600 ptrRegs[REG_INDEX(EFL)] = context.EFlags;
601 ptrRegs[REG_INDEX(SP)] = context.Esp;
602 ptrRegs[REG_INDEX(SS)] = context.SegSs;
604 ptrRegs[REG_INDEX(DR0)] = context.Dr0;
605 ptrRegs[REG_INDEX(DR1)] = context.Dr1;
606 ptrRegs[REG_INDEX(DR2)] = context.Dr2;
607 ptrRegs[REG_INDEX(DR3)] = context.Dr3;
608 ptrRegs[REG_INDEX(DR6)] = context.Dr6;
609 ptrRegs[REG_INDEX(DR7)] = context.Dr7;
611 #elif _M_AMD64
612 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
614 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
615 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
617 // Segment Registers and processor flags
618 ptrRegs[REG_INDEX(CS)] = context.SegCs;
619 ptrRegs[REG_INDEX(DS)] = context.SegDs;
620 ptrRegs[REG_INDEX(ES)] = context.SegEs;
621 ptrRegs[REG_INDEX(FS)] = context.SegFs;
622 ptrRegs[REG_INDEX(GS)] = context.SegGs;
623 ptrRegs[REG_INDEX(SS)] = context.SegSs;
624 ptrRegs[REG_INDEX(RFL)] = context.EFlags;
626 // Integer registers
627 ptrRegs[REG_INDEX(RDI)] = context.Rdi;
628 ptrRegs[REG_INDEX(RSI)] = context.Rsi;
629 ptrRegs[REG_INDEX(RAX)] = context.Rax;
630 ptrRegs[REG_INDEX(RCX)] = context.Rcx;
631 ptrRegs[REG_INDEX(RDX)] = context.Rdx;
632 ptrRegs[REG_INDEX(RBX)] = context.Rbx;
633 ptrRegs[REG_INDEX(RBP)] = context.Rbp;
634 ptrRegs[REG_INDEX(RSP)] = context.Rsp;
636 ptrRegs[REG_INDEX(R8)] = context.R8;
637 ptrRegs[REG_INDEX(R9)] = context.R9;
638 ptrRegs[REG_INDEX(R10)] = context.R10;
639 ptrRegs[REG_INDEX(R11)] = context.R11;
640 ptrRegs[REG_INDEX(R12)] = context.R12;
641 ptrRegs[REG_INDEX(R13)] = context.R13;
642 ptrRegs[REG_INDEX(R14)] = context.R14;
643 ptrRegs[REG_INDEX(R15)] = context.R15;
645 // Program counter
646 ptrRegs[REG_INDEX(RIP)] = context.Rip;
647 #endif
649 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
650 CHECK_EXCEPTION_(false);
652 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
653 (jlong) ptrThreadIds.asPtr()[t], regs);
654 CHECK_EXCEPTION_(false);
656 ULONG sysId;
657 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
658 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
659 }
661 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
662 CHECK_EXCEPTION_(false);
663 }
665 return true;
666 }
668 /*
669 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
670 * Method: attach0
671 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
672 */
673 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
674 (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {
676 if (getWindbgInterfaces(env, obj) == false) {
677 return;
678 }
680 if (openDumpFile(env, obj, coreFileName) == false) {
681 return;
682 }
684 if (addLoadObjects(env, obj) == false) {
685 return;
686 }
688 if (addThreads(env, obj) == false) {
689 return;
690 }
691 }
693 /*
694 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
695 * Method: attach0
696 * Signature: (I)V
697 */
698 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I
699 (JNIEnv *env, jobject obj, jint pid) {
701 if (getWindbgInterfaces(env, obj) == false) {
702 return;
703 }
705 if (attachToProcess(env, obj, pid) == false) {
706 return;
707 }
709 if (addLoadObjects(env, obj) == false) {
710 return;
711 }
713 if (addThreads(env, obj) == false) {
714 return;
715 }
716 }
719 static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {
720 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
721 ptrIDebugDataSpaces_ID);
722 CHECK_EXCEPTION_(false);
723 if (ptrIDebugDataSpaces != 0) {
724 ptrIDebugDataSpaces->Release();
725 }
727 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
728 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
729 CHECK_EXCEPTION_(false);
730 if (ptrIDebugOutputCallbacks != 0) {
731 ptrIDebugOutputCallbacks->Release();
732 }
734 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
735 ptrIDebugAdvanced_ID);
736 CHECK_EXCEPTION_(false);
738 if (ptrIDebugAdvanced != 0) {
739 ptrIDebugAdvanced->Release();
740 }
742 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
743 ptrIDebugSymbols_ID);
744 CHECK_EXCEPTION_(false);
745 if (ptrIDebugSymbols != 0) {
746 ptrIDebugSymbols->Release();
747 }
749 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
750 ptrIDebugSystemObjects_ID);
751 CHECK_EXCEPTION_(false);
752 if (ptrIDebugSystemObjects != 0) {
753 ptrIDebugSystemObjects->Release();
754 }
756 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
757 ptrIDebugControl_ID);
758 CHECK_EXCEPTION_(false);
759 if (ptrIDebugControl != 0) {
760 ptrIDebugControl->Release();
761 }
763 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
764 ptrIDebugClient_ID);
765 CHECK_EXCEPTION_(false);
766 if (ptrIDebugClient != 0) {
767 ptrIDebugClient->Release();
768 }
770 return true;
771 }
773 /*
774 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
775 * Method: detach0
776 * Signature: ()V
777 */
778 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0
779 (JNIEnv *env, jobject obj) {
780 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
781 ptrIDebugClient_ID);
782 CHECK_EXCEPTION;
783 ptrIDebugClient->DetachProcesses();
784 releaseWindbgInterfaces(env, obj);
785 }
788 /*
789 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
790 * Method: readBytesFromProcess0
791 * Signature: (JJ)[B
792 */
793 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0
794 (JNIEnv *env, jobject obj, jlong address, jlong numBytes) {
795 jbyteArray byteArray = env->NewByteArray((long) numBytes);
796 CHECK_EXCEPTION_(0);
798 jboolean isCopy = JNI_FALSE;
799 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
800 CHECK_EXCEPTION_(0);
802 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
803 ptrIDebugDataSpaces_ID);
804 CHECK_EXCEPTION_(0);
806 ULONG bytesRead;
807 if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr,
808 (ULONG)numBytes, &bytesRead) != S_OK) {
809 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0);
810 }
812 if (bytesRead != numBytes) {
813 return 0;
814 }
816 env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
817 CHECK_EXCEPTION_(0);
819 return byteArray;
820 }
822 /*
823 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
824 * Method: getThreadIdFromSysId0
825 * Signature: (J)J
826 */
827 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0
828 (JNIEnv *env, jobject obj, jlong sysId) {
829 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
830 ptrIDebugSystemObjects_ID);
831 CHECK_EXCEPTION_(0);
833 ULONG id = 0;
834 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
835 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
836 }
838 return (jlong) id;
839 }
841 // manage COM 'auto' pointers (to avoid multiple Release
842 // calls at every early (exception) returns). Similar to AutoArrayPtr.
844 template <class T>
845 class AutoCOMPtr {
846 T* m_ptr;
848 public:
849 AutoCOMPtr(T* ptr) : m_ptr(ptr) {
850 }
852 ~AutoCOMPtr() {
853 if (m_ptr) {
854 m_ptr->Release();
855 }
856 }
858 T* operator->() {
859 return m_ptr;
860 }
861 };
863 /*
864 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
865 * Method: consoleExecuteCommand0
866 * Signature: (Ljava/lang/String;)Ljava/lang/String;
867 */
868 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0
869 (JNIEnv *env, jobject obj, jstring cmd) {
870 jboolean isCopy = JNI_FALSE;
871 const char* buf = env->GetStringUTFChars(cmd, &isCopy);
872 CHECK_EXCEPTION_(0);
873 AutoJavaString command(env, cmd, buf);
875 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
876 CHECK_EXCEPTION_(0);
878 IDebugClient* tmpClientPtr = 0;
879 if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) {
880 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0);
881 }
882 AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);
884 IDebugControl* tmpControlPtr = 0;
885 if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) {
886 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0);
887 }
888 AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);
890 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
891 ptrIDebugOutputCallbacks_ID);
892 CHECK_EXCEPTION_(0);
894 saOutputCallbacks->clearBuffer();
896 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
897 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
898 }
900 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
902 const char* output = saOutputCallbacks->getBuffer();
903 if (output == 0) {
904 output = "";
905 }
907 jstring res = env->NewStringUTF(output);
908 saOutputCallbacks->clearBuffer();
909 return res;
910 }
912 /*
913 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
914 * Method: lookupByName0
915 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
916 */
918 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0
919 (JNIEnv *env, jobject obj, jstring objName, jstring sym) {
920 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
921 ptrIDebugSymbols_ID);
922 CHECK_EXCEPTION_(0);
924 jboolean isCopy;
925 const char* buf = env->GetStringUTFChars(sym, &isCopy);
926 CHECK_EXCEPTION_(0);
927 AutoJavaString name(env, sym, buf);
929 ULONG64 offset = 0L;
930 if (strstr(name, "::") != 0) {
931 ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);
932 } else {
933 ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);
934 }
935 if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
936 return (jlong) 0;
937 }
938 return (jlong) offset;
939 }
941 #define SYMBOL_BUFSIZE 512
942 /*
943 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
944 * Method: lookupByAddress0
945 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
946 */
947 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0
948 (JNIEnv *env, jobject obj, jlong address) {
949 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
950 ptrIDebugSymbols_ID);
951 CHECK_EXCEPTION_(0);
953 ULONG64 disp = 0L;
954 char buf[SYMBOL_BUFSIZE];
955 memset(buf, 0, sizeof(buf));
957 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
958 != S_OK) {
959 return 0;
960 }
962 jstring sym = env->NewStringUTF(buf);
963 CHECK_EXCEPTION_(0);
964 jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);
965 CHECK_EXCEPTION_(0);
966 return res;
967 }