5

I would like to use some of the last features (e.g. generators) of javascript in Node.js, so I download the latest unstable version of Node.js (v0.11.14) and compiled it on my RPi.

But when I try to run it, it throws an Illegal Instruction error, except when I run node --version (which answers v0.11.14).

When I installed the stable version of Node (v0.10.32), I didn't have any problem, and I use the same command lines to build it :

./configure --without-snapshot
make
sudo make install

I read here that it could be a problem with libv8 but I'm not sure this is the same problem because this bug is about Node.js v0.10.26.

Does anybody encounter the same issue ?

For information, I'm using Raspbian.

  • Is it when you run it or when you build it you get the error? Would you consider pasting the full error message? – Bex Oct 23 '14 at 14:06
  • This build is successful, it's when I run it. Unfortunately, the full error message is simply Illegal Instruction. I can paste you the strace of the execution if you want. – Eaque Oct 23 '14 at 15:48
8

This is still an unresolved issue with the newest version of Node (as of this writing, v0.12.2)

When browsing Node distributions, the latest ARM build is in v0.11.9, meaning you will currently need to compile from the source, if you want Node.js v0.12.

The following is only related to compiling from source in Raspbian.

Reason for 'Illegal instruction'

The V8 Javascript engine used by Node, is issuing ARMv7 CPU instructions, while the Raspberry Pi only understands v6 instructions (note: Raspberry Pi 2 uses an ARM v7 processor)

When compiling from source, V8 is compiled as well, and it does not detect and is not told, that the processor is ARMv6, so it is defaulting to ARMv7.

Test node

To test whether this is the reason you are experiencing the 'Illegal instruction' error, run node --v8-options and look at the second line. If it is:

ARMv7=1 VFP3=0 VFP32DREGS=0 NEON=0 SUDIV=0 ...

then the ARMv7=1 hints that V8 is compiled for ARMv7.

Raspberry Pi ARM version

To see which ARM version the processor supports, open /proc/cpuinfo

For Raspberry Pi model B (rev. 2), the model name is ARMv6-compatible processor rev 7 (v6l).

V8 ARM version detection

V8 tries to detect which ARM version to use, but in this case, it does not get it right. The detection happens in deps/v8/src/base/cpu.cc (tip: search for v6l - lowercase L). The area of interest is:

// Unfortunately, it seems that certain ARMv6-based CPUs
// report an incorrect architecture number of 7!
//
// ...
//
// We try to correct this by looking at the 'elf_format'
// field reported by the 'Processor' field, which is of the
// form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
// an ARMv6-one. For example, the Raspberry Pi is one popular
// ARMv6 device that reports architecture 7.
if (architecture_ == 7) {
  char* processor = cpu_info.ExtractField("Processor");
  if (HasListItem(processor, "(v6l)")) {
    architecture_ = 6;
  }
  delete[] processor;
}

( See also V8 cpu.cc )

Even though it tries to detect the v6l string in /proc/cpuinfo, it is looking at the Processor field - but the info is in the model name field - as stated in the Raspberry Pi ARM version section of this post.

Node configure script

The configure script for Node also needs to be edited.

The code is:

  if is_arch_armv7():
    o['variables']['arm_version'] = '7'
  elif is_arch_armv6():
    o['variables']['arm_version'] = '6'
  else:
    o['variables']['arm_version'] = 'default'

  o['variables']['arm_fpu'] = 'vfpv3'  # V8 3.18 no longer supports VFP2.
  o['variables']['arm_neon'] = int(is_arm_neon())
  o['variables']['arm_thumb'] = 0      # -marm
  o['variables']['arm_float_abi'] = arm_float_abi

Assuming vfpv3 seems to make V8 compile to ARMv7, and while the comment says:

# V8 3.18 no longer supports VFP2.

All I could find on the topic, is that V8 3.17 is that last version to support "no-VFPv2", which makes VFPv2 the minimum requirement for V8 3.18+.

Solution

  1. Run make uninstall
  2. Run make clean
  3. Edit the line in deps/v8/src/base/cpu.cc, from
    char* processor = cpu_info.ExtractField("Processor");
    to
    char* processor = cpu_info.ExtractField("model name");
    An even better solution would probably be to add a whole new check for model name, instead of replacing the Processor check.
  4. Edit the Node configure script, from
  if is_arch_armv7():
    o['variables']['arm_version'] = '7'
  elif is_arch_armv6():
    o['variables']['arm_version'] = '6'
  else:
    o['variables']['arm_version'] = 'default'

  o['variables']['arm_fpu'] = 'vfpv3'  # V8 3.18 no longer supports VFP2.
  o['variables']['arm_neon'] = int(is_arm_neon())
  o['variables']['arm_thumb'] = 0      # -marm
  o['variables']['arm_float_abi'] = arm_float_abi

to

  
  if is_arch_armv7():
    o['variables']['arm_fpu'] = 'vfpv3'
    o['variables']['arm_neon'] = int(is_arm_neon())
    o['variables']['arm_version'] = '7'
  else:
    o['variables']['arm_fpu'] = 'vfpv2'
    o['variables']['arm_neon'] = 0
    o['variables']['arm_version'] = '6' if is_arch_armv6() else 'default'

  o['variables']['arm_thumb'] = 0      # -marm
  o['variables']['arm_float_abi'] = arm_float_abi
  1. Run ./configure --without-snapshot
  2. Run make
  3. Run make install
  4. Verify that node --v8-options has ARMv7=0
  5. Run make test to verify that the Node tests succeed.

Attribution and notes

  • Many of the details in this post, are gathered from the identical io.js issue #283
  • When running make test, I got 770 passed and 18 failed. The failures were mainly due to timeouts, which probably occurs because of limited resources on a Raspberry Pi.
  • I successfully ran a small Node.js application on a Raspberry Pi, using this solution. However, I cannot guarantee that all functionality of Node will work.
2

After some research, I'm not the only one concerned :

Currently, there is an open issue on the Node.js github.

The field containing the model name has been moved is the last versions of raspian. Thus, when v8 tries to scan the field to get the ARM version, it does not find it and assumes that it's ARMV7 by default.

  • 2
    So, Whats the solution? – Waqas Feb 22 '15 at 2:20
1

Something with your build. The Illegal Instruction message usually means that you have some binary which has invalid CPU instruction.

That could be for various reasons. For example, but not limited to:

  • Your compilation generated broken binary for your platform
  • Your system has bad binary from different architecture (not armv6h) which it is trying to run
  • Your source code of Node.js has a bug (for example, integer overflow) which causes memory corruption and leads to Illegal Instruction
1

Node.js does have a history of dependence on x86 architecture. I have not researched this extensively, but I have had similar issues in the past, probably having to do with endianess.

There is a special node.js for raspberry pi arm_hf. See if that one works better: http://weworkweplay.com/play/raspberry-pi-nodejs/

  • Thank you for your answer. I tried the trick suggested in your post but it did not work. I looked at the special Node.js, but it's the v10 (the actual running node on my RPi) and I'm looking for the v11. – Eaque Oct 28 '14 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.