[英]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 源,它也在發生。 (但在 linux-5.4,21 和 defconfig 中並沒有發生。在 qemu 5.1.0 或 6.2.0 中)
如果有人可以檢查這種情況是發生在其他人身上還是只發生在我身上,我將不勝感激。
nproc
Image” 現在,在 gdb 中,當您按兩次“c”時,它會停在第一個 __driver_attach 處。 (第一個停在 start_kernel 處)。 當您在 __attach_driver 時,鍵入“bt”。 查看您是否看到完整的 function 堆棧跟蹤。
這就是我所看到的。
(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,kernel 將正常啟動到 shell 提示符。 所以 linux 運行正常,但只有 gdb 無法顯示堆棧級別。
我的操作系統:ubuntu-20.04 5.13.0-35-generic
$ aarch64-none-elf-gdb --version
GNU gdb(A-profile 架構 10.2-2020.11 (arm-10.16) 的 GNU 工具鏈)10.1.90.20201028-git 版權所有 (C) 2020 Free Software Foundation, Inc. License 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 虛擬機做這件事。
我在 __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 到達 function __driver_attach 之后,sp 仍然沒有從之前的 function (bus_for_each_dev) 更新。 $sp 的前兩個值應該是前一個 function 的 fp 和 lr(請參閱理解 aarch64 程序集 function 調用,堆棧操作的方式 arm64 在新堆棧幀的底部存儲前一個函數的 fp 和 lr 進入一個函數)。 lr(鏈接寄存器,在此 bus_for_each_dev 函數之后返回的地址)是 0xb8cd80001076a594,這很奇怪(不是 kernel 地址)。 以下 3 個值是 function arguments for bus_for_each_dev,它們看起來是正確的。
我試圖打破 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 function 中,我輸入 __driver_attach。 此時我檢查了$sp中的兩個值(sp值還是bus_for_each_dev的值)。 它們是 0xffff800011efbd20(正確)和 0xc9a48000107a52f8(錯誤)? 為什么高16位變了??
而且我很快發現當x29,x30寫到新的棧底時,x30的高16位一開始就寫錯了。 因此,如果我將這 16 位修復為正確的值(通常為 0xffff,因為頂部 kernel 地址位為 0xffff),bt output 顯示更多。 x30 修復得越多,我能看到的堆棧幀就越多。我已經向 bugs.linaro.org 提交了一個錯誤,以便專家可以檢查這個。
我剛剛發現在構建 linux 時在 armv8.3 中關閉 CONFIG_ARM64_PTR_AUTH,我可以避免這個問題。 (我注意到 function 匯編代碼開頭的指令“pacia”)(我詢問了 kernelnewbies 和 qemu-discuss email 列表,但專家不經常回復..)希望這對以后的人有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.