运行 简单的 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-eng
、x86_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,坦率地说,所有各种架构扩展都是一团糟
我在 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-eng
、x86_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,坦率地说,所有各种架构扩展都是一团糟