Python在Arm上,非法指令

5
我正试图为ARM920T(架构4T)编译Python 3.2,但我遇到了一些奇怪的错误。
我在Scratchbox环境中编译Python,配置使用以下编译器:"gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203)",这是一个ARM交叉编译器。
编译时,我确保设置了-march = armv4t架构标志,在以下环境变量中:CFLAGS,CPPFLAGS,SBOX_EXTRA_COMPILER_FLAGS。
它在scratchbox中编译得很好,我能够使用scratchbox arm模拟器运行python解释器。
然而,当我将其移动到我的ARM920T时,我在运行python exe后立即收到一个非法指令错误。
核心转储产生以下输出:
Program terminated with signal 4, Illegal instruction.
#0 0x00138810 in __aeabi_dadd ()

以下是回溯的前几行:

#0  0x00138810 in __aeabi_dadd ()
#1  0x001134f4 in PyLong_FromString (str=0x402de300 "3644798167", pend=0x0, base=10) at Objects/longobject.c:2001
#2  0x00132478 in parsenumber (s=<value optimized out>, c=<value optimized out>) at Python/ast.c:3189
#3  ast_for_atom (n=<value optimized out>, c=<value optimized out>) at Python/ast.c:1396
#4  ast_for_power (n=<value optimized out>, c=<value optimized out>) at Python/ast.c:1726
#5  ast_for_expr (c=0xbeaf7f50, n=0x402f5b78) at Python/ast.c:191

据我所了解,__aeabi_dadd调用是一个库调用,用于将两个浮点数相加(双精度加法)。
我查看了导致错误的Python代码(longobject.c第2001行):
if (log_base_BASE[base] == 0.0) {
            twodigits convmax = base;
            int i = 1;

            log_base_BASE[base] = (log((double)base) /        // Line 2001
                                   log((double)PyLong_BASE));
            for (;;) {
                twodigits next = convmax * base;
                if (next > PyLong_BASE)
                    break;
                convmax = next;
                ++i;
            }

我并不认为这段代码会引起任何错误。我尝试编写了一个小的 C++ 程序,类似于上面的代码,对许多双精度数进行加、减、除等运算,在设备上运行良好。
非常感谢任何帮助。我能想到的唯一原因是可能将错误的浮点库编译到 exe 中。据我从 Google 上了解到,ARM920T 不支持硬件浮点。
另一个原因可能是对齐错误。在使用 -Wcast-align 标志编译 Python 时,确实会报告一些强制转换警告。当某些数据类型在内存中的地址不是偶数时,ARM 就不喜欢它。但 /proc/cpu/alignment 并未报告任何错误。
抱歉给你带来了大量文本,如果你阅读到这里,感谢你:)
2个回答

3
我找到了解决办法!我在make调用期间的控制台上生成一个文件转储,并注意到一些对gcc的调用不包含-march=armv4t选项。我发现我拼错了SBOX_EXTRA_COMPILER_FLAGS,应该是SBOX_EXTRA_COMPILER_ARGS。设置了这个后,将CFLAGS设置为-march=armv4t,Python现在成功构建并运行而没有非法指令。感谢Leo指引我正确方向!

2

看起来你链接了一些编译为高于设备架构的库。当我们使用CodeSourcery为ARMv4 CPU设备编译时,也遇到了同样的问题。显然,CodeSourcery库是为ARMv5编译的。就像你所说的,可能是浮点库,也可能是其他库。你能找到构建脚本中涉及该文件的位置,并检查使用了哪些库吗?


太好了!这是正确的方向!我成功地在GNU调试器中进行了反汇编,以查看非法指令是什么。结果发现它是一个CLZ指令,在aeabi_*函数中执行。根据ARM文档,CLZ指令是ARM5及以上版本的指令。这就解释了错误的原因。现在我需要做的就是追踪生成此指令的位置,这有点复杂。我检查了链接的所有库,发现没有包含此指令。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接