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