comparison agent/src/os/win32/windbg/sawindbg.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2002-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 // this is source code windbg based SA debugger agent to debug
26 // Dr. Watson dump files and process snapshots.
27
28 #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"
29
30 #ifdef _M_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
42
43 #include <limits.h>
44 #include <windows.h>
45
46 #ifndef STDMETHODV
47 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
48 #endif
49
50 #define DEBUG_NO_IMPLEMENTATION
51 #include <dbgeng.h>
52 #include <dbghelp.h>
53
54 // simple template to manage array delete across early (error) returns
55
56 template <class T>
57 class AutoArrayPtr {
58 T* m_ptr;
59 public:
60 AutoArrayPtr(T* ptr) : m_ptr(ptr) {
61 }
62
63 ~AutoArrayPtr() {
64 delete [] m_ptr;
65 }
66
67 T* asPtr() {
68 return m_ptr;
69 }
70 };
71
72 class AutoJavaString {
73 JNIEnv* m_env;
74 jstring m_str;
75 const char* m_buf;
76
77 public:
78 AutoJavaString(JNIEnv* env, jstring str, const char* buf)
79 : m_env(env), m_str(str), m_buf(buf) {
80 }
81
82 ~AutoJavaString() {
83 m_env->ReleaseStringUTFChars(m_str, m_buf);
84 }
85
86 operator const char* () {
87 return m_buf;
88 }
89 };
90
91 // field and method IDs we want here
92
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;
102
103 static jmethodID addLoadObject_ID = 0;
104 static jmethodID addThread_ID = 0;
105 static jmethodID createClosestSymbol_ID = 0;
106 static jmethodID setThreadIntegerRegisterSet_ID = 0;
107
108 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
109 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
110
111 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
112 throwNewDebuggerException(env, str); return value; }
113
114 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \
115 return;}
116
117 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
118 env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
119 }
120
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;
130
131 symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
132 CHECK_EXCEPTION;
133
134 ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
135 CHECK_EXCEPTION;
136
137 ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
138 CHECK_EXCEPTION;
139
140 ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
141 CHECK_EXCEPTION;
142
143 ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz,
144 "ptrIDebugOutputCallbacks", "J");
145 CHECK_EXCEPTION;
146
147 ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
148 CHECK_EXCEPTION;
149
150 ptrIDebugSymbols_ID = env->GetFieldID(clazz,
151 "ptrIDebugSymbols", "J");
152 CHECK_EXCEPTION;
153
154 ptrIDebugSystemObjects_ID = env->GetFieldID(clazz,
155 "ptrIDebugSystemObjects", "J");
156 CHECK_EXCEPTION;
157
158 addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject",
159 "(Ljava/lang/String;JJ)V");
160 CHECK_EXCEPTION;
161
162 addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
163 CHECK_EXCEPTION;
164
165 createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
166 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
167 CHECK_EXCEPTION;
168
169 setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
170 "setThreadIntegerRegisterSet", "(J[J)V");
171 CHECK_EXCEPTION;
172
173 }
174
175 // class for IDebugOutputCallbacks
176
177 class SAOutputCallbacks : public IDebugOutputCallbacks {
178 LONG m_refCount;
179 char* m_msgBuffer;
180
181 public:
182 SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) {
183 }
184
185 ~SAOutputCallbacks() {
186 clearBuffer();
187 }
188
189 const char* getBuffer() const {
190 return m_msgBuffer;
191 }
192
193 void clearBuffer() {
194 if (m_msgBuffer) {
195 free(m_msgBuffer);
196 m_msgBuffer = 0;
197 }
198 }
199
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 };
209
210 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
211 InterlockedIncrement(&m_refCount);
212 return m_refCount;
213 }
214
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 }
224
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 }
238
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 }
260
261 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
262 // get windbg interfaces ..
263
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);
269
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);
276
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);
283
284 SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
285 ptrIDebugOutputCallbacks->AddRef();
286 env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
287 CHECK_EXCEPTION_(false);
288
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);
295
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);
302
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);
309
310 return true;
311 }
312
313 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
314 jboolean isCopy;
315 jclass clazz = env->GetObjectClass(obj);
316 jstring path;
317 const char* buf;
318
319 path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
320 buf = env->GetStringUTFChars(path, &isCopy);
321 CHECK_EXCEPTION_(false);
322 AutoJavaString imagePath(env, path, buf);
323
324 path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
325 buf = env->GetStringUTFChars(path, &isCopy);
326 CHECK_EXCEPTION_(false);
327 AutoJavaString symbolPath(env, path, buf);
328
329 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
330 ptrIDebugSymbols_ID);
331 CHECK_EXCEPTION_(false);
332
333 ptrIDebugSymbols->SetImagePath(imagePath);
334 ptrIDebugSymbols->SetSymbolPath(symbolPath);
335 return true;
336 }
337
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 }
347
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 }
354
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 }
361
362 return true;
363 }
364
365
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);
373
374 /***********************************************************************************
375
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.
380
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.
385
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.
388
389 ***********************************************************************************/
390
391
392 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
393 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
394 }
395
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 }
402
403 return true;
404 }
405
406
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 }
415
416 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
417
418 if (params.asPtr() == 0) {
419 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
420 }
421
422 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
423 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
424 }
425
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 }
433
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 }
440
441 return true;
442 }
443
444 static bool addThreads(JNIEnv* env, jobject obj) {
445 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
446 ptrIDebugSystemObjects_ID);
447 CHECK_EXCEPTION_(false);
448
449 ULONG numThreads = 0;
450 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
451 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
452 }
453
454 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
455
456 if (ptrSysThreadIds.asPtr() == 0) {
457 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
458 }
459
460 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
461
462 if (ptrThreadIds.asPtr() == 0) {
463 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
464 }
465
466 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
467 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
468 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
469 }
470
471
472 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
473 ptrIDebugAdvanced_ID);
474 CHECK_EXCEPTION_(false);
475
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 }
481
482 jlongArray regs = env->NewLongArray(NPRGREG);
483 CHECK_EXCEPTION_(false);
484
485 jboolean isCopy = JNI_FALSE;
486 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
487 CHECK_EXCEPTION_(false);
488
489 // copy register values from the CONTEXT struct
490 CONTEXT context;
491 memset(&context, 0, sizeof(CONTEXT));
492
493 #undef REG_INDEX
494 #ifdef _M_IA64
495 #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x
496
497 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG;
498 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
499
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;
532
533 ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats;
534 ptrRegs[REG_INDEX(PREDS)] = context.Preds;
535
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;
544
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;
550
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;
556
557 ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR;
558 ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP;
559 ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS;
560
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;
569
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;
578
579 #elif _M_IX86
580 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
581
582 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
583 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
584
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;
589
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;
596
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;
603
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;
610
611 #elif _M_AMD64
612 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
613
614 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
615 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
616
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;
625
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;
635
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;
644
645 // Program counter
646 ptrRegs[REG_INDEX(RIP)] = context.Rip;
647 #endif
648
649 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
650 CHECK_EXCEPTION_(false);
651
652 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
653 (jlong) ptrThreadIds.asPtr()[t], regs);
654 CHECK_EXCEPTION_(false);
655
656 ULONG sysId;
657 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
658 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
659 }
660
661 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
662 CHECK_EXCEPTION_(false);
663 }
664
665 return true;
666 }
667
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) {
675
676 if (getWindbgInterfaces(env, obj) == false) {
677 return;
678 }
679
680 if (openDumpFile(env, obj, coreFileName) == false) {
681 return;
682 }
683
684 if (addLoadObjects(env, obj) == false) {
685 return;
686 }
687
688 if (addThreads(env, obj) == false) {
689 return;
690 }
691 }
692
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) {
700
701 if (getWindbgInterfaces(env, obj) == false) {
702 return;
703 }
704
705 if (attachToProcess(env, obj, pid) == false) {
706 return;
707 }
708
709 if (addLoadObjects(env, obj) == false) {
710 return;
711 }
712
713 if (addThreads(env, obj) == false) {
714 return;
715 }
716 }
717
718
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 }
726
727 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
728 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
729 CHECK_EXCEPTION_(false);
730 if (ptrIDebugOutputCallbacks != 0) {
731 ptrIDebugOutputCallbacks->Release();
732 }
733
734 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
735 ptrIDebugAdvanced_ID);
736 CHECK_EXCEPTION_(false);
737
738 if (ptrIDebugAdvanced != 0) {
739 ptrIDebugAdvanced->Release();
740 }
741
742 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
743 ptrIDebugSymbols_ID);
744 CHECK_EXCEPTION_(false);
745 if (ptrIDebugSymbols != 0) {
746 ptrIDebugSymbols->Release();
747 }
748
749 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
750 ptrIDebugSystemObjects_ID);
751 CHECK_EXCEPTION_(false);
752 if (ptrIDebugSystemObjects != 0) {
753 ptrIDebugSystemObjects->Release();
754 }
755
756 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
757 ptrIDebugControl_ID);
758 CHECK_EXCEPTION_(false);
759 if (ptrIDebugControl != 0) {
760 ptrIDebugControl->Release();
761 }
762
763 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
764 ptrIDebugClient_ID);
765 CHECK_EXCEPTION_(false);
766 if (ptrIDebugClient != 0) {
767 ptrIDebugClient->Release();
768 }
769
770 return true;
771 }
772
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 }
786
787
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);
797
798 jboolean isCopy = JNI_FALSE;
799 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
800 CHECK_EXCEPTION_(0);
801
802 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
803 ptrIDebugDataSpaces_ID);
804 CHECK_EXCEPTION_(0);
805
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 }
811
812 if (bytesRead != numBytes) {
813 return 0;
814 }
815
816 env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
817 CHECK_EXCEPTION_(0);
818
819 return byteArray;
820 }
821
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);
832
833 ULONG id = 0;
834 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
835 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
836 }
837
838 return (jlong) id;
839 }
840
841 // manage COM 'auto' pointers (to avoid multiple Release
842 // calls at every early (exception) returns). Similar to AutoArrayPtr.
843
844 template <class T>
845 class AutoCOMPtr {
846 T* m_ptr;
847
848 public:
849 AutoCOMPtr(T* ptr) : m_ptr(ptr) {
850 }
851
852 ~AutoCOMPtr() {
853 if (m_ptr) {
854 m_ptr->Release();
855 }
856 }
857
858 T* operator->() {
859 return m_ptr;
860 }
861 };
862
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);
874
875 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
876 CHECK_EXCEPTION_(0);
877
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);
883
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);
889
890 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
891 ptrIDebugOutputCallbacks_ID);
892 CHECK_EXCEPTION_(0);
893
894 saOutputCallbacks->clearBuffer();
895
896 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
897 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
898 }
899
900 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
901
902 const char* output = saOutputCallbacks->getBuffer();
903 if (output == 0) {
904 output = "";
905 }
906
907 jstring res = env->NewStringUTF(output);
908 saOutputCallbacks->clearBuffer();
909 return res;
910 }
911
912 /*
913 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
914 * Method: lookupByName0
915 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
916 */
917
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);
923
924 jboolean isCopy;
925 const char* buf = env->GetStringUTFChars(sym, &isCopy);
926 CHECK_EXCEPTION_(0);
927 AutoJavaString name(env, sym, buf);
928
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 }
940
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);
952
953 ULONG64 disp = 0L;
954 char buf[SYMBOL_BUFSIZE];
955 memset(buf, 0, sizeof(buf));
956
957 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
958 != S_OK) {
959 return 0;
960 }
961
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 }