Path: blob/master/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
41149 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324// Disable CRT security warning against strcpy/strcat25#pragma warning(disable: 4996)2627// this is source code windbg based SA debugger agent to debug28// Dr. Watson dump files and process snapshots.2930#include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"3132#ifdef _M_IX8633#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"34#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG35#elif _M_AMD6436#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"37#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG38#elif _M_ARM6439#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"40#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG41#else42#error "SA windbg back-end is not supported for your cpu!"43#endif4445#include <limits.h>46#include <windows.h>47#include <inttypes.h>4849#define DEBUG_NO_IMPLEMENTATION50#include <dbgeng.h>51#include <dbghelp.h>525354// Wrappers to simplify cleanup on errors.55namespace {5657template <class T>58class AutoArrayPtr {59T* m_ptr;60public:61AutoArrayPtr(T* ptr) : m_ptr(ptr) {62}6364~AutoArrayPtr() {65delete [] m_ptr;66}6768operator T* () const {69return m_ptr;70}71};7273// Manage COM 'auto' pointers to avoid multiple Release74// calls at every early (exception) returns.7576template <class T>77class AutoCOMPtr {78T* m_ptr;7980public:81AutoCOMPtr(T* ptr) : m_ptr(ptr) {82}8384~AutoCOMPtr() {85if (m_ptr) {86m_ptr->Release();87}88}8990T* operator->() const {91return m_ptr;92}93};9495class AutoJavaString {96JNIEnv* m_env;97jstring m_str;98const char* m_buf;99100public:101// check env->ExceptionOccurred() after ctor102AutoJavaString(JNIEnv* env, jstring str)103: m_env(env), m_str(str), m_buf(str == nullptr ? nullptr : env->GetStringUTFChars(str, nullptr)) {104}105106~AutoJavaString() {107if (m_buf) {108m_env->ReleaseStringUTFChars(m_str, m_buf);109}110}111112operator const char* () const {113return m_buf;114}115};116117class AutoJavaByteArray {118JNIEnv* env;119jbyteArray byteArray;120jbyte* bytePtr;121jint releaseMode;122123public:124// check env->ExceptionOccurred() after ctor125AutoJavaByteArray(JNIEnv* env, jbyteArray byteArray, jint releaseMode = JNI_ABORT)126: env(env), byteArray(byteArray), releaseMode(releaseMode),127bytePtr(env->GetByteArrayElements(byteArray, nullptr)) {128}129130~AutoJavaByteArray() {131if (bytePtr) {132env->ReleaseByteArrayElements(byteArray, bytePtr, releaseMode);133}134}135136void setReleaseMode(jint mode) {137releaseMode = mode;138}139140operator jbyte* () const {141return bytePtr;142}143};144145} // unnamed namespace146147148// field and method IDs we want here149150static jfieldID imagePath_ID = 0;151static jfieldID symbolPath_ID = 0;152static jfieldID ptrIDebugClient_ID = 0;153static jfieldID ptrIDebugControl_ID = 0;154static jfieldID ptrIDebugDataSpaces_ID = 0;155static jfieldID ptrIDebugOutputCallbacks_ID = 0;156static jfieldID ptrIDebugAdvanced_ID = 0;157static jfieldID ptrIDebugSymbols_ID = 0;158static jfieldID ptrIDebugSystemObjects_ID = 0;159160static jmethodID addLoadObject_ID = 0;161static jmethodID addThread_ID = 0;162static jmethodID createClosestSymbol_ID = 0;163static jmethodID setThreadIntegerRegisterSet_ID = 0;164165#define CHECK_EXCEPTION_(value) if (env->ExceptionOccurred()) { return value; }166#define CHECK_EXCEPTION if (env->ExceptionOccurred()) { return; }167168#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { \169throwNewDebuggerException(env, str); return value; }170171#define THROW_NEW_DEBUGGER_EXCEPTION(str) { \172throwNewDebuggerException(env, str); return; }173174static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {175jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");176CHECK_EXCEPTION;177env->ThrowNew(clazz, errMsg);178}179180// Verifies COM call result is S_OK, throws DebuggerException and exits otherwise.181// Note: other success results (like S_FALSE) are considered errors.182#define COM_VERIFY_OK_(v, str, retValue) \183do { \184const HRESULT hr = (v); \185if (hr != S_OK) { \186AutoArrayPtr<char> errmsg(new char[strlen(str) + 32]); \187if (errmsg == nullptr) { \188THROW_NEW_DEBUGGER_EXCEPTION_(str, retValue); \189} else { \190sprintf(errmsg, "%s (hr: 0x%08X)", str, hr); \191THROW_NEW_DEBUGGER_EXCEPTION_(errmsg, retValue); \192} \193} \194} while (false)195196/*197* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal198* Method: initIDs199* Signature: ()V200*/201JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_initIDs202(JNIEnv *env, jclass clazz) {203imagePath_ID = env->GetStaticFieldID(clazz, "imagePath", "Ljava/lang/String;");204CHECK_EXCEPTION;205206symbolPath_ID = env->GetStaticFieldID(clazz, "symbolPath", "Ljava/lang/String;");207CHECK_EXCEPTION;208209ptrIDebugClient_ID = env->GetFieldID(clazz, "ptrIDebugClient", "J");210CHECK_EXCEPTION;211212ptrIDebugControl_ID = env->GetFieldID(clazz, "ptrIDebugControl", "J");213CHECK_EXCEPTION;214215ptrIDebugDataSpaces_ID = env->GetFieldID(clazz, "ptrIDebugDataSpaces", "J");216CHECK_EXCEPTION;217218ptrIDebugOutputCallbacks_ID = env->GetFieldID(clazz, "ptrIDebugOutputCallbacks", "J");219CHECK_EXCEPTION;220221ptrIDebugAdvanced_ID = env->GetFieldID(clazz, "ptrIDebugAdvanced", "J");222CHECK_EXCEPTION;223224ptrIDebugSymbols_ID = env->GetFieldID(clazz, "ptrIDebugSymbols", "J");225CHECK_EXCEPTION;226227ptrIDebugSystemObjects_ID = env->GetFieldID(clazz, "ptrIDebugSystemObjects", "J");228CHECK_EXCEPTION;229230addLoadObject_ID = env->GetMethodID(clazz, "addLoadObject", "(Ljava/lang/String;JJ)V");231CHECK_EXCEPTION;232233addThread_ID = env->GetMethodID(clazz, "addThread", "(J)V");234CHECK_EXCEPTION;235236createClosestSymbol_ID = env->GetMethodID(clazz, "createClosestSymbol",237"(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");238CHECK_EXCEPTION;239240setThreadIntegerRegisterSet_ID = env->GetMethodID(clazz,241"setThreadIntegerRegisterSet", "(J[J)V");242CHECK_EXCEPTION;243}244245// class for IDebugOutputCallbacks246247class SAOutputCallbacks : public IDebugOutputCallbacks {248LONG m_refCount;249char* m_msgBuffer;250251public:252SAOutputCallbacks() : m_refCount(1), m_msgBuffer(nullptr) {253}254255~SAOutputCallbacks() {256clearBuffer();257}258259const char* getBuffer() const {260return m_msgBuffer;261}262263void clearBuffer() {264if (m_msgBuffer) {265free(m_msgBuffer);266m_msgBuffer = 0;267}268}269270STDMETHOD_(ULONG, AddRef)(THIS);271STDMETHOD_(ULONG, Release)(THIS);272STDMETHOD(QueryInterface)(THIS_273IN REFIID interfaceId,274OUT PVOID* ppInterface);275STDMETHOD(Output)(THIS_276IN ULONG mask,277IN PCSTR msg);278};279280STDMETHODIMP_(ULONG) SAOutputCallbacks::AddRef(THIS) {281return InterlockedIncrement(&m_refCount);282}283284STDMETHODIMP_(ULONG) SAOutputCallbacks::Release(THIS) {285LONG retVal = InterlockedDecrement(&m_refCount);286if (retVal == 0) {287delete this;288}289return retVal;290}291292STDMETHODIMP SAOutputCallbacks::QueryInterface(THIS_293IN REFIID interfaceId,294OUT PVOID* ppInterface) {295*ppInterface = nullptr;296if (IsEqualIID(interfaceId, __uuidof(IUnknown)) ||297IsEqualIID(interfaceId, __uuidof(IDebugOutputCallbacks))) {298*ppInterface = static_cast<IDebugOutputCallbacks*>(this);299} else {300return E_NOINTERFACE;301}302AddRef();303return S_OK;304}305306STDMETHODIMP SAOutputCallbacks::Output(THIS_307IN ULONG mask,308IN PCSTR msg) {309size_t len = strlen(msg) + 1;310if (m_msgBuffer == 0) {311m_msgBuffer = (char*) malloc(len);312if (m_msgBuffer == 0) {313fprintf(stderr, "out of memory debugger output!\n");314return S_FALSE;315}316strcpy(m_msgBuffer, msg);317} else {318char* newBuffer = (char*)realloc(m_msgBuffer, len + strlen(m_msgBuffer));319if (newBuffer == nullptr) {320// old m_msgBuffer buffer is still valid321fprintf(stderr, "out of memory debugger output!\n");322return S_FALSE;323}324m_msgBuffer = newBuffer;325strcat(m_msgBuffer, msg);326}327return S_OK;328}329330static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {331// get windbg interfaces ..332333IDebugClient* ptrIDebugClient = 0;334COM_VERIFY_OK_(DebugCreate(__uuidof(IDebugClient), (PVOID*) &ptrIDebugClient),335"Windbg Error: not able to create IDebugClient object!", false);336env->SetLongField(obj, ptrIDebugClient_ID, (jlong) ptrIDebugClient);337338IDebugControl* ptrIDebugControl = 0;339COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(340__uuidof(IDebugControl), (PVOID*) &ptrIDebugControl),341"Windbg Error: not able to get IDebugControl", false);342env->SetLongField(obj, ptrIDebugControl_ID, (jlong) ptrIDebugControl);343344IDebugDataSpaces* ptrIDebugDataSpaces = 0;345COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(346__uuidof(IDebugDataSpaces), (PVOID*) &ptrIDebugDataSpaces),347"Windbg Error: not able to get IDebugDataSpaces object!", false);348env->SetLongField(obj, ptrIDebugDataSpaces_ID, (jlong) ptrIDebugDataSpaces);349350SAOutputCallbacks* ptrIDebugOutputCallbacks = new SAOutputCallbacks();351env->SetLongField(obj, ptrIDebugOutputCallbacks_ID, (jlong) ptrIDebugOutputCallbacks);352CHECK_EXCEPTION_(false);353354IDebugAdvanced* ptrIDebugAdvanced = 0;355COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(356__uuidof(IDebugAdvanced), (PVOID*) &ptrIDebugAdvanced),357"Windbg Error: not able to get IDebugAdvanced object!", false);358env->SetLongField(obj, ptrIDebugAdvanced_ID, (jlong) ptrIDebugAdvanced);359360IDebugSymbols* ptrIDebugSymbols = 0;361COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(362__uuidof(IDebugSymbols), (PVOID*) &ptrIDebugSymbols),363"Windbg Error: not able to get IDebugSymbols object!", false);364env->SetLongField(obj, ptrIDebugSymbols_ID, (jlong) ptrIDebugSymbols);365366IDebugSystemObjects* ptrIDebugSystemObjects = 0;367COM_VERIFY_OK_(ptrIDebugClient->QueryInterface(368__uuidof(IDebugSystemObjects), (PVOID*) &ptrIDebugSystemObjects),369"Windbg Error: not able to get IDebugSystemObjects object!", false);370env->SetLongField(obj, ptrIDebugSystemObjects_ID, (jlong) ptrIDebugSystemObjects);371372return true;373}374375static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {376jclass clazz = env->GetObjectClass(obj);377CHECK_EXCEPTION_(false);378jstring path;379380path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);381CHECK_EXCEPTION_(false);382if (path == nullptr) {383THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get imagePath field ID!", false);384}385AutoJavaString imagePath(env, path);386CHECK_EXCEPTION_(false);387388path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);389CHECK_EXCEPTION_(false);390if (path == nullptr) {391THROW_NEW_DEBUGGER_EXCEPTION_("Windbg Error: not able to get symbolPath field ID!", false);392}393AutoJavaString symbolPath(env, path);394CHECK_EXCEPTION_(false);395396IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*)env->GetLongField(obj, ptrIDebugSymbols_ID);397CHECK_EXCEPTION_(false);398399ptrIDebugSymbols->SetImagePath(imagePath);400ptrIDebugSymbols->SetSymbolPath(symbolPath);401return true;402}403404static HRESULT WaitForEvent(IDebugControl *ptrIDebugControl) {405HRESULT hr = ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);406// see JDK-8204994: sometimes WaitForEvent fails with E_ACCESSDENIED,407// but succeeds on 2nd call.408// To minimize possible noise retry 3 times.409for (int i = 0; hr == E_ACCESSDENIED && i < 3; i++) {410// yield current thread use of a processor (short delay).411SwitchToThread();412hr = ptrIDebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);413}414return hr;415}416417static bool openDumpFile(JNIEnv* env, jobject obj, jstring coreFileName) {418// open the dump file419AutoJavaString coreFile(env, coreFileName);420CHECK_EXCEPTION_(false);421if (!setImageAndSymbolPath(env, obj)) {422return false;423}424425IDebugClient* ptrIDebugClient = (IDebugClient*)env->GetLongField(obj, ptrIDebugClient_ID);426CHECK_EXCEPTION_(false);427COM_VERIFY_OK_(ptrIDebugClient->OpenDumpFile(coreFile),428"Windbg Error: OpenDumpFile failed!", false);429430IDebugControl* ptrIDebugControl = (IDebugControl*)env->GetLongField(obj, ptrIDebugControl_ID);431CHECK_EXCEPTION_(false);432COM_VERIFY_OK_(WaitForEvent(ptrIDebugControl),433"Windbg Error: WaitForEvent failed!", false);434435return true;436}437438439static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) {440if (!setImageAndSymbolPath(env, obj)) {441return false;442}443IDebugClient* ptrIDebugClient = (IDebugClient*)env->GetLongField(obj, ptrIDebugClient_ID);444CHECK_EXCEPTION_(false);445446/***********************************************************************************447448We are attaching to a process in 'read-only' mode. i.e., we do not want to449put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of450usage this should suffice.451452Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.453In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not454actually debugging at all. We can safely 'detach' from the process anytime455we want and debuggee process is left as is on all Windows variants.456457This also makes JDI-on-SA installation/usage simpler because with this we would458not need a tool like ServiceInstaller from http://www.kcmultimedia.com/smaster.459460***********************************************************************************/461462463COM_VERIFY_OK_(ptrIDebugClient->AttachProcess(0, pid, DEBUG_ATTACH_NONINVASIVE),464"Windbg Error: AttachProcess failed!", false);465466IDebugControl* ptrIDebugControl = (IDebugControl*) env->GetLongField(obj,467ptrIDebugControl_ID);468CHECK_EXCEPTION_(false);469COM_VERIFY_OK_(WaitForEvent(ptrIDebugControl),470"Windbg Error: WaitForEvent failed!", false);471472return true;473}474475476static bool addLoadObjects(JNIEnv* env, jobject obj) {477IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj,478ptrIDebugSymbols_ID);479CHECK_EXCEPTION_(false);480ULONG loaded = 0, unloaded = 0;481COM_VERIFY_OK_(ptrIDebugSymbols->GetNumberModules(&loaded, &unloaded),482"Windbg Error: GetNumberModules failed!", false);483484AutoArrayPtr<DEBUG_MODULE_PARAMETERS> params(new DEBUG_MODULE_PARAMETERS[loaded]);485486if (params == nullptr) {487THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate debug module params!", false);488}489490COM_VERIFY_OK_(ptrIDebugSymbols->GetModuleParameters(loaded, nullptr, 0, params),491"Windbg Error: GetModuleParameters failed!", false);492493for (int u = 0; u < (int)loaded; u++) {494TCHAR imageName[MAX_PATH];495COM_VERIFY_OK_(ptrIDebugSymbols->GetModuleNames(DEBUG_ANY_ID, params[u].Base,496imageName, MAX_PATH, nullptr, nullptr,4970, nullptr, nullptr, 0, nullptr),498"Windbg Error: GetModuleNames failed!", false);499500jstring strName = env->NewStringUTF(imageName);501CHECK_EXCEPTION_(false);502env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params[u].Size,503(jlong) params[u].Base);504CHECK_EXCEPTION_(false);505env->DeleteLocalRef(strName);506}507508return true;509}510511static bool addThreads(JNIEnv* env, jobject obj) {512IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,513ptrIDebugSystemObjects_ID);514CHECK_EXCEPTION_(false);515516ULONG numThreads = 0;517COM_VERIFY_OK_(ptrIDebugSystemObjects->GetNumberThreads(&numThreads),518"Windbg Error: GetNumberThreads failed!", false);519520AutoArrayPtr<ULONG> ptrSysThreadIds(new ULONG[numThreads]);521522if (ptrSysThreadIds == nullptr) {523THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);524}525526AutoArrayPtr<ULONG> ptrThreadIds(new ULONG[numThreads]);527528if (ptrThreadIds == nullptr) {529THROW_NEW_DEBUGGER_EXCEPTION_("out of memory to allocate thread ids!", false);530}531532COM_VERIFY_OK_(ptrIDebugSystemObjects->GetThreadIdsByIndex(0, numThreads,533ptrThreadIds, ptrSysThreadIds),534"Windbg Error: GetThreadIdsByIndex failed!", false);535536537IDebugAdvanced* ptrIDebugAdvanced = (IDebugAdvanced*) env->GetLongField(obj,538ptrIDebugAdvanced_ID);539CHECK_EXCEPTION_(false);540541// for each thread, get register context and save it.542for (ULONG t = 0; t < numThreads; t++) {543COM_VERIFY_OK_(ptrIDebugSystemObjects->SetCurrentThreadId(ptrThreadIds[t]),544"Windbg Error: SetCurrentThread failed!", false);545546jlongArray regs = env->NewLongArray(NPRGREG);547CHECK_EXCEPTION_(false);548549jlong* ptrRegs = env->GetLongArrayElements(regs, nullptr);550CHECK_EXCEPTION_(false);551552// copy register values from the CONTEXT struct553CONTEXT context;554memset(&context, 0, sizeof(CONTEXT));555556#undef REG_INDEX557#ifdef _M_IX86558#define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x559560context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;561ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));562563ptrRegs[REG_INDEX(GS)] = context.SegGs;564ptrRegs[REG_INDEX(FS)] = context.SegFs;565ptrRegs[REG_INDEX(ES)] = context.SegEs;566ptrRegs[REG_INDEX(DS)] = context.SegDs;567568ptrRegs[REG_INDEX(EDI)] = context.Edi;569ptrRegs[REG_INDEX(ESI)] = context.Esi;570ptrRegs[REG_INDEX(EBX)] = context.Ebx;571ptrRegs[REG_INDEX(EDX)] = context.Edx;572ptrRegs[REG_INDEX(ECX)] = context.Ecx;573ptrRegs[REG_INDEX(EAX)] = context.Eax;574575ptrRegs[REG_INDEX(FP)] = context.Ebp;576ptrRegs[REG_INDEX(PC)] = context.Eip;577ptrRegs[REG_INDEX(CS)] = context.SegCs;578ptrRegs[REG_INDEX(EFL)] = context.EFlags;579ptrRegs[REG_INDEX(SP)] = context.Esp;580ptrRegs[REG_INDEX(SS)] = context.SegSs;581582ptrRegs[REG_INDEX(DR0)] = context.Dr0;583ptrRegs[REG_INDEX(DR1)] = context.Dr1;584ptrRegs[REG_INDEX(DR2)] = context.Dr2;585ptrRegs[REG_INDEX(DR3)] = context.Dr3;586ptrRegs[REG_INDEX(DR6)] = context.Dr6;587ptrRegs[REG_INDEX(DR7)] = context.Dr7;588589#elif _M_AMD64590#define REG_INDEX(x) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##x591592context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;593ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));594595// Segment Registers and processor flags596ptrRegs[REG_INDEX(CS)] = context.SegCs;597ptrRegs[REG_INDEX(DS)] = context.SegDs;598ptrRegs[REG_INDEX(ES)] = context.SegEs;599ptrRegs[REG_INDEX(FS)] = context.SegFs;600ptrRegs[REG_INDEX(GS)] = context.SegGs;601ptrRegs[REG_INDEX(SS)] = context.SegSs;602ptrRegs[REG_INDEX(RFL)] = context.EFlags;603604// Integer registers605ptrRegs[REG_INDEX(RDI)] = context.Rdi;606ptrRegs[REG_INDEX(RSI)] = context.Rsi;607ptrRegs[REG_INDEX(RAX)] = context.Rax;608ptrRegs[REG_INDEX(RCX)] = context.Rcx;609ptrRegs[REG_INDEX(RDX)] = context.Rdx;610ptrRegs[REG_INDEX(RBX)] = context.Rbx;611ptrRegs[REG_INDEX(RBP)] = context.Rbp;612ptrRegs[REG_INDEX(RSP)] = context.Rsp;613614ptrRegs[REG_INDEX(R8)] = context.R8;615ptrRegs[REG_INDEX(R9)] = context.R9;616ptrRegs[REG_INDEX(R10)] = context.R10;617ptrRegs[REG_INDEX(R11)] = context.R11;618ptrRegs[REG_INDEX(R12)] = context.R12;619ptrRegs[REG_INDEX(R13)] = context.R13;620ptrRegs[REG_INDEX(R14)] = context.R14;621ptrRegs[REG_INDEX(R15)] = context.R15;622623// Program counter624ptrRegs[REG_INDEX(RIP)] = context.Rip;625#endif626627env->ReleaseLongArrayElements(regs, ptrRegs, JNI_COMMIT);628CHECK_EXCEPTION_(false);629630env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, (jlong)ptrThreadIds[t], regs);631CHECK_EXCEPTION_(false);632env->DeleteLocalRef(regs);633634ULONG sysId;635COM_VERIFY_OK_(ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId),636"Windbg Error: GetCurrentThreadSystemId failed!", false);637638env->CallVoidMethod(obj, addThread_ID, (jlong) sysId);639CHECK_EXCEPTION_(false);640}641642return true;643}644645/*646* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal647* Method: attach0648* Signature: (Ljava/lang/String;Ljava/lang/String;)V649*/650JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2651(JNIEnv *env, jobject obj, jstring execName, jstring coreFileName) {652653if (!getWindbgInterfaces(env, obj)) {654return;655}656657if (!openDumpFile(env, obj, coreFileName)) {658return;659}660661if (!addLoadObjects(env, obj)) {662return;663}664665if (!addThreads(env, obj)) {666return;667}668}669670/*671* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal672* Method: attach0673* Signature: (I)V674*/675JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_attach0__I676(JNIEnv *env, jobject obj, jint pid) {677678if (!getWindbgInterfaces(env, obj)) {679return;680}681682if (!attachToProcess(env, obj, pid)) {683return;684}685686if (!addLoadObjects(env, obj)) {687return;688}689690if (!addThreads(env, obj)) {691return;692}693}694695696#define RELEASE(fieldID) \697do { \698IUnknown* ptr = (IUnknown*)env->GetLongField(obj, fieldID); \699CHECK_EXCEPTION_(false); \700if (ptr) { \701ptr->Release(); \702} \703} while (false)704705static bool releaseWindbgInterfaces(JNIEnv* env, jobject obj) {706RELEASE(ptrIDebugDataSpaces_ID);707RELEASE(ptrIDebugOutputCallbacks_ID);708RELEASE(ptrIDebugAdvanced_ID);709RELEASE(ptrIDebugSymbols_ID);710RELEASE(ptrIDebugSystemObjects_ID);711RELEASE(ptrIDebugControl_ID);712RELEASE(ptrIDebugClient_ID);713714return true;715}716717/*718* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal719* Method: detach0720* Signature: ()V721*/722JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_detach0723(JNIEnv *env, jobject obj) {724IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);725CHECK_EXCEPTION;726ptrIDebugClient->DetachProcesses();727releaseWindbgInterfaces(env, obj);728}729730731/*732* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal733* Method: readBytesFromProcess0734* Signature: (JJ)[B735*/736JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_readBytesFromProcess0737(JNIEnv *env, jobject obj, jlong address, jlong numBytes) {738jbyteArray byteArray = env->NewByteArray((jsize)numBytes);739CHECK_EXCEPTION_(0);740741AutoJavaByteArray arrayBytes(env, byteArray);742CHECK_EXCEPTION_(0);743744IDebugDataSpaces* ptrIDebugDataSpaces = (IDebugDataSpaces*) env->GetLongField(obj,745ptrIDebugDataSpaces_ID);746CHECK_EXCEPTION_(0);747748ULONG bytesRead;749const HRESULT hr = ptrIDebugDataSpaces->ReadVirtual((ULONG64)address, arrayBytes,750(ULONG)numBytes, &bytesRead);751if (hr != S_OK || bytesRead != numBytes) {752return 0;753}754755arrayBytes.setReleaseMode(0);756757return byteArray;758}759760/*761* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal762* Method: getThreadIdFromSysId0763* Signature: (J)J764*/765JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_getThreadIdFromSysId0766(JNIEnv *env, jobject obj, jlong sysId) {767IDebugSystemObjects* ptrIDebugSystemObjects = (IDebugSystemObjects*) env->GetLongField(obj,768ptrIDebugSystemObjects_ID);769CHECK_EXCEPTION_(0);770771ULONG id = 0;772HRESULT hr = ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id);773if (hr != S_OK) {774// This is not considered fatal and does happen on occassion, usually with an775// 0x80004002 "No such interface supported". The root cause is not fully understood,776// but by ignoring this error and returning NULL, stacking walking code will get777// null registers and fallback to using the "last java frame" if setup.778printf("WARNING: GetThreadIdBySystemId failed with 0x%x for sysId (%" PRIu64 ")\n",779hr, sysId);780return -1;781}782return (jlong) id;783}784785/*786* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal787* Method: consoleExecuteCommand0788* Signature: (Ljava/lang/String;)Ljava/lang/String;789*/790JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_consoleExecuteCommand0791(JNIEnv *env, jobject obj, jstring cmd) {792AutoJavaString command(env, cmd);793CHECK_EXCEPTION_(0);794795IDebugClient* ptrIDebugClient = (IDebugClient*) env->GetLongField(obj, ptrIDebugClient_ID);796CHECK_EXCEPTION_(0);797798IDebugClient* tmpClientPtr = 0;799COM_VERIFY_OK_(ptrIDebugClient->CreateClient(&tmpClientPtr),800"Windbg Error: CreateClient failed!", 0);801AutoCOMPtr<IDebugClient> tmpClient(tmpClientPtr);802803IDebugControl* tmpControlPtr = 0;804COM_VERIFY_OK_(tmpClient->QueryInterface(__uuidof(IDebugControl), (PVOID*) &tmpControlPtr),805"Windbg Error: QueryInterface (IDebugControl) failed", 0);806AutoCOMPtr<IDebugControl> tmpControl(tmpControlPtr);807808SAOutputCallbacks* saOutputCallbacks = (SAOutputCallbacks*) env->GetLongField(obj,809ptrIDebugOutputCallbacks_ID);810CHECK_EXCEPTION_(0);811812saOutputCallbacks->clearBuffer();813814COM_VERIFY_OK_(tmpClient->SetOutputCallbacks(saOutputCallbacks),815"Windbg Error: SetOutputCallbacks failed!", 0);816817tmpControl->Execute(DEBUG_OUTPUT_VERBOSE, command, DEBUG_EXECUTE_DEFAULT);818819const char* output = saOutputCallbacks->getBuffer();820if (output == 0) {821output = "";822}823824jstring res = env->NewStringUTF(output);825saOutputCallbacks->clearBuffer();826return res;827}828829/*830* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal831* Method: lookupByName0832* Signature: (Ljava/lang/String;Ljava/lang/String;)J833*/834835JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByName0836(JNIEnv *env, jobject obj, jstring objName, jstring sym) {837IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*)env->GetLongField(obj, ptrIDebugSymbols_ID);838CHECK_EXCEPTION_(0);839840AutoJavaString name(env, sym);841CHECK_EXCEPTION_(0);842843ULONG64 offset = 0L;844if (strstr(name, "::") != 0) {845ptrIDebugSymbols->AddSymbolOptions(SYMOPT_UNDNAME);846} else {847ptrIDebugSymbols->RemoveSymbolOptions(SYMOPT_UNDNAME);848}849if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {850return (jlong) 0;851}852return (jlong) offset;853}854855#define SYMBOL_BUFSIZE 512856/*857* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal858* Method: lookupByAddress0859* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;860*/861JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal_lookupByAddress0862(JNIEnv *env, jobject obj, jlong address) {863IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*) env->GetLongField(obj, ptrIDebugSymbols_ID);864CHECK_EXCEPTION_(0);865866ULONG64 disp = 0L;867char buf[SYMBOL_BUFSIZE];868memset(buf, 0, sizeof(buf));869870if (ptrIDebugSymbols->GetNameByOffset(address, buf, sizeof(buf), 0, &disp) != S_OK) {871return 0;872}873874jstring sym = env->NewStringUTF(buf);875CHECK_EXCEPTION_(0);876jobject res = env->CallObjectMethod(obj, createClosestSymbol_ID, sym, disp);877CHECK_EXCEPTION_(0);878return res;879}880881882