Hi Leslie, The problem really lies in the OpenJDK code, as it is attempting to write to a const object. If this seems to work with certain compiler(s) and optimization settings, it is just luck. :-)
Here is a reduced example, which shows the issue: ====================================================================== #include <new> class NativeCallStack { public: static const NativeCallStack EMPTY_STACK; private: enum { DEPTH = 4 }; void* stack[DEPTH]; public: NativeCallStack() { for (int i = 0; i < DEPTH; ++i) { stack[i] = nullptr; } } }; const NativeCallStack NativeCallStack::EMPTY_STACK; int main(void) { // The following should segfault, if EMPTY_STACK was placed into .rodata. ::new ((void*)&NativeCallStack::EMPTY_STACK) NativeCallStack(); return 0; } ====================================================================== clang 7.0.0 rc2 produces this assembly: .globl main # -- Begin function main .p2align 4, 0x90 .type main,@function main: # @main .cfi_startproc # %bb.0: # %entry pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset %rbp, -16 movq %rsp, %rbp .cfi_def_cfa_register %rbp xorps %xmm0, %xmm0 movups %xmm0, NativeCallStack::EMPTY_STACK+16(%rip) movups %xmm0, NativeCallStack::EMPTY_STACK(%rip) xorl %eax, %eax popq %rbp .cfi_def_cfa %rsp, 8 retq .Lfunc_end0: .size main, .Lfunc_end0-main .cfi_endproc # -- End function .type NativeCallStack::EMPTY_STACK,@object # @NativeCallStack::EMPTY_STACK .section .rodata,"a",@progbits .globl NativeCallStack::EMPTY_STACK .p2align 3 NativeCallStack::EMPTY_STACK: .zero 32 .size NativeCallStack::EMPTY_STACK, 32 The whole constructor has been optimized out, and EMPTY_STACK has been replaced by .zero 32, placed in the .rodata segment, which is a perfectly valid transformation. Then, in main(), an attempt is made to write to that read-only segment, which will usually segfault, depending on how strictly the underlying operating system enforces these protections. In contrast, gcc 8.2.0 produces: .globl main .type main, @function main: .LFB74: .cfi_startproc movq $0, NativeCallStack::EMPTY_STACK(%rip) xorl %eax, %eax movq $0, NativeCallStack::EMPTY_STACK+8(%rip) movq $0, NativeCallStack::EMPTY_STACK+16(%rip) movq $0, NativeCallStack::EMPTY_STACK+24(%rip) ret .cfi_endproc .LFE74: .size main, .-main .p2align 4,,15 .type _GLOBAL__sub_I__ZN15NativeCallStack11EMPTY_STACKE, @function _GLOBAL__sub_I__ZN15NativeCallStack11EMPTY_STACKE: .LFB76: .cfi_startproc movq $0, NativeCallStack::EMPTY_STACK(%rip) movq $0, NativeCallStack::EMPTY_STACK+8(%rip) movq $0, NativeCallStack::EMPTY_STACK+16(%rip) movq $0, NativeCallStack::EMPTY_STACK+24(%rip) ret .cfi_endproc .LFE76: .size _GLOBAL__sub_I__ZN15NativeCallStack11EMPTY_STACKE, .-_GLOBAL__sub_I__ZN15NativeCallStack11EMPTY_STACKE .section .ctors,"aw",@progbits .align 8 .quad _GLOBAL__sub_I__ZN15NativeCallStack11EMPTY_STACKE .globl NativeCallStack::EMPTY_STACK .bss .align 32 .type NativeCallStack::EMPTY_STACK, @object .size NativeCallStack::EMPTY_STACK, 32 NativeCallStack::EMPTY_STACK: .zero 32 Here you can see that gcc decided to not place EMPTY_STACK in .rodata, but in .bss, which is read/write. It adds the global constructor to the .ctors section, so the dynamic linker is made responsible for calling it. Note that now the EMPTY_STACK object is unnecessarily initialized twice, once by the global constructor, and once in main. -Dimitry > On 11 Sep 2018, at 03:38, Leslie Zhai <zhaixi...@loongson.cn> wrote: > > Hi Dimitry, > > Thanks for your kind response! > > Thanks for the commit message of Jung's patch, I found that the bug had been > fixed in OpenJDK 12 by Zhengyu > https://bugs.openjdk.java.net/browse/JDK-8205965 But only backported to 11. > So Jung could backport it for OpenJDK 8, thanks a lot! > > But I argue that the root cause might be in the compiler side, why > clang-3.9.1, gcc-6.4.1 couldn't reproduce the bug? And it might be work for > clang-4.0 https://bugs.openjdk.java.net/browse/JDK-8208494 I will test LLVM > 5 to check out whether or not reproducible. > > > 在 2018年09月11日 00:59, Dimitry Andric 写道: >> Hi Leslie, >> >> This is likely the same problem as was reported in >> https://bugs.freebsd.org/225054#c8, and fixed by the following patch: >> >> https://svnweb.freebsd.org/ports/head/java/openjdk8/files/patch-hotspot_src_share_vm_services_memTracker.cpp?view=markup&pathrev=459368 >> >> Can you please try that out, and see if it fixes it for you too? >> >> -Dimitry >> >>> On 10 Sep 2018, at 18:20, Leslie Zhai via llvm-dev >>> <llvm-...@lists.llvm.org> wrote: >>> >>> Hi all, >>> >>> OpenJDK8 jdk8u-dev[1] is just able to work after compiled with LLVM 3.9.1 >>> for X86: >>> >>> $ ./build/linux-x86_64-normal-server-slowdebug/images/j2sdk-image/bin/java >>> -version >>> openjdk version "1.8.0-internal-debug" >>> OpenJDK Runtime Environment (build >>> 1.8.0-internal-debug-xiangzhai_2018_09_09_21_08-b00) >>> OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode) >>> >>> $ strings >>> ./build/linux-x86_64-normal-server-slowdebug/images/j2sdk-image/bin/java | >>> grep clang >>> clang version 3.9.1 (tags/RELEASE_391/final) >>> >>> But it failed to work after compiled with LLVM 8 for X86: >>> >>> $ ./build/linux-x86_64-normal-server-fastdebug/images/j2sdk-image/bin/java >>> -version >>> Segmentation fault >>> >>> $ gdb --ex run --args >>> ./build/linux-x86_64-normal-server-fastdebug/images/j2sdk-image/bin/java >>> -version >>> GNU gdb (GDB) Fedora 7.12.1-48.fc25 >>> ... >>> Starting program: >>> /home/xiangzhai/project/jdk8u-llvm/build/linux-x86_64-normal-server-fastdebug/images/j2sdk-image/bin/java >>> -version >>> [Thread debugging using libthread_db enabled] >>> Using host libthread_db library "/lib64/libthread_db.so.1". >>> >>> Program received signal SIGSEGV, Segmentation fault. >>> [ Legend: Modified register | Code | Heap | Stack | String ] >>> ───────────────────────────────────────────────────────────────────────────────────────────────[ >>> registers ]──── >>> $rax : 0x0 >>> $rbx : 0x0 >>> $rcx : 0x7ffff7315eb0 → 0x00007ffff6ae30a0 → >>> <NativeCallStack::print_on(outputStream*)+0> xor edx, edx >>> $rdx : 0x0 >>> $rsp : 0x7fffffff9328 → 0x00007ffff6a76822 → >>> <MemTracker::init_tracking_level()+178> mov edi, ebx >>> $rbp : 0x7fffffff93c0 → 0x00007fffffff94f0 → 0x00007fffffff9510 → >>> 0x0000000000000002 >>> $rsi : 0x0 >>> $rdi : 0x7ffff7315e70 → 0x00007ffff7315eb0 → 0x00007ffff6ae30a0 → >>> <NativeCallStack::print_on(outputStream*)+0> xor edx, edx >>> $rip : 0x7ffff6ae2f5b → <NativeCallStack::NativeCallStack(int,+0> >>> mov QWORD PTR [rdi], rcx >>> $r8 : 0x1 >>> $r9 : 0xf >>> $r10 : 0x64 >>> $r11 : 0x0 >>> $r12 : 0x7fffffffdc88 → 0x00007fffffffe04c → >>> "/home/xiangzhai/project/jdk8u-llvm/build/linux-x86[...]" >>> $r13 : 0x7fffffffdca0 → 0x00007fffffffe0bf → "XDG_VTNR=1" >>> $r14 : 0x7fffffff9330 → "NMT_LEVEL_10535" >>> $r15 : 0x6 >>> $eflags: [carry parity adjust zero sign trap INTERRUPT direction overflow >>> RESUME virtualx86 identification] >>> $ss: 0x002b $ds: 0x0000 $cs: 0x0033 $es: 0x0000 $gs: 0x0000 $fs: 0x0000 >>> ───────────────────────────────────────────────────────────────────────────────────────────────────[ >>> stack ]──── >>> 0x00007fffffff9328│+0x00: 0x00007ffff6a76822 → >>> <MemTracker::init_tracking_level()+178> mov edi, ebx ← $rsp >>> 0x00007fffffff9330│+0x08: "NMT_LEVEL_10535" ← $r14 >>> 0x00007fffffff9338│+0x10: 0x0035333530315f4c ("L_10535"?) >>> 0x00007fffffff9340│+0x18: 0x0000000000000001 >>> 0x00007fffffff9348│+0x20: 0x0000000000602190 → 0x00007ffff5eb7000 → >>> 0x00010102464c457f >>> 0x00007fffffff9350│+0x28: 0x0000000000000004 >>> 0x00007fffffff9358│+0x30: 0x000000066474e551 >>> 0x00007fffffff9360│+0x38: 0x0000000000000000 >>> ────────────────────────────────────────────────────────────────────────────────────────[ >>> code:i386:x86-64 ]──── >>> 0x7ffff6ae2f4b <print_owned_locks_on_error(outputStream*)+187> add >>> eax, 0x1f0f00 >>> 0x7ffff6ae2f50 <NativeCallStack::NativeCallStack(int,+0> mov rcx, >>> QWORD PTR [rip+0x842781] # 0x7ffff73256d8 >>> 0x7ffff6ae2f57 <NativeCallStack::NativeCallStack(int,+0> add rcx, 0x10 >>> → 0x7ffff6ae2f5b <NativeCallStack::NativeCallStack(int,+0> mov QWORD >>> PTR [rdi], rcx >>> 0x7ffff6ae2f5e <NativeCallStack::NativeCallStack(int,+0> mov DWORD >>> PTR [rdi+0x28], 0x0 >>> 0x7ffff6ae2f65 <NativeCallStack::NativeCallStack(int,+0> add rdi, 0x8 >>> 0x7ffff6ae2f69 <NativeCallStack::NativeCallStack(int,+0> test edx, edx >>> 0x7ffff6ae2f6b <NativeCallStack::NativeCallStack(int,+0> je >>> 0x7ffff6ae2f7b <NativeCallStack::NativeCallStack(int, bool)+43> >>> 0x7ffff6ae2f6d <NativeCallStack::NativeCallStack(int,+0> mov eax, esi >>> ─────────[ >>> source:/home/xiangzhai/project/jdk8u-llvm/hotspot/src/share/vm/utilities/nativeCallStack.cpp+33 >>> ]──── >>> 28 #include "utilities/nativeCallStack.hpp" >>> 29 >>> 30 const NativeCallStack NativeCallStack::EMPTY_STACK(0, false); >>> 31 >>> 32 NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : >>> → 33 _hash_value(0) { >>> 34 >>> 35 #if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED >>> 36 fillStack = false; >>> 37 #endif >>> 38 >>> ─────────────────────────────────────────────────────────────────────────────────────────────────[ >>> threads ]──── >>> [#0] Id 1, Name: "java", stopped, reason: SIGSEGV >>> ───────────────────────────────────────────────────────────────────────────────────────────────────[ >>> trace ]──── >>> [#0] 0x7ffff6ae2f5b → Name: >>> NativeCallStack::NativeCallStack(this=0x7ffff7315e70 >>> <NativeCallStack::EMPTY_STACK>, toSkip=0x0, fillStack=0x0) >>> [#1] 0x7ffff6a76822 → Name: MemTracker::init_tracking_level() >>> [#2] 0x7ffff62eff49 → Name: MemTracker::tracking_level() >>> [#3] 0x7ffff62eff49 → Name: ResourceObj::operator new(size=0x20, >>> type=ResourceObj::STACK_OR_EMBEDDED, flags=<optimized out>) >>> [#4] 0x7ffff61369ec → Name: _GLOBAL__sub_I_c1_Greedy.cpp() >>> [#5] 0x7ffff7de7d9a → Name: call_init(l=<optimized out>, argc=0x2, >>> argv=0x7fffffffdc88, env=0x7fffffffdca0) >>> [#6] 0x7ffff7de7eab → Name: call_init(env=0x7fffffffdca0, >>> argv=0x7fffffffdc88, argc=0x2, l=<optimized out>) >>> [#7] 0x7ffff7de7eab → Name: _dl_init(main_map=0x602190, argc=0x2, >>> argv=0x7fffffffdc88, env=0x7fffffffdca0) >>> [#8] 0x7ffff7dece46 → Name: dl_open_worker(a=0x7fffffff97e0) >>> [#9] 0x7ffff7de7c44 → Name: _dl_catch_error(objname=0x7fffffff97d0, >>> errstring=0x7fffffff97d8, mallocedp=0x7fffffff97cf, operate=0x7ffff7decae0 >>> <dl_open_worker>, args=0x7fffffff97e0) >>> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────── >>> 0x00007ffff6ae2f5b in NativeCallStack::NativeCallStack (this=0x7ffff7315e70 >>> <NativeCallStack::EMPTY_STACK>, toSkip=0x0, fillStack=0x0) at >>> /home/xiangzhai/project/jdk8u-llvm/hotspot/src/share/vm/utilities/nativeCallStack.cpp:33 >>> 33 _hash_value(0) { >>> gef➤ c >>> Continuing. >>> >>> Program terminated with signal SIGSEGV, Segmentation fault. >>> The program no longer exists. >>> gef➤ >>> >>> ----- 8< -------- 8< -------- 8< -------- 8< -------- 8< -------- 8< --- >>> >>> I started to use and contribute clang static analyzer[2] just for finding >>> the bugs for open source software from LLVM 3.x, perhaps it is a bug of >>> LLVM 8, because jdk8u is just able to print out '-version' after compiled >>> with llvm-3.9.1, I will rebuild the LLVM 8 again, then rebuild jdk8u for >>> triple check. >>> >>> 1. Workaround-compile-with-llvm.patch >>> https://raw.githubusercontent.com/xiangzhai/jdk8u-dev/master/Workaround-compile-with-llvm.patch >>> >>> 2. >>> https://github.com/llvm-mirror/clang/commit/a530e823ed2793ac149de7a984014e242a787682#diff-ff9160d4628cb9b6186559837c2c8668 >>> >>> 3. The build option of LLVM 8 (bootstrap with LLVM 3.9.1): >>> >>> cmake .. -DCMAKE_BUILD_TYPE=Release \ >>> -DCMAKE_C_COMPILER=clang \ >>> -DCMAKE_CXX_COMPILER=clang++ \ >>> -DCMAKE_C_FLAGS="-fPIC" \ >>> -DCMAKE_CXX_FLAGS="-std=c++11 -fPIC" \ >>> -DLLVM_BUILD_LLVM_DYLIB=ON \ >>> -DLLVM_LINK_LLVM_DYLIB=ON \ >>> -DLLVM_INSTALL_UTILS=ON \ >>> -DLLVM_ENABLE_RTTI=ON \ >>> -DLLVM_ENABLE_FFI=ON \ >>> -DLLVM_ENABLE_EH=ON \ >>> -DLLVM_BUILD_TESTS=ON \ >>> -DLLVM_BUILD_DOCS=OFF \ >>> -DLLVM_ENABLE_SPHINX=OFF \ >>> -DLLVM_ENABLE_DOXYGEN=OFF \ >>> -DLLDB_DISABLE_LIBEDIT=1 \ >>> -DSPHINX_WARNINGS_AS_ERRORS=OFF \ >>> -DFFI_INCLUDE_DIR=$(pkg-config --variable=includedir libffi) \ >>> -DFFI_LIBRARY_DIR:PATH="$(pkg-config --variable=libdir libffi)" \ >>> -DLLVM_BINUTILS_INCDIR=/usr/include \ >>> -DLLVM_LIBDIR_SUFFIX=64 \ >>> -DLIBCXX_ENABLE_ABI_LINKER_SCRIPT=ON \ >>> -DLIBUNWIND_ENABLE_SHARED=ON \ >>> -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ >>> -DLLDB_TEST_C_COMPILER=clang \ >>> -DLLDB_TEST_CXX_COMPILER=clang++ \ >>> -DLLVM_DEFAULT_TARGET_TRIPLE="x86_64-redhat-linux" \ >>> -DCLANG_VENDOR="LLVM China" >>> >>> 4. $ clang -v >>> LLVM China clang version 8.0.0 (g...@github.com:llvm-mirror/clang.git >>> 81ef98628ebf5186d746c0986dcbf5073e842043) >>> (g...@github.com:llvm-mirror/llvm.git >>> e1aac9723d55497e74d83d216329f08d9842e494) (based on LLVM 8.0.0svn) >>> Target: x86_64-redhat-linux >>> Thread model: posix >>> InstalledDir: /usr/bin >>> Found candidate GCC installation: >>> /usr/bin/../lib/gcc/i686-redhat-linux/6.4.1 >>> Found candidate GCC installation: >>> /usr/bin/../lib/gcc/x86_64-redhat-linux/6.4.1 >>> Found candidate GCC installation: /usr/lib/gcc/i686-redhat-linux/6.4.1 >>> Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/6.4.1 >>> Selected GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/6.4.1 >>> Candidate multilib: .;@m64 >>> Candidate multilib: 32;@m32 >>> Selected multilib: .;@m64 >>> >>> -- >>> Regards, >>> Leslie Zhai >>> >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-...@lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > -- > Regards, > Leslie Zhai > >