See http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2013-September/009131.html
src/os_cpu/windows_x86/vm/os_windows_x86.cpp:
frame os::current_frame() {
#ifdef AMD64
// apparently _asm not supported on windows amd64
typedef intptr_t* get_fp_func ();
get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry());
if (func == NULL) return frame();
intptr_t* fp = (*func)();
#else
...
The code in get_previous_fp_entry() assumes the we have a frame pointer register (which is not always true), and RBP is that register (which is not always true). In some cases, especially when the C stack is shallow (e.g., when using -XX:ErrorHandlerTest=9), RBP can actually be NULL, because is has never been used by any of the C functions.
It turns out we also have the same problem in here:
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
CONTEXT* uc = (CONTEXT*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC((address)uc->REG_PC);
if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP;
if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP;
} else {
// construct empty ExtendedPC for return value checking
epc = ExtendedPC(NULL);
if (ret_sp) *ret_sp = (intptr_t *)NULL;
if (ret_fp) *ret_fp = (intptr_t *)NULL;
}
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
There is no guarantee that "fp" would be related to "sp" in any way. It could be NULL, or could be just garbage.
So the use of os::current_frame() and os::fetch_frame_from_context(_context) is simply wrong on Win/x64. We haven't got much problem because most of the use is in debug code:
ps() in debug.cpp
oop::register_oop()
src/os_cpu/windows_x86/vm/os_windows_x86.cpp:
frame os::current_frame() {
#ifdef AMD64
// apparently _asm not supported on windows amd64
typedef intptr_t* get_fp_func ();
get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry());
if (func == NULL) return frame();
intptr_t* fp = (*func)();
#else
...
The code in get_previous_fp_entry() assumes the we have a frame pointer register (which is not always true), and RBP is that register (which is not always true). In some cases, especially when the C stack is shallow (e.g., when using -XX:ErrorHandlerTest=9), RBP can actually be NULL, because is has never been used by any of the C functions.
It turns out we also have the same problem in here:
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
CONTEXT* uc = (CONTEXT*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC((address)uc->REG_PC);
if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP;
if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP;
} else {
// construct empty ExtendedPC for return value checking
epc = ExtendedPC(NULL);
if (ret_sp) *ret_sp = (intptr_t *)NULL;
if (ret_fp) *ret_fp = (intptr_t *)NULL;
}
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
There is no guarantee that "fp" would be related to "sp" in any way. It could be NULL, or could be just garbage.
So the use of os::current_frame() and os::fetch_frame_from_context(_context) is simply wrong on Win/x64. We haven't got much problem because most of the use is in debug code:
ps() in debug.cpp
oop::register_oop()
- relates to
-
JDK-8022335 Native stack walk while generating hs_err does not work on Windows x64
- Closed
-
JDK-8025569 -XX:+CheckUnhandledOops crashes on Windows
- Closed
-
JDK-8024363 Native stack printing on Win/x64 cannot print the Java frames
- Closed