agent/src/os/win32/windbg/sawindbg.cpp

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 2002-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 // this is source code windbg based SA debugger agent to debug
    26 // Dr. Watson dump files and process snapshots.
    28 #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"
    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
    43 #include <limits.h>
    44 #include <windows.h>
    46 #ifndef STDMETHODV
    47 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
    48 #endif
    50 #define DEBUG_NO_IMPLEMENTATION
    51 #include <dbgeng.h>
    52 #include <dbghelp.h>
    54 // simple template to manage array delete across early (error) returns
    56 template <class T>
    57 class AutoArrayPtr {
    58       T* m_ptr;
    59    public:
    60       AutoArrayPtr(T* ptr) : m_ptr(ptr) {
    61       }
    63       ~AutoArrayPtr() {
    64          delete [] m_ptr;
    65       }
    67       T* asPtr() {
    68          return m_ptr;
    69       }
    70 };
    72 class AutoJavaString {
    73       JNIEnv* m_env;
    74       jstring m_str;
    75       const char* m_buf;
    77    public:
    78       AutoJavaString(JNIEnv* env, jstring str, const char* buf)
    79         : m_env(env), m_str(str), m_buf(buf) {
    80       }
    82       ~AutoJavaString() {
    83          m_env->ReleaseStringUTFChars(m_str, m_buf);
    84       }
    86       operator const char* () {
    87          return m_buf;
    88       }
    89 };
    91 // field and method IDs we want here
    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;
   103 static jmethodID addLoadObject_ID               = 0;
   104 static jmethodID addThread_ID                   = 0;
   105 static jmethodID createClosestSymbol_ID         = 0;
   106 static jmethodID setThreadIntegerRegisterSet_ID = 0;
   108 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
   109 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
   111 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
   112                           throwNewDebuggerException(env, str); return value; }
   114 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \
   115  return;}
   117 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
   118   env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
   119 }
   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;
   131   symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
   132   CHECK_EXCEPTION;
   134   ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
   135   CHECK_EXCEPTION;
   137   ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
   138   CHECK_EXCEPTION;
   140   ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
   141   CHECK_EXCEPTION;
   143   ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz,
   144                                             "ptrIDebugOutputCallbacks", "J");
   145   CHECK_EXCEPTION;
   147   ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
   148   CHECK_EXCEPTION;
   150   ptrIDebugSymbols_ID = env->GetFieldID(clazz,
   151                                          "ptrIDebugSymbols", "J");
   152   CHECK_EXCEPTION;
   154   ptrIDebugSystemObjects_ID = env->GetFieldID(clazz,
   155                                          "ptrIDebugSystemObjects", "J");
   156   CHECK_EXCEPTION;
   158   addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject",
   159                                          "(Ljava/lang/String;JJ)V");
   160   CHECK_EXCEPTION;
   162   addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
   163   CHECK_EXCEPTION;
   165   createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
   166     "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
   167   CHECK_EXCEPTION;
   169   setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
   170                                          "setThreadIntegerRegisterSet", "(J[J)V");
   171   CHECK_EXCEPTION;
   173 }
   175 // class for IDebugOutputCallbacks
   177 class SAOutputCallbacks : public IDebugOutputCallbacks {
   178    LONG  m_refCount;
   179    char* m_msgBuffer;
   181    public:
   182       SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) {
   183       }
   185       ~SAOutputCallbacks() {
   186          clearBuffer();
   187       }
   189       const char* getBuffer() const {
   190          return m_msgBuffer;
   191       }
   193       void clearBuffer() {
   194          if (m_msgBuffer) {
   195             free(m_msgBuffer);
   196             m_msgBuffer = 0;
   197          }
   198       }
   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 };
   210 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
   211    InterlockedIncrement(&m_refCount);
   212    return m_refCount;
   213 }
   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 }
   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 }
   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 }
   261 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
   262   // get windbg interfaces ..
   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);
   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);
   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);
   284   SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
   285   ptrIDebugOutputCallbacks->AddRef();
   286   env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
   287   CHECK_EXCEPTION_(false);
   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);
   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);
   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);
   310   return true;
   311 }
   313 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
   314   jboolean isCopy;
   315   jclass clazz = env->GetObjectClass(obj);
   316   jstring path;
   317   const char* buf;
   319   path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
   320   buf = env->GetStringUTFChars(path, &isCopy);
   321   CHECK_EXCEPTION_(false);
   322   AutoJavaString imagePath(env, path, buf);
   324   path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
   325   buf = env->GetStringUTFChars(path, &isCopy);
   326   CHECK_EXCEPTION_(false);
   327   AutoJavaString symbolPath(env, path, buf);
   329   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   330                                                       ptrIDebugSymbols_ID);
   331   CHECK_EXCEPTION_(false);
   333   ptrIDebugSymbols->SetImagePath(imagePath);
   334   ptrIDebugSymbols->SetSymbolPath(symbolPath);
   335   return true;
   336 }
   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   }
   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   }
   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   }
   362   return true;
   363 }
   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);
   374   /***********************************************************************************
   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.
   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.
   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.
   389   ***********************************************************************************/
   392   if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
   393      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
   394   }
   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   }
   403   return true;
   404 }
   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   }
   416   AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
   418   if (params.asPtr() == 0) {
   419       THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
   420   }
   422   if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
   423      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
   424   }
   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      }
   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   }
   441   return true;
   442 }
   444 static bool addThreads(JNIEnv* env, jobject obj) {
   445   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   446                                                       ptrIDebugSystemObjects_ID);
   447   CHECK_EXCEPTION_(false);
   449   ULONG numThreads = 0;
   450   if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
   451      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
   452   }
   454   AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
   456   if (ptrSysThreadIds.asPtr() == 0) {
   457      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   458   }
   460   AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
   462   if (ptrThreadIds.asPtr() == 0) {
   463      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   464   }
   466   if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
   467                                       ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
   468      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
   469   }
   472   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   473                                                       ptrIDebugAdvanced_ID);
   474   CHECK_EXCEPTION_(false);
   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      }
   482      jlongArray regs = env->NewLongArray(NPRGREG);
   483      CHECK_EXCEPTION_(false);
   485      jboolean isCopy = JNI_FALSE;
   486      jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
   487      CHECK_EXCEPTION_(false);
   489      // copy register values from the CONTEXT struct
   490      CONTEXT context;
   491      memset(&context, 0, sizeof(CONTEXT));
   493 #undef REG_INDEX
   494 #ifdef _M_IA64
   495      #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x
   497      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG;
   498      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   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;
   533      ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats;
   534      ptrRegs[REG_INDEX(PREDS)]    = context.Preds;
   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;
   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;
   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;
   557      ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR;
   558      ptrRegs[REG_INDEX(ST_IIP)]  = context.StIIP;
   559      ptrRegs[REG_INDEX(ST_IFS)]  = context.StIFS;
   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;
   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;
   579 #elif _M_IX86
   580      #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
   582      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   583      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   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;
   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;
   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;
   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;
   611 #elif _M_AMD64
   612      #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
   614      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   615      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   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;
   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;
   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;
   645      // Program counter
   646      ptrRegs[REG_INDEX(RIP)] = context.Rip;
   647 #endif
   649      env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
   650      CHECK_EXCEPTION_(false);
   652      env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
   653                         (jlong) ptrThreadIds.asPtr()[t], regs);
   654      CHECK_EXCEPTION_(false);
   656      ULONG sysId;
   657      if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
   658         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
   659      }
   661      env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
   662      CHECK_EXCEPTION_(false);
   663   }
   665   return true;
   666 }
   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) {
   676   if (getWindbgInterfaces(env, obj) == false) {
   677      return;
   678   }
   680   if (openDumpFile(env, obj, coreFileName) == false) {
   681      return;
   682   }
   684   if (addLoadObjects(env, obj) == false) {
   685      return;
   686   }
   688   if (addThreads(env, obj) == false) {
   689      return;
   690   }
   691 }
   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) {
   701   if (getWindbgInterfaces(env, obj) == false) {
   702      return;
   703   }
   705   if (attachToProcess(env, obj, pid) == false) {
   706      return;
   707   }
   709   if (addLoadObjects(env, obj) == false) {
   710      return;
   711   }
   713   if (addThreads(env, obj) == false) {
   714      return;
   715   }
   716 }
   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   }
   727   IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
   728                           env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
   729   CHECK_EXCEPTION_(false);
   730   if (ptrIDebugOutputCallbacks != 0) {
   731      ptrIDebugOutputCallbacks->Release();
   732   }
   734   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   735                                                       ptrIDebugAdvanced_ID);
   736   CHECK_EXCEPTION_(false);
   738   if (ptrIDebugAdvanced != 0) {
   739      ptrIDebugAdvanced->Release();
   740   }
   742   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   743                                                       ptrIDebugSymbols_ID);
   744   CHECK_EXCEPTION_(false);
   745   if (ptrIDebugSymbols != 0) {
   746      ptrIDebugSymbols->Release();
   747   }
   749   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   750                                                       ptrIDebugSystemObjects_ID);
   751   CHECK_EXCEPTION_(false);
   752   if (ptrIDebugSystemObjects != 0) {
   753      ptrIDebugSystemObjects->Release();
   754   }
   756   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   757                                                      ptrIDebugControl_ID);
   758   CHECK_EXCEPTION_(false);
   759   if (ptrIDebugControl != 0) {
   760      ptrIDebugControl->Release();
   761   }
   763   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   764                                                       ptrIDebugClient_ID);
   765   CHECK_EXCEPTION_(false);
   766   if (ptrIDebugClient != 0) {
   767      ptrIDebugClient->Release();
   768   }
   770   return true;
   771 }
   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 }
   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);
   798   jboolean isCopy = JNI_FALSE;
   799   jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
   800   CHECK_EXCEPTION_(0);
   802   IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
   803                                                        ptrIDebugDataSpaces_ID);
   804   CHECK_EXCEPTION_(0);
   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   }
   812   if (bytesRead != numBytes) {
   813      return 0;
   814   }
   816   env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
   817   CHECK_EXCEPTION_(0);
   819   return byteArray;
   820 }
   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);
   833   ULONG id = 0;
   834   if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
   835      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
   836   }
   838   return (jlong) id;
   839 }
   841 // manage COM 'auto' pointers (to avoid multiple Release
   842 // calls at every early (exception) returns). Similar to AutoArrayPtr.
   844 template <class T>
   845 class AutoCOMPtr {
   846       T* m_ptr;
   848    public:
   849       AutoCOMPtr(T* ptr) : m_ptr(ptr) {
   850       }
   852       ~AutoCOMPtr() {
   853          if (m_ptr) {
   854             m_ptr->Release();
   855          }
   856       }
   858       T* operator->() {
   859          return m_ptr;
   860       }
   861 };
   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);
   875   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
   876   CHECK_EXCEPTION_(0);
   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);
   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);
   890   SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
   891                                                                    ptrIDebugOutputCallbacks_ID);
   892   CHECK_EXCEPTION_(0);
   894   saOutputCallbacks->clearBuffer();
   896   if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
   897      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
   898   }
   900   tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
   902   const char* output = saOutputCallbacks->getBuffer();
   903   if (output == 0) {
   904      output = "";
   905   }
   907   jstring res = env->NewStringUTF(output);
   908   saOutputCallbacks->clearBuffer();
   909   return res;
   910 }
   912 /*
   913  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   914  * Method:    lookupByName0
   915  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
   916  */
   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);
   924   jboolean isCopy;
   925   const char* buf = env->GetStringUTFChars(sym, &isCopy);
   926   CHECK_EXCEPTION_(0);
   927   AutoJavaString name(env, sym, buf);
   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 }
   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);
   953   ULONG64 disp = 0L;
   954   char buf[SYMBOL_BUFSIZE];
   955   memset(buf, 0, sizeof(buf));
   957   if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
   958       != S_OK) {
   959     return 0;
   960   }
   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 }

mercurial