运行 简单的 ELLCC 生成的 ELF 二进制文件在 Raspberry Pi 上的非法指令

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

我在 LLVM IR 中有一个空程序:

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

我正在使用 ELLCC 在 Intel x86-64 Windows for ARM Linux 上交叉编译它,命令如下:

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

它无误地完成并生成了一个 ELF 二进制文件。

当我将二进制文件带到 Raspberry Pi 模型 B+ (运行 Raspbian) 时,我只收到以下错误:

Illegal instruction

我不知道如何判断 the disassembled code 出了什么问题。我尝试了其他 ARM Linux 目标,但行为是一样的。怎么了?


完全相同的文件构建、链接和运行良好,适用于 i386-linux-engx86_64-w64-mingw32 等其他目标(我可以测试),再次使用 ELLCC 工具链.


假设库和启动代码没有问题,这就是 main 本身的反汇编:

.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

我猜它在 0x0001018c 的 movw 上窒息了。可以处理完整 16 位立即值的 movw/movt 编码首先出现在架构的 ARMv6T2 版本中 - 原始 Pi 模型中的 ARM1176 早于它,仅支持原始 ARMv6*.

您需要告诉编译器生成适合您 运行 的代码 - 我不知道 ELLCC,但我猜它是相当现代和最新的日期,因此默认为较新的东西,如 ARMv6T2 或 ARMv7。否则,这类似于为 Pentium 生成代码并希望它能在 80486 上运行——你可能很幸运,也可能不会。也就是说,没有充分的理由应该首先选择该编码 - 这并不是说 0 不能在 'classic' mov 指令中编码...

然而,颓废的选择是认为这是用 Pi 2 替换 Pi 的完美借口——其中的 Cortex-A7s 是功能强大的 ARMv7 内核;)

* 为了清楚起见撒谎。我认为 1176 实际上可能是 v6K,但这与这里无关。我不确定是否真的存在纯 ARMv6,坦率地说,所有各种架构扩展都是一团糟