首页 > 解决方案 > 为什么编译器要添加额外的“sxtw”指令(进一步导致内核恐慌)?

问题描述

问题/症状:

在函数返回的末尾,编译器添加了一条反汇编中的 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.cw/o func1 声明中添加的。(基本上 func1 的包含在 files.h 中被意外遗漏了。)

编译后的代码没有错误,但出现了预期的警告 -- Implicit declaration of function func1

但是,在运行时,从 file2 中的 func1 返回后,系统在尝试从 func1 取消引用返回的地址时崩溃。

进一步分析表明,在函数返回的末尾,编译器在反汇编中添加了一条 sxtw 指令,导致返回地址只有 32 位而不是 64 位,从而导致内核恐慌。

Unable to handle kernel paging request at virtual address xxxx

sxtw x19, w0 /* 这是编译器添加的额外指令/ ldp x1, x0, [x19,#304] / System crashed here */

寄存器:

[   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

在 files.h 中添加 func1 的声明后,没有看到额外的指令,因此没有看到崩溃。

有人可以解释为什么编译器在这种情况下添加了 sxtw 吗?

标签: linuxgccarmimplicit-conversionfunction-declaration

解决方案


您应该至少收到两个警告,一个是关于缺少函数声明,另一个是关于从隐式转换int为指针类型。

原因是隐式声明的函数的返回类型为int. 将此int值转换为 64 位指针会丢弃 32 位结果。这是预期的 GNU C 行为,基于早期 64 位目标的 C 编译器所做的。该sxtw指令是实现此行为所必需的。(当前的 C 标准不再有隐式函数声明,但 GCC 仍然必须支持它们以向后兼容现有的 autoconf 测试。)

请注意,您的平台显然是 Aarch64(带有 64 位寄存器),而不是 32 位 ARMv7。


推荐阅读