linux - 为什么编译器添加额外的 'sxtw' 指令(进一步导致内核 panic )?

标签 linux gcc arm implicit-conversion function-declaration

问题/症状:

在函数返回的末尾,编译器添加了一条 sxtw 指令,如反汇编所示,导致返回地址只有 32 位而不是 64 位,从而导致内核 panic :

Unable to handle kernel paging request at virtual address xxxx

构建环境:

  平台:ARMV7LE
海湾合作委员会,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/
header 中没有声明 func1() */

问题原因:

从 file2.c 添加了对 func1() 的调用,而没有在 files.h 或 file2.c 中声明 func1。 (基本上,func1 的包含在 files.h 中被意外遗漏。)

代码编译时没有错误,但出现了预期的警告 - 函数 func1 的隐式声明

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

进一步分析表明,在函数返回结束时,编译器添加了一条sxtw指令(如反汇编所示),导致返回地址只有32位而不是64位,从而导致内核 panic 。

Unable to handle kernel paging request at virtual address xxxx
  • 请注意,x19 是 64 位,而 w0 是 32 位。
  • 请注意,x0 LS 单词与 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

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

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

最佳答案

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

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

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

关于linux - 为什么编译器添加额外的 'sxtw' 指令(进一步导致内核 panic )?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55351940/

相关文章:

gcc - 如何使用 ARM 的 OpenMAX 开发层 (DL) 进行构建和解码

linux - 交叉编译 NTFS-3G

linux - bash 重定向 stdout 和 stderr 以通过 ssh 分隔命令

linux - 使用 hcitool 扫描低功耗蓝牙?

java - 不满意的链接错误 : no library file in java. library.path

c - 返回包含数组的结构

macos - x64 nasm : pushing memory addresses onto the stack & call function

python - 无法在 Linux 和 Windows 下构建示例模型并出现不同的错误

c - 如何用C重写文件的全部内容

linux - 我想通过 minicom 使用 gdb 在 arm board 上调试 vmlinux。我需要做什么?