用 kGDB 除錯 Linux 核心

2022-03-29 23:44:35 字數 3592 閱讀 6617

這個文件記錄了用kgdb除錯linux核心的全過程,都是在前人工作基礎上的一些總結。以下操作都是基於特定板子來進行,但是大部分都能應用於其他平台。

要使用kgdb來除錯核心,首先需要修改config配置檔案,開啟相應的配置,配置核心啟動引數,甚至修改串列埠驅動新增poll支援,然後才能通過串列埠遠端除錯核心。

在核心配置檔案:.config中,需要開啟如下選項

config_kgdb

加入kgdb支援

config_kgdb_serial_console

使kgdb通過串列埠與主機通訊(開啟這個選項,缺省會開啟config_console_poll和config_magic_sysrq)

config_kgdb_kdb

加入kdb支援

config_debug_kernel

包含驅動除錯資訊

config_debug_info

使核心包含基本除錯資訊

config_debug_rodata=n

關閉這個,能在唯讀區域設定斷點

config_panic_timeout=5

config_bootparam_softlockup_panic_value=1

config_bootparam_hung_task_panic_value=1

config_s3c2410_watchdog_atboot=0

config_frame_pointer -- 使kdb能夠列印更多的棧資訊

config_kallsyms -- 加入符號資訊

config_kdb_keyboard -- 如果是通過目標版的鍵盤與kdb通訊,需要把這個開啟,且鍵盤不能是usb介面

config_kgdb_tests

開啟相應的選項後,需要配置kernel啟動引數,使kgdb和核心能夠找到正確的通訊介面。如果是使用串列埠,則需要配置如下選項:

console=ttysac3,115200 kgdboc=ttysac3,115200
如果需要除錯核心的啟動過程,則需要在kgdboc後面加入kgdbwait。

在其他板子上,若使用乙太網口來和kgdb進行通訊,則要把kgdboc換成kgdboe(kgdb 

over ethernet))。

kgdb: unregistered i/o driver, debugger disabled.
則需要根據這一部分,修改串列埠驅動程式,若能正常進入kgdb,則忽略該節,直接進入下一節使用kgdb。

在drivers/tty/serial/kgdboc.c中的configure_kgdboc函式,會通過tty_find_polling_driver(cptr, 

&tty_line)來找尋核心啟動引數中指定的串列埠驅動。然後通過kgdboc_get_char()和kgdboc_put_char()來和主機串列埠正常通訊。

可以看到在config配置檔案的config_console_poll就是使能串列埠與kgdboc的介面。如果 tty_find_polling_driver沒有找到對應的串列埠通訊介面,則會呼叫kernel/debug/debug_core.c中的 kgdb_unregister_io_module進行錯誤處理。

有的板子的串列埠驅動並沒有加入對kgdboc通訊的支援,例如samsung的串列埠驅動需要在drivers/tty/serial/samsung.c中手動新增。 

新增與kgdboc通訊的介面,只需新增乙個傳送函式和接收函式,然後在驅動操作結構體中加入對應的函式就可以了。具體的patch如下:

drivers/tty/serial/samsung.c | 22 ++++++++++++++++++++++

1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c

index ff6a4f8..5ceb7d7 100755

--- a/drivers/tty/serial/samsung.c

+++ b/drivers/tty/serial/samsung.c

@@ -893,7 +893,29 @@ static struct console s3c24xx_serial_console;

#define s3c24xx_serial_console null

#endif

+#ifdef config_console_poll

+static void s3c24xx_serial_poll_put_char(struct uart_port *port, unsigned char c)++

+static int s3c24xx_serial_poll_get_char(struct uart_port *port)

++#endif

+static struct uart_ops s3c24xx_serial_ops = {

+#ifdef config_console_poll

+ .poll_get_char = s3c24xx_serial_poll_get_char,

+ .poll_put_char = s3c24xx_serial_poll_put_char,

+#endif

.pm = s3c24xx_serial_pm,

.tx_empty = s3c24xx_serial_tx_empty,

.get_mctrl = s3c24xx_serial_get_mctrl,

--1.7.5.4

加入這個patch,重新編譯核心,之後就能正常進入kgdb

如果在核心啟動引數中加入了kgdbwait,則核心會在完成基本的初始化之後,停留在kgdb的除錯陷阱中,等待主機的gdb的遠端連線。

由於大部分的板子只有乙個除錯串列埠,所以你需要把之前與串列埠通訊的minicom退出來,然後在核心原始碼的目錄下,執行以下命令:

$ arm-linux-gnueabi-gcc vmlinux

(gdb) target remote /dev/ttyusb0

(gdb) set detach-on-fork on

(gdb) b panic()

(gdb) c

當然,你也可以agent-proxy來復用乙個串列埠,通過虛擬出兩個tcp埠。這時候,gdb就需要用target 

remote命令連線kgdb,例如:

(gdb) target remote localhost:5551
agent-proxy可以通過這裡獲取:git:具體用法,請看該repo下的readme。

在用gdb來除錯核心的時候,由於核心在初始化的時候,會建立很多子執行緒。而預設gdb會接管所有的執行緒,如果你從乙個執行緒切換到另外乙個執行緒,gdb會馬上把原先的執行緒暫停。但是這樣很容易導致kernel死掉,所以需要設定一下gdb。 

一般用gdb進行多執行緒除錯,需要注意兩個引數:follow-fork-mode和detach-on-fork。

follow-fork-mode指定的程序將被除錯,另乙個程序置於暫停(suspended)狀態。follow-fork-mode的用法為:

set follow-fork-mode [parent|child]

ubuntu用qemu除錯linux核心

出於對用虛擬機器 除錯 核心 看是否能對學習核心有比較大的幫助。進行了下驗證 中間 的命令僅作為參考,是使用過程中的一些記錄,檔案命名 路徑名 使用時 作出對應調整 需。wget 解壓 tar xvf linux 3.10.104.tar.xz cd linux 3.10.104 進行配置 make...

kgdb除錯注意事項

0 首先提下注意事項的背景 kgdb和printk共用乙個串列埠 1設定波特率 最高支援460800波特率 arm eabi gdb vmlinux gdb set remotebaud 460800 設定使用哪個埠,作為通訊埠 gdb target remote dev ttyusb0 2 使用的...

linux 核心除錯

debug.hacks 一書中,介紹了如果除錯核心問題,在第五章的 實踐核心除錯 總體來說,有一下的方法來除錯核心 1.用kgdb單步除錯。具體請參見 2.加列印printk來定位。3.根據核心出錯的kernel panic oops資訊,反彙編,定位問題 4.編寫復現程式,或者創造復現條件。5.g...