gdb back-trace 没有显示 linux-5.10.0 或 linux-5.10.122 的所有函数调用堆栈,为什么?

gdb back-trace doesn't show all the function call stacks for linux-5.10.0 or linux-5.10.122, why?

这里发生了非常奇怪的事情。我在 gdb 中看不到 'bt' 命令的完整堆栈跟踪。 所以我尝试使用新的 linux-5.10.122 源和 qemu-6.2.0 源,它也在发生! (但是使用 defconfig 的 linux-5.4.21、qemu 5.1.0 或 6.2.0 不会发生这种情况)

如果有人能检查这是否发生在其他人身上或只是我身上,我将不胜感激。

  1. https://www.kernel.org/
  2. 下载 linux-5.1.122 tarball
  3. 解压缩并设置环境变量 ARCH=arm64,CROSS_COMPILE=aarch64-none-elf-,执行“make defconfig”和“make -jnproc Image”。 =58=]
  4. https://www.qemu.org/
  5. 下载 qemu-6.2.0
  6. 解压缩并执行“mkdir build”“cd build”“../configure --target-list=aarch64-softmmu --enable-debug”
  7. 运行 qemu 并等待调试器附加。
    qemu-6.2.0/build/aarch64-softmmu/qemu-system-aarch64 -machine virt,gic-version=max,secure=off,virtualization=true -cpu max -kernel linux-5.10.112/arch/arm64/boot/Image -m 2G -nographic -netdev user,id=vnet,hostfwd=:127.0.0.1:0-:22,tftp=/srv/tftp -device virtio-net-pci,netdev=vnet -machine iommu=smmuv3 --append "root=/dev/ram init=/init nokaslr earlycon ip=dhcp hugepages=16" -s -S
  8. 运行 调试器,执行“aarch64-none-elf-gdb linux-6.10.112/vmlinux -x gdb_script” (gdb_script 内容: 目标遥控器:1234 布局源 b start_kernel b __driver_attach )

现在,在 gdb 中,当您按两次 'c' 时,它会在第一个 __driver_attach 处停止。 (第一个停在 start_kernel)。 当您在 __attach_driver 时,键入 'bt'。查看您是否看到完整的函数堆栈跟踪。
这是我看到的。

(gdb) bt
#0  __driver_attach (dev=0xffff000002582810, data=0xffff800011dc2358 <dummy_regulator_driver+40>)
    at drivers/base/dd.c:1060
#1  0xffff8000107a3ed0 in bus_for_each_dev (bus=<optimized out>, start=<optimized out>,
    data=0xffff800011dc2358 <dummy_regulator_driver+40>, fn=0xffff8000107a6f60 <__driver_attach>)
    at drivers/base/bus.c:305
#2  0xd6d78000107a5c58 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

我曾经看到过 20 多个堆栈帧,但奇怪的是我只看到了两个。 我仍然可以看到我过去使用的 linux-5.4.21 的许多堆栈。
谁能检查其他人是否也发生这种情况? 尽管我看不到整个堆栈帧,但我认为如果我在 linux 构建中添加 BLK_DEV_RAM 并设置 initramfs.cpio.gz,内核将正常启动到 shell迅速的。所以 linux 运行 正常,但只有 gdb 无法显示堆栈级别。

我的OS:ubuntu-20.04 5.13.0-35-generic

$ aarch64-none-elf-gdb --version
GNU gdb(A-profile 架构的 GNU 工具链 10.2-2020.11 (arm-10.16))10.1.90.20201028-git 版权所有 (C) 2020 Free Software Foundation, Inc. 许可 GPLv3+:GNU GPL 版本 3 或更高版本 http://gnu.org/licenses/gpl.html 这是免费软件:您可以自由更改和重新分发它。 在法律允许的范围内,不提供任何保证。 看起来随着内核版本的增加,在某些时候 gdb 'bt' 命令有问题?

添加

我发现 CONFIG_DEBUG_FRAME_POINTER、CONFIG_DEBUG_INFO 已经默认设置了。我尝试添加 CONFIG_DEBUG_KERNEL、CONFIG_KGDB、CONFIG_GDB_SCRIPTS、CONFIG_STACKTRACE 都无济于事。我需要为 arm64 qemu 虚拟机做这件事。

ADD2 01:10 2022 年 4 月 26 日协调世界时

我在 __driver_attach,

的另一个断点案例中发现
(gdb) bt
#0  __driver_attach (dev=dev@entry=0xffff0000401d1810, data=data@entry=0xffff800011bbbbb8 <mxc_gpio_driver+40>) at drivers/base/dd.c:1046
#1  0xffff8000107684f8 in bus_for_each_dev (bus=0xffff800011cba910 <platform_bus_type>, start=0x0, data=0xffff800011bbbbb8 <mxc_gpio_driver+40>, fn=0xffff80001076b860 <__driver_attach>) at drivers/base/bus.c:307
#2  0xb8cd80001076a594 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

(gdb) x/5g $sp
0xffff800011dcbcc0: 0xffff800011dcbd20  0xb8cd80001076a594
0xffff800011dcbcd0: 0xffff80001076b860  0xffff800011bbbbb8
0xffff800011dcbce0: 0x0000000000000000

因为在 pc 到达函数 __driver_attach 之后,sp 仍然没有从上一个函数 (bus_for_each_dev) 更新。 $sp 的前两个值应该是前一个函数的 fp 和 lr(参见 arm64 在进入函数时将前一个函数的 fp 和 lr 存储在新堆栈帧的底部)。 lr(link 寄存器,bus_for_each_dev 函数之后到 return 的地址)是 0xb8cd80001076a594,这很奇怪(不是内核地址)。以下 3 个值是 bus_for_each_dev 的函数参数,它们看起来是正确的。

添加(08:20 27/04/2022 UTC)

我试图在 driver_attach 突破。它调用 bus_for_each_dev,bus_for_each_dev 调用 __driver_attach。当我输入bus_for_each_dev时,我检查了汇编代码。它把 x29 和 x30 放在 [sp, #-80]! (stp x29, x30, [sp, #-80]!) 所以我检查了 x29(fp) 和 x30(lr) 的值。它们分别是 0xffff800011efbd20 和 0xffff8000107a52f8。这些值被放置在 bus_for_each_dev 堆栈框架的底部。现在在 bus_for_each_dev 函数中,我输入 __driver_attach。此时我检查了$sp中的两个值(sp值还是bus_for_each_dev的值)。它们是 0xffff800011efbd20(正确)和 0xc9a48000107a52f8(错误!)。为什么高16位变了??
而且我很快发现当x29,x30写到新的栈底时,x30的高16位一开始就写错了。因此,如果我将这 16 位修复为正确的值(通常为 0xffff,因为顶部内核地址位为 0xffff),bt 输出会显示更多。 x30 修复越多,我能看到的堆栈帧就越多。我已经向 bugs.linaro.org 提交了一个错误,以便专家可以检查这个。

我刚刚发现在构建linux时在armv8.3中关闭CONFIG_ARM64_PTR_AUTH,我可以避免这个问题。 (我注意到函数汇编代码开头的指令“pacia”) (我问了 kernelnewbies 和 qemu-discuss 电子邮件列表,但专家不经常回复..) 希望这对以后的人有帮助。