[llvm-dev] OpenJDK8 failed to work after compiled by LLVM 8 for X86
Martin Buchholz via llvm-dev
llvm-dev at lists.llvm.org
Wed Sep 12 04:47:28 PDT 2018
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?)
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