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

Mon, 28 Jul 2014 15:06:38 -0700

author
fzhinkin
date
Mon, 28 Jul 2014 15:06:38 -0700
changeset 6997
dbb05f6d93c4
parent 6198
55fb97c4c58d
child 6876
710a3c8b516e
permissions
-rw-r--r--

8051344: JVM crashed in Compile::start() during method parsing w/ UseRTMDeopt turned on
Summary: call rtm_deopt() only if there were no compilation bailouts before.
Reviewed-by: kvn

     1 /*
     2  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    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.
   377      Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
   378      In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
   379      actually debugging at all. We can safely 'detach' from the process anytime
   380      we want and debuggee process is left as is on all Windows variants.
   382      This also makes JDI-on-SA installation/usage simpler because with this we would
   383      not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.
   385   ***********************************************************************************/
   388   if (ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE) != S_OK) {
   389      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: AttachProcess failed!", false);
   390   }
   392   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   393                                                      ptrIDebugControl_ID);
   394   CHECK_EXCEPTION_(false);
   395   if (ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE) != S_OK) {
   396      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: WaitForEvent failed!", false);
   397   }
   399   return true;
   400 }
   403 static bool addLoadObjects(JNIEnv* env, jobject obj) {
   404   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   405                                                       ptrIDebugSymbols_ID);
   406   CHECK_EXCEPTION_(false);
   407   ULONG loaded = 0, unloaded = 0;
   408   if (ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded) != S_OK) {
   409      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberModules failed!", false);
   410   }
   412   AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);
   414   if (params.asPtr() == 0) {
   415       THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);
   416   }
   418   if (ptrIDebugSymbols->GetModuleParameters(loaded, 0, NULL, params.asPtr()) != S_OK) {
   419      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleParameters failed!", false);
   420   }
   422   for (int u = 0; u < (int)loaded; u++) {
   423      TCHAR imageName[MAX_PATH];
   424      if (ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params.asPtr()[u].Base,
   425                                       imageName, MAX_PATH, NULL, NULL,
   426                                       0, NULL, NULL, 0, NULL) != S_OK) {
   427         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetModuleNames failed!", false);
   428      }
   430      jstring strName = env->NewStringUTF(imageName);
   431      CHECK_EXCEPTION_(false);
   432      env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params.asPtr()[u].Size,
   433                                (jlong) params.asPtr()[u].Base);
   434      CHECK_EXCEPTION_(false);
   435   }
   437   return true;
   438 }
   440 static bool addThreads(JNIEnv* env, jobject obj) {
   441   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   442                                                       ptrIDebugSystemObjects_ID);
   443   CHECK_EXCEPTION_(false);
   445   ULONG numThreads = 0;
   446   if (ptrIDebugSystemObjects->GetNumberThreads(&numThreads) != S_OK) {
   447      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetNumberThreads failed!", false);
   448   }
   450   AutoArrayPtr<ULONG> ptrSysThreadIds = new ULONG[numThreads];
   452   if (ptrSysThreadIds.asPtr() == 0) {
   453      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   454   }
   456   AutoArrayPtr<ULONG> ptrThreadIds = new ULONG[numThreads];
   458   if (ptrThreadIds.asPtr() == 0) {
   459      THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);
   460   }
   462   if (ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,
   463                                       ptrThreadIds.asPtr(), ptrSysThreadIds.asPtr()) != S_OK) {
   464      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdsByIndex failed!", false);
   465   }
   468   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   469                                                       ptrIDebugAdvanced_ID);
   470   CHECK_EXCEPTION_(false);
   472   // for each thread, get register context and save it.
   473   for (ULONG t = 0; t < numThreads; t++) {
   474      if (ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds.asPtr()[t]) != S_OK) {
   475         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetCurrentThread failed!", false);
   476      }
   478      jlongArray regs = env->NewLongArray(NPRGREG);
   479      CHECK_EXCEPTION_(false);
   481      jboolean isCopy = JNI_FALSE;
   482      jlong* ptrRegs = env->GetLongArrayElements(regs, &isCopy);
   483      CHECK_EXCEPTION_(false);
   485      // copy register values from the CONTEXT struct
   486      CONTEXT context;
   487      memset(&context, 0, sizeof(CONTEXT));
   489 #undef REG_INDEX
   490 #ifdef _M_IX86
   491      #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
   493      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   494      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   496      ptrRegs[REG_INDEX(GS)]  = context.SegGs;
   497      ptrRegs[REG_INDEX(FS)]  = context.SegFs;
   498      ptrRegs[REG_INDEX(ES)]  = context.SegEs;
   499      ptrRegs[REG_INDEX(DS)]  = context.SegDs;
   501      ptrRegs[REG_INDEX(EDI)] = context.Edi;
   502      ptrRegs[REG_INDEX(ESI)] = context.Esi;
   503      ptrRegs[REG_INDEX(EBX)] = context.Ebx;
   504      ptrRegs[REG_INDEX(EDX)] = context.Edx;
   505      ptrRegs[REG_INDEX(ECX)] = context.Ecx;
   506      ptrRegs[REG_INDEX(EAX)] = context.Eax;
   508      ptrRegs[REG_INDEX(FP)] = context.Ebp;
   509      ptrRegs[REG_INDEX(PC)] = context.Eip;
   510      ptrRegs[REG_INDEX(CS)]  = context.SegCs;
   511      ptrRegs[REG_INDEX(EFL)] = context.EFlags;
   512      ptrRegs[REG_INDEX(SP)] = context.Esp;
   513      ptrRegs[REG_INDEX(SS)]  = context.SegSs;
   515      ptrRegs[REG_INDEX(DR0)] = context.Dr0;
   516      ptrRegs[REG_INDEX(DR1)] = context.Dr1;
   517      ptrRegs[REG_INDEX(DR2)] = context.Dr2;
   518      ptrRegs[REG_INDEX(DR3)] = context.Dr3;
   519      ptrRegs[REG_INDEX(DR6)] = context.Dr6;
   520      ptrRegs[REG_INDEX(DR7)] = context.Dr7;
   522 #elif _M_AMD64
   523      #define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x
   525      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
   526      ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
   528      // Segment Registers and processor flags
   529      ptrRegs[REG_INDEX(CS)]  = context.SegCs;
   530      ptrRegs[REG_INDEX(DS)]  = context.SegDs;
   531      ptrRegs[REG_INDEX(ES)]  = context.SegEs;
   532      ptrRegs[REG_INDEX(FS)]  = context.SegFs;
   533      ptrRegs[REG_INDEX(GS)]  = context.SegGs;
   534      ptrRegs[REG_INDEX(SS)]  = context.SegSs;
   535      ptrRegs[REG_INDEX(RFL)] = context.EFlags;
   537      // Integer registers
   538      ptrRegs[REG_INDEX(RDI)] = context.Rdi;
   539      ptrRegs[REG_INDEX(RSI)] = context.Rsi;
   540      ptrRegs[REG_INDEX(RAX)] = context.Rax;
   541      ptrRegs[REG_INDEX(RCX)] = context.Rcx;
   542      ptrRegs[REG_INDEX(RDX)] = context.Rdx;
   543      ptrRegs[REG_INDEX(RBX)] = context.Rbx;
   544      ptrRegs[REG_INDEX(RBP)] = context.Rbp;
   545      ptrRegs[REG_INDEX(RSP)] = context.Rsp;
   547      ptrRegs[REG_INDEX(R8)]  = context.R8;
   548      ptrRegs[REG_INDEX(R9)]  = context.R9;
   549      ptrRegs[REG_INDEX(R10)] = context.R10;
   550      ptrRegs[REG_INDEX(R11)] = context.R11;
   551      ptrRegs[REG_INDEX(R12)] = context.R12;
   552      ptrRegs[REG_INDEX(R13)] = context.R13;
   553      ptrRegs[REG_INDEX(R14)] = context.R14;
   554      ptrRegs[REG_INDEX(R15)] = context.R15;
   556      // Program counter
   557      ptrRegs[REG_INDEX(RIP)] = context.Rip;
   558 #endif
   560      env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);
   561      CHECK_EXCEPTION_(false);
   563      env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID,
   564                         (jlong) ptrThreadIds.asPtr()[t], regs);
   565      CHECK_EXCEPTION_(false);
   567      ULONG sysId;
   568      if (ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId) != S_OK) {
   569         THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetCurrentThreadSystemId failed!", false);
   570      }
   572      env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);
   573      CHECK_EXCEPTION_(false);
   574   }
   576   return true;
   577 }
   579 /*
   580  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   581  * Method:    attach0
   582  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
   583  */
   584 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
   585   (JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {
   587   if (getWindbgInterfaces(env, obj) == false) {
   588      return;
   589   }
   591   if (openDumpFile(env, obj, coreFileName) == false) {
   592      return;
   593   }
   595   if (addLoadObjects(env, obj) == false) {
   596      return;
   597   }
   599   if (addThreads(env, obj) == false) {
   600      return;
   601   }
   602 }
   604 /*
   605  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   606  * Method:    attach0
   607  * Signature: (I)V
   608  */
   609 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I
   610   (JNIEnv *env, jobject obj, jint pid) {
   612   if (getWindbgInterfaces(env, obj) == false) {
   613      return;
   614   }
   616   if (attachToProcess(env, obj, pid) == false) {
   617      return;
   618   }
   620   if (addLoadObjects(env, obj) == false) {
   621      return;
   622   }
   624   if (addThreads(env, obj) == false) {
   625      return;
   626   }
   627 }
   630 static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {
   631   IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
   632                                                       ptrIDebugDataSpaces_ID);
   633   CHECK_EXCEPTION_(false);
   634   if (ptrIDebugDataSpaces != 0) {
   635      ptrIDebugDataSpaces->Release();
   636   }
   638   IDebugOutputCallbacks* ptrIDebugOutputCallbacks = (IDebugOutputCallbacks*)
   639                           env->GetLongField(obj, ptrIDebugOutputCallbacks_ID);
   640   CHECK_EXCEPTION_(false);
   641   if (ptrIDebugOutputCallbacks != 0) {
   642      ptrIDebugOutputCallbacks->Release();
   643   }
   645   IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,
   646                                                       ptrIDebugAdvanced_ID);
   647   CHECK_EXCEPTION_(false);
   649   if (ptrIDebugAdvanced != 0) {
   650      ptrIDebugAdvanced->Release();
   651   }
   653   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   654                                                       ptrIDebugSymbols_ID);
   655   CHECK_EXCEPTION_(false);
   656   if (ptrIDebugSymbols != 0) {
   657      ptrIDebugSymbols->Release();
   658   }
   660   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   661                                                       ptrIDebugSystemObjects_ID);
   662   CHECK_EXCEPTION_(false);
   663   if (ptrIDebugSystemObjects != 0) {
   664      ptrIDebugSystemObjects->Release();
   665   }
   667   IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,
   668                                                      ptrIDebugControl_ID);
   669   CHECK_EXCEPTION_(false);
   670   if (ptrIDebugControl != 0) {
   671      ptrIDebugControl->Release();
   672   }
   674   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   675                                                       ptrIDebugClient_ID);
   676   CHECK_EXCEPTION_(false);
   677   if (ptrIDebugClient != 0) {
   678      ptrIDebugClient->Release();
   679   }
   681   return true;
   682 }
   684 /*
   685  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   686  * Method:    detach0
   687  * Signature: ()V
   688  */
   689 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0
   690   (JNIEnv *env, jobject obj) {
   691   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj,
   692                                                       ptrIDebugClient_ID);
   693   CHECK_EXCEPTION;
   694   ptrIDebugClient->DetachProcesses();
   695   releaseWindbgInterfaces(env, obj);
   696 }
   699 /*
   700  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   701  * Method:    readBytesFromProcess0
   702  * Signature: (JJ)[B
   703  */
   704 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0
   705   (JNIEnv *env, jobject obj, jlong address, jlong numBytes) {
   706   jbyteArray byteArray = env->NewByteArray((long) numBytes);
   707   CHECK_EXCEPTION_(0);
   709   jboolean isCopy = JNI_FALSE;
   710   jbyte* bytePtr = env->GetByteArrayElements(byteArray, &isCopy);
   711   CHECK_EXCEPTION_(0);
   713   IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,
   714                                                        ptrIDebugDataSpaces_ID);
   715   CHECK_EXCEPTION_(0);
   717   ULONG bytesRead;
   718   if (ptrIDebugDataSpaces->ReadVirtual((ULONG64) address, (PVOID) bytePtr,
   719                                   (ULONG)numBytes, &bytesRead) != S_OK) {
   720      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: ReadVirtual failed!", 0);
   721   }
   723   if (bytesRead != numBytes) {
   724      return 0;
   725   }
   727   env->ReleaseByteArrayElements(byteArray, bytePtr, 0);
   728   CHECK_EXCEPTION_(0);
   730   return byteArray;
   731 }
   733 /*
   734  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   735  * Method:    getThreadIdFromSysId0
   736  * Signature: (J)J
   737  */
   738 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0
   739   (JNIEnv *env, jobject obj, jlong sysId) {
   740   IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,
   741                                                     ptrIDebugSystemObjects_ID);
   742   CHECK_EXCEPTION_(0);
   744   ULONG id = 0;
   745   if (ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id) != S_OK) {
   746      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: GetThreadIdBySystemId failed!", 0);
   747   }
   749   return (jlong) id;
   750 }
   752 // manage COM 'auto' pointers (to avoid multiple Release
   753 // calls at every early (exception) returns). Similar to AutoArrayPtr.
   755 template <class T>
   756 class AutoCOMPtr {
   757       T* m_ptr;
   759    public:
   760       AutoCOMPtr(T* ptr) : m_ptr(ptr) {
   761       }
   763       ~AutoCOMPtr() {
   764          if (m_ptr) {
   765             m_ptr->Release();
   766          }
   767       }
   769       T* operator->() {
   770          return m_ptr;
   771       }
   772 };
   774 /*
   775  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   776  * Method:    consoleExecuteCommand0
   777  * Signature: (Ljava/lang/String;)Ljava/lang/String;
   778  */
   779 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0
   780   (JNIEnv *env, jobject obj, jstring cmd) {
   781   jboolean isCopy = JNI_FALSE;
   782   const char* buf = env->GetStringUTFChars(cmd, &isCopy);
   783   CHECK_EXCEPTION_(0);
   784   AutoJavaString command(env, cmd, buf);
   786   IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);
   787   CHECK_EXCEPTION_(0);
   789   IDebugClient*  tmpClientPtr = 0;
   790   if (ptrIDebugClient->CreateClient(&tmpClientPtr) != S_OK) {
   791      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: CreateClient failed!", 0);
   792   }
   793   AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);
   795   IDebugControl* tmpControlPtr = 0;
   796   if (tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr) != S_OK) {
   797      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: QueryInterface (IDebugControl) failed", 0);
   798   }
   799   AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);
   801   SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,
   802                                                                    ptrIDebugOutputCallbacks_ID);
   803   CHECK_EXCEPTION_(0);
   805   saOutputCallbacks->clearBuffer();
   807   if (tmpClient->SetOutputCallbacks(saOutputCallbacks) != S_OK) {
   808      THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: SetOutputCallbacks failed!", 0);
   809   }
   811   tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);
   813   const char* output = saOutputCallbacks->getBuffer();
   814   if (output == 0) {
   815      output = "";
   816   }
   818   jstring res = env->NewStringUTF(output);
   819   saOutputCallbacks->clearBuffer();
   820   return res;
   821 }
   823 /*
   824  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   825  * Method:    lookupByName0
   826  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
   827  */
   829 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0
   830 (JNIEnv *env, jobject obj, jstring objName, jstring sym) {
   831   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   832                                                       ptrIDebugSymbols_ID);
   833   CHECK_EXCEPTION_(0);
   835   jboolean isCopy;
   836   const char* buf = env->GetStringUTFChars(sym, &isCopy);
   837   CHECK_EXCEPTION_(0);
   838   AutoJavaString name(env, sym, buf);
   840   ULONG64 offset = 0L;
   841   if (strstr(name, "::") != 0) {
   842     ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);
   843   } else {
   844     ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);
   845   }
   846   if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
   847     return (jlong) 0;
   848   }
   849   return (jlong) offset;
   850 }
   852 #define SYMBOL_BUFSIZE 512
   853 /*
   854  * Class:     sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
   855  * Method:    lookupByAddress0
   856  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
   857  */
   858 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0
   859 (JNIEnv *env, jobject obj, jlong address) {
   860   IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,
   861                                                       ptrIDebugSymbols_ID);
   862   CHECK_EXCEPTION_(0);
   864   ULONG64 disp = 0L;
   865   char buf[SYMBOL_BUFSIZE];
   866   memset(buf, 0, sizeof(buf));
   868   if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf),0,&disp)
   869       != S_OK) {
   870     return 0;
   871   }
   873   jstring sym = env->NewStringUTF(buf);
   874   CHECK_EXCEPTION_(0);
   875   jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);
   876   CHECK_EXCEPTION_(0);
   877   return res;
   878 }

mercurial