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