问题/症状:
在函数返回的末尾,编译器添加了反汇编中看到的sxtw指令,导致返回地址只有32位而不是64位,从而导致内核死机:
Unable to handle kernel paging request at virtual address xxxx
构建环境:
平台:ARMV7LE
GCC,Linux-4.4.60
体系结构:ARM64
gdb:aarch64-5.3-glibc-2.22/usr/bin/aarch64-linux-gdb
细节:
这是简化的项目结构。它在相应的makefile中得到了正确的处理。还要注意,file1.c和file2.c是同一模块的一部分。
../src/file1.c/*它定义了func1()并调用/
../src/file2.c
../inc/files.h/头中没有声明func1()*/
问题原因:
对func1()的调用是从files.h或file2.c中的file2.c w/o func1声明中添加的(基本上func1的包含是在files.h中意外丢失的)。
编译的代码没有错误,但像预期的那样发出警告--
Implicit declaration of function func1
。但在运行时,在从文件2中的func1返回后,系统在尝试取消引用从func1返回的地址时崩溃。
进一步分析表明,在函数返回的末尾,编译器添加了反汇编中看到的sxtw指令,导致返回地址只有32位而不是64位,从而导致内核死机。
Unable to handle kernel paging request at virtual address xxxx
注意x19是64位的,而w0是32位的。
请注意,x0 ls word与x19的匹配。
系统在取消引用X19时崩溃。
sxtw x19,w0/*这是编译器作为额外指令添加的/
ldp x1,x0,[x19,304]/系统在这里崩溃*/
寄存器:
[ 91.388130] pc : [<ffffff80016c9074>] lr : [<ffffff80016c906c>] pstate: 80000145
[ 91.462090] sp : ffffff80094333b0
[ 91.552708] x29: ffffff80094333d0 x28: ffffffc06995408a
[ 91.652701] x27: ffffffc06c400a00 x26: 0000000000000000
[ 91.716243] x25: 0000000000000000 x24: ffffffc069958000
[ 91.779784] x23: ffffffc076e00000 x22: ffffffc06c400a00
[ 91.843326] x21: 0000000000000031 x20: ffffffc073060000
[ 91.906867] x19: 0000000066bfc780 x18: ffffff8009436888
[ 91.970409] x17: 0000000000000000 x16: ffffff8008193074
[ 92.033952] x15: 00000000000a8c06 x14: 2c30323030387830
[ 92.097492] x13: 3d7367616c66202c x12: 3038653030303030
[ 92.161034] x11: 3038666666666666 x10: 78303d646e65202c
[ 92.224576] x9 : 3063303030303030 x8 : 3030303030303030
[ 92.288117] x7 : 0000000000000880 x6 : 0000000000000000
[ 92.351659] x5 : ffffffc07fd10ad8 x4 : 0000000000000001
[ 92.415202] x3 : 0000000000000007 x2 : cb88537fdc8ba63c
[ 92.478743] x1 : 0000000000000000 x0 : ffffffc066bfc780
在文件.h中添加func1的声明之后,没有看到额外的指令,因此也没有看到崩溃。
有人能解释一下为什么编译器在这种情况下添加了sxtw吗?
最佳答案
您应该至少收到了两个警告,一个关于缺少函数声明,另一个关于从int
到指针类型的隐式转换。
原因是隐式声明的函数的返回类型为int
。将此int
值转换为64位指针会丢弃32位结果。这是预期的gnu c行为,基于早期64位目标的c编译器所做的。需要sxtw
指令才能实现此行为。(当前的C标准不再具有隐式函数声明,但GCC仍然必须支持它们与现有的AutoCOF测试的向后兼容性。)
注意,您的平台显然是aarch64(带有64位寄存器),而不是32位armv7。
关于linux - 为什么编译器要添加额外的“sxtw”指令(进一步导致内核崩溃)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55351940/