Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make official ChakraCore Linux binaries that work on all currently maintained versions of Linux #3494

Open
cosinusoidally opened this issue Aug 8, 2017 · 9 comments

Comments

@cosinusoidally
Copy link

This is is a follow on from #2278 . The currently available Linux ChakraCore binaries only work on some Linux distros. Ideally they would work on all (currently maintained) Linux distros.

I've put together a rough build system that is capable of generating such binaries (https://github.com/cosinusoidally/ChakraCore-experiments/tree/master/build-chakracore). It does this by generating a CentOS 6 based root filesystem, and building a copy of CMake 3.5.2 and Clang 3.8. It then uses CMake and Clang to build ChakraCore. Unfortunately there are still one or two manual steps since ChakraCore's CMakeFiles do not instruct the compiler to link to librt. I'm sure that would be easy to patch, but my knowledge of CMake is quite limited. My current work around is to manually invoke the compiler with "-lrt" appended to the command line (only 3 or 4 build steps error out, so this isn't too tedious to do).

I also noticed that the binary I built would crash on my Core 2 Duo based system. I was running a simple "Hello World" JavaScript script. The same binary did not crash on a Haswell based system. Any idea why that would be? I am guessing that you may be using SSE 4 instructions? If so, is it possible to build ChakraCore to target only SSE 2?

@digitalinfinity
Copy link
Contributor

@cosinusoidally cool! cc @obastemur since he's our xplat build expert

@cosinusoidally do you have a stack trace for your crash?

@obastemur
Copy link
Collaborator

I understand making ChakraCore binaries available to older distros could be beneficial to some.

Reminder; ChakraCore can be build from source code on older distros. (AFAIK)

Concerns;

  • Are we going to support those distros? That comes with CI changes. Otherwise it will be hard.
  • Are we going to provide bug / security fixes ?
  • That means we will target / embed some older versions of dependencies. We have to update our license / binary release docs and internally start process for these?
  • This is an open source project. If there are parties interested, patches welcome and I'm ready to put my personal time into helping to those patches etc. (as long as they do not break the current targets). Do we have to make this official ? (read the list above again)
  • We have some other targets (x86, arm64 etc.) with IMHO bigger priorities.

@cosinusoidally
Copy link
Author

@digitalinfinity stack trace for official Linux x86_64 binary from here: https://github.com/Microsoft/ChakraCore/releases/tag/v1.7.0

This is running on a T5300 Core 2 Duo, see below flags from /proc/cpuinfo:

flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm 

gdb session:

ljw@ubuntu:~/Desktop$ ./ch
Illegal instruction
ljw@ubuntu:~/Desktop$ gdb ./ch
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./ch...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/ljw/Desktop/ch
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff70d2700 (LWP 1201)]

Program received signal SIGILL, Illegal instruction.
0x000055555568aae3 in _GLOBAL__sub_I_RecyclerHeuristic.cpp ()
(gdb) bt
#0  0x000055555568aae3 in _GLOBAL__sub_I_RecyclerHeuristic.cpp ()
#1  0x0000555555f5aa9d in __libc_csu_init ()
#2  0x00007ffff70f4ed5 in __libc_start_main (main=0x5555556abda0 <main>, argc=1, argv=0x7fffffffe238,
    init=0x555555f5aa50 <__libc_csu_init>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fffffffe228)
    at libc-start.c:246
#3  0x00005555556a7b29 in _start ()
(gdb) disassemble
Dump of assembler code for function _GLOBAL__sub_I_RecyclerHeuristic.cpp:
   0x000055555568aa90 <+0>:     push   %rbp
   0x000055555568aa91 <+1>:     mov    %rsp,%rbp
   0x000055555568aa94 <+4>:     push   %rbx
   0x000055555568aa95 <+5>:     sub    $0x18,%rsp
   0x000055555568aa99 <+9>:     mov    $0x55,%edi
   0x000055555568aa9e <+14>:    callq  0x5555556893d0 <sysconf@plt>
   0x000055555568aaa3 <+19>:    mov    %rax,%rbx
   0x000055555568aaa6 <+22>:    mov    $0x1e,%edi
   0x000055555568aaab <+27>:    callq  0x5555556893d0 <sysconf@plt>
   0x000055555568aab0 <+32>:    imul   %rbx,%rax
   0x000055555568aab4 <+36>:    movq   %rax,%xmm0
   0x000055555568aab9 <+41>:    test   %rax,%rax
   0x000055555568aabc <+44>:    je     0x55555568aaea <_GLOBAL__sub_I_RecyclerHeuristic.cpp+90>
   0x000055555568aabe <+46>:    mov    $0x56,%edi
   0x000055555568aac3 <+51>:    movdqa %xmm0,-0x20(%rbp)
   0x000055555568aac8 <+56>:    callq  0x5555556893d0 <sysconf@plt>
   0x000055555568aacd <+61>:    mov    %rax,%rbx
   0x000055555568aad0 <+64>:    mov    $0x1e,%edi
   0x000055555568aad5 <+69>:    callq  0x5555556893d0 <sysconf@plt>
   0x000055555568aada <+74>:    movdqa -0x20(%rbp),%xmm0
   0x000055555568aadf <+79>:    imul   %rbx,%rax
=> 0x000055555568aae3 <+83>:    pinsrq $0x1,%rax,%xmm0
   0x000055555568aaea <+90>:    movq   %xmm0,%rax
   0x000055555568aaef <+95>:    cmp    $0x20000000,%rax
   0x000055555568aaf5 <+101>:   ja     0x55555568ab12 <_GLOBAL__sub_I_RecyclerHeuristic.cpp+130>
   0x000055555568aaf7 <+103>:   mov    0x25eb97d(%rip),%cl        # 0x555557c7647a <_ZN14AutoSystemInfo4DataE+634>
   0x000055555568aafd <+109>:   test   %cl,%cl
   0x000055555568aaff <+111>:   je     0x55555568ab12 <_GLOBAL__sub_I_RecyclerHeuristic.cpp+130>
   0x000055555568ab01 <+113>:   mov    $0x20,%edx
   0x000055555568ab06 <+118>:   mov    $0x1000,%ecx
   0x000055555568ab0b <+123>:   mov    $0x10,%eax
   0x000055555568ab10 <+128>:   jmp    0x55555568ab3a <_GLOBAL__sub_I_RecyclerHeuristic.cpp+170>
   0x000055555568ab12 <+130>:   cmp    $0x40000001,%rax
   0x000055555568ab18 <+136>:   mov    $0x40,%esi
   0x000055555568ab1d <+141>:   mov    $0xc0,%eax
   0x000055555568ab22 <+146>:   cmovb  %esi,%eax
   0x000055555568ab25 <+149>:   mov    $0x4000,%edx
   0x000055555568ab2a <+154>:   mov    $0x20000,%ecx
   0x000055555568ab2f <+159>:   cmovb  %edx,%ecx
   0x000055555568ab32 <+162>:   mov    $0x100,%edx
   0x000055555568ab37 <+167>:   cmovb  %esi,%edx
   0x000055555568ab3a <+170>:   mov    %ecx,0x25f4f60(%rip)        # 0x555557c7faa0 <_ZN6Memory17RecyclerHeuristic8InstanceE.7>
   0x000055555568ab40 <+176>:   mov    %edx,0x25f4f52(%rip)        # 0x555557c7fa98 <_ZN6Memory17RecyclerHeuristic8InstanceE.6>
   0x000055555568ab46 <+182>:   mov    %eax,%ecx
   0x000055555568ab48 <+184>:   shl    $0x14,%ecx
   0x000055555568ab4b <+187>:   mov    %ecx,0x25f4f1f(%rip)        # 0x555557c7fa70 <_ZN6Memory17RecyclerHeuristic8InstanceE.0>
---Type <return> to continue, or q <return> to quit---q
Quit

The crash above is on the pinsrq instruction, which is a SSE 4.1 instruction according to https://en.wikipedia.org/wiki/SSE4

Similarly my binary also crashes, but with my binary you actually need to run some js code first (I think it is because the version of ch I have built will dlopen libChakraCore.so, and so will not crash until after it has opened libChakraCore.so ):

ljw@ubuntu:~/src/build-ch-artif/centos6-root/root/release$ ls
a.js  ch  libChakraCore.so
ljw@ubuntu:~/src/build-ch-artif/centos6-root/root/release$ ./ch

Usage: ch [-v|-version] [-h|-help|-?] <source file>
Note: [flaglist] is not supported in Release builds; try a Debug or Test build to enable these flags.
        -v|-version             Displays version info
        -h|-help|-?             Displays this help message
ljw@ubuntu:~/src/build-ch-artif/centos6-root/root/release$ ./ch a.js
hello world
Illegal instruction
ljw@ubuntu:~/src/build-ch-artif/centos6-root/root/release$ gdb ./ch
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./ch...(no debugging symbols found)...done.
(gdb) run a.js
Starting program: /home/ljw/src/build-ch-artif/centos6-root/root/release/ch a.js
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6bc6700 (LWP 1296)]
[New Thread 0x7ffff55f2700 (LWP 1297)]
[New Thread 0x7ff7effff700 (LWP 1298)]
[New Thread 0x7ff7ef7fe700 (LWP 1299)]
hello world

Program received signal SIGILL, Illegal instruction.
0x00007ffff59a7904 in Memory::Recycler::AbortConcurrent(bool) ()
   from /home/ljw/src/build-ch-artif/centos6-root/root/release/libChakraCore.so
(gdb) bt
#0  0x00007ffff59a7904 in Memory::Recycler::AbortConcurrent(bool) ()
   from /home/ljw/src/build-ch-artif/centos6-root/root/release/libChakraCore.so
#1  0x00007ffff59a7a6a in Memory::Recycler::FinalizeConcurrent(bool) ()
   from /home/ljw/src/build-ch-artif/centos6-root/root/release/libChakraCore.so
#2  0x00007ffff5798371 in JsDisposeRuntime () from /home/ljw/src/build-ch-artif/centos6-root/root/release/libChakraCore.so
#3  0x000055555555c216 in ExecuteTest(char const*) ()
#4  0x000055555555c835 in main ()
(gdb) disassemble
Dump of assembler code for function _ZN6Memory8Recycler15AbortConcurrentEb:
   0x00007ffff59a78e0 <+0>:     push   %rbp
   0x00007ffff59a78e1 <+1>:     mov    %rsp,%rbp
   0x00007ffff59a78e4 <+4>:     push   %r15
   0x00007ffff59a78e6 <+6>:     push   %r14
   0x00007ffff59a78e8 <+8>:     push   %r12
   0x00007ffff59a78ea <+10>:    push   %rbx
   0x00007ffff59a78eb <+11>:    sub    $0x10,%rsp
   0x00007ffff59a78ef <+15>:    mov    %esi,%r15d
   0x00007ffff59a78f2 <+18>:    mov    %rdi,%r12
   0x00007ffff59a78f5 <+21>:    movdqu 0xb40(%r12),%xmm0
   0x00007ffff59a78ff <+31>:    movdqa %xmm0,-0x30(%rbp)
=> 0x00007ffff59a7904 <+36>:    pextrq $0x1,%xmm0,%rdi
   0x00007ffff59a790b <+43>:    cmp    $0x1,%rdi
   0x00007ffff59a790f <+47>:    mov    $0x1,%ebx
   0x00007ffff59a7914 <+52>:    sbb    $0xffffffff,%ebx
   0x00007ffff59a7917 <+55>:    mov    $0x1,%r14b
   0x00007ffff59a791a <+58>:    testb  $0x20,0x3e9(%r12)
   0x00007ffff59a7923 <+67>:    je     0x7ffff59a7a38 <_ZN6Memory8Recycler15AbortConcurrentEb+344>
   0x00007ffff59a7929 <+73>:    movb   $0x1,0xbc4(%r12)
   0x00007ffff59a7932 <+82>:    test   %rdi,%rdi
   0x00007ffff59a7935 <+85>:    je     0x7ffff59a793e <_ZN6Memory8Recycler15AbortConcurrentEb+94>
   0x00007ffff59a7937 <+87>:    xor    %esi,%esi
   0x00007ffff59a7939 <+89>:    callq  0x7ffff578f170 <SetThreadPriority>
   0x00007ffff59a793e <+94>:    lea    -0x30(%rbp),%rsi
   0x00007ffff59a7942 <+98>:    xor    %edx,%edx
   0x00007ffff59a7944 <+100>:   mov    $0xffffffff,%ecx
   0x00007ffff59a7949 <+105>:   xor    %r8d,%r8d
   0x00007ffff59a794c <+108>:   mov    %ebx,%edi
   0x00007ffff59a794e <+110>:   callq  0x7ffff5789ac0 <WaitForMultipleObjectsEx>
   0x00007ffff59a7953 <+115>:   mov    %eax,%ebx
   0x00007ffff59a7955 <+117>:   movb   $0x0,0xbc4(%r12)
   0x00007ffff59a795e <+126>:   test   %ebx,%ebx
   0x00007ffff59a7960 <+128>:   jne    0x7ffff59a798f <_ZN6Memory8Recycler15AbortConcurrentEb+175>
   0x00007ffff59a7962 <+130>:   xor    $0x1,%r15b
   0x00007ffff59a7966 <+134>:   jne    0x7ffff59a798f <_ZN6Memory8Recycler15AbortConcurrentEb+175>
   0x00007ffff59a7968 <+136>:   mov    0x3e8(%r12),%eax
   0x00007ffff59a7970 <+144>:   cmp    $0xa002,%eax
   0x00007ffff59a7975 <+149>:   je     0x7ffff59a79b1 <_ZN6Memory8Recycler15AbortConcurrentEb+209>
   0x00007ffff59a7977 <+151>:   cmp    $0xa001,%eax
   0x00007ffff59a797c <+156>:   jne    0x7ffff59a7a38 <_ZN6Memory8Recycler15AbortConcurrentEb+344>
   0x00007ffff59a7982 <+162>:   mov    %r12,%rdi
   0x00007ffff59a7985 <+165>:   callq  0x7ffff59a40e0 <_ZN6Memory8Recycler24ResetMarkCollectionStateEv>
   0x00007ffff59a798a <+170>:   jmpq   0x7ffff59a7a38 <_ZN6Memory8Recycler15AbortConcurrentEb+344>
   0x00007ffff59a798f <+175>:   mov    %r12,%rdi
   0x00007ffff59a7992 <+178>:   callq  0x7ffff59a3eb0 <_ZN6Memory8Recycler20CleanupPendingUnrootEv>
   0x00007ffff59a7997 <+183>:   add    $0x480,%r12
---Type <return> to continue, or q <return> to quit---q

The a.js sample program just runs print("Hello world"); . Again this is crashing on a SSE 4.1 instruction (pextrq in this case). I assume the cuprit is this: https://github.com/Microsoft/ChakraCore/blob/v1.7.0/CMakeLists.txt#L156

@obastemur
Copy link
Collaborator

Were you creating this binary on Core 2 Duo system ?

@obastemur
Copy link
Collaborator

I assume the cuprit is this: https://github.com/Microsoft/ChakraCore/blob/v1.7.0/CMakeLists.txt#L156

We could add a feature detection for given instruction yet if you were compiling on another machine with support to SSE 4.1, the result wouldn't be different. Optionally, we may add a build time argument for target arch compatibility level.

i.e --custom-cpu-argument:<argument(s) here> to build.sh. Would you like to send a PR?

@cosinusoidally
Copy link
Author

Were you creating this binary on Core 2 Duo system ?

Yep, though the resultant binary works fine on machines with SSE 4.1 and 4.2 support, it will not work on the Core 2 Duo machine. This makes sense as it appears that the CMakeLists.txt is instructing clang to generate SSE 4.2 code.

i.e --custom-cpu-argument:<argument(s) here> to build.sh. Would you like to send a PR?

I'll try and build a SSE2 copy of ChakraCore next week and let you know how I get on. If possible I will try and create a PR.

@obastemur
Copy link
Collaborator

@cosinusoidally any update on this?

@cosinusoidally
Copy link
Author

@obastemur proof of concept for the 1.7.x series is here https://github.com/cosinusoidally/ChakraCore-experiments/tree/master/build-chakracore . In that version I disable the -msse4.2 flag and remove any SSE > 2 intrinsics, I think the general solution is to remove the -msse4.2 flag and then write inline assembler versions of any required intrinsics. I've got a couple of spare hours today so I'll give that a go on master.

cosinusoidally added a commit to cosinusoidally/ChakraCore that referenced this issue Nov 15, 2017
@cosinusoidally
Copy link
Author

@obastemur See commit cosinusoidally@055784b . I think the inline assembler will need some review by someone more knowledgeable than me. It seems to work and passes the test suite on a SSE4.2 based system and my old SSE2 only based system (but I am not 100% confident that my asm constraints are correct). I created inline assembly versions of all the required intrinsics (called simd_*). The reason to use inline asm rather than __attribute__ target is that only the inline assembler versions of the functions will get inlined (__attribute__ target versions of the functions are also included, but commented out).

There is also the question as to where the implemented intrisics should go. In my patch I simply put them in the files where they are required. In theory they should be inline functions insider a header somewhere. I'm not sure where the best place would be.

@MikeHolman MikeHolman modified the milestones: vNext, Backlog May 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants