3

我在 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 Model B+(运行 Raspbian)时,我只收到以下错误:

Illegal instruction

我不知道如何从反汇编代码中判断出什么问题。我尝试了其他 ARM Linux 目标,但行为相同。怎么了?


同样使用 ELLCC 工具链,对于其他目标(如 , 等)(我可以测试),i386-linux-eng完全相同的文件构建、链接和运行良好。x86_64-w64-mingw32


假设库和启动代码没有问题,这就是反汇编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
4

1 回答 1

3

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

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

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

* 为清楚起见而撒谎。我认为 1176 实际上可能是 v6K,但这在这里无关紧要。我不确定是否有任何东西作为普通的 ARMv6 存在,坦率地说,所有各种架构扩展都是一团糟

于 2015-05-14T17:11:08.687 回答