1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 // Disable CRT security warning against strcpy/strcat 26 #pragma warning(disable: 4996) 27 28 #if _MSC_VER >= 1900 29 // typedef ignored on left when no variable is declared 30 #pragma warning(disable: 4091) 31 #endif 32 33 // this is source code windbg based SA debugger agent to debug 34 // Dr. Watson dump files and process snapshots. 35 36 #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" 37 38 #ifdef _M_IX86 39 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" 40 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG 41 #elif _M_AMD64 42 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" 43 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 44 #else 45 #error "SA windbg back-end is not supported for your cpu!" 46 #endif 47 48 #include <limits.h> 49 #include <windows.h> 50 51 #ifndef STDMETHODV 52 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method 53 #endif 54 55 #define DEBUG_NO_IMPLEMENTATION 56 #include <dbgeng.h> 57 #include <dbghelp.h> 58 59 // simple template to manage array delete across early (error) returns 60 61 template <class T> 62 class AutoArrayPtr { 63 T* m_ptr; 64 public: 65 AutoArrayPtr(T* ptr) : m_ptr(ptr) { 66 } 67 68 ~AutoArrayPtr() { 69 delete [] m_ptr; 70 } 71 72 T* asPtr() { 73 return m_ptr; 74 } 75 }; 76 77 class AutoJavaString { 78 JNIEnv* m_env; 79 jstring m_str; 80 const char* m_buf; 81 82 public: 83 AutoJavaString(JNIEnv* env, jstring str, const char* buf) 84 : m_env(env), m_str(str), m_buf(buf) { 85 } 86 87 ~AutoJavaString() { 88 m_env->ReleaseStringUTFChars(m_str, m_buf); 89 } 90 91 operator const char* () { 92 return m_buf; 93 } 94 }; 95 96 // field and method IDs we want here 97 98 static jfieldID imagePath_ID = 0; 99 static jfieldID symbolPath_ID = 0; 100 static jfieldID ptrIDebugClient_ID = 0; 101 static jfieldID ptrIDebugControl_ID = 0; 102 static jfieldID ptrIDebugDataSpaces_ID = 0; 103 static jfieldID ptrIDebugOutputCallbacks_ID = 0; 104 static jfieldID ptrIDebugAdvanced_ID = 0; 105 static jfieldID ptrIDebugSymbols_ID = 0; 106 static jfieldID ptrIDebugSystemObjects_ID = 0; 107 108 static jmethodID addLoadObject_ID = 0; 109 static jmethodID addThread_ID = 0; 110 static jmethodID createClosestSymbol_ID = 0; 111 static jmethodID setThreadIntegerRegisterSet_ID = 0; 112 113 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; } 114 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;} 115 116 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \ 117 throwNewDebuggerException(env, str); return value; } 118 119 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \ 120 return;} 121 122 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) { 123 jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"); 124 CHECK_EXCEPTION; 125 env->ThrowNew(clazz, errMsg); 126 } 127 128 /* 129 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 130 * Method: initIDs 131 * Signature: ()V 132 */ 133 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs 134 (JNIEnv *env, jclass clazz) { 135 imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;"); 136 CHECK_EXCEPTION; 137 138 symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;"); 139 CHECK_EXCEPTION; 140 141 ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J"); 142 CHECK_EXCEPTION; 143 144 ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J"); 145 CHECK_EXCEPTION; 146 147 ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J"); 148 CHECK_EXCEPTION; 149 150 ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz, 151 "ptrIDebugOutputCallbacks", "J"); 152 CHECK_EXCEPTION; 153 154 ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J"); 155 CHECK_EXCEPTION; 156 157 ptrIDebugSymbols_ID = env->GetFieldID(clazz, 158 "ptrIDebugSymbols", "J"); 159 CHECK_EXCEPTION; 160 161 ptrIDebugSystemObjects_ID = env->GetFieldID(clazz, 162 "ptrIDebugSystemObjects", "J"); 163 CHECK_EXCEPTION; 164 165 addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject", 166 "(Ljava/lang/String;JJ)V"); 167 CHECK_EXCEPTION; 168 169 addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V"); 170 CHECK_EXCEPTION; 171 172 createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol", 173 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 174 CHECK_EXCEPTION; 175 176 setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz, 177 "setThreadIntegerRegisterSet", "(J[J)V"); 178 CHECK_EXCEPTION; 179 180 } 181 182 // class for IDebugOutputCallbacks 183 184 class SAOutputCallbacks : public IDebugOutputCallbacks { 185 LONG m_refCount; 186 char* m_msgBuffer; 187 188 public: 189 SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) { 190 } 191 192 ~SAOutputCallbacks() { 193 clearBuffer(); 194 } 195 196 const char* getBuffer() const { 197 return m_msgBuffer; 198 } 199 200 void clearBuffer() { 201 if (m_msgBuffer) { 202 free(m_msgBuffer); 203 m_msgBuffer = 0; 204 } 205 } 206 207 STDMETHOD_(ULONG, AddRef)(THIS); 208 STDMETHOD_(ULONG, Release)(THIS); 209 STDMETHOD(QueryInterface)(THIS_ 210 IN REFIID interfaceId, 211 OUT PVOID* ppInterface); 212 STDMETHOD(Output)(THIS_ 213 IN ULONG mask, 214 IN PCSTR msg); 215 }; 216 217 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) { 218 InterlockedIncrement(&m_refCount); 219 return m_refCount; 220 } 221 222 STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) { 223 LONG retVal; 224 InterlockedDecrement(&m_refCount); 225 retVal = m_refCount; 226 if (retVal == 0) { 227 delete this; 228 } 229 return retVal; 230 } 231 232 STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_ 233 IN REFIID interfaceId, 234 OUT PVOID* ppInterface) { 235 *ppInterface = 0; 236 HRESULT res = E_NOINTERFACE; 237 if (TRUE == IsEqualIID(interfaceId, __uuidof(IUnknown)) || 238 TRUE == IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) { 239 *ppInterface = (IDebugOutputCallbacks*) this; 240 AddRef(); 241 res = S_OK; 242 } 243 return res; 244 } 245 246 STDMETHODIMP SAOutputCallbacks::Output(THIS_ 247 IN ULONG mask, 248 IN PCSTR msg) { 249 int len = (int) (strlen(msg) + 1); 250 if (m_msgBuffer == 0) { 251 m_msgBuffer = (char*) malloc(len); 252 if (m_msgBuffer == 0) { 253 fprintf(stderr, "out of memory debugger output!\n"); 254 return S_FALSE; 255 } 256 strcpy(m_msgBuffer, msg); 257 } else { 258 m_msgBuffer = (char*) realloc(m_msgBuffer, len + strlen(m_msgBuffer)); 259 if (m_msgBuffer == 0) { 260 fprintf(stderr, "out of memory debugger output!\n"); 261 return S_FALSE; 262 } 263 strcat(m_msgBuffer, msg); 264 } 265 return S_OK; 266 } 267 268 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) { 269 // get windbg interfaces .. 270 271 IDebugClient* ptrIDebugClient = 0; 272 if (DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient) != S_OK) { 273 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to create IDebugClient object!", false); 274 } 275 env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient); 276 277 IDebugControl* ptrIDebugControl = 0; 278 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl) 279 != S_OK) { 280 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugControl", false); 281 } 282 env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl); 283 284 IDebugDataSpaces* ptrIDebugDataSpaces = 0; 285 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces) 286 != S_OK) { 287 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugDataSpaces object!", false); 288 } 289 env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces); 290 291 SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks(); 292 ptrIDebugOutputCallbacks->AddRef(); 293 env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks); 294 CHECK_EXCEPTION_(false); 295 296 IDebugAdvanced* ptrIDebugAdvanced = 0; 297 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced) 298 != S_OK) { 299 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugAdvanced object!", false); 300 } 301 env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced); 302 303 IDebugSymbols* ptrIDebugSymbols = 0; 304 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols) 305 != S_OK) { 306 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSymbols object!", false); 307 } 308 env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols); 309 310 IDebugSystemObjects* ptrIDebugSystemObjects = 0; 311 if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects) 312 != S_OK) { 313 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSystemObjects object!", false); 314 } 315 env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects); 316 317 return true; 318 } 319 320 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) { 321 jboolean isCopy; 322 jclass clazz = env->GetObjectClass(obj); 323 CHECK_EXCEPTION_(false); 324 jstring path; 325 const char* buf; 326 327 path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID); 328 CHECK_EXCEPTION_(false); 329 if (path == NULL) { 330 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get imagePath field ID!", false); 331 } 332 buf = env->GetStringUTFChars(path, &isCopy); 333 CHECK_EXCEPTION_(false); 334 AutoJavaString imagePath(env, path, buf); 335 336 path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID); 337 CHECK_EXCEPTION_(false); 338 if (path == NULL) { 339 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get symbolPath field ID!", false); 340 } 341 buf = env->GetStringUTFChars(path, &isCopy); 342 CHECK_EXCEPTION_(false); 343 AutoJavaString symbolPath(env, path, buf); 344 345 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 346 ptrIDebugSymbols_ID); 347 CHECK_EXCEPTION_(false); 348 349 ptrIDebugSymbols->SetImagePath(imagePath); 350 ptrIDebugSymbols->SetSymbolPath(symbolPath); 351 return true; 352 } 353 354 static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) { 355 // open the dump file 356 jboolean isCopy; 357 const char* buf = env->GetStringUTFChars(coreFileName, &isCopy); 358 CHECK_EXCEPTION_(false); 359 AutoJavaString coreFile(env, coreFileName, buf); 360 if (setImageAndSymbolPath(env, obj) == false) { 361 return false; 362 } 363 364 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 365 ptrIDebugClient_ID); 366 CHECK_EXCEPTION_(false); 367 if (ptrIDebugClient->OpenDumpFile(coreFile) != S_OK) { 368 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: OpenDumpFile failed!", false); 369 } 370 371 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 372 ptrIDebugControl_ID); 373 CHECK_EXCEPTION_(false); 374 if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) { 375 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false); 376 } 377 378 return true; 379 } 380 381 382 static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) { 383 if (setImageAndSymbolPath(env, obj) == false) { 384 return false; 385 } 386 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 387 ptrIDebugClient_ID); 388 CHECK_EXCEPTION_(false); 389 390 /*********************************************************************************** 391 392 We are attaching to a process in 'read-only' mode. i.e., we do not want to 393 put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of 394 usage this should suffice. 395 396 Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h. 397 In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not 398 actually debugging at all. We can safely 'detach' from the process anytime 399 we want and debuggee process is left as is on all Windows variants. 400 401 This also makes JDI-on-SA installation/usage simpler because with this we would 402 not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster. 403 404 ***********************************************************************************/ 405 406 407 if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) { 408 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false); 409 } 410 411 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 412 ptrIDebugControl_ID); 413 CHECK_EXCEPTION_(false); 414 if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) { 415 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false); 416 } 417 418 return true; 419 } 420 421 422 static bool addLoadObjects(JNIEnv* env, jobject obj) { 423 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 424 ptrIDebugSymbols_ID); 425 CHECK_EXCEPTION_(false); 426 ULONG loaded = 0, unloaded = 0; 427 if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) { 428 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false); 429 } 430 431 AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]); 432 433 if (params.asPtr() == 0) { 434 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false); 435 } 436 437 if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) { 438 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false); 439 } 440 441 for (int u = 0; u < (int)loaded; u++) { 442 TCHAR imageName[MAX_PATH]; 443 if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base, 444 imageName, MAX_PATH, NULL, NULL, 445 0, NULL, NULL, 0, NULL) != S_OK) { 446 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false); 447 } 448 449 jstring strName = env->NewStringUTF(imageName); 450 CHECK_EXCEPTION_(false); 451 env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size, 452 (jlong) params.asPtr()[u].Base); 453 CHECK_EXCEPTION_(false); 454 } 455 456 return true; 457 } 458 459 static bool addThreads(JNIEnv* env, jobject obj) { 460 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 461 ptrIDebugSystemObjects_ID); 462 CHECK_EXCEPTION_(false); 463 464 ULONG numThreads = 0; 465 if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) { 466 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false); 467 } 468 469 AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads]; 470 471 if (ptrSysThreadIds.asPtr() == 0) { 472 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); 473 } 474 475 AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads]; 476 477 if (ptrThreadIds.asPtr() == 0) { 478 THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false); 479 } 480 481 if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads, 482 ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) { 483 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false); 484 } 485 486 487 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, 488 ptrIDebugAdvanced_ID); 489 CHECK_EXCEPTION_(false); 490 491 // for each thread, get register context and save it. 492 for (ULONG t = 0; t < numThreads; t++) { 493 if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) { 494 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false); 495 } 496 497 jlongArray regs = env->NewLongArray(NPRGREG); 498 CHECK_EXCEPTION_(false); 499 500 jboolean isCopy = JNI_FALSE; 501 jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy); 502 CHECK_EXCEPTION_(false); 503 504 // copy register values from the CONTEXT struct 505 CONTEXT context; 506 memset(&context, 0, sizeof(CONTEXT)); 507 508 #undef REG_INDEX 509 #ifdef _M_IX86 510 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x 511 512 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 513 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); 514 515 ptrRegs[REG_INDEX(GS)] = context.SegGs; 516 ptrRegs[REG_INDEX(FS)] = context.SegFs; 517 ptrRegs[REG_INDEX(ES)] = context.SegEs; 518 ptrRegs[REG_INDEX(DS)] = context.SegDs; 519 520 ptrRegs[REG_INDEX(EDI)] = context.Edi; 521 ptrRegs[REG_INDEX(ESI)] = context.Esi; 522 ptrRegs[REG_INDEX(EBX)] = context.Ebx; 523 ptrRegs[REG_INDEX(EDX)] = context.Edx; 524 ptrRegs[REG_INDEX(ECX)] = context.Ecx; 525 ptrRegs[REG_INDEX(EAX)] = context.Eax; 526 527 ptrRegs[REG_INDEX(FP)] = context.Ebp; 528 ptrRegs[REG_INDEX(PC)] = context.Eip; 529 ptrRegs[REG_INDEX(CS)] = context.SegCs; 530 ptrRegs[REG_INDEX(EFL)] = context.EFlags; 531 ptrRegs[REG_INDEX(SP)] = context.Esp; 532 ptrRegs[REG_INDEX(SS)] = context.SegSs; 533 534 ptrRegs[REG_INDEX(DR0)] = context.Dr0; 535 ptrRegs[REG_INDEX(DR1)] = context.Dr1; 536 ptrRegs[REG_INDEX(DR2)] = context.Dr2; 537 ptrRegs[REG_INDEX(DR3)] = context.Dr3; 538 ptrRegs[REG_INDEX(DR6)] = context.Dr6; 539 ptrRegs[REG_INDEX(DR7)] = context.Dr7; 540 541 #elif _M_AMD64 542 #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x 543 544 context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 545 ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); 546 547 // Segment Registers and processor flags 548 ptrRegs[REG_INDEX(CS)] = context.SegCs; 549 ptrRegs[REG_INDEX(DS)] = context.SegDs; 550 ptrRegs[REG_INDEX(ES)] = context.SegEs; 551 ptrRegs[REG_INDEX(FS)] = context.SegFs; 552 ptrRegs[REG_INDEX(GS)] = context.SegGs; 553 ptrRegs[REG_INDEX(SS)] = context.SegSs; 554 ptrRegs[REG_INDEX(RFL)] = context.EFlags; 555 556 // Integer registers 557 ptrRegs[REG_INDEX(RDI)] = context.Rdi; 558 ptrRegs[REG_INDEX(RSI)] = context.Rsi; 559 ptrRegs[REG_INDEX(RAX)] = context.Rax; 560 ptrRegs[REG_INDEX(RCX)] = context.Rcx; 561 ptrRegs[REG_INDEX(RDX)] = context.Rdx; 562 ptrRegs[REG_INDEX(RBX)] = context.Rbx; 563 ptrRegs[REG_INDEX(RBP)] = context.Rbp; 564 ptrRegs[REG_INDEX(RSP)] = context.Rsp; 565 566 ptrRegs[REG_INDEX(R8)] = context.R8; 567 ptrRegs[REG_INDEX(R9)] = context.R9; 568 ptrRegs[REG_INDEX(R10)] = context.R10; 569 ptrRegs[REG_INDEX(R11)] = context.R11; 570 ptrRegs[REG_INDEX(R12)] = context.R12; 571 ptrRegs[REG_INDEX(R13)] = context.R13; 572 ptrRegs[REG_INDEX(R14)] = context.R14; 573 ptrRegs[REG_INDEX(R15)] = context.R15; 574 575 // Program counter 576 ptrRegs[REG_INDEX(RIP)] = context.Rip; 577 #endif 578 579 env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT); 580 CHECK_EXCEPTION_(false); 581 582 env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, 583 (jlong) ptrThreadIds.asPtr()[t], regs); 584 CHECK_EXCEPTION_(false); 585 586 ULONG sysId; 587 if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) { 588 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false); 589 } 590 591 env->CallVoidMethod(obj, addThread_ID, (jlong) sysId); 592 CHECK_EXCEPTION_(false); 593 } 594 595 return true; 596 } 597 598 /* 599 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 600 * Method: attach0 601 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 602 */ 603 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 604 (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) { 605 606 if (getWindbgInterfaces(env, obj) == false) { 607 return; 608 } 609 610 if (openDumpFile(env, obj, coreFileName) == false) { 611 return; 612 } 613 614 if (addLoadObjects(env, obj) == false) { 615 return; 616 } 617 618 if (addThreads(env, obj) == false) { 619 return; 620 } 621 } 622 623 /* 624 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 625 * Method: attach0 626 * Signature: (I)V 627 */ 628 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I 629 (JNIEnv *env, jobject obj, jint pid) { 630 631 if (getWindbgInterfaces(env, obj) == false) { 632 return; 633 } 634 635 if (attachToProcess(env, obj, pid) == false) { 636 return; 637 } 638 639 if (addLoadObjects(env, obj) == false) { 640 return; 641 } 642 643 if (addThreads(env, obj) == false) { 644 return; 645 } 646 } 647 648 649 static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) { 650 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj, 651 ptrIDebugDataSpaces_ID); 652 CHECK_EXCEPTION_(false); 653 if (ptrIDebugDataSpaces != 0) { 654 ptrIDebugDataSpaces->Release(); 655 } 656 657 IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*) 658 env->GetLongField(obj, ptrIDebugOutputCallbacks_ID); 659 CHECK_EXCEPTION_(false); 660 if (ptrIDebugOutputCallbacks != 0) { 661 ptrIDebugOutputCallbacks->Release(); 662 } 663 664 IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj, 665 ptrIDebugAdvanced_ID); 666 CHECK_EXCEPTION_(false); 667 668 if (ptrIDebugAdvanced != 0) { 669 ptrIDebugAdvanced->Release(); 670 } 671 672 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 673 ptrIDebugSymbols_ID); 674 CHECK_EXCEPTION_(false); 675 if (ptrIDebugSymbols != 0) { 676 ptrIDebugSymbols->Release(); 677 } 678 679 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 680 ptrIDebugSystemObjects_ID); 681 CHECK_EXCEPTION_(false); 682 if (ptrIDebugSystemObjects != 0) { 683 ptrIDebugSystemObjects->Release(); 684 } 685 686 IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj, 687 ptrIDebugControl_ID); 688 CHECK_EXCEPTION_(false); 689 if (ptrIDebugControl != 0) { 690 ptrIDebugControl->Release(); 691 } 692 693 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 694 ptrIDebugClient_ID); 695 CHECK_EXCEPTION_(false); 696 if (ptrIDebugClient != 0) { 697 ptrIDebugClient->Release(); 698 } 699 700 return true; 701 } 702 703 /* 704 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 705 * Method: detach0 706 * Signature: ()V 707 */ 708 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0 709 (JNIEnv *env, jobject obj) { 710 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, 711 ptrIDebugClient_ID); 712 CHECK_EXCEPTION; 713 ptrIDebugClient->DetachProcesses(); 714 releaseWindbgInterfaces(env, obj); 715 } 716 717 718 /* 719 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 720 * Method: readBytesFromProcess0 721 * Signature: (JJ)[B 722 */ 723 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0 724 (JNIEnv *env, jobject obj, jlong address, jlong numBytes) { 725 jbyteArray byteArray = env->NewByteArray((long) numBytes); 726 CHECK_EXCEPTION_(0); 727 728 jboolean isCopy = JNI_FALSE; 729 jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy); 730 CHECK_EXCEPTION_(0); 731 732 IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj, 733 ptrIDebugDataSpaces_ID); 734 CHECK_EXCEPTION_(0); 735 736 ULONG bytesRead; 737 if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr, 738 (ULONG)numBytes, &bytesRead) != S_OK) { 739 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0); 740 } 741 742 if (bytesRead != numBytes) { 743 return 0; 744 } 745 746 env->ReleaseByteArrayElements(byteArray, bytePtr, 0); 747 CHECK_EXCEPTION_(0); 748 749 return byteArray; 750 } 751 752 /* 753 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 754 * Method: getThreadIdFromSysId0 755 * Signature: (J)J 756 */ 757 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0 758 (JNIEnv *env, jobject obj, jlong sysId) { 759 IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj, 760 ptrIDebugSystemObjects_ID); 761 CHECK_EXCEPTION_(0); 762 763 ULONG id = 0; 764 if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) { 765 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0); 766 } 767 768 return (jlong) id; 769 } 770 771 // manage COM 'auto' pointers (to avoid multiple Release 772 // calls at every early (exception) returns). Similar to AutoArrayPtr. 773 774 template <class T> 775 class AutoCOMPtr { 776 T* m_ptr; 777 778 public: 779 AutoCOMPtr(T* ptr) : m_ptr(ptr) { 780 } 781 782 ~AutoCOMPtr() { 783 if (m_ptr) { 784 m_ptr->Release(); 785 } 786 } 787 788 T* operator->() { 789 return m_ptr; 790 } 791 }; 792 793 /* 794 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 795 * Method: consoleExecuteCommand0 796 * Signature: (Ljava/lang/String;)Ljava/lang/String; 797 */ 798 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0 799 (JNIEnv *env, jobject obj, jstring cmd) { 800 jboolean isCopy = JNI_FALSE; 801 const char* buf = env->GetStringUTFChars(cmd, &isCopy); 802 CHECK_EXCEPTION_(0); 803 AutoJavaString command(env, cmd, buf); 804 805 IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID); 806 CHECK_EXCEPTION_(0); 807 808 IDebugClient* tmpClientPtr = 0; 809 if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) { 810 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0); 811 } 812 AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr); 813 814 IDebugControl* tmpControlPtr = 0; 815 if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) { 816 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0); 817 } 818 AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr); 819 820 SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj, 821 ptrIDebugOutputCallbacks_ID); 822 CHECK_EXCEPTION_(0); 823 824 saOutputCallbacks->clearBuffer(); 825 826 if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) { 827 THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0); 828 } 829 830 tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT); 831 832 const char* output = saOutputCallbacks->getBuffer(); 833 if (output == 0) { 834 output = ""; 835 } 836 837 jstring res = env->NewStringUTF(output); 838 saOutputCallbacks->clearBuffer(); 839 return res; 840 } 841 842 /* 843 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 844 * Method: lookupByName0 845 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 846 */ 847 848 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0 849 (JNIEnv *env, jobject obj, jstring objName, jstring sym) { 850 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 851 ptrIDebugSymbols_ID); 852 CHECK_EXCEPTION_(0); 853 854 jboolean isCopy; 855 const char* buf = env->GetStringUTFChars(sym, &isCopy); 856 CHECK_EXCEPTION_(0); 857 AutoJavaString name(env, sym, buf); 858 859 ULONG64 offset = 0L; 860 if (strstr(name, "::") != 0) { 861 ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME); 862 } else { 863 ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME); 864 } 865 if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) { 866 return (jlong) 0; 867 } 868 return (jlong) offset; 869 } 870 871 #define SYMBOL_BUFSIZE 512 872 /* 873 * Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal 874 * Method: lookupByAddress0 875 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 876 */ 877 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0 878 (JNIEnv *env, jobject obj, jlong address) { 879 IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, 880 ptrIDebugSymbols_ID); 881 CHECK_EXCEPTION_(0); 882 883 ULONG64 disp = 0L; 884 char buf[SYMBOL_BUFSIZE]; 885 memset(buf, 0, sizeof(buf)); 886 887 if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp) 888 != S_OK) { 889 return 0; 890 } 891 892 jstring sym = env->NewStringUTF(buf); 893 CHECK_EXCEPTION_(0); 894 jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp); 895 CHECK_EXCEPTION_(0); 896 return res; 897 }