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