0
|
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 }
|