RFR (S) 8022335 - (round 2) Native stack walk on Windows x64

Volker Simonis volker.simonis at gmail.com
Fri Aug 30 07:32:27 PDT 2013


On Fri, Aug 30, 2013 at 12:37 AM, Ioi Lam <ioi.lam at oracle.com> wrote:
> Please review this fix:
>
> http://cr.openjdk.java.net/~iklam/8022335/win64_stack_walk_002/
>
> Bug: Native stack walk while generating hs_err does not work on Windows
x64
>
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8022335
>     https://bugs.openjdk.java.net/browse/JDK-8022335
>
> What's new:
>
>     The code is much more simplified than my last version. All interesting
>     code is in a single function -- os::platform_print_native_stack
>     in os_windows_x86.cpp. The rest is just busy work.
>
> Summary of fix:
>
>     Windows x64 binaries are built (unconditionally) with the equivalent
of
>     -fomit-frame-pointer,

Why do you think so? If I'm looking at the build logs and
make/windows/makefiles/compile.make I see that we always compile with '/O2
/Oy-' which according to
http://msdn.microsoft.com/en-us/library/2kxx5t2c%28v=vs.100%29.aspx means
'disable frame-pointer omission'. So according to that documentation, we
should have frame pointers in all functions.

Actually '/Oy-' was introduced in order to get better native stack traces
with http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6655385
Doesn’t it help or are there any other additional problem?

Currently I get the following in the hs_err file on Windows for a Java
program which crashes in Unsafe:

# JRE version: OpenJDK Runtime Environment (8.0) (build
1.8.0-internal-fastdebug-_2013_08_29_21_12-b00)
# Java VM: OpenJDK 64-Bit Server VM (25.0-b45-fastdebug mixed mode
windows-amd64 compressed oops)
# Problematic frame:
# V  [jvm.dll+0x28c7a7]
...
*Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native
code)
V  [jvm.dll+0x28c7a7]
J  Crash.crashIt(Lsun/misc/Unsafe;I)V @ 0x0000000008e9b19c
[0x0000000008e9b140+92]
v  ~StubRoutines::call_stub
V  [jvm.dll+0x2c961a]
*
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  sun.misc.Unsafe.putAddress(JJ)V+0
J  Crash.crashIt(Lsun/misc/Unsafe;I)V @ 0x0000000008e9b19c
[0x0000000008e9b140+92]
j  Crash.doIt()V+45
v  ~StubRoutines::call_stub
j
 sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j
 sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j
 sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j
 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+56
j  Crash.main([Ljava/lang/String;)V+32
v  ~StubRoutines::call_stub


On Linux, the same crashing program produces the following output in the
hs_err file:

# JRE version: OpenJDK Runtime Environment (8.0) (build
1.8.0-internal-jvmtests_2013_08_29_20_14-b00)
# Java VM: OpenJDK 64-Bit Server VM (25.0-b45 mixed mode linux-amd64
compressed oops)
# Problematic frame:
# V  [libjvm.so+0x9b4ba7]  Unsafe_SetNativeAddress+0xa7
...
*Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native
code)
V  [libjvm.so+0x9b4ba7]  Unsafe_SetNativeAddress+0xa7
j  sun.misc.Unsafe.putAddress(JJ)V+0
J  Crash.crashIt(Lsun/misc/Unsafe;I)V @ 0x00007f0b4d0f2c9c
[0x00007f0b4d0f2b80+284]
v  ~StubRoutines::call_stub
V  [libjvm.so+0x6174ee]  JavaCalls::call_helper(JavaValue*, methodHandle*,
JavaCallArguments*, Thread*)+0x104e
V  [libjvm.so+0x8c2e12]  Reflection::invoke(instanceKlassHandle,
methodHandle, Handle, bool, objArrayHandle, BasicType, objArrayHandle,
bool, Thread*)+0x5e2
V  [libjvm.so+0x8c63e7]  Reflection::invoke_method(oopDesc*, Handle,
objArrayHandle, Thread*)+0x147
V  [libjvm.so+0x66dd8e]  JVM_InvokeMethod+0x25e
j
 sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j
 sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j
 sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j
 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+56
j  Crash.main([Ljava/lang/String;)V+32
v  ~StubRoutines::call_stub
V  [libjvm.so+0x6174ee]  JavaCalls::call_helper(JavaValue*, methodHandle*,
JavaCallArguments*, Thread*)+0x104e
V  [libjvm.so+0x631226]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*,
JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)+0x346
V  [libjvm.so+0x63b98a]  jni_CallStaticVoidMethod+0x17a
C  [libjli.so+0x75ed]  JavaMain+0x83d*

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  sun.misc.Unsafe.putAddress(JJ)V+0
J  Crash.crashIt(Lsun/misc/Unsafe;I)V @ 0x00007f0b4d0f2c9c
[0x00007f0b4d0f2b80+284]
j  Crash.doIt()V+45
v  ~StubRoutines::call_stub
j
 sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j
 sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j
 sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j
 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+56
j  Crash.main([Ljava/lang/String;)V+32
v  ~StubRoutines::call_stub

So while the native (i.e. "mixed") stack trace is still much more accurate
on Linux, it isn't just a single line as you wrote. Maybe we could work on
improving this situation on Windows without a separate Windows stack
tracing routine or are there any fundamental problems which prevent this?

>     so HotSpot's build-in native stack walking code
>     will fail to find the sender frame. As a result, hs_err on Windows/x64
>     will always list a single frame.
>
>     I have added the os::platform_print_native_stack() function for
>     Windows/x64 only. It uses the StackWalk64 API to walk the stace.
>
>     Because the Win/x64 frame layout is very different than what HotSpot
> expects,
>     I decided to implement os::platform_print_native_stack() as a
completely
>     stand-alone function, and do not interact with the existing "frame"
C++
> class.
>     See comments in os_windows_x86.cpp for details.
>
> Deficiency of fix:
>
>     StackWalk64 knows nothing about the Java frames. So hs_err will
display
> only
>     the native frames, and stop as soon as the first Java frame is
reached.
> It will
>     also NOT display any native frames below Java frames.
>
>     Printing the Java frames *may* be possible. However, at this point, I
> want
>     to keep the code simple and crash proof. I will file a different bug
for
>     printing the Java frames.
>
> Bonus:
>
>     As a side-fix, I refactored a bunch of duplicated code in decoder.cpp
> into
>     the DecoderLocker class.
>

I would really appreciate if you could do this in a separate change. I
think it is commonly agreed upon that "small unrelated fixes" (like
comments, white-space changes or single line fixes) may go into another
change but these changes are in IMHO big enough to justify a different bug
ID and change set.

> Tests:
>
>     JPRT
>     UTE (vm.runtime.testlist, vm.quick.testlist,
> vm.parallel_class_loading.testlist)
>
>     I also manually inserted some crashes into jvm.dll and verified that
the
>     native stack trace is printed as expected on Win/x64.
>

Maybe you can use/extend the WhiteBox API to write some good tests?

>
> Thanks
> - Ioi
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/attachments/20130830/26fbf9b8/attachment-0001.html 


More information about the hotspot-runtime-dev mailing list