Search code examples
androidc++assemblyandroid-ndkarm

SIGILL in Android NDK code


I have an NDK app out on market and got a native crash report about a SIGILL signal. (I use google breakpad to generate native crash reports.) Here are the details:

  • My app is compiled for armeabi-v7a, with NEON support.
  • It crashed on a NVIDIA Tegra 2 Processor, which is ARM-7 (Cortex-A9).
  • It happens every time. (contacted the user)
  • The crash address was at 0x399cc, the signal was SIGILL, and it's in my code.

Registers and disassembly:

 r4 = 0x001d50f0    r5 = 0x001d50f0    r6 = 0x598e2a3c    r7 = 0x00000000
 r8 = 0x00000001    r9 = 0x001c22b0   r10 = 0x00000000    fp = 0x81216264
 sp = 0x598e2a18    lr = 0x816399cb    pc = 0x816399cc

0x000399c6 <_ZN8Analyzer15setExpAvgFactorEi+22>:    blx 0x30508
0x000399ca <_ZN8Analyzer15setExpAvgFactorEi+26>:    fconstd d16, #7
0x000399ce <_ZN8Analyzer15setExpAvgFactorEi+30>:    vldr    d17, [pc, #32]  ; 0x399f2 <_ZN8Analyzer15setExpAvgFactorEi+66>

Full source and assembler available here (it's short, basically 2 lines of C++.)

You can see that 0x399cc is in the middle of the fconstd instruction. According to arm.com this instruction was added in VFP-v3, which should (I think) be available in any modern processor.

What could be going on? Does the fact that the address is in the middle of an instruction point to a corrupt pointer somewhere? (Note that the backtrace makes perfect sense, so it's not like this function was somehow called on accident.) Or is it something else?


Solution

  • Ok, I got it: the NVIDIA Tegra 2 only has 16 64-bit GPU registers, and therefore to target it you must compile using -mfpu=vfpv3-d16. The instruction in question uses register d16, which is "just too many". :(

    Here is a reference to an NVIDIA forum where an employee mentions this limitation: http://developer.nvidia.com/tegra/forum/optimal-performance-guidelines