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 }