Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
57a2f1cf
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
57a2f1cf
编写于
9月 06, 2013
作者:
I
iklam
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8022335: Native stack walk while generating hs_err does not work on Windows x64
Summary: Use WinDbg API StackWalk64() Reviewed-by: zgu, dholmes
上级
49535140
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
275 addition
and
7 deletion
+275
-7
src/os/windows/vm/decoder_windows.cpp
src/os/windows/vm/decoder_windows.cpp
+86
-5
src/os/windows/vm/decoder_windows.hpp
src/os/windows/vm/decoder_windows.hpp
+41
-0
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
+92
-0
src/os_cpu/windows_x86/vm/os_windows_x86.hpp
src/os_cpu/windows_x86/vm/os_windows_x86.hpp
+6
-0
src/share/vm/runtime/frame.cpp
src/share/vm/runtime/frame.cpp
+1
-1
src/share/vm/runtime/frame.hpp
src/share/vm/runtime/frame.hpp
+1
-0
src/share/vm/runtime/os.hpp
src/share/vm/runtime/os.hpp
+8
-0
src/share/vm/utilities/decoder.cpp
src/share/vm/utilities/decoder.cpp
+17
-1
src/share/vm/utilities/decoder.hpp
src/share/vm/utilities/decoder.hpp
+14
-0
src/share/vm/utilities/vmError.cpp
src/share/vm/utilities/vmError.cpp
+5
-0
src/share/vm/utilities/vmError.hpp
src/share/vm/utilities/vmError.hpp
+4
-0
未找到文件。
src/os/windows/vm/decoder_windows.cpp
浏览文件 @
57a2f1cf
...
...
@@ -32,7 +32,11 @@ WindowsDecoder::WindowsDecoder() {
_can_decode_in_vm
=
false
;
_pfnSymGetSymFromAddr64
=
NULL
;
_pfnUndecorateSymbolName
=
NULL
;
#ifdef AMD64
_pfnStackWalk64
=
NULL
;
_pfnSymFunctionTableAccess64
=
NULL
;
_pfnSymGetModuleBase64
=
NULL
;
#endif
_decoder_status
=
no_error
;
initialize
();
}
...
...
@@ -53,14 +57,24 @@ void WindowsDecoder::initialize() {
_pfnUndecorateSymbolName
=
(
pfn_UndecorateSymbolName
)
::
GetProcAddress
(
handle
,
"UnDecorateSymbolName"
);
if
(
_pfnSymSetOptions
==
NULL
||
_pfnSymInitialize
==
NULL
||
_pfnSymGetSymFromAddr64
==
NULL
)
{
_pfnSymGetSymFromAddr64
=
NULL
;
_pfnUndecorateSymbolName
=
NULL
;
::
FreeLibrary
(
handle
);
_dbghelp_handle
=
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
HANDLE
hProcess
=
::
GetCurrentProcess
();
_pfnSymSetOptions
(
SYMOPT_UNDNAME
|
SYMOPT_DEFERRED_LOADS
|
SYMOPT_EXACT_SYMBOLS
);
if
(
!
_pfnSymInitialize
(
hProcess
,
NULL
,
TRUE
))
{
...
...
@@ -156,6 +170,11 @@ void WindowsDecoder::initialize() {
void
WindowsDecoder
::
uninitialize
()
{
_pfnSymGetSymFromAddr64
=
NULL
;
_pfnUndecorateSymbolName
=
NULL
;
#ifdef AMD64
_pfnStackWalk64
=
NULL
;
_pfnSymFunctionTableAccess64
=
NULL
;
_pfnSymGetModuleBase64
=
NULL
;
#endif
if
(
_dbghelp_handle
!=
NULL
)
{
::
FreeLibrary
(
_dbghelp_handle
);
}
...
...
@@ -195,3 +214,65 @@ bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
_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
src/os/windows/vm/decoder_windows.hpp
浏览文件 @
57a2f1cf
...
...
@@ -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_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:
...
...
@@ -61,7 +75,34 @@ private:
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
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
浏览文件 @
57a2f1cf
...
...
@@ -29,6 +29,7 @@
#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"
...
...
@@ -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
;
#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
,
intptr_t
**
ret_sp
,
intptr_t
**
ret_fp
)
{
...
...
@@ -401,6 +490,9 @@ frame os::current_frame() {
StubRoutines
::
x86
::
get_previous_fp_entry
());
if
(
func
==
NULL
)
return
frame
();
intptr_t
*
fp
=
(
*
func
)();
if
(
fp
==
NULL
)
{
return
frame
();
}
#else
intptr_t
*
fp
=
_get_previous_fp
();
#endif // AMD64
...
...
src/os_cpu/windows_x86/vm/os_windows_x86.hpp
浏览文件 @
57a2f1cf
...
...
@@ -62,4 +62,10 @@
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
src/share/vm/runtime/frame.cpp
浏览文件 @
57a2f1cf
...
...
@@ -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.
// Otherwise, it's likely a bug in the native library that the Java code calls,
// 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
bool
in_vm
=
os
::
address_is_in_vm
(
pc
);
st
->
print
(
in_vm
?
"V"
:
"C"
);
...
...
src/share/vm/runtime/frame.hpp
浏览文件 @
57a2f1cf
...
...
@@ -406,6 +406,7 @@ class frame VALUE_OBJ_CLASS_SPEC {
void
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
;
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
void
describe
(
FrameValues
&
values
,
int
frame_no
);
...
...
src/share/vm/runtime/os.hpp
浏览文件 @
57a2f1cf
...
...
@@ -795,6 +795,14 @@ class os: AllStatic {
#endif
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)
static
bool
find
(
address
pc
,
outputStream
*
st
=
tty
);
// OS specific function to make sense out of an address
...
...
src/share/vm/utilities/decoder.cpp
浏览文件 @
57a2f1cf
...
...
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "prims/jvm.h"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "utilities/decoder.hpp"
#include "utilities/vmError.hpp"
...
...
@@ -80,6 +79,23 @@ AbstractDecoder* Decoder::create_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
)
{
assert
(
_shared_decoder_lock
!=
NULL
,
"Just check"
);
bool
error_handling_thread
=
os
::
current_thread_id
()
==
VMError
::
first_error_tid
;
...
...
src/share/vm/utilities/decoder.hpp
浏览文件 @
57a2f1cf
...
...
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
class
AbstractDecoder
:
public
CHeapObj
<
mtInternal
>
{
public:
...
...
@@ -124,6 +125,19 @@ private:
protected:
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
src/share/vm/utilities/vmError.cpp
浏览文件 @
57a2f1cf
...
...
@@ -574,6 +574,10 @@ void VMError::report(outputStream* st) {
STEP
(
120
,
"(printing native stack)"
)
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
)
:
os
::
current_frame
();
...
...
@@ -604,6 +608,7 @@ void VMError::report(outputStream* st) {
st
->
cr
();
}
}
}
STEP
(
130
,
"(printing Java stack)"
)
...
...
src/share/vm/utilities/vmError.hpp
浏览文件 @
57a2f1cf
...
...
@@ -136,6 +136,10 @@ public:
// check to see if fatal error reporting is in progress
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
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录