--- a/hotspot/src/os/windows/vm/decoder_windows.cpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/os/windows/vm/decoder_windows.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,160 +27,99 @@
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "decoder_windows.hpp"
+#include "windbghelp.hpp"
WindowsDecoder::WindowsDecoder() {
- _dbghelp_handle = NULL;
- _can_decode_in_vm = false;
- _pfnSymGetSymFromAddr64 = NULL;
- _pfnUndecorateSymbolName = NULL;
-#ifdef AMD64
- _pfnStackWalk64 = NULL;
- _pfnSymFunctionTableAccess64 = NULL;
- _pfnSymGetModuleBase64 = NULL;
-#endif
+ _can_decode_in_vm = true;
_decoder_status = no_error;
initialize();
}
void WindowsDecoder::initialize() {
- if (!has_error() && _dbghelp_handle == NULL) {
- HMODULE handle = ::LoadLibrary("dbghelp.dll");
- if (!handle) {
- _decoder_status = helper_not_found;
- return;
- }
-
- _dbghelp_handle = handle;
-
- pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");
- pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");
- _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");
- _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
-
- if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
- uninitialize();
- _decoder_status = helper_func_error;
- return;
- }
-
-#ifdef AMD64
- _pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64");
- _pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64");
- _pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64");
- if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) {
- // We can't call StackWalk64 to walk the stack, but we are still
- // able to decode the symbols. Let's limp on.
- _pfnStackWalk64 = NULL;
- _pfnSymFunctionTableAccess64 = NULL;
- _pfnSymGetModuleBase64 = NULL;
- }
-#endif
-
+ if (!has_error()) {
HANDLE hProcess = ::GetCurrentProcess();
- _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
- if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
- _pfnSymGetSymFromAddr64 = NULL;
- _pfnUndecorateSymbolName = NULL;
- ::FreeLibrary(handle);
- _dbghelp_handle = NULL;
+ WindowsDbgHelp::symSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
+ if (!WindowsDbgHelp::symInitialize(hProcess, NULL, TRUE)) {
_decoder_status = helper_init_error;
return;
}
// set pdb search paths
- pfn_SymSetSearchPath _pfn_SymSetSearchPath =
- (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath");
- pfn_SymGetSearchPath _pfn_SymGetSearchPath =
- (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath");
- if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) {
- char paths[MAX_PATH];
- int len = sizeof(paths);
- if (!_pfn_SymGetSearchPath(hProcess, paths, len)) {
- paths[0] = '\0';
- } else {
- // available spaces in path buffer
- len -= (int)strlen(paths);
- }
+ char paths[MAX_PATH];
+ int len = sizeof(paths);
+ if (!WindowsDbgHelp::symGetSearchPath(hProcess, paths, len)) {
+ paths[0] = '\0';
+ } else {
+ // available spaces in path buffer
+ len -= (int)strlen(paths);
+ }
- char tmp_path[MAX_PATH];
- DWORD dwSize;
- HMODULE hJVM = ::GetModuleHandle("jvm.dll");
- tmp_path[0] = '\0';
- // append the path where jvm.dll is located
- if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
- while (dwSize > 0 && tmp_path[dwSize] != '\\') {
- dwSize --;
- }
-
- tmp_path[dwSize] = '\0';
-
- if (dwSize > 0 && len > (int)dwSize + 1) {
- strncat(paths, os::path_separator(), 1);
- strncat(paths, tmp_path, dwSize);
- len -= dwSize + 1;
- }
+ char tmp_path[MAX_PATH];
+ DWORD dwSize;
+ HMODULE hJVM = ::GetModuleHandle("jvm.dll");
+ tmp_path[0] = '\0';
+ // append the path where jvm.dll is located
+ if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
+ while (dwSize > 0 && tmp_path[dwSize] != '\\') {
+ dwSize --;
}
- // append $JRE/bin. Arguments::get_java_home actually returns $JRE
- // path
- char *p = Arguments::get_java_home();
- assert(p != NULL, "empty java home");
- size_t java_home_len = strlen(p);
- if (len > (int)java_home_len + 5) {
+ tmp_path[dwSize] = '\0';
+
+ if (dwSize > 0 && len > (int)dwSize + 1) {
strncat(paths, os::path_separator(), 1);
- strncat(paths, p, java_home_len);
- strncat(paths, "\\bin", 4);
- len -= (int)(java_home_len + 5);
+ strncat(paths, tmp_path, dwSize);
+ len -= dwSize + 1;
}
+ }
- // append $JDK/bin path if it exists
- assert(java_home_len < MAX_PATH, "Invalid path length");
- // assume $JRE is under $JDK, construct $JDK/bin path and
- // see if it exists or not
- if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
- strncpy(tmp_path, p, java_home_len - 3);
- tmp_path[java_home_len - 3] = '\0';
- strncat(tmp_path, "bin", 3);
+ // append $JRE/bin. Arguments::get_java_home actually returns $JRE
+ // path
+ char *p = Arguments::get_java_home();
+ assert(p != NULL, "empty java home");
+ size_t java_home_len = strlen(p);
+ if (len > (int)java_home_len + 5) {
+ strncat(paths, os::path_separator(), 1);
+ strncat(paths, p, java_home_len);
+ strncat(paths, "\\bin", 4);
+ len -= (int)(java_home_len + 5);
+ }
- // if the directory exists
- DWORD dwAttrib = GetFileAttributes(tmp_path);
- if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
- (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
- // tmp_path should have the same length as java_home_len, since we only
- // replaced 'jre' with 'bin'
- if (len > (int)java_home_len + 1) {
- strncat(paths, os::path_separator(), 1);
- strncat(paths, tmp_path, java_home_len);
- }
+ // append $JDK/bin path if it exists
+ assert(java_home_len < MAX_PATH, "Invalid path length");
+ // assume $JRE is under $JDK, construct $JDK/bin path and
+ // see if it exists or not
+ if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
+ strncpy(tmp_path, p, java_home_len - 3);
+ tmp_path[java_home_len - 3] = '\0';
+ strncat(tmp_path, "bin", 3);
+
+ // if the directory exists
+ DWORD dwAttrib = GetFileAttributes(tmp_path);
+ if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
+ (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
+ // tmp_path should have the same length as java_home_len, since we only
+ // replaced 'jre' with 'bin'
+ if (len > (int)java_home_len + 1) {
+ strncat(paths, os::path_separator(), 1);
+ strncat(paths, tmp_path, java_home_len);
}
}
-
- _pfn_SymSetSearchPath(hProcess, paths);
}
- // find out if jvm.dll contains private symbols, by decoding
- // current function and comparing the result
- address addr = (address)Decoder::demangle;
- char buf[MAX_PATH];
- if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
- _can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
- }
+ WindowsDbgHelp::symSetSearchPath(hProcess, paths);
+
+ // find out if jvm.dll contains private symbols, by decoding
+ // current function and comparing the result
+ address addr = (address)Decoder::demangle;
+ char buf[MAX_PATH];
+ if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
+ _can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
+ }
}
}
-void WindowsDecoder::uninitialize() {
- _pfnSymGetSymFromAddr64 = NULL;
- _pfnUndecorateSymbolName = NULL;
-#ifdef AMD64
- _pfnStackWalk64 = NULL;
- _pfnSymFunctionTableAccess64 = NULL;
- _pfnSymGetModuleBase64 = NULL;
-#endif
- if (_dbghelp_handle != NULL) {
- ::FreeLibrary(_dbghelp_handle);
- }
- _dbghelp_handle = NULL;
-}
+void WindowsDecoder::uninitialize() {}
bool WindowsDecoder::can_decode_C_frame_in_vm() const {
return (!has_error() && _can_decode_in_vm);
@@ -188,14 +127,14 @@
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) {
- if (_pfnSymGetSymFromAddr64 != NULL) {
+ if (!has_error()) {
PIMAGEHLP_SYMBOL64 pSymbol;
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
DWORD64 displacement;
- if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
+ if (WindowsDbgHelp::symGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
if (buf != NULL) {
if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) {
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
@@ -211,69 +150,9 @@
}
bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
- return _pfnUndecorateSymbolName != NULL &&
- _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
-}
-
-#ifdef AMD64
-BOOL WindowsDbgHelp::StackWalk64(DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME64 StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) {
- DecoderLocker locker;
- WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
-
- if (!wd->has_error() && wd->_pfnStackWalk64) {
- return wd->_pfnStackWalk64(MachineType,
- hProcess,
- hThread,
- StackFrame,
- ContextRecord,
- ReadMemoryRoutine,
- FunctionTableAccessRoutine,
- GetModuleBaseRoutine,
- TranslateAddress);
- } else {
- return false;
+ if (!has_error()) {
+ return WindowsDbgHelp::unDecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE) > 0;
}
+ return false;
}
-PVOID WindowsDbgHelp::SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
- DecoderLocker locker;
- WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
-
- if (!wd->has_error() && wd->_pfnSymFunctionTableAccess64) {
- return wd->_pfnSymFunctionTableAccess64(hProcess, AddrBase);
- } else {
- return NULL;
- }
-}
-
-pfn_SymFunctionTableAccess64 WindowsDbgHelp::pfnSymFunctionTableAccess64() {
- DecoderLocker locker;
- WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
-
- if (!wd->has_error()) {
- return wd->_pfnSymFunctionTableAccess64;
- } else {
- return NULL;
- }
-}
-
-pfn_SymGetModuleBase64 WindowsDbgHelp::pfnSymGetModuleBase64() {
- DecoderLocker locker;
- WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
-
- if (!wd->has_error()) {
- return wd->_pfnSymGetModuleBase64;
- } else {
- return NULL;
- }
-}
-
-#endif // AMD64
--- a/hotspot/src/os/windows/vm/decoder_windows.hpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/os/windows/vm/decoder_windows.hpp Mon Aug 28 23:46:22 2017 +0000
@@ -25,33 +25,8 @@
#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP
#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP
-#include <windows.h>
-#include <imagehlp.h>
-
#include "utilities/decoder.hpp"
-// functions needed for decoding symbols
-typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
-typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
-typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
-typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
-typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
-typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
-
-#ifdef AMD64
-typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME64 StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
-typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
-typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);
-#endif
-
class WindowsDecoder : public AbstractDecoder {
public:
@@ -70,38 +45,8 @@
void initialize();
void uninitialize();
-private:
- HMODULE _dbghelp_handle;
bool _can_decode_in_vm;
- pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
- pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
-#ifdef AMD64
- pfn_StackWalk64 _pfnStackWalk64;
- pfn_SymFunctionTableAccess64 _pfnSymFunctionTableAccess64;
- pfn_SymGetModuleBase64 _pfnSymGetModuleBase64;
- friend class WindowsDbgHelp;
-#endif
};
-#ifdef AMD64
-// TODO: refactor and move the handling of dbghelp.dll outside of Decoder
-class WindowsDbgHelp : public Decoder {
-public:
- static BOOL StackWalk64(DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME64 StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
- static PVOID SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
-
- static pfn_SymFunctionTableAccess64 pfnSymFunctionTableAccess64();
- static pfn_SymGetModuleBase64 pfnSymGetModuleBase64();
-};
-#endif
-
#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP
--- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -74,6 +74,8 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
+#include "windbghelp.hpp"
+
#ifdef _DEBUG
#include <crtdbg.h>
@@ -1009,7 +1011,6 @@
}
void os::abort(bool dump_core, void* siginfo, const void* context) {
- HINSTANCE dbghelp;
EXCEPTION_POINTERS ep;
MINIDUMP_EXCEPTION_INFORMATION mei;
MINIDUMP_EXCEPTION_INFORMATION* pmei;
@@ -1026,28 +1027,6 @@
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
- dbghelp = os::win32::load_Windows_dll("DBGHELP.DLL", NULL, 0);
-
- if (dbghelp == NULL) {
- jio_fprintf(stderr, "Failed to load dbghelp.dll\n");
- CloseHandle(dumpFile);
- win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
- }
-
- _MiniDumpWriteDump =
- CAST_TO_FN_PTR(BOOL(WINAPI *)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
- PMINIDUMP_EXCEPTION_INFORMATION,
- PMINIDUMP_USER_STREAM_INFORMATION,
- PMINIDUMP_CALLBACK_INFORMATION),
- GetProcAddress(dbghelp,
- "MiniDumpWriteDump"));
-
- if (_MiniDumpWriteDump == NULL) {
- jio_fprintf(stderr, "Failed to find MiniDumpWriteDump() in module dbghelp.dll.\n");
- CloseHandle(dumpFile);
- win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
- }
-
dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |
MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules);
@@ -1064,8 +1043,8 @@
// Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
// the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
- if (_MiniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) == false &&
- _MiniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL) == false) {
+ if (!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) &&
+ !WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL)) {
jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());
}
CloseHandle(dumpFile);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/vm/windbghelp.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "utilities/ostream.hpp"
+#include "windbghelp.hpp"
+
+#include <windows.h>
+
+typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
+typedef DWORD (WINAPI *pfn_SymGetOptions)(void);
+typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
+typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
+typedef DWORD (WINAPI *pfn_UnDecorateSymbolName)(const char*, char*, DWORD, DWORD);
+typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
+typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
+typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME64 StackFrame,
+ PVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
+typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
+typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);
+typedef BOOL (WINAPI *pfn_MiniDumpWriteDump) (HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
+ MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+typedef BOOL (WINAPI *pfn_SymGetLineFromAddr64) (HANDLE hProcess, DWORD64 dwAddr,
+ PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);
+typedef LPAPI_VERSION (WINAPI *pfn_ImagehlpApiVersion)(void);
+
+// Add functions as needed.
+#define FOR_ALL_FUNCTIONS(DO) \
+ DO(ImagehlpApiVersion) \
+ DO(SymGetOptions) \
+ DO(SymSetOptions) \
+ DO(SymInitialize) \
+ DO(SymGetSymFromAddr64) \
+ DO(UnDecorateSymbolName) \
+ DO(SymSetSearchPath) \
+ DO(SymGetSearchPath) \
+ DO(StackWalk64) \
+ DO(SymFunctionTableAccess64) \
+ DO(SymGetModuleBase64) \
+ DO(MiniDumpWriteDump) \
+ DO(SymGetLineFromAddr64)
+
+
+#define DECLARE_FUNCTION_POINTER(functionname) \
+static pfn_##functionname g_pfn_##functionname;
+
+FOR_ALL_FUNCTIONS(DECLARE_FUNCTION_POINTER)
+
+
+static HMODULE g_dll_handle = NULL;
+static DWORD g_dll_load_error = 0;
+static API_VERSION g_version = { 0, 0, 0, 0 };
+
+static enum {
+ state_uninitialized = 0,
+ state_ready = 1,
+ state_error = 2
+} g_state = state_uninitialized;
+
+static void initialize() {
+
+ assert(g_state == state_uninitialized, "wrong sequence");
+ g_state = state_error;
+
+ g_dll_handle = ::LoadLibrary("DBGHELP.DLL");
+ if (g_dll_handle == NULL) {
+ g_dll_load_error = ::GetLastError();
+ } else {
+ // Note: We loaded the DLL successfully. From here on we count
+ // initialization as success. We still may fail to load all of the
+ // desired function pointers successfully, but DLL may still be usable
+ // enough for our purposes.
+ g_state = state_ready;
+
+#define DO_RESOLVE(functionname) \
+ g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);
+
+ FOR_ALL_FUNCTIONS(DO_RESOLVE)
+
+ // Retrieve version information.
+ if (g_pfn_ImagehlpApiVersion) {
+ const API_VERSION* p = g_pfn_ImagehlpApiVersion();
+ memcpy(&g_version, p, sizeof(API_VERSION));
+ }
+ }
+
+}
+
+///////////////////// External functions //////////////////////////
+
+// All outside facing functions are synchronized. Also, we run
+// initialization on first touch.
+
+
+// Call InitializeCriticalSection as early as possible.
+class CritSect {
+ CRITICAL_SECTION cs;
+public:
+ CritSect() { ::InitializeCriticalSection(&cs); }
+ void enter() { ::EnterCriticalSection(&cs); }
+ void leave() { ::LeaveCriticalSection(&cs); }
+};
+
+static CritSect g_cs;
+
+class EntryGuard {
+public:
+ EntryGuard() {
+ g_cs.enter();
+ if (g_state == state_uninitialized) {
+ initialize();
+ }
+ }
+ ~EntryGuard() {
+ g_cs.leave();
+ }
+};
+
+DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymSetOptions != NULL) {
+ return g_pfn_SymSetOptions(arg);
+ }
+ return 0;
+}
+
+DWORD WindowsDbgHelp::symGetOptions(void) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymGetOptions != NULL) {
+ return g_pfn_SymGetOptions();
+ }
+ return 0;
+}
+
+BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymInitialize != NULL) {
+ return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
+ }
+ return FALSE;
+}
+
+BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,
+ PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymGetSymFromAddr64 != NULL) {
+ return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);
+ }
+ return FALSE;
+}
+
+DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,
+ DWORD UndecoratedLength, DWORD Flags) {
+ EntryGuard entry_guard;
+ if (g_pfn_UnDecorateSymbolName != NULL) {
+ return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);
+ }
+ if (UnDecoratedName != NULL && UndecoratedLength > 0) {
+ UnDecoratedName[0] = '\0';
+ }
+ return 0;
+}
+
+BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymSetSearchPath != NULL) {
+ return g_pfn_SymSetSearchPath(hProcess, SearchPath);
+ }
+ return FALSE;
+}
+
+BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymGetSearchPath != NULL) {
+ return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
+ }
+ return FALSE;
+}
+
+BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME64 StackFrame,
+ PVOID ContextRecord) {
+ EntryGuard entry_guard;
+ if (g_pfn_StackWalk64 != NULL) {
+ return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,
+ ContextRecord,
+ NULL, // ReadMemoryRoutine
+ g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,
+ g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine
+ NULL // TranslateAddressRoutine
+ );
+ }
+ return FALSE;
+}
+
+PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymFunctionTableAccess64 != NULL) {
+ return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);
+ }
+ return NULL;
+}
+
+DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymGetModuleBase64 != NULL) {
+ return g_pfn_SymGetModuleBase64(hProcess, dwAddr);
+ }
+ return 0;
+}
+
+BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
+ MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
+ EntryGuard entry_guard;
+ if (g_pfn_MiniDumpWriteDump != NULL) {
+ return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,
+ ExceptionParam, UserStreamParam, CallbackParam);
+ }
+ return FALSE;
+}
+
+BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
+ PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {
+ EntryGuard entry_guard;
+ if (g_pfn_SymGetLineFromAddr64 != NULL) {
+ return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);
+ }
+ return FALSE;
+}
+
+// Print one liner describing state (if library loaded, which functions are
+// missing - if any, and the dbhelp API version)
+void WindowsDbgHelp::print_state_on(outputStream* st) {
+ // Note: We should not lock while printing, but this should be
+ // safe to do without lock anyway.
+ st->print("dbghelp: ");
+
+ if (g_state == state_uninitialized) {
+ st->print("uninitialized.");
+ } else if (g_state == state_error) {
+ st->print("loading error: %u", g_dll_load_error);
+ } else {
+ st->print("loaded successfully ");
+
+ // We may want to print dll file name here - which may be interesting for
+ // cases where more than one version exists on the system, e.g. with a
+ // debugging sdk separately installed. But we get the file name in the DLL
+ // section of the hs-err file too, so this may be redundant.
+
+ // Print version.
+ st->print("- version: %u.%u.%u",
+ g_version.MajorVersion, g_version.MinorVersion, g_version.Revision);
+
+ // Print any functions which failed to load.
+ int num_missing = 0;
+ st->print(" - missing functions: ");
+
+ #define CHECK_AND_PRINT_IF_NULL(functionname) \
+ if (g_pfn_##functionname == NULL) { \
+ st->print("%s" #functionname, ((num_missing > 0) ? ", " : "")); \
+ num_missing ++; \
+ }
+
+ FOR_ALL_FUNCTIONS(CHECK_AND_PRINT_IF_NULL)
+
+ if (num_missing == 0) {
+ st->print("none");
+ }
+ }
+ st->cr();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/vm/windbghelp.hpp Mon Aug 28 23:46:22 2017 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_WINDOWS_VM_DBGHELPLOADER_HPP
+#define OS_WINDOWS_VM_DBGHELPLOADER_HPP
+
+#include <windows.h>
+#include <imagehlp.h>
+
+// This is a very plain wrapper for loading dbghelp.dll. It does not offer
+// any additional functionality. It takes care of locking.
+
+class outputStream;
+
+// Please note: dbghelp.dll may not have been loaded, or it may have been loaded but not
+// all functions may be available (because on the target system dbghelp.dll is of an
+// older version).
+// In all these cases we return an error from the WindowsDbgHelp::symXXXX() wrapper. We never
+// assert. It should always be safe to call these functions, but caller has to process the
+// return code (which he would have to do anyway).
+namespace WindowsDbgHelp {
+
+ DWORD symSetOptions(DWORD);
+ DWORD symGetOptions(void);
+ BOOL symInitialize(HANDLE, PCTSTR, BOOL);
+ BOOL symGetSymFromAddr64(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
+ DWORD unDecorateSymbolName(const char*, char*, DWORD, DWORD);
+ BOOL symSetSearchPath(HANDLE, PCTSTR);
+ BOOL symGetSearchPath(HANDLE, PTSTR, int);
+ BOOL stackWalk64(DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME64 StackFrame,
+ PVOID ContextRecord);
+ PVOID symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
+ DWORD64 symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr);
+ BOOL miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
+ MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+ BOOL symGetLineFromAddr64 (HANDLE hProcess, DWORD64 dwAddr,
+ PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);
+
+ // Print one liner describing state (if library loaded, which functions are
+ // missing - if any, and the dbhelp API version)
+ void print_state_on(outputStream* st);
+
+};
+
+
+#endif // OS_WINDOWS_VM_DBGHELPLOADER_HPP
+
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -29,7 +29,6 @@
#include "classfile/vmSymbols.hpp"
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
-#include "decoder_windows.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm_windows.h"
#include "memory/allocation.inline.hpp"
@@ -51,10 +50,12 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
+#include "unwind_windows_x86.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
+#include "windbghelp.hpp"
-# include "unwind_windows_x86.hpp"
+
#undef REG_SP
#undef REG_FP
#undef REG_PC
@@ -401,24 +402,18 @@
lastpc = pc;
}
- PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
+ PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
if (!p) {
// StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
break;
}
- BOOL result = WindowsDbgHelp::StackWalk64(
+ BOOL result = WindowsDbgHelp::stackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
- &ctx, // __inout PVOID ContextRecord,
- NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
- WindowsDbgHelp::pfnSymFunctionTableAccess64(),
- // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
- WindowsDbgHelp::pfnSymGetModuleBase64(),
- // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
- NULL); // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
+ &ctx); // __inout PVOID ContextRecord,
if (!result) {
break;
--- a/hotspot/src/share/vm/utilities/decoder.cpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/share/vm/utilities/decoder.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
#if defined(_WINDOWS)
#include "decoder_windows.hpp"
+ #include "windbghelp.hpp"
#elif defined(__APPLE__)
#include "decoder_machO.hpp"
#elif defined(AIX)
@@ -162,3 +163,9 @@
_shared_decoder = &_do_nothing_decoder;
}
+void Decoder::print_state_on(outputStream* st) {
+#ifdef _WINDOWS
+ WindowsDbgHelp::print_state_on(st);
+#endif
+}
+
--- a/hotspot/src/share/vm/utilities/decoder.hpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/share/vm/utilities/decoder.hpp Mon Aug 28 23:46:22 2017 +0000
@@ -29,6 +29,7 @@
#include "memory/allocation.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
+#include "utilities/ostream.hpp"
class AbstractDecoder : public CHeapObj<mtInternal> {
public:
@@ -41,7 +42,6 @@
out_of_memory, // out of memory
file_invalid, // invalid elf file
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
- helper_not_found, // could not load dbghelp.dll (Windows only)
helper_func_error, // decoding functions not found (Windows only)
helper_init_error // SymInitialize failed (Windows only)
};
@@ -117,6 +117,9 @@
// shutdown shared instance
static void shutdown();
+
+ static void print_state_on(outputStream* st);
+
protected:
// shared decoder instance, _shared_instance_lock is needed
static AbstractDecoder* get_shared_instance();
--- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Aug 28 22:45:56 2017 +0000
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Aug 28 23:46:22 2017 +0000
@@ -890,6 +890,13 @@
st->cr();
}
+ STEP("printing native decoder state")
+
+ if (_verbose) {
+ Decoder::print_state_on(st);
+ st->cr();
+ }
+
STEP("printing VM options")
if (_verbose) {