Illegal instruction when running simple ELLCC-generated ELF binary on a Raspberry Pi

618 views Asked by At

I have an empty program in LLVM IR:

define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
    ret i32 0
}

I'm cross-compiling it on Intel x86-64 Windows for ARM Linux using ELLCC, with the following command:

ecc++ hw.ll -o hw.o -target arm-linux-engeabihf

It completes without errors and generates an ELF binary.

When I take the binary to a Raspberry Pi Model B+ (running Raspbian), I get only the following error:

Illegal instruction

I don't know how to tell what's wrong from the disassembled code. I tried other ARM Linux targets but the behavior was the same. What's wrong?


The exact same file builds, links and runs fine for other targets like i386-linux-eng, x86_64-w64-mingw32, etc (that I could test on), again using the ELLCC toolchain.


Assuming the library and startup code isn't at fault, this is what the disassembly of main itself looks like:

.text:00010188  e24dd008    sub sp, sp, #8
.text:0001018c  e3002000    movw r2, #0
.text:00010190  e58d0004    str r0, [sp, #4]
.text:00010194  e1a00002    mov r0, r2
.text:00010198  e58d1000    str r1, [sp]
.text:0001019c  e28dd008    add sp, sp, #8
.text:000101a0  e12fff1e    bx lr
1

There are 1 answers

6
Notlikethat On BEST ANSWER

I'd guess it's choking on the movw at 0x0001018c. The movw/movt encodings which can handle full 16-bit immediate values first appeared in the ARMv6T2 version of the architecture - the ARM1176 in the original Pi models predates that, only supporting original ARMv6*.

You need to tell the compiler to generate code appropriate to the thing you're running on - I don't know ELLCC, but I'd guess from this it's fairly modern and up-to-date and thus defaulting to something newer like ARMv6T2 or ARMv7. Otherwise, it's akin to generating code for a Pentium and hoping it works on an 80486 - you might be lucky, you might not. That said, there's no good reason it should have chosen that encoding in the first place - it's not as if 0 can't be encoded in a 'classic' mov instruction...

The decadent option, however, would be to consider this a perfect excuse to replace the Pi with a Pi 2 - the Cortex-A7s in that are nice capable ARMv7 cores ;)

* Lies for clarity. I think 1176 might actually be v6K, but that's irrelevant here. I'm not sure if anything actually exists as plain ARMv6, and all the various architecture extensions are frankly a hideous mess