[llvm-dev] OpenJDK8 failed to work after compiled by LLVM 8 for X86
Leslie Zhai via llvm-dev
llvm-dev at lists.llvm.org
Wed Sep 12 04:55:54 PDT 2018
Hi Martin,
Thanks for your response!
在 2018年09月12日 19:47, Martin Buchholz 写道:
> I tend to think that clang's optimization was valid, and if placing
> data into .rodata has any value at all (why else does .rodata exist?)
placing data into .rodata is *not* wrong! But it needs to double check
the setter of isReadOnly() if condition in the
llvm/lib/Analysis/MemoryDependenceAnalysis.cpp and
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Thanks,
Leslie Zhai
> then the optimization is valuable.
>
> On Wed, Sep 12, 2018 at 4:10 AM, Leslie Zhai <zhaixiang at loongson.cn> wrote:
>> Reported https://bugs.llvm.org/show_bug.cgi?id=38911
>>
>> Thanks,
>>
>> Leslie Zhai
>>
>>
>>
>> 在 2018年09月11日 16:55, Dimitry Andric 写道:
>>> 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, at 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, at object #
>>> @NativeCallStack::EMPTY_STACK
>>> .section .rodata,"a", at 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", at 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 <zhaixiang at 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-dev at 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 (git at github.com:llvm-mirror/clang.git
>>>>>> 81ef98628ebf5186d746c0986dcbf5073e842043)
>>>>>> (git at 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-dev at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>> --
>>>> Regards,
>>>> Leslie Zhai
>>>>
>>>>
>>
More information about the llvm-dev
mailing list