mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 03:24:38 +02:00
8022335: Native stack walk while generating hs_err does not work on Windows x64
Use WinDbg API StackWalk64() Reviewed-by: zgu, dholmes
This commit is contained in:
parent
34d47bd672
commit
1c2a7eea85
11 changed files with 275 additions and 7 deletions
|
@ -32,7 +32,11 @@ WindowsDecoder::WindowsDecoder() {
|
||||||
_can_decode_in_vm = false;
|
_can_decode_in_vm = false;
|
||||||
_pfnSymGetSymFromAddr64 = NULL;
|
_pfnSymGetSymFromAddr64 = NULL;
|
||||||
_pfnUndecorateSymbolName = NULL;
|
_pfnUndecorateSymbolName = NULL;
|
||||||
|
#ifdef AMD64
|
||||||
|
_pfnStackWalk64 = NULL;
|
||||||
|
_pfnSymFunctionTableAccess64 = NULL;
|
||||||
|
_pfnSymGetModuleBase64 = NULL;
|
||||||
|
#endif
|
||||||
_decoder_status = no_error;
|
_decoder_status = no_error;
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
@ -53,14 +57,24 @@ void WindowsDecoder::initialize() {
|
||||||
_pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
|
_pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
|
||||||
|
|
||||||
if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
|
if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
|
||||||
_pfnSymGetSymFromAddr64 = NULL;
|
uninitialize();
|
||||||
_pfnUndecorateSymbolName = NULL;
|
|
||||||
::FreeLibrary(handle);
|
|
||||||
_dbghelp_handle = NULL;
|
|
||||||
_decoder_status = helper_func_error;
|
_decoder_status = helper_func_error;
|
||||||
return;
|
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
|
||||||
|
|
||||||
HANDLE hProcess = ::GetCurrentProcess();
|
HANDLE hProcess = ::GetCurrentProcess();
|
||||||
_pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
|
_pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
|
||||||
if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
|
if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
|
||||||
|
@ -156,6 +170,11 @@ void WindowsDecoder::initialize() {
|
||||||
void WindowsDecoder::uninitialize() {
|
void WindowsDecoder::uninitialize() {
|
||||||
_pfnSymGetSymFromAddr64 = NULL;
|
_pfnSymGetSymFromAddr64 = NULL;
|
||||||
_pfnUndecorateSymbolName = NULL;
|
_pfnUndecorateSymbolName = NULL;
|
||||||
|
#ifdef AMD64
|
||||||
|
_pfnStackWalk64 = NULL;
|
||||||
|
_pfnSymFunctionTableAccess64 = NULL;
|
||||||
|
_pfnSymGetModuleBase64 = NULL;
|
||||||
|
#endif
|
||||||
if (_dbghelp_handle != NULL) {
|
if (_dbghelp_handle != NULL) {
|
||||||
::FreeLibrary(_dbghelp_handle);
|
::FreeLibrary(_dbghelp_handle);
|
||||||
}
|
}
|
||||||
|
@ -195,3 +214,65 @@ bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||||
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -38,6 +38,20 @@ typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWOR
|
||||||
typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
|
typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
|
||||||
typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
|
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 {
|
class WindowsDecoder : public AbstractDecoder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -61,7 +75,34 @@ private:
|
||||||
bool _can_decode_in_vm;
|
bool _can_decode_in_vm;
|
||||||
pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
||||||
pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
|
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
|
#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
|
#include "decoder_windows.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "jvm_windows.h"
|
#include "jvm_windows.h"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
@ -327,6 +328,94 @@ add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap
|
||||||
|
|
||||||
cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
|
cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
|
||||||
|
|
||||||
|
#ifdef AMD64
|
||||||
|
/*
|
||||||
|
* Windows/x64 does not use stack frames the way expected by Java:
|
||||||
|
* [1] in most cases, there is no frame pointer. All locals are addressed via RSP
|
||||||
|
* [2] in rare cases, when alloca() is used, a frame pointer is used, but this may
|
||||||
|
* not be RBP.
|
||||||
|
* See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
|
||||||
|
*
|
||||||
|
* So it's not possible to print the native stack using the
|
||||||
|
* while (...) {... fr = os::get_sender_for_C_frame(&fr); }
|
||||||
|
* loop in vmError.cpp. We need to roll our own loop.
|
||||||
|
*/
|
||||||
|
bool os::platform_print_native_stack(outputStream* st, void* context,
|
||||||
|
char *buf, int buf_size)
|
||||||
|
{
|
||||||
|
CONTEXT ctx;
|
||||||
|
if (context != NULL) {
|
||||||
|
memcpy(&ctx, context, sizeof(ctx));
|
||||||
|
} else {
|
||||||
|
RtlCaptureContext(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
||||||
|
|
||||||
|
STACKFRAME stk;
|
||||||
|
memset(&stk, 0, sizeof(stk));
|
||||||
|
stk.AddrStack.Offset = ctx.Rsp;
|
||||||
|
stk.AddrStack.Mode = AddrModeFlat;
|
||||||
|
stk.AddrFrame.Offset = ctx.Rbp;
|
||||||
|
stk.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
stk.AddrPC.Offset = ctx.Rip;
|
||||||
|
stk.AddrPC.Mode = AddrModeFlat;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
address lastpc = 0;
|
||||||
|
while (count++ < StackPrintLimit) {
|
||||||
|
intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;
|
||||||
|
intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
|
||||||
|
address pc = (address)stk.AddrPC.Offset;
|
||||||
|
|
||||||
|
if (pc != NULL && sp != NULL && fp != NULL) {
|
||||||
|
if (count == 2 && lastpc == pc) {
|
||||||
|
// Skip it -- StackWalk64() may return the same PC
|
||||||
|
// (but different SP) on the first try.
|
||||||
|
} else {
|
||||||
|
// Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame
|
||||||
|
// may not contain what Java expects, and may cause the frame() constructor
|
||||||
|
// to crash. Let's just print out the symbolic address.
|
||||||
|
frame::print_C_frame(st, buf, buf_size, pc);
|
||||||
|
st->cr();
|
||||||
|
}
|
||||||
|
lastpc = pc;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
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
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > StackPrintLimit) {
|
||||||
|
st->print_cr("...<more frames>...");
|
||||||
|
}
|
||||||
|
st->cr();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // AMD64
|
||||||
|
|
||||||
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
|
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
|
||||||
intptr_t** ret_sp, intptr_t** ret_fp) {
|
intptr_t** ret_sp, intptr_t** ret_fp) {
|
||||||
|
|
||||||
|
@ -401,6 +490,9 @@ frame os::current_frame() {
|
||||||
StubRoutines::x86::get_previous_fp_entry());
|
StubRoutines::x86::get_previous_fp_entry());
|
||||||
if (func == NULL) return frame();
|
if (func == NULL) return frame();
|
||||||
intptr_t* fp = (*func)();
|
intptr_t* fp = (*func)();
|
||||||
|
if (fp == NULL) {
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
intptr_t* fp = _get_previous_fp();
|
intptr_t* fp = _get_previous_fp();
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
|
|
|
@ -62,4 +62,10 @@
|
||||||
|
|
||||||
static bool register_code_area(char *low, char *high);
|
static bool register_code_area(char *low, char *high);
|
||||||
|
|
||||||
|
#ifdef AMD64
|
||||||
|
#define PLATFORM_PRINT_NATIVE_STACK 1
|
||||||
|
static bool platform_print_native_stack(outputStream* st, void* context,
|
||||||
|
char *buf, int buf_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_HPP
|
#endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_HPP
|
||||||
|
|
|
@ -652,7 +652,7 @@ void frame::interpreter_frame_print_on(outputStream* st) const {
|
||||||
// Return whether the frame is in the VM or os indicating a Hotspot problem.
|
// Return whether the frame is in the VM or os indicating a Hotspot problem.
|
||||||
// Otherwise, it's likely a bug in the native library that the Java code calls,
|
// Otherwise, it's likely a bug in the native library that the Java code calls,
|
||||||
// hopefully indicating where to submit bugs.
|
// hopefully indicating where to submit bugs.
|
||||||
static void print_C_frame(outputStream* st, char* buf, int buflen, address pc) {
|
void frame::print_C_frame(outputStream* st, char* buf, int buflen, address pc) {
|
||||||
// C/C++ frame
|
// C/C++ frame
|
||||||
bool in_vm = os::address_is_in_vm(pc);
|
bool in_vm = os::address_is_in_vm(pc);
|
||||||
st->print(in_vm ? "V" : "C");
|
st->print(in_vm ? "V" : "C");
|
||||||
|
|
|
@ -406,6 +406,7 @@ class frame VALUE_OBJ_CLASS_SPEC {
|
||||||
void print_on(outputStream* st) const;
|
void print_on(outputStream* st) const;
|
||||||
void interpreter_frame_print_on(outputStream* st) const;
|
void interpreter_frame_print_on(outputStream* st) const;
|
||||||
void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const;
|
void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const;
|
||||||
|
static void print_C_frame(outputStream* st, char* buf, int buflen, address pc);
|
||||||
|
|
||||||
// Add annotated descriptions of memory locations belonging to this frame to values
|
// Add annotated descriptions of memory locations belonging to this frame to values
|
||||||
void describe(FrameValues& values, int frame_no);
|
void describe(FrameValues& values, int frame_no);
|
||||||
|
|
|
@ -795,6 +795,14 @@ class os: AllStatic {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifndef PLATFORM_PRINT_NATIVE_STACK
|
||||||
|
// No platform-specific code for printing the native stack.
|
||||||
|
static bool platform_print_native_stack(outputStream* st, void* context,
|
||||||
|
char *buf, int buf_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// debugging support (mostly used by debug.cpp but also fatal error handler)
|
// debugging support (mostly used by debug.cpp but also fatal error handler)
|
||||||
static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address
|
static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
#include "runtime/mutexLocker.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder.hpp"
|
||||||
#include "utilities/vmError.hpp"
|
#include "utilities/vmError.hpp"
|
||||||
|
@ -80,6 +79,23 @@ AbstractDecoder* Decoder::create_decoder() {
|
||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool DecoderLocker::is_first_error_thread() {
|
||||||
|
return (os::current_thread_id() == VMError::get_first_error_tid());
|
||||||
|
}
|
||||||
|
|
||||||
|
DecoderLocker::DecoderLocker() :
|
||||||
|
MutexLockerEx(DecoderLocker::is_first_error_thread() ?
|
||||||
|
NULL : Decoder::shared_decoder_lock(), true) {
|
||||||
|
_decoder = is_first_error_thread() ?
|
||||||
|
Decoder::get_error_handler_instance() : Decoder::get_shared_instance();
|
||||||
|
assert(_decoder != NULL, "null decoder");
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex* Decoder::shared_decoder_lock() {
|
||||||
|
assert(_shared_decoder_lock != NULL, "Just check");
|
||||||
|
return _shared_decoder_lock;
|
||||||
|
}
|
||||||
|
|
||||||
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
||||||
assert(_shared_decoder_lock != NULL, "Just check");
|
assert(_shared_decoder_lock != NULL, "Just check");
|
||||||
bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
|
bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "runtime/mutex.hpp"
|
#include "runtime/mutex.hpp"
|
||||||
|
#include "runtime/mutexLocker.hpp"
|
||||||
|
|
||||||
class AbstractDecoder : public CHeapObj<mtInternal> {
|
class AbstractDecoder : public CHeapObj<mtInternal> {
|
||||||
public:
|
public:
|
||||||
|
@ -124,6 +125,19 @@ private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static Mutex* _shared_decoder_lock;
|
static Mutex* _shared_decoder_lock;
|
||||||
|
static Mutex* shared_decoder_lock();
|
||||||
|
|
||||||
|
friend class DecoderLocker;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DecoderLocker : public MutexLockerEx {
|
||||||
|
AbstractDecoder* _decoder;
|
||||||
|
inline bool is_first_error_thread();
|
||||||
|
public:
|
||||||
|
DecoderLocker();
|
||||||
|
AbstractDecoder* decoder() {
|
||||||
|
return _decoder;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_UTILITIES_DECODER_HPP
|
#endif // SHARE_VM_UTILITIES_DECODER_HPP
|
||||||
|
|
|
@ -574,6 +574,10 @@ void VMError::report(outputStream* st) {
|
||||||
STEP(120, "(printing native stack)" )
|
STEP(120, "(printing native stack)" )
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
|
if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
|
||||||
|
// We have printed the native stack in platform-specific code
|
||||||
|
// Windows/x64 needs special handling.
|
||||||
|
} else {
|
||||||
frame fr = _context ? os::fetch_frame_from_context(_context)
|
frame fr = _context ? os::fetch_frame_from_context(_context)
|
||||||
: os::current_frame();
|
: os::current_frame();
|
||||||
|
|
||||||
|
@ -604,6 +608,7 @@ void VMError::report(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
STEP(130, "(printing Java stack)" )
|
STEP(130, "(printing Java stack)" )
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,10 @@ public:
|
||||||
|
|
||||||
// check to see if fatal error reporting is in progress
|
// check to see if fatal error reporting is in progress
|
||||||
static bool fatal_error_in_progress() { return first_error != NULL; }
|
static bool fatal_error_in_progress() { return first_error != NULL; }
|
||||||
|
|
||||||
|
static jlong get_first_error_tid() {
|
||||||
|
return first_error_tid;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_UTILITIES_VMERROR_HPP
|
#endif // SHARE_VM_UTILITIES_VMERROR_HPP
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue