1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/agent/src/os/win32/windbg/sawindbg.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,878 @@ 1.4 +/* 1.5 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// this is source code windbg based SA debugger agent to debug 1.29 +// Dr. Watson dump files and process snapshots. 1.30 + 1.31 +#include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" 1.32 + 1.33 +#ifdef _M_IX86 1.34 + #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" 1.35 + #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG 1.36 +#elif _M_AMD64 1.37 + #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" 1.38 + #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 1.39 +#else 1.40 + #error "SA windbg back-end is not supported for your cpu!" 1.41 +#endif 1.42 + 1.43 +#include <limits.h> 1.44 +#include <windows.h> 1.45 + 1.46 +#ifndef STDMETHODV 1.47 +#define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method 1.48 +#endif 1.49 + 1.50 +#define DEBUG_NO_IMPLEMENTATION 1.51 +#include <dbgeng.h> 1.52 +#include <dbghelp.h> 1.53 + 1.54 +// simple template to manage array delete across early (error) returns 1.55 + 1.56 +template <class T> 1.57 +class AutoArrayPtr { 1.58 + T* m_ptr; 1.59 + public: 1.60 + AutoArrayPtr(T* ptr) : m_ptr(ptr) { 1.61 + } 1.62 + 1.63 + ~AutoArrayPtr() { 1.64 + delete [] m_ptr; 1.65 + } 1.66 + 1.67 + T* asPtr() { 1.68 + return m_ptr; 1.69 + } 1.70 +}; 1.71 + 1.72 +class AutoJavaString { 1.73 + JNIEnv* m_env; 1.74 + jstring m_str; 1.75 + const char* m_buf; 1.76 + 1.77 + public: 1.78 + AutoJavaString(JNIEnv* env, jstring str, const char* buf) 1.79 + : m_env(env), m_str(str), m_buf(buf) { 1.80 + } 1.81 + 1.82 + ~AutoJavaString() { 1.83 + m_env->ReleaseStringUTFChars(m_str, m_buf); 1.84 + } 1.85 + 1.86 + operator const char* () { 1.87 + return m_buf; 1.88 + } 1.89 +}; 1.90 + 1.91 +// field and method IDs we want here 1.92 + 1.93 +static jfieldID imagePath_ID = 0; 1.94 +static jfieldID symbolPath_ID = 0; 1.95 +static jfieldID ptrIDebugClient_ID = 0; 1.96 +static jfieldID ptrIDebugControl_ID = 0; 1.97 +static jfieldID ptrIDebugDataSpaces_ID = 0; 1.98 +static jfieldID ptrIDebugOutputCallbacks_ID = 0; 1.99 +static jfieldID ptrIDebugAdvanced_ID = 0; 1.100 +static jfieldID ptrIDebugSymbols_ID = 0; 1.101 +static jfieldID ptrIDebugSystemObjects_ID = 0; 1.102 + 1.103 +static jmethodID addLoadObject_ID = 0; 1.104 +static jmethodID addThread_ID = 0; 1.105 +static jmethodID createClosestSymbol_ID = 0; 1.106 +static jmethodID setThreadIntegerRegisterSet_ID = 0; 1.107 + 1.108 +#define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; } 1.109 +#define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;} 1.110 + 1.111 +#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \ 1.112 + throwNewDebuggerException(env, str); return value; } 1.113 + 1.114 +#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \ 1.115 + return;} 1.116 + 1.117 +static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) { 1.118 + env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg); 1.119 +} 1.120 + 1.121 +/* 1.122 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.123 + * Method: initIDs 1.124 + * Signature: ()V 1.125 + */ 1.126 +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs 1.127 + (JNIEnv *env, jclass clazz) { 1.128 + imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;"); 1.129 + CHECK_EXCEPTION; 1.130 + 1.131 + symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;"); 1.132 + CHECK_EXCEPTION; 1.133 + 1.134 + ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J"); 1.135 + CHECK_EXCEPTION; 1.136 + 1.137 + ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J"); 1.138 + CHECK_EXCEPTION; 1.139 + 1.140 + ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J"); 1.141 + CHECK_EXCEPTION; 1.142 + 1.143 + ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz, 1.144 + "ptrIDebugOutputCallbacks", "J"); 1.145 + CHECK_EXCEPTION; 1.146 + 1.147 + ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J"); 1.148 + CHECK_EXCEPTION; 1.149 + 1.150 + ptrIDebugSymbols_ID = env->GetFieldID(clazz, 1.151 + "ptrIDebugSymbols", "J"); 1.152 + CHECK_EXCEPTION; 1.153 + 1.154 + ptrIDebugSystemObjects_ID = env->GetFieldID(clazz, 1.155 + "ptrIDebugSystemObjects", "J"); 1.156 + CHECK_EXCEPTION; 1.157 + 1.158 + addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject", 1.159 + "(Ljava/lang/String;JJ)V"); 1.160 + CHECK_EXCEPTION; 1.161 + 1.162 + addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V"); 1.163 + CHECK_EXCEPTION; 1.164 + 1.165 + createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol", 1.166 + "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 1.167 + CHECK_EXCEPTION; 1.168 + 1.169 + setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz, 1.170 + "setThreadIntegerRegisterSet", "(J[J)V"); 1.171 + CHECK_EXCEPTION; 1.172 + 1.173 +} 1.174 + 1.175 +// class for IDebugOutputCallbacks 1.176 + 1.177 +class SAOutputCallbacks : public IDebugOutputCallbacks { 1.178 + LONG m_refCount; 1.179 + char* m_msgBuffer; 1.180 + 1.181 + public: 1.182 + SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) { 1.183 + } 1.184 + 1.185 + ~SAOutputCallbacks() { 1.186 + clearBuffer(); 1.187 + } 1.188 + 1.189 + const char* getBuffer() const { 1.190 + return m_msgBuffer; 1.191 + } 1.192 + 1.193 + void clearBuffer() { 1.194 + if (m_msgBuffer) { 1.195 + free(m_msgBuffer); 1.196 + m_msgBuffer = 0; 1.197 + } 1.198 + } 1.199 + 1.200 + STDMETHOD_(ULONG, AddRef)(THIS); 1.201 + STDMETHOD_(ULONG, Release)(THIS); 1.202 + STDMETHOD(QueryInterface)(THIS_ 1.203 + IN REFIID interfaceId, 1.204 + OUT PVOID* ppInterface); 1.205 + STDMETHOD(Output)(THIS_ 1.206 + IN ULONG mask, 1.207 + IN PCSTR msg); 1.208 +}; 1.209 + 1.210 +STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) { 1.211 + InterlockedIncrement(&m_refCount); 1.212 + return m_refCount; 1.213 +} 1.214 + 1.215 +STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) { 1.216 + LONG retVal; 1.217 + InterlockedDecrement(&m_refCount); 1.218 + retVal = m_refCount; 1.219 + if (retVal == 0) { 1.220 + delete this; 1.221 + } 1.222 + return retVal; 1.223 +} 1.224 + 1.225 +STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_ 1.226 + IN REFIID interfaceId, 1.227 + OUT PVOID* ppInterface) { 1.228 + *ppInterface = 0; 1.229 + HRESULT res = E_NOINTERFACE; 1.230 + if (TRUE == IsEqualIID(interfaceId, __uuidof(IUnknown)) || 1.231 + TRUE == IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) { 1.232 + *ppInterface = (IDebugOutputCallbacks*) this; 1.233 + AddRef(); 1.234 + res = S_OK; 1.235 + } 1.236 + return res; 1.237 +} 1.238 + 1.239 +STDMETHODIMP SAOutputCallbacks::Output(THIS_ 1.240 + IN ULONG mask, 1.241 + IN PCSTR msg) { 1.242 + int len = (int) (strlen(msg) + 1); 1.243 + if (m_msgBuffer == 0) { 1.244 + m_msgBuffer = (char*) malloc(len); 1.245 + if (m_msgBuffer == 0) { 1.246 + fprintf(stderr, "out of memory debugger output!\n"); 1.247 + return S_FALSE; 1.248 + } 1.249 + strcpy(m_msgBuffer, msg); 1.250 + } else { 1.251 + m_msgBuffer = (char*) realloc(m_msgBuffer, len + strlen(m_msgBuffer)); 1.252 + if (m_msgBuffer == 0) { 1.253 + fprintf(stderr, "out of memory debugger output!\n"); 1.254 + return S_FALSE; 1.255 + } 1.256 + strcat(m_msgBuffer, msg); 1.257 + } 1.258 + return S_OK; 1.259 +} 1.260 + 1.261 +static bool getWindbgInterfaces(JNIEnv* env, jobject obj) { 1.262 + // get windbg interfaces .. 1.263 + 1.264 + IDebugClient* ptrIDebugClient = 0; 1.265 + if (DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient) != S_OK) { 1.266 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to create IDebugClient object!", false); 1.267 + } 1.268 + env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient); 1.269 + 1.270 + IDebugControl* ptrIDebugControl = 0; 1.271 + if (ptrIDebugClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl) 1.272 + != S_OK) { 1.273 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugControl", false); 1.274 + } 1.275 + env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl); 1.276 + 1.277 + IDebugDataSpaces* ptrIDebugDataSpaces = 0; 1.278 + if (ptrIDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces) 1.279 + != S_OK) { 1.280 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugDataSpaces object!", false); 1.281 + } 1.282 + env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces); 1.283 + 1.284 + SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks(); 1.285 + ptrIDebugOutputCallbacks->AddRef(); 1.286 + env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks); 1.287 + CHECK_EXCEPTION_(false); 1.288 + 1.289 + IDebugAdvanced* ptrIDebugAdvanced = 0; 1.290 + if (ptrIDebugClient->QueryInterface(__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced) 1.291 + != S_OK) { 1.292 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugAdvanced object!", false); 1.293 + } 1.294 + env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced); 1.295 + 1.296 + IDebugSymbols* ptrIDebugSymbols = 0; 1.297 + if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols) 1.298 + != S_OK) { 1.299 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSymbols object!", false); 1.300 + } 1.301 + env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols); 1.302 + 1.303 + IDebugSystemObjects* ptrIDebugSystemObjects = 0; 1.304 + if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects) 1.305 + != S_OK) { 1.306 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSystemObjects object!", false); 1.307 + } 1.308 + env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects); 1.309 + 1.310 + return true; 1.311 +} 1.312 + 1.313 +static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) { 1.314 + jboolean isCopy; 1.315 + jclass clazz = env->GetObjectClass(obj); 1.316 + jstring path; 1.317 + const char* buf; 1.318 + 1.319 + path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID); 1.320 + buf = env->GetStringUTFChars(path, &isCopy); 1.321 + CHECK_EXCEPTION_(false); 1.322 + AutoJavaString imagePath(env, path, buf); 1.323 + 1.324 + path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID); 1.325 + buf = env->GetStringUTFChars(path, &isCopy); 1.326 + CHECK_EXCEPTION_(false); 1.327 + AutoJavaString symbolPath(env, path, buf); 1.328 + 1.329 + IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 1.330 + ptrIDebugSymbols_ID); 1.331 + CHECK_EXCEPTION_(false); 1.332 + 1.333 + ptrIDebugSymbols->SetImagePath(imagePath); 1.334 + ptrIDebugSymbols->SetSymbolPath(symbolPath); 1.335 + return true; 1.336 +} 1.337 + 1.338 +static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) { 1.339 + // open the dump file 1.340 + jboolean isCopy; 1.341 + const char* buf = env->GetStringUTFChars(coreFileName, &isCopy); 1.342 + CHECK_EXCEPTION_(false); 1.343 + AutoJavaString coreFile(env, coreFileName, buf); 1.344 + if (setImageAndSymbolPath(env, obj) == false) { 1.345 + return false; 1.346 + } 1.347 + 1.348 + IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 1.349 + ptrIDebugClient_ID); 1.350 + CHECK_EXCEPTION_(false); 1.351 + if (ptrIDebugClient->OpenDumpFile(coreFile) != S_OK) { 1.352 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: OpenDumpFile failed!", false); 1.353 + } 1.354 + 1.355 + IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 1.356 + ptrIDebugControl_ID); 1.357 + CHECK_EXCEPTION_(false); 1.358 + if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) { 1.359 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false); 1.360 + } 1.361 + 1.362 + return true; 1.363 +} 1.364 + 1.365 + 1.366 +static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) { 1.367 + if (setImageAndSymbolPath(env, obj) == false) { 1.368 + return false; 1.369 + } 1.370 + IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 1.371 + ptrIDebugClient_ID); 1.372 + CHECK_EXCEPTION_(false); 1.373 + 1.374 + /*********************************************************************************** 1.375 + 1.376 + We are attaching to a process in 'read-only' mode. i.e., we do not want to 1.377 + put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of 1.378 + usage this should suffice. 1.379 + 1.380 + Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h. 1.381 + In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not 1.382 + actually debugging at all. We can safely 'detach' from the process anytime 1.383 + we want and debuggee process is left as is on all Windows variants. 1.384 + 1.385 + This also makes JDI-on-SA installation/usage simpler because with this we would 1.386 + not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster. 1.387 + 1.388 + ***********************************************************************************/ 1.389 + 1.390 + 1.391 + if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) { 1.392 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false); 1.393 + } 1.394 + 1.395 + IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 1.396 + ptrIDebugControl_ID); 1.397 + CHECK_EXCEPTION_(false); 1.398 + if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) { 1.399 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false); 1.400 + } 1.401 + 1.402 + return true; 1.403 +} 1.404 + 1.405 + 1.406 +static bool addLoadObjects(JNIEnv* env, jobject obj) { 1.407 + IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 1.408 + ptrIDebugSymbols_ID); 1.409 + CHECK_EXCEPTION_(false); 1.410 + ULONG loaded = 0, unloaded = 0; 1.411 + if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) { 1.412 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false); 1.413 + } 1.414 + 1.415 + AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]); 1.416 + 1.417 + if (params.asPtr() == 0) { 1.418 + THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false); 1.419 + } 1.420 + 1.421 + if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) { 1.422 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false); 1.423 + } 1.424 + 1.425 + for (int u = 0; u < (int)loaded; u++) { 1.426 + TCHAR imageName[MAX_PATH]; 1.427 + if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base, 1.428 + imageName, MAX_PATH, NULL, NULL, 1.429 + 0, NULL, NULL, 0, NULL) != S_OK) { 1.430 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false); 1.431 + } 1.432 + 1.433 + jstring strName = env->NewStringUTF(imageName); 1.434 + CHECK_EXCEPTION_(false); 1.435 + env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size, 1.436 + (jlong) params.asPtr()[u].Base); 1.437 + CHECK_EXCEPTION_(false); 1.438 + } 1.439 + 1.440 + return true; 1.441 +} 1.442 + 1.443 +static bool addThreads(JNIEnv* env, jobject obj) { 1.444 + IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 1.445 + ptrIDebugSystemObjects_ID); 1.446 + CHECK_EXCEPTION_(false); 1.447 + 1.448 + ULONG numThreads = 0; 1.449 + if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) { 1.450 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false); 1.451 + } 1.452 + 1.453 + AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads]; 1.454 + 1.455 + if (ptrSysThreadIds.asPtr() == 0) { 1.456 + THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); 1.457 + } 1.458 + 1.459 + AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads]; 1.460 + 1.461 + if (ptrThreadIds.asPtr() == 0) { 1.462 + THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); 1.463 + } 1.464 + 1.465 + if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads, 1.466 + ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) { 1.467 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false); 1.468 + } 1.469 + 1.470 + 1.471 + IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, 1.472 + ptrIDebugAdvanced_ID); 1.473 + CHECK_EXCEPTION_(false); 1.474 + 1.475 + // for each thread, get register context and save it. 1.476 + for (ULONG t = 0; t < numThreads; t++) { 1.477 + if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) { 1.478 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false); 1.479 + } 1.480 + 1.481 + jlongArray regs = env->NewLongArray(NPRGREG); 1.482 + CHECK_EXCEPTION_(false); 1.483 + 1.484 + jboolean isCopy = JNI_FALSE; 1.485 + jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy); 1.486 + CHECK_EXCEPTION_(false); 1.487 + 1.488 + // copy register values from the CONTEXT struct 1.489 + CONTEXT context; 1.490 + memset(&context, 0, sizeof(CONTEXT)); 1.491 + 1.492 +#undef REG_INDEX 1.493 +#ifdef _M_IX86 1.494 + #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x 1.495 + 1.496 + context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 1.497 + ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); 1.498 + 1.499 + ptrRegs[REG_INDEX(GS)] = context.SegGs; 1.500 + ptrRegs[REG_INDEX(FS)] = context.SegFs; 1.501 + ptrRegs[REG_INDEX(ES)] = context.SegEs; 1.502 + ptrRegs[REG_INDEX(DS)] = context.SegDs; 1.503 + 1.504 + ptrRegs[REG_INDEX(EDI)] = context.Edi; 1.505 + ptrRegs[REG_INDEX(ESI)] = context.Esi; 1.506 + ptrRegs[REG_INDEX(EBX)] = context.Ebx; 1.507 + ptrRegs[REG_INDEX(EDX)] = context.Edx; 1.508 + ptrRegs[REG_INDEX(ECX)] = context.Ecx; 1.509 + ptrRegs[REG_INDEX(EAX)] = context.Eax; 1.510 + 1.511 + ptrRegs[REG_INDEX(FP)] = context.Ebp; 1.512 + ptrRegs[REG_INDEX(PC)] = context.Eip; 1.513 + ptrRegs[REG_INDEX(CS)] = context.SegCs; 1.514 + ptrRegs[REG_INDEX(EFL)] = context.EFlags; 1.515 + ptrRegs[REG_INDEX(SP)] = context.Esp; 1.516 + ptrRegs[REG_INDEX(SS)] = context.SegSs; 1.517 + 1.518 + ptrRegs[REG_INDEX(DR0)] = context.Dr0; 1.519 + ptrRegs[REG_INDEX(DR1)] = context.Dr1; 1.520 + ptrRegs[REG_INDEX(DR2)] = context.Dr2; 1.521 + ptrRegs[REG_INDEX(DR3)] = context.Dr3; 1.522 + ptrRegs[REG_INDEX(DR6)] = context.Dr6; 1.523 + ptrRegs[REG_INDEX(DR7)] = context.Dr7; 1.524 + 1.525 +#elif _M_AMD64 1.526 + #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x 1.527 + 1.528 + context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 1.529 + ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); 1.530 + 1.531 + // Segment Registers and processor flags 1.532 + ptrRegs[REG_INDEX(CS)] = context.SegCs; 1.533 + ptrRegs[REG_INDEX(DS)] = context.SegDs; 1.534 + ptrRegs[REG_INDEX(ES)] = context.SegEs; 1.535 + ptrRegs[REG_INDEX(FS)] = context.SegFs; 1.536 + ptrRegs[REG_INDEX(GS)] = context.SegGs; 1.537 + ptrRegs[REG_INDEX(SS)] = context.SegSs; 1.538 + ptrRegs[REG_INDEX(RFL)] = context.EFlags; 1.539 + 1.540 + // Integer registers 1.541 + ptrRegs[REG_INDEX(RDI)] = context.Rdi; 1.542 + ptrRegs[REG_INDEX(RSI)] = context.Rsi; 1.543 + ptrRegs[REG_INDEX(RAX)] = context.Rax; 1.544 + ptrRegs[REG_INDEX(RCX)] = context.Rcx; 1.545 + ptrRegs[REG_INDEX(RDX)] = context.Rdx; 1.546 + ptrRegs[REG_INDEX(RBX)] = context.Rbx; 1.547 + ptrRegs[REG_INDEX(RBP)] = context.Rbp; 1.548 + ptrRegs[REG_INDEX(RSP)] = context.Rsp; 1.549 + 1.550 + ptrRegs[REG_INDEX(R8)] = context.R8; 1.551 + ptrRegs[REG_INDEX(R9)] = context.R9; 1.552 + ptrRegs[REG_INDEX(R10)] = context.R10; 1.553 + ptrRegs[REG_INDEX(R11)] = context.R11; 1.554 + ptrRegs[REG_INDEX(R12)] = context.R12; 1.555 + ptrRegs[REG_INDEX(R13)] = context.R13; 1.556 + ptrRegs[REG_INDEX(R14)] = context.R14; 1.557 + ptrRegs[REG_INDEX(R15)] = context.R15; 1.558 + 1.559 + // Program counter 1.560 + ptrRegs[REG_INDEX(RIP)] = context.Rip; 1.561 +#endif 1.562 + 1.563 + env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT); 1.564 + CHECK_EXCEPTION_(false); 1.565 + 1.566 + env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, 1.567 + (jlong) ptrThreadIds.asPtr()[t], regs); 1.568 + CHECK_EXCEPTION_(false); 1.569 + 1.570 + ULONG sysId; 1.571 + if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) { 1.572 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false); 1.573 + } 1.574 + 1.575 + env->CallVoidMethod(obj, addThread_ID, (jlong) sysId); 1.576 + CHECK_EXCEPTION_(false); 1.577 + } 1.578 + 1.579 + return true; 1.580 +} 1.581 + 1.582 +/* 1.583 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.584 + * Method: attach0 1.585 + * Signature: (Ljava/lang/String;Ljava/lang/String;)V 1.586 + */ 1.587 +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 1.588 + (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) { 1.589 + 1.590 + if (getWindbgInterfaces(env, obj) == false) { 1.591 + return; 1.592 + } 1.593 + 1.594 + if (openDumpFile(env, obj, coreFileName) == false) { 1.595 + return; 1.596 + } 1.597 + 1.598 + if (addLoadObjects(env, obj) == false) { 1.599 + return; 1.600 + } 1.601 + 1.602 + if (addThreads(env, obj) == false) { 1.603 + return; 1.604 + } 1.605 +} 1.606 + 1.607 +/* 1.608 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.609 + * Method: attach0 1.610 + * Signature: (I)V 1.611 + */ 1.612 +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I 1.613 + (JNIEnv *env, jobject obj, jint pid) { 1.614 + 1.615 + if (getWindbgInterfaces(env, obj) == false) { 1.616 + return; 1.617 + } 1.618 + 1.619 + if (attachToProcess(env, obj, pid) == false) { 1.620 + return; 1.621 + } 1.622 + 1.623 + if (addLoadObjects(env, obj) == false) { 1.624 + return; 1.625 + } 1.626 + 1.627 + if (addThreads(env, obj) == false) { 1.628 + return; 1.629 + } 1.630 +} 1.631 + 1.632 + 1.633 +static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) { 1.634 + IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj, 1.635 + ptrIDebugDataSpaces_ID); 1.636 + CHECK_EXCEPTION_(false); 1.637 + if (ptrIDebugDataSpaces != 0) { 1.638 + ptrIDebugDataSpaces->Release(); 1.639 + } 1.640 + 1.641 + IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*) 1.642 + env->GetLongField(obj, ptrIDebugOutputCallbacks_ID); 1.643 + CHECK_EXCEPTION_(false); 1.644 + if (ptrIDebugOutputCallbacks != 0) { 1.645 + ptrIDebugOutputCallbacks->Release(); 1.646 + } 1.647 + 1.648 + IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, 1.649 + ptrIDebugAdvanced_ID); 1.650 + CHECK_EXCEPTION_(false); 1.651 + 1.652 + if (ptrIDebugAdvanced != 0) { 1.653 + ptrIDebugAdvanced->Release(); 1.654 + } 1.655 + 1.656 + IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 1.657 + ptrIDebugSymbols_ID); 1.658 + CHECK_EXCEPTION_(false); 1.659 + if (ptrIDebugSymbols != 0) { 1.660 + ptrIDebugSymbols->Release(); 1.661 + } 1.662 + 1.663 + IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 1.664 + ptrIDebugSystemObjects_ID); 1.665 + CHECK_EXCEPTION_(false); 1.666 + if (ptrIDebugSystemObjects != 0) { 1.667 + ptrIDebugSystemObjects->Release(); 1.668 + } 1.669 + 1.670 + IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 1.671 + ptrIDebugControl_ID); 1.672 + CHECK_EXCEPTION_(false); 1.673 + if (ptrIDebugControl != 0) { 1.674 + ptrIDebugControl->Release(); 1.675 + } 1.676 + 1.677 + IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 1.678 + ptrIDebugClient_ID); 1.679 + CHECK_EXCEPTION_(false); 1.680 + if (ptrIDebugClient != 0) { 1.681 + ptrIDebugClient->Release(); 1.682 + } 1.683 + 1.684 + return true; 1.685 +} 1.686 + 1.687 +/* 1.688 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.689 + * Method: detach0 1.690 + * Signature: ()V 1.691 + */ 1.692 +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0 1.693 + (JNIEnv *env, jobject obj) { 1.694 + IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 1.695 + ptrIDebugClient_ID); 1.696 + CHECK_EXCEPTION; 1.697 + ptrIDebugClient->DetachProcesses(); 1.698 + releaseWindbgInterfaces(env, obj); 1.699 +} 1.700 + 1.701 + 1.702 +/* 1.703 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.704 + * Method: readBytesFromProcess0 1.705 + * Signature: (JJ)[B 1.706 + */ 1.707 +JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0 1.708 + (JNIEnv *env, jobject obj, jlong address, jlong numBytes) { 1.709 + jbyteArray byteArray = env->NewByteArray((long) numBytes); 1.710 + CHECK_EXCEPTION_(0); 1.711 + 1.712 + jboolean isCopy = JNI_FALSE; 1.713 + jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy); 1.714 + CHECK_EXCEPTION_(0); 1.715 + 1.716 + IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj, 1.717 + ptrIDebugDataSpaces_ID); 1.718 + CHECK_EXCEPTION_(0); 1.719 + 1.720 + ULONG bytesRead; 1.721 + if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr, 1.722 + (ULONG)numBytes, &bytesRead) != S_OK) { 1.723 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0); 1.724 + } 1.725 + 1.726 + if (bytesRead != numBytes) { 1.727 + return 0; 1.728 + } 1.729 + 1.730 + env->ReleaseByteArrayElements(byteArray, bytePtr, 0); 1.731 + CHECK_EXCEPTION_(0); 1.732 + 1.733 + return byteArray; 1.734 +} 1.735 + 1.736 +/* 1.737 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.738 + * Method: getThreadIdFromSysId0 1.739 + * Signature: (J)J 1.740 + */ 1.741 +JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0 1.742 + (JNIEnv *env, jobject obj, jlong sysId) { 1.743 + IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 1.744 + ptrIDebugSystemObjects_ID); 1.745 + CHECK_EXCEPTION_(0); 1.746 + 1.747 + ULONG id = 0; 1.748 + if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) { 1.749 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0); 1.750 + } 1.751 + 1.752 + return (jlong) id; 1.753 +} 1.754 + 1.755 +// manage COM 'auto' pointers (to avoid multiple Release 1.756 +// calls at every early (exception) returns). Similar to AutoArrayPtr. 1.757 + 1.758 +template <class T> 1.759 +class AutoCOMPtr { 1.760 + T* m_ptr; 1.761 + 1.762 + public: 1.763 + AutoCOMPtr(T* ptr) : m_ptr(ptr) { 1.764 + } 1.765 + 1.766 + ~AutoCOMPtr() { 1.767 + if (m_ptr) { 1.768 + m_ptr->Release(); 1.769 + } 1.770 + } 1.771 + 1.772 + T* operator->() { 1.773 + return m_ptr; 1.774 + } 1.775 +}; 1.776 + 1.777 +/* 1.778 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.779 + * Method: consoleExecuteCommand0 1.780 + * Signature: (Ljava/lang/String;)Ljava/lang/String; 1.781 + */ 1.782 +JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0 1.783 + (JNIEnv *env, jobject obj, jstring cmd) { 1.784 + jboolean isCopy = JNI_FALSE; 1.785 + const char* buf = env->GetStringUTFChars(cmd, &isCopy); 1.786 + CHECK_EXCEPTION_(0); 1.787 + AutoJavaString command(env, cmd, buf); 1.788 + 1.789 + IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID); 1.790 + CHECK_EXCEPTION_(0); 1.791 + 1.792 + IDebugClient* tmpClientPtr = 0; 1.793 + if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) { 1.794 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0); 1.795 + } 1.796 + AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr); 1.797 + 1.798 + IDebugControl* tmpControlPtr = 0; 1.799 + if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) { 1.800 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0); 1.801 + } 1.802 + AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr); 1.803 + 1.804 + SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj, 1.805 + ptrIDebugOutputCallbacks_ID); 1.806 + CHECK_EXCEPTION_(0); 1.807 + 1.808 + saOutputCallbacks->clearBuffer(); 1.809 + 1.810 + if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) { 1.811 + THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0); 1.812 + } 1.813 + 1.814 + tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT); 1.815 + 1.816 + const char* output = saOutputCallbacks->getBuffer(); 1.817 + if (output == 0) { 1.818 + output = ""; 1.819 + } 1.820 + 1.821 + jstring res = env->NewStringUTF(output); 1.822 + saOutputCallbacks->clearBuffer(); 1.823 + return res; 1.824 +} 1.825 + 1.826 +/* 1.827 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.828 + * Method: lookupByName0 1.829 + * Signature: (Ljava/lang/String;Ljava/lang/String;)J 1.830 + */ 1.831 + 1.832 +JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0 1.833 +(JNIEnv *env, jobject obj, jstring objName, jstring sym) { 1.834 + IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 1.835 + ptrIDebugSymbols_ID); 1.836 + CHECK_EXCEPTION_(0); 1.837 + 1.838 + jboolean isCopy; 1.839 + const char* buf = env->GetStringUTFChars(sym, &isCopy); 1.840 + CHECK_EXCEPTION_(0); 1.841 + AutoJavaString name(env, sym, buf); 1.842 + 1.843 + ULONG64 offset = 0L; 1.844 + if (strstr(name, "::") != 0) { 1.845 + ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME); 1.846 + } else { 1.847 + ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME); 1.848 + } 1.849 + if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) { 1.850 + return (jlong) 0; 1.851 + } 1.852 + return (jlong) offset; 1.853 +} 1.854 + 1.855 +#define SYMBOL_BUFSIZE 512 1.856 +/* 1.857 + * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 1.858 + * Method: lookupByAddress0 1.859 + * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 1.860 + */ 1.861 +JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0 1.862 +(JNIEnv *env, jobject obj, jlong address) { 1.863 + IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 1.864 + ptrIDebugSymbols_ID); 1.865 + CHECK_EXCEPTION_(0); 1.866 + 1.867 + ULONG64 disp = 0L; 1.868 + char buf[SYMBOL_BUFSIZE]; 1.869 + memset(buf, 0, sizeof(buf)); 1.870 + 1.871 + if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp) 1.872 + != S_OK) { 1.873 + return 0; 1.874 + } 1.875 + 1.876 + jstring sym = env->NewStringUTF(buf); 1.877 + CHECK_EXCEPTION_(0); 1.878 + jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp); 1.879 + CHECK_EXCEPTION_(0); 1.880 + return res; 1.881 +}