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