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

问题描述 投票:1回答:1

问题/症状:

在函数返回结束时,编译器添加一个sxtw指令,如反汇编中所示,导致返回地址仅为32位而不是64位,从而导致内核崩溃:

Unable to handle kernel paging request at virtual address xxxx

建立环境:

平台:ARMV7LE gcc,linux-4.4.60 Archictecture: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()* /

问题原因:

从file.h或file2.c中的file2.c w / o func1声明添加了对func1()的调用。 (基本上在files.h中偶然错过了func1的包含。)

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

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

进一步分析表明,在函数返回结束时,编译器添加了一个sxtw指令,如反汇编中所示,导致返回地址仅为32位而不是64位,从而导致内核崩溃。

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?

linux gcc arm implicit-conversion function-declaration
1个回答
2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.