Mercurial > hg > truffle
annotate agent/src/os/win32/windbg/sawindbg.cpp @ 7994:9fae07c31641
6518907: cleanup IA64 specific code in Hotspot
Summary: removed unused IA64 specific code
Reviewed-by: twisti, kvn, dholmes
author | morris |
---|---|
date | Fri, 25 Jan 2013 16:50:33 -0800 |
parents | c18cbe5936b8 |
children | 5ed317b25e23 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 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 | |
7994 | 30 #ifdef _M_IX86 |
0 | 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 | |
39 | |
40 #include <limits.h> | |
41 #include <windows.h> | |
42 | |
43 #ifndef STDMETHODV | |
44 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method | |
45 #endif | |
46 | |
47 #define DEBUG_NO_IMPLEMENTATION | |
48 #include <dbgeng.h> | |
49 #include <dbghelp.h> | |
50 | |
51 // simple template to manage array delete across early (error) returns | |
52 | |
53 template <class T> | |
54 class AutoArrayPtr { | |
55 T* m_ptr; | |
56 public: | |
57 AutoArrayPtr(T* ptr) : m_ptr(ptr) { | |
58 } | |
59 | |
60 ~AutoArrayPtr() { | |
61 delete [] m_ptr; | |
62 } | |
63 | |
64 T* asPtr() { | |
65 return m_ptr; | |
66 } | |
67 }; | |
68 | |
69 class AutoJavaString { | |
70 JNIEnv* m_env; | |
71 jstring m_str; | |
72 const char* m_buf; | |
73 | |
74 public: | |
75 AutoJavaString(JNIEnv* env, jstring str, const char* buf) | |
76 : m_env(env), m_str(str), m_buf(buf) { | |
77 } | |
78 | |
79 ~AutoJavaString() { | |
80 m_env->ReleaseStringUTFChars(m_str, m_buf); | |
81 } | |
82 | |
83 operator const char* () { | |
84 return m_buf; | |
85 } | |
86 }; | |
87 | |
88 // field and method IDs we want here | |
89 | |
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; | |
99 | |
100 static jmethodID addLoadObject_ID = 0; | |
101 static jmethodID addThread_ID = 0; | |
102 static jmethodID createClosestSymbol_ID = 0; | |
103 static jmethodID setThreadIntegerRegisterSet_ID = 0; | |
104 | |
105 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; } | |
106 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;} | |
107 | |
108 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \ | |
109 throwNewDebuggerException(env, str); return value; } | |
110 | |
111 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \ | |
112 return;} | |
113 | |
114 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) { | |
115 env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg); | |
116 } | |
117 | |
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; | |
127 | |
128 symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;"); | |
129 CHECK_EXCEPTION; | |
130 | |
131 ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J"); | |
132 CHECK_EXCEPTION; | |
133 | |
134 ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J"); | |
135 CHECK_EXCEPTION; | |
136 | |
137 ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J"); | |
138 CHECK_EXCEPTION; | |
139 | |
140 ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz, | |
141 "ptrIDebugOutputCallbacks", "J"); | |
142 CHECK_EXCEPTION; | |
143 | |
144 ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J"); | |
145 CHECK_EXCEPTION; | |
146 | |
147 ptrIDebugSymbols_ID = env->GetFieldID(clazz, | |
148 "ptrIDebugSymbols", "J"); | |
149 CHECK_EXCEPTION; | |
150 | |
151 ptrIDebugSystemObjects_ID = env->GetFieldID(clazz, | |
152 "ptrIDebugSystemObjects", "J"); | |
153 CHECK_EXCEPTION; | |
154 | |
155 addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject", | |
156 "(Ljava/lang/String;JJ)V"); | |
157 CHECK_EXCEPTION; | |
158 | |
159 addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V"); | |
160 CHECK_EXCEPTION; | |
161 | |
162 createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol", | |
163 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); | |
164 CHECK_EXCEPTION; | |
165 | |
166 setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz, | |
167 "setThreadIntegerRegisterSet", "(J[J)V"); | |
168 CHECK_EXCEPTION; | |
169 | |
170 } | |
171 | |
172 // class for IDebugOutputCallbacks | |
173 | |
174 class SAOutputCallbacks : public IDebugOutputCallbacks { | |
175 LONG m_refCount; | |
176 char* m_msgBuffer; | |
177 | |
178 public: | |
179 SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) { | |
180 } | |
181 | |
182 ~SAOutputCallbacks() { | |
183 clearBuffer(); | |
184 } | |
185 | |
186 const char* getBuffer() const { | |
187 return m_msgBuffer; | |
188 } | |
189 | |
190 void clearBuffer() { | |
191 if (m_msgBuffer) { | |
192 free(m_msgBuffer); | |
193 m_msgBuffer = 0; | |
194 } | |
195 } | |
196 | |
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 }; | |
206 | |
207 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) { | |
208 InterlockedIncrement(&m_refCount); | |
209 return m_refCount; | |
210 } | |
211 | |
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 } | |
221 | |
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 } | |
235 | |
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 } | |
257 | |
258 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) { | |
259 // get windbg interfaces .. | |
260 | |
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); | |
266 | |
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); | |
273 | |
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); | |
280 | |
281 SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks(); | |
282 ptrIDebugOutputCallbacks->AddRef(); | |
283 env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks); | |
284 CHECK_EXCEPTION_(false); | |
285 | |
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); | |
292 | |
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); | |
299 | |
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); | |
306 | |
307 return true; | |
308 } | |
309 | |
310 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) { | |
311 jboolean isCopy; | |
312 jclass clazz = env->GetObjectClass(obj); | |
313 jstring path; | |
314 const char* buf; | |
315 | |
316 path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID); | |
317 buf = env->GetStringUTFChars(path, &isCopy); | |
318 CHECK_EXCEPTION_(false); | |
319 AutoJavaString imagePath(env, path, buf); | |
320 | |
321 path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID); | |
322 buf = env->GetStringUTFChars(path, &isCopy); | |
323 CHECK_EXCEPTION_(false); | |
324 AutoJavaString symbolPath(env, path, buf); | |
325 | |
326 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, | |
327 ptrIDebugSymbols_ID); | |
328 CHECK_EXCEPTION_(false); | |
329 | |
330 ptrIDebugSymbols->SetImagePath(imagePath); | |
331 ptrIDebugSymbols->SetSymbolPath(symbolPath); | |
332 return true; | |
333 } | |
334 | |
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 } | |
344 | |
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 } | |
351 | |
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 } | |
358 | |
359 return true; | |
360 } | |
361 | |
362 | |
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); | |
370 | |
371 /*********************************************************************************** | |
372 | |
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. | |
377 | |
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. | |
382 | |
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. | |
385 | |
386 ***********************************************************************************/ | |
387 | |
388 | |
389 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) { | |
390 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false); | |
391 } | |
392 | |
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 } | |
399 | |
400 return true; | |
401 } | |
402 | |
403 | |
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 } | |
412 | |
413 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]); | |
414 | |
415 if (params.asPtr() == 0) { | |
416 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false); | |
417 } | |
418 | |
419 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) { | |
420 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false); | |
421 } | |
422 | |
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 } | |
430 | |
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 } | |
437 | |
438 return true; | |
439 } | |
440 | |
441 static bool addThreads(JNIEnv* env, jobject obj) { | |
442 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, | |
443 ptrIDebugSystemObjects_ID); | |
444 CHECK_EXCEPTION_(false); | |
445 | |
446 ULONG numThreads = 0; | |
447 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) { | |
448 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false); | |
449 } | |
450 | |
451 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads]; | |
452 | |
453 if (ptrSysThreadIds.asPtr() == 0) { | |
454 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); | |
455 } | |
456 | |
457 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads]; | |
458 | |
459 if (ptrThreadIds.asPtr() == 0) { | |
460 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); | |
461 } | |
462 | |
463 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads, | |
464 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) { | |
465 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false); | |
466 } | |
467 | |
468 | |
469 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, | |
470 ptrIDebugAdvanced_ID); | |
471 CHECK_EXCEPTION_(false); | |
472 | |
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 } | |
478 | |
479 jlongArray regs = env->NewLongArray(NPRGREG); | |
480 CHECK_EXCEPTION_(false); | |
481 | |
482 jboolean isCopy = JNI_FALSE; | |
483 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy); | |
484 CHECK_EXCEPTION_(false); | |
485 | |
486 // copy register values from the CONTEXT struct | |
487 CONTEXT context; | |
488 memset(&context, 0, sizeof(CONTEXT)); | |
489 | |
490 #undef REG_INDEX | |
7994 | 491 #ifdef _M_IX86 |
0 | 492 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x |
493 | |
494 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; | |
495 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); | |
496 | |
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; | |
501 | |
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; | |
508 | |
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; | |
515 | |
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; | |
522 | |
523 #elif _M_AMD64 | |
524 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x | |
525 | |
526 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; | |
527 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); | |
528 | |
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; | |
537 | |
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; | |
547 | |
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; | |
556 | |
557 // Program counter | |
558 ptrRegs[REG_INDEX(RIP)] = context.Rip; | |
559 #endif | |
560 | |
561 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT); | |
562 CHECK_EXCEPTION_(false); | |
563 | |
564 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, | |
565 (jlong) ptrThreadIds.asPtr()[t], regs); | |
566 CHECK_EXCEPTION_(false); | |
567 | |
568 ULONG sysId; | |
569 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) { | |
570 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false); | |
571 } | |
572 | |
573 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId); | |
574 CHECK_EXCEPTION_(false); | |
575 } | |
576 | |
577 return true; | |
578 } | |
579 | |
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) { | |
587 | |
588 if (getWindbgInterfaces(env, obj) == false) { | |
589 return; | |
590 } | |
591 | |
592 if (openDumpFile(env, obj, coreFileName) == false) { | |
593 return; | |
594 } | |
595 | |
596 if (addLoadObjects(env, obj) == false) { | |
597 return; | |
598 } | |
599 | |
600 if (addThreads(env, obj) == false) { | |
601 return; | |
602 } | |
603 } | |
604 | |
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) { | |
612 | |
613 if (getWindbgInterfaces(env, obj) == false) { | |
614 return; | |
615 } | |
616 | |
617 if (attachToProcess(env, obj, pid) == false) { | |
618 return; | |
619 } | |
620 | |
621 if (addLoadObjects(env, obj) == false) { | |
622 return; | |
623 } | |
624 | |
625 if (addThreads(env, obj) == false) { | |
626 return; | |
627 } | |
628 } | |
629 | |
630 | |
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 } | |
638 | |
639 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*) | |
640 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID); | |
641 CHECK_EXCEPTION_(false); | |
642 if (ptrIDebugOutputCallbacks != 0) { | |
643 ptrIDebugOutputCallbacks->Release(); | |
644 } | |
645 | |
646 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, | |
647 ptrIDebugAdvanced_ID); | |
648 CHECK_EXCEPTION_(false); | |
649 | |
650 if (ptrIDebugAdvanced != 0) { | |
651 ptrIDebugAdvanced->Release(); | |
652 } | |
653 | |
654 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, | |
655 ptrIDebugSymbols_ID); | |
656 CHECK_EXCEPTION_(false); | |
657 if (ptrIDebugSymbols != 0) { | |
658 ptrIDebugSymbols->Release(); | |
659 } | |
660 | |
661 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, | |
662 ptrIDebugSystemObjects_ID); | |
663 CHECK_EXCEPTION_(false); | |
664 if (ptrIDebugSystemObjects != 0) { | |
665 ptrIDebugSystemObjects->Release(); | |
666 } | |
667 | |
668 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, | |
669 ptrIDebugControl_ID); | |
670 CHECK_EXCEPTION_(false); | |
671 if (ptrIDebugControl != 0) { | |
672 ptrIDebugControl->Release(); | |
673 } | |
674 | |
675 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, | |
676 ptrIDebugClient_ID); | |
677 CHECK_EXCEPTION_(false); | |
678 if (ptrIDebugClient != 0) { | |
679 ptrIDebugClient->Release(); | |
680 } | |
681 | |
682 return true; | |
683 } | |
684 | |
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 } | |
698 | |
699 | |
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); | |
709 | |
710 jboolean isCopy = JNI_FALSE; | |
711 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy); | |
712 CHECK_EXCEPTION_(0); | |
713 | |
714 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj, | |
715 ptrIDebugDataSpaces_ID); | |
716 CHECK_EXCEPTION_(0); | |
717 | |
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 } | |
723 | |
724 if (bytesRead != numBytes) { | |
725 return 0; | |
726 } | |
727 | |
728 env->ReleaseByteArrayElements(byteArray, bytePtr, 0); | |
729 CHECK_EXCEPTION_(0); | |
730 | |
731 return byteArray; | |
732 } | |
733 | |
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); | |
744 | |
745 ULONG id = 0; | |
746 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) { | |
747 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0); | |
748 } | |
749 | |
750 return (jlong) id; | |
751 } | |
752 | |
753 // manage COM 'auto' pointers (to avoid multiple Release | |
754 // calls at every early (exception) returns). Similar to AutoArrayPtr. | |
755 | |
756 template <class T> | |
757 class AutoCOMPtr { | |
758 T* m_ptr; | |
759 | |
760 public: | |
761 AutoCOMPtr(T* ptr) : m_ptr(ptr) { | |
762 } | |
763 | |
764 ~AutoCOMPtr() { | |
765 if (m_ptr) { | |
766 m_ptr->Release(); | |
767 } | |
768 } | |
769 | |
770 T* operator->() { | |
771 return m_ptr; | |
772 } | |
773 }; | |
774 | |
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); | |
786 | |
787 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID); | |
788 CHECK_EXCEPTION_(0); | |
789 | |
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); | |
795 | |
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); | |
801 | |
802 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj, | |
803 ptrIDebugOutputCallbacks_ID); | |
804 CHECK_EXCEPTION_(0); | |
805 | |
806 saOutputCallbacks->clearBuffer(); | |
807 | |
808 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) { | |
809 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0); | |
810 } | |
811 | |
812 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT); | |
813 | |
814 const char* output = saOutputCallbacks->getBuffer(); | |
815 if (output == 0) { | |
816 output = ""; | |
817 } | |
818 | |
819 jstring res = env->NewStringUTF(output); | |
820 saOutputCallbacks->clearBuffer(); | |
821 return res; | |
822 } | |
823 | |
824 /* | |
825 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal | |
826 * Method: lookupByName0 | |
827 * Signature: (Ljava/lang/String;Ljava/lang/String;)J | |
828 */ | |
829 | |
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); | |
835 | |
836 jboolean isCopy; | |
837 const char* buf = env->GetStringUTFChars(sym, &isCopy); | |
838 CHECK_EXCEPTION_(0); | |
839 AutoJavaString name(env, sym, buf); | |
840 | |
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 } | |
852 | |
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); | |
864 | |
865 ULONG64 disp = 0L; | |
866 char buf[SYMBOL_BUFSIZE]; | |
867 memset(buf, 0, sizeof(buf)); | |
868 | |
869 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp) | |
870 != S_OK) { | |
871 return 0; | |
872 } | |
873 | |
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 } |