Undefined behaviour in hotspot
Omair Majid
omajid at redhat.com
Mon Apr 21 15:19:56 UTC 2014
Hi,
I recently tried to build OpenJDK on i686 using a prerelease version of GCC
4.9. It turns out that new optimizations have been enabled in GCC which now
cause hotspot to break in a few places where hotspot relies on undefined
behaviour.
$ uname -a
Linux rawhide 3.15.0-0.rc1.git1.1.fc21.i686+PAE #1 SMP Tue Apr 15 14:40:42 UTC 2014 i686 i686 i386 GNU/Linux
$ gcc --version
gcc (GCC) 4.9.0 20140411 (Red Hat 4.9.0-0.10)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
A `java -version` is sufficient to trigger a crash:
$ ./build/images/j2sdk-image/bin/java -version
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0xb637a10e, pid=1014, tid=3053837120
#
# JRE version: (8.0_05-b13) (build )
# Java VM: OpenJDK Server VM (25.5-b02-fastdebug mixed mode linux-x86 )
# Problematic frame:
# V [libjvm.so+0x31c10e] Assembler::push(RegisterImpl*)+0x4e
#
# Failed to write core dump. Core dumps have been disabled. To enable
# core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/omajid/java-1.8.0-openjdk/hs_err_pid1014.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
#
The above report is from jdk8u5b13 (also, [1]), but this is reproducible on
jdk8-b132 [2] and jdk7u [3] as well.
Following the advice posted here [4], I built OpenJDK8 with
"-fsanitize=undefined" which pointed out:
/home/omajid/java-1.8.0-openjdk/java-1.8.0-openjdk/jdk8/hotspot/src/share/vm/code/relocInfo.hpp:855:24: runtime error: load of null pointer of type '<unknown> *'
/home/omajid/java-1.8.0-openjdk/java-1.8.0-openjdk/jdk8/hotspot/src/share/vm/asm/codeBuffer.hpp:181:51: runtime error: member access within null pointer of type 'struct CodeSection'
==15676==ERROR: SanitizerTool failed to allocate 0x200000 (2097152) bytes of SizeClassAllocator32: 12
==15676==Process memory map follows:
0x00100000-0x00200000
(snip)
0xbff8f000-0xbffb0000 [stack]
==15676==End of process memory map.
==15676==Sanitizer CHECK failed: ../../../../libsanitizer/sanitizer_common/sanitizer_posix.cc:66 (("unable to mmap" && 0)) != (0) (0, 0)
I ran through the code with gdb. Please ignore the java-abrt executable name:
on Fedora, jre/bin/java-abrt is the original jre/bin/java and jre/bin/java is a
shell script that runs jre/bin/java-abrt with additional options.
(gdb) r -version
Starting program: /home/omajid/java-1.8.0-openjdk/java-1.8.0-openjdk/jdk8/build/jdk8.build/images/j2sdk-image/jre/bin/java-abrt -version
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
[New Thread 0xb689bb40 (LWP 15144)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb689bb40 (LWP 15144)]
0xb6bb810e in Assembler::push (this=0xb689ae14, src=0x0)
at /home/omajid/java-1.8.0-openjdk/java-1.8.0-openjdk/jdk8/hotspot/src/cpu/x86/vm/assembler_x86.cpp:2580
2580 emit_int8(0x50 | encode);
(gdb) l
2575 }
2576
2577 void Assembler::push(Register src) {
2578 int encode = prefix_and_encode(src->encoding());
2579
2580 emit_int8(0x50 | encode);
2581 }
2582
2583 void Assembler::pushf() {
2584 emit_int8((unsigned char)0x9C);
(gdb) p encode
$1 = <optimized out>
(gdb) p src
$2 = (Register) 0x0
Dereferencing a NULL pointer is undefined behaviour in C++ [5] and it seems
perfectly acceptable for a compiler to compile hotspot in a way so that it ends
up not working.
If I disable optimizations done by the compiler (using slowdebug), then the
built copy of hotspot works correctly. Both fastdebug and release (which keep
compiler optimizations enabled) result in builds that crash when run.
Obviously, I would like to get hotspot to work correctly when compiled against
GCC 4.9. But I believe the micro-optimizations made to use the address of the
object instead of using a field in the object is to save space and I would
rather not blindly undo it. Does anyone here have any advice on what the best
course of action there is?
Thanks,
Omair
[1] http://kojipkgs.fedoraproject.org//work/tasks/4320/6744320/build.log
[2] http://kojipkgs.fedoraproject.org//work/tasks/6501/6746501/build.log
[3] http://kojipkgs.fedoraproject.org//work/tasks/5509/6755509/build.log
[4] https://lists.fedoraproject.org/pipermail/devel/2014-April/197741.html
[5] http://stackoverflow.com/questions/2474018/
--
PGP Key: 66484681 (http://pgp.mit.edu/)
Fingerprint = F072 555B 0A17 3957 4E95 0056 F286 F14F 6648 4681
More information about the hotspot-dev
mailing list