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

Fri, 25 Jan 2013 16:50:33 -0800

author
morris
date
Fri, 25 Jan 2013 16:50:33 -0800
changeset 4535
9fae07c31641
parent 1907
c18cbe5936b8
child 4642
5ed317b25e23
permissions
-rw-r--r--

6518907: cleanup IA64 specific code in Hotspot
Summary: removed unused IA64 specific code
Reviewed-by: twisti, kvn, dholmes

     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, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * 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_IX86
    31   #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
    32   #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
    33 #elif _M_AMD64
    34   #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
    35   #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
    36 #else
    37   #error "SA windbg back-end is not supported for your cpu!"
    38 #endif
    40 #include <limits.h>
    41 #include <windows.h>
    43 #ifndef STDMETHODV
    44 #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
    45 #endif
    47 #define DEBUG_NO_IMPLEMENTATION
    48 #include <dbgeng.h>
    49 #include <dbghelp.h>
    51 // simple template to manage array delete across early (error) returns
    53 template <class T>
    54 class AutoArrayPtr {
    55       T* m_ptr;
    56    public:
    57       AutoArrayPtr(T* ptr) : m_ptr(ptr) {
    58       }
    60       ~AutoArrayPtr() {
    61          delete [] m_ptr;
    62       }
    64       T* asPtr() {
    65          return m_ptr;
    66       }
    67 };
    69 class AutoJavaString {
    70       JNIEnv* m_env;
    71       jstring m_str;
    72       const char* m_buf;
    74    public:
    75       AutoJavaString(JNIEnv* env, jstring str, const char* buf)
    76         : m_env(env), m_str(str), m_buf(buf) {
    77       }
    79       ~AutoJavaString() {
    80          m_env->ReleaseStringUTFChars(m_str, m_buf);
    81       }
    83       operator const char* () {
    84          return m_buf;
    85       }
    86 };
    88 // field and method IDs we want here
    90 static jfieldID imagePath_ID                    = 0;
    91 static jfieldID symbolPath_ID                   = 0;
    92 static jfieldID ptrIDebugClient_ID              = 0;
    93 static jfieldID ptrIDebugControl_ID             = 0;
    94 static jfieldID ptrIDebugDataSpaces_ID          = 0;
    95 static jfieldID ptrIDebugOutputCallbacks_ID     = 0;
    96 static jfieldID ptrIDebugAdvanced_ID            = 0;
    97 static jfieldID ptrIDebugSymbols_ID             = 0;
    98 static jfieldID ptrIDebugSystemObjects_ID       = 0;
   100 static jmethodID addLoadObject_ID               = 0;
   101 static jmethodID addThread_ID                   = 0;
   102 static jmethodID createClosestSymbol_ID         = 0;
   103 static jmethodID setThreadIntegerRegisterSet_ID = 0;
   105 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
   106 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
   108 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \
   109                           throwNewDebuggerException(env, str); return value; }
   111 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); \
   112  return;}
   114 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
   115   env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
   116 }
   118 /*
   119  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   120  * Method:    initIDs
   121  * Signature: ()V
   122  */
   123 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs
   124   (JNIEnv *env, jclass clazz) {
   125   imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;");
   126   CHECK_EXCEPTION;
   128   symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");
   129   CHECK_EXCEPTION;
   131   ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");
   132   CHECK_EXCEPTION;
   134   ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");
   135   CHECK_EXCEPTION;
   137   ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");
   138   CHECK_EXCEPTION;
   140   ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz,
   141                                             "ptrIDebugOutputCallbacks", "J");
   142   CHECK_EXCEPTION;
   144   ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");
   145   CHECK_EXCEPTION;
   147   ptrIDebugSymbols_ID = env->GetFieldID(clazz,
   148                                          "ptrIDebugSymbols", "J");
   149   CHECK_EXCEPTION;
   151   ptrIDebugSystemObjects_ID = env->GetFieldID(clazz,
   152                                          "ptrIDebugSystemObjects", "J");
   153   CHECK_EXCEPTION;
   155   addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject",
   156                                          "(Ljava/lang/String;JJ)V");
   157   CHECK_EXCEPTION;
   159   addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");
   160   CHECK_EXCEPTION;
   162   createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",
   163     "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
   164   CHECK_EXCEPTION;
   166   setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,
   167                                          "setThreadIntegerRegisterSet", "(J[J)V");
   168   CHECK_EXCEPTION;
   170 }
   172 // class for IDebugOutputCallbacks
   174 class SAOutputCallbacks : public IDebugOutputCallbacks {
   175    LONG  m_refCount;
   176    char* m_msgBuffer;
   178    public:
   179       SAOutputCallbacks() : m_refCount(0), m_msgBuffer(0) {
   180       }
   182       ~SAOutputCallbacks() {
   183          clearBuffer();
   184       }
   186       const char* getBuffer() const {
   187          return m_msgBuffer;
   188       }
   190       void clearBuffer() {
   191          if (m_msgBuffer) {
   192             free(m_msgBuffer);
   193             m_msgBuffer = 0;
   194          }
   195       }
   197       STDMETHOD_(ULONG, AddRef)(THIS);
   198       STDMETHOD_(ULONG, Release)(THIS);
   199       STDMETHOD(QueryInterface)(THIS_
   200                                 IN REFIID interfaceId,
   201                                 OUT PVOID* ppInterface);
   202       STDMETHOD(Output)(THIS_
   203                         IN ULONG mask,
   204                         IN PCSTR msg);
   205 };
   207 STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {
   208    InterlockedIncrement(&m_refCount);
   209    return m_refCount;
   210 }
   212 STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) {
   213    LONG retVal;
   214    InterlockedDecrement(&m_refCount);
   215    retVal = m_refCount;
   216    if (retVal == 0) {
   217       delete this;
   218    }
   219    return retVal;
   220 }
   222 STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_
   223                                           IN REFIID interfaceId,
   224                                           OUT PVOID* ppInterface) {
   225    *ppInterface = 0;
   226    HRESULT res = E_NOINTERFACE;
   227    if (TRUE == IsEqualIID(interfaceId, __uuidof(IUnknown)) ||
   228        TRUE == IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) {
   229       *ppInterface = (IDebugOutputCallbacks*) this;
   230       AddRef();
   231       res = S_OK;
   232    }
   233    return res;
   234 }
   236 STDMETHODIMP SAOutputCallbacks::Output(THIS_
   237                                        IN ULONG mask,
   238                                        IN PCSTR msg) {
   239    int len = (int) (strlen(msg) + 1);
   240    if (m_msgBuffer == 0) {
   241       m_msgBuffer = (char*) malloc(len);
   242       if (m_msgBuffer == 0) {
   243          fprintf(stderr, "out of memory debugger output!\n");
   244          return S_FALSE;
   245       }
   246       strcpy(m_msgBuffer, msg);
   247    } else {
   248       m_msgBuffer = (char*) realloc(m_msgBuffer, len + strlen(m_msgBuffer));
   249       if (m_msgBuffer == 0) {
   250          fprintf(stderr, "out of memory debugger output!\n");
   251          return S_FALSE;
   252       }
   253       strcat(m_msgBuffer, msg);
   254    }
   255    return S_OK;
   256 }
   258 static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
   259   // get windbg interfaces ..
   261   IDebugClient* ptrIDebugClient = 0;
   262   if (DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient) != S_OK) {
   263      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to create IDebugClient object!", false);
   264   }
   265   env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient);
   267   IDebugControl* ptrIDebugControl = 0;
   268   if (ptrIDebugClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl)
   269      != S_OK) {
   270      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugControl", false);
   271   }
   272   env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl);
   274   IDebugDataSpaces* ptrIDebugDataSpaces = 0;
   275   if (ptrIDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces)
   276      != S_OK) {
   277      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugDataSpaces object!", false);
   278   }
   279   env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces);
   281   SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();
   282   ptrIDebugOutputCallbacks->AddRef();
   283   env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);
   284   CHECK_EXCEPTION_(false);
   286   IDebugAdvanced* ptrIDebugAdvanced = 0;
   287   if (ptrIDebugClient->QueryInterface(__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced)
   288      != S_OK) {
   289      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugAdvanced object!", false);
   290   }
   291   env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced);
   293   IDebugSymbols* ptrIDebugSymbols = 0;
   294   if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols)
   295      != S_OK) {
   296      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSymbols object!", false);
   297   }
   298   env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols);
   300   IDebugSystemObjects* ptrIDebugSystemObjects = 0;
   301   if (ptrIDebugClient->QueryInterface(__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects)
   302      != S_OK) {
   303      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get IDebugSystemObjects object!", false);
   304   }
   305   env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects);
   307   return true;
   308 }
   310 static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
   311   jboolean isCopy;
   312   jclass clazz = env->GetObjectClass(obj);
   313   jstring path;
   314   const char* buf;
   316   path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
   317   buf = env->GetStringUTFChars(path, &isCopy);
   318   CHECK_EXCEPTION_(false);
   319   AutoJavaString imagePath(env, path, buf);
   321   path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
   322   buf = env->GetStringUTFChars(path, &isCopy);
   323   CHECK_EXCEPTION_(false);
   324   AutoJavaString symbolPath(env, path, buf);
   326   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   327                                                       ptrIDebugSymbols_ID);
   328   CHECK_EXCEPTION_(false);
   330   ptrIDebugSymbols->SetImagePath(imagePath);
   331   ptrIDebugSymbols->SetSymbolPath(symbolPath);
   332   return true;
   333 }
   335 static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) {
   336   // open the dump file
   337   jboolean isCopy;
   338   const char* buf = env->GetStringUTFChars(coreFileName, &isCopy);
   339   CHECK_EXCEPTION_(false);
   340   AutoJavaString coreFile(env, coreFileName, buf);
   341   if (setImageAndSymbolPath(env, obj) == false) {
   342      return false;
   343   }
   345   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   346                                                       ptrIDebugClient_ID);
   347   CHECK_EXCEPTION_(false);
   348   if (ptrIDebugClient->OpenDumpFile(coreFile) != S_OK) {
   349      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: OpenDumpFile failed!", false);
   350   }
   352   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   353                                                      ptrIDebugControl_ID);
   354   CHECK_EXCEPTION_(false);
   355   if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
   356      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
   357   }
   359   return true;
   360 }
   363 static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) {
   364   if (setImageAndSymbolPath(env, obj) == false) {
   365      return false;
   366   }
   367   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   368                                                       ptrIDebugClient_ID);
   369   CHECK_EXCEPTION_(false);
   371   /***********************************************************************************
   373      We are attaching to a process in 'read-only' mode. i.e., we do not want to
   374      put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
   375      usage this should suffice. We are not intending to use this for full-fledged
   376      ProcessControl implementation to be used with BugSpotAgent.
   378      Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
   379      In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
   380      actually debugging at all. We can safely 'detach' from the process anytime
   381      we want and debuggee process is left as is on all Windows variants.
   383      This also makes JDI-on-SA installation/usage simpler because with this we would
   384      not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.
   386   ***********************************************************************************/
   389   if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
   390      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
   391   }
   393   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   394                                                      ptrIDebugControl_ID);
   395   CHECK_EXCEPTION_(false);
   396   if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
   397      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
   398   }
   400   return true;
   401 }
   404 static bool addLoadObjects(JNIEnv* env, jobject obj) {
   405   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   406                                                       ptrIDebugSymbols_ID);
   407   CHECK_EXCEPTION_(false);
   408   ULONG loaded = 0, unloaded = 0;
   409   if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) {
   410      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false);
   411   }
   413   AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
   415   if (params.asPtr() == 0) {
   416       THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
   417   }
   419   if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
   420      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
   421   }
   423   for (int u = 0; u < (int)loaded; u++) {
   424      TCHAR imageName[MAX_PATH];
   425      if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base,
   426                                       imageName, MAX_PATH, NULL, NULL,
   427                                       0, NULL, NULL, 0, NULL) != S_OK) {
   428         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false);
   429      }
   431      jstring strName = env->NewStringUTF(imageName);
   432      CHECK_EXCEPTION_(false);
   433      env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size,
   434                                (jlong) params.asPtr()[u].Base);
   435      CHECK_EXCEPTION_(false);
   436   }
   438   return true;
   439 }
   441 static bool addThreads(JNIEnv* env, jobject obj) {
   442   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   443                                                       ptrIDebugSystemObjects_ID);
   444   CHECK_EXCEPTION_(false);
   446   ULONG numThreads = 0;
   447   if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
   448      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
   449   }
   451   AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
   453   if (ptrSysThreadIds.asPtr() == 0) {
   454      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   455   }
   457   AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
   459   if (ptrThreadIds.asPtr() == 0) {
   460      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   461   }
   463   if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
   464                                       ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
   465      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
   466   }
   469   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   470                                                       ptrIDebugAdvanced_ID);
   471   CHECK_EXCEPTION_(false);
   473   // for each thread, get register context and save it.
   474   for (ULONG t = 0; t < numThreads; t++) {
   475      if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) {
   476         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false);
   477      }
   479      jlongArray regs = env->NewLongArray(NPRGREG);
   480      CHECK_EXCEPTION_(false);
   482      jboolean isCopy = JNI_FALSE;
   483      jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
   484      CHECK_EXCEPTION_(false);
   486      // copy register values from the CONTEXT struct
   487      CONTEXT context;
   488      memset(&context, 0, sizeof(CONTEXT));
   490 #undef REG_INDEX
   491 #ifdef _M_IX86
   492      #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
   494      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   495      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   497      ptrRegs[REG_INDEX(GS)]  = context.SegGs;
   498      ptrRegs[REG_INDEX(FS)]  = context.SegFs;
   499      ptrRegs[REG_INDEX(ES)]  = context.SegEs;
   500      ptrRegs[REG_INDEX(DS)]  = context.SegDs;
   502      ptrRegs[REG_INDEX(EDI)] = context.Edi;
   503      ptrRegs[REG_INDEX(ESI)] = context.Esi;
   504      ptrRegs[REG_INDEX(EBX)] = context.Ebx;
   505      ptrRegs[REG_INDEX(EDX)] = context.Edx;
   506      ptrRegs[REG_INDEX(ECX)] = context.Ecx;
   507      ptrRegs[REG_INDEX(EAX)] = context.Eax;
   509      ptrRegs[REG_INDEX(FP)] = context.Ebp;
   510      ptrRegs[REG_INDEX(PC)] = context.Eip;
   511      ptrRegs[REG_INDEX(CS)]  = context.SegCs;
   512      ptrRegs[REG_INDEX(EFL)] = context.EFlags;
   513      ptrRegs[REG_INDEX(SP)] = context.Esp;
   514      ptrRegs[REG_INDEX(SS)]  = context.SegSs;
   516      ptrRegs[REG_INDEX(DR0)] = context.Dr0;
   517      ptrRegs[REG_INDEX(DR1)] = context.Dr1;
   518      ptrRegs[REG_INDEX(DR2)] = context.Dr2;
   519      ptrRegs[REG_INDEX(DR3)] = context.Dr3;
   520      ptrRegs[REG_INDEX(DR6)] = context.Dr6;
   521      ptrRegs[REG_INDEX(DR7)] = context.Dr7;
   523 #elif _M_AMD64
   524      #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
   526      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   527      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   529      // Segment Registers and processor flags
   530      ptrRegs[REG_INDEX(CS)]  = context.SegCs;
   531      ptrRegs[REG_INDEX(DS)]  = context.SegDs;
   532      ptrRegs[REG_INDEX(ES)]  = context.SegEs;
   533      ptrRegs[REG_INDEX(FS)]  = context.SegFs;
   534      ptrRegs[REG_INDEX(GS)]  = context.SegGs;
   535      ptrRegs[REG_INDEX(SS)]  = context.SegSs;
   536      ptrRegs[REG_INDEX(RFL)] = context.EFlags;
   538      // Integer registers
   539      ptrRegs[REG_INDEX(RDI)] = context.Rdi;
   540      ptrRegs[REG_INDEX(RSI)] = context.Rsi;
   541      ptrRegs[REG_INDEX(RAX)] = context.Rax;
   542      ptrRegs[REG_INDEX(RCX)] = context.Rcx;
   543      ptrRegs[REG_INDEX(RDX)] = context.Rdx;
   544      ptrRegs[REG_INDEX(RBX)] = context.Rbx;
   545      ptrRegs[REG_INDEX(RBP)] = context.Rbp;
   546      ptrRegs[REG_INDEX(RSP)] = context.Rsp;
   548      ptrRegs[REG_INDEX(R8)]  = context.R8;
   549      ptrRegs[REG_INDEX(R9)]  = context.R9;
   550      ptrRegs[REG_INDEX(R10)] = context.R10;
   551      ptrRegs[REG_INDEX(R11)] = context.R11;
   552      ptrRegs[REG_INDEX(R12)] = context.R12;
   553      ptrRegs[REG_INDEX(R13)] = context.R13;
   554      ptrRegs[REG_INDEX(R14)] = context.R14;
   555      ptrRegs[REG_INDEX(R15)] = context.R15;
   557      // Program counter
   558      ptrRegs[REG_INDEX(RIP)] = context.Rip;
   559 #endif
   561      env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
   562      CHECK_EXCEPTION_(false);
   564      env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
   565                         (jlong) ptrThreadIds.asPtr()[t], regs);
   566      CHECK_EXCEPTION_(false);
   568      ULONG sysId;
   569      if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
   570         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
   571      }
   573      env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
   574      CHECK_EXCEPTION_(false);
   575   }
   577   return true;
   578 }
   580 /*
   581  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   582  * Method:    attach0
   583  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
   584  */
   585 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
   586   (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {
   588   if (getWindbgInterfaces(env, obj) == false) {
   589      return;
   590   }
   592   if (openDumpFile(env, obj, coreFileName) == false) {
   593      return;
   594   }
   596   if (addLoadObjects(env, obj) == false) {
   597      return;
   598   }
   600   if (addThreads(env, obj) == false) {
   601      return;
   602   }
   603 }
   605 /*
   606  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   607  * Method:    attach0
   608  * Signature: (I)V
   609  */
   610 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I
   611   (JNIEnv *env, jobject obj, jint pid) {
   613   if (getWindbgInterfaces(env, obj) == false) {
   614      return;
   615   }
   617   if (attachToProcess(env, obj, pid) == false) {
   618      return;
   619   }
   621   if (addLoadObjects(env, obj) == false) {
   622      return;
   623   }
   625   if (addThreads(env, obj) == false) {
   626      return;
   627   }
   628 }
   631 static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {
   632   IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
   633                                                       ptrIDebugDataSpaces_ID);
   634   CHECK_EXCEPTION_(false);
   635   if (ptrIDebugDataSpaces != 0) {
   636      ptrIDebugDataSpaces->Release();
   637   }
   639   IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
   640                           env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
   641   CHECK_EXCEPTION_(false);
   642   if (ptrIDebugOutputCallbacks != 0) {
   643      ptrIDebugOutputCallbacks->Release();
   644   }
   646   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   647                                                       ptrIDebugAdvanced_ID);
   648   CHECK_EXCEPTION_(false);
   650   if (ptrIDebugAdvanced != 0) {
   651      ptrIDebugAdvanced->Release();
   652   }
   654   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   655                                                       ptrIDebugSymbols_ID);
   656   CHECK_EXCEPTION_(false);
   657   if (ptrIDebugSymbols != 0) {
   658      ptrIDebugSymbols->Release();
   659   }
   661   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   662                                                       ptrIDebugSystemObjects_ID);
   663   CHECK_EXCEPTION_(false);
   664   if (ptrIDebugSystemObjects != 0) {
   665      ptrIDebugSystemObjects->Release();
   666   }
   668   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   669                                                      ptrIDebugControl_ID);
   670   CHECK_EXCEPTION_(false);
   671   if (ptrIDebugControl != 0) {
   672      ptrIDebugControl->Release();
   673   }
   675   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   676                                                       ptrIDebugClient_ID);
   677   CHECK_EXCEPTION_(false);
   678   if (ptrIDebugClient != 0) {
   679      ptrIDebugClient->Release();
   680   }
   682   return true;
   683 }
   685 /*
   686  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   687  * Method:    detach0
   688  * Signature: ()V
   689  */
   690 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0
   691   (JNIEnv *env, jobject obj) {
   692   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   693                                                       ptrIDebugClient_ID);
   694   CHECK_EXCEPTION;
   695   ptrIDebugClient->DetachProcesses();
   696   releaseWindbgInterfaces(env, obj);
   697 }
   700 /*
   701  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   702  * Method:    readBytesFromProcess0
   703  * Signature: (JJ)[B
   704  */
   705 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0
   706   (JNIEnv *env, jobject obj, jlong address, jlong numBytes) {
   707   jbyteArray byteArray = env->NewByteArray((long) numBytes);
   708   CHECK_EXCEPTION_(0);
   710   jboolean isCopy = JNI_FALSE;
   711   jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
   712   CHECK_EXCEPTION_(0);
   714   IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
   715                                                        ptrIDebugDataSpaces_ID);
   716   CHECK_EXCEPTION_(0);
   718   ULONG bytesRead;
   719   if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr,
   720                                   (ULONG)numBytes, &bytesRead) != S_OK) {
   721      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0);
   722   }
   724   if (bytesRead != numBytes) {
   725      return 0;
   726   }
   728   env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
   729   CHECK_EXCEPTION_(0);
   731   return byteArray;
   732 }
   734 /*
   735  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   736  * Method:    getThreadIdFromSysId0
   737  * Signature: (J)J
   738  */
   739 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0
   740   (JNIEnv *env, jobject obj, jlong sysId) {
   741   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   742                                                     ptrIDebugSystemObjects_ID);
   743   CHECK_EXCEPTION_(0);
   745   ULONG id = 0;
   746   if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
   747      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
   748   }
   750   return (jlong) id;
   751 }
   753 // manage COM 'auto' pointers (to avoid multiple Release
   754 // calls at every early (exception) returns). Similar to AutoArrayPtr.
   756 template <class T>
   757 class AutoCOMPtr {
   758       T* m_ptr;
   760    public:
   761       AutoCOMPtr(T* ptr) : m_ptr(ptr) {
   762       }
   764       ~AutoCOMPtr() {
   765          if (m_ptr) {
   766             m_ptr->Release();
   767          }
   768       }
   770       T* operator->() {
   771          return m_ptr;
   772       }
   773 };
   775 /*
   776  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   777  * Method:    consoleExecuteCommand0
   778  * Signature: (Ljava/lang/String;)Ljava/lang/String;
   779  */
   780 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0
   781   (JNIEnv *env, jobject obj, jstring cmd) {
   782   jboolean isCopy = JNI_FALSE;
   783   const char* buf = env->GetStringUTFChars(cmd, &isCopy);
   784   CHECK_EXCEPTION_(0);
   785   AutoJavaString command(env, cmd, buf);
   787   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
   788   CHECK_EXCEPTION_(0);
   790   IDebugClient*  tmpClientPtr = 0;
   791   if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) {
   792      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0);
   793   }
   794   AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);
   796   IDebugControl* tmpControlPtr = 0;
   797   if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) {
   798      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0);
   799   }
   800   AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);
   802   SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
   803                                                                    ptrIDebugOutputCallbacks_ID);
   804   CHECK_EXCEPTION_(0);
   806   saOutputCallbacks->clearBuffer();
   808   if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
   809      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
   810   }
   812   tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
   814   const char* output = saOutputCallbacks->getBuffer();
   815   if (output == 0) {
   816      output = "";
   817   }
   819   jstring res = env->NewStringUTF(output);
   820   saOutputCallbacks->clearBuffer();
   821   return res;
   822 }
   824 /*
   825  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   826  * Method:    lookupByName0
   827  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
   828  */
   830 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0
   831 (JNIEnv *env, jobject obj, jstring objName, jstring sym) {
   832   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   833                                                       ptrIDebugSymbols_ID);
   834   CHECK_EXCEPTION_(0);
   836   jboolean isCopy;
   837   const char* buf = env->GetStringUTFChars(sym, &isCopy);
   838   CHECK_EXCEPTION_(0);
   839   AutoJavaString name(env, sym, buf);
   841   ULONG64 offset = 0L;
   842   if (strstr(name, "::") != 0) {
   843     ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);
   844   } else {
   845     ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);
   846   }
   847   if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
   848     return (jlong) 0;
   849   }
   850   return (jlong) offset;
   851 }
   853 #define SYMBOL_BUFSIZE 512
   854 /*
   855  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   856  * Method:    lookupByAddress0
   857  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
   858  */
   859 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0
   860 (JNIEnv *env, jobject obj, jlong address) {
   861   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   862                                                       ptrIDebugSymbols_ID);
   863   CHECK_EXCEPTION_(0);
   865   ULONG64 disp = 0L;
   866   char buf[SYMBOL_BUFSIZE];
   867   memset(buf, 0, sizeof(buf));
   869   if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
   870       != S_OK) {
   871     return 0;
   872   }
   874   jstring sym = env->NewStringUTF(buf);
   875   CHECK_EXCEPTION_(0);
   876   jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);
   877   CHECK_EXCEPTION_(0);
   878   return res;
   879 }

mercurial