轉載:Linux內核調試方法

深度解析KGDB調試Linux模塊和內核

轉載文章請註明做者和二維碼及全文信息。linux

轉自:http://blog.csdn.net/swingwang/article/details/72331196程序員

不會編程的程序員,不是好的架構師,編程和內核調試也是出色架構師的必修課。談起編程人員的數量,基於Linux平臺的軟件工程師確定是最多的,沒有之一。那今天咱們就以Linux爲例,深刻講一下內核模塊和內核的調試技術和調試工具KGDB。編程

1 KGDB背景

KGDB是在內核2.6.26版本中正式支持的,對應發行版即SLES11及以上、RHEL6及以上,在此以前的內核版本由Linsyssoft Technologies公司提供補丁以支持KGDB,但並非全部內核版本都有補丁可用,同時打補丁操做也比較繁瑣且問題多多,所以可用性不高。微信

2 調試環境搭建

注:如下稱 「被調試的主機」爲目標機,運行gdb進行調試的主機爲開發機網絡

2.1 目標機配置架構

2.1.1 配置串口函數

物理機串口根據實際環境要求配置,虛擬機按以下方式配置,pipe名字能夠修改,但要保證和開發機一致:工具

深度解析KGDB調試Linux模塊和內核

2.1.2 更新內核以支持kgdb.net

注:本文以SLES11SP1做爲目標機爲例,內核源碼直接安裝RPM包就可使用,RHEL要稍微麻煩一些,須要下載源碼包,進行編譯後進行安裝。線程

更新內核前準備

加入調試信息後內核及各個ko的體積會增大數倍,所以編譯內核前必定要確認磁盤有7G以上剩餘空間(保險起見建議預留10G),執行make後源碼目錄空間佔用超過5G。

深度解析KGDB調試Linux模塊和內核

執行make modules_install後/lib/modules目錄還要佔用1.4G

深度解析KGDB調試Linux模塊和內核

SLES系列默認內核源碼目錄是/usr/src/linux-xxx/,但因爲試驗用的虛擬機建立時磁盤選擇默認大小隻有8G,所以額外建立了一塊20G的磁盤掛載到/home目錄做爲內核編譯目錄,可直接將目錄usr/src/linux-xxx/拷貝到/home/linux-xxx/不影響編譯。

更新內核步驟

一、執行uname –r確認當前運行內核的類型,拷貝/boot/目錄下對應內核類型的config文件到內核源碼目錄並重命名爲.config;大多數狀況下編譯內核後啓動失敗都是由於內核配置不當,所以最好在系統原有配置文件基礎上修改。

深度解析KGDB調試Linux模塊和內核

二、在內核源碼目錄執行make menuconfig進行內核配置;

深度解析KGDB調試Linux模塊和內核

  • 進入Kernel hacking子選項,確認激活如下項目:

[*]Compile the kernel with debug info

[*]Compile the kernel with frame pointers

[*]KGDB: kernel debugging with remote gdb

  • 清除 Write protect kernel read-only data structures選項;此項默認是激活的,會致使後續使用gdb調試時沒法加斷點;

深度解析KGDB調試Linux模塊和內核

在SLES11SP1上去掉Write protect kernel read-only data structures後編譯會出錯,緣由是函數mark_rodata_ro在init/main.c和cacheflush.h中重複定義了

深度解析KGDB調試Linux模塊和內核

解決辦法是注掉main.c中的定義:

深度解析KGDB調試Linux模塊和內核

三、執行make all編譯內核;(耗時約1小時,可以使用make –j x all加快編譯速度,x表示線程數)

四、安裝模塊,編譯完成後,新生成的模塊ko還在源碼目錄,並未更新到/lib/module/對應目錄:

深度解析KGDB調試Linux模塊和內核

  • 注意,在安裝模塊前強烈建議備份原模塊目錄,以便調試完成後或新編譯模塊有問題時恢復環境,以下。

深度解析KGDB調試Linux模塊和內核

  • 執行make modules_install(注意:不是make modules install)將拷貝ko到/lib/module/

深度解析KGDB調試Linux模塊和內核

五、建立啓動內核及initrd

  • 注:依然強烈建議先備份/boot/目錄下的原vmlinuz和initrd文件,由於雖然內核install腳本會自動備份,但若是install執行兩次或以上,則以前的備份會被新備份覆蓋。

  • 設置/etc/modprobe.d/unsupported-modules中allow_unsupported_modules爲1,不然新編譯生成的模塊ko可能沒法加載:

深度解析KGDB調試Linux模塊和內核

  • 執行make install,將會拷貝源碼目錄下的vmlinux到/boot/目錄並壓縮爲vmlinuz,並建立initrd:

深度解析KGDB調試Linux模塊和內核

六、爲KGDB內核建立新的啓動項

  • 注:繼續強烈建議先備份原始啓動項,將原始啓動項使用的內核和initrd文件指定爲以前備份的文件:

深度解析KGDB調試Linux模塊和內核

  • 新增的KGDB啓動項,與原始啓動項相比只增長了一個參數:kgdboc=ttyS0,115200

深度解析KGDB調試Linux模塊和內核

  • 若是須要目標機一啓動就斷住(好比要調試啓動階段的代碼),則再增長一個參數kgdbwait

七、重啓目標機,以KGDB選項啓動

2.2 開發機配置

開發機不須要和目標機硬件或內核相同,只要上面裝的gdb版本知足kgdb的要求就能夠。本文使用一個SLES10SP4的32位虛擬機做爲開發機。

2.2.1 配置串口

物理機串口根據實際環境要求配置,虛擬機按以下方式配置:

深度解析KGDB調試Linux模塊和內核

檢查參數,確認串口配置正確:

  • 一、 在目標機執行cat /dev/ttyS0;

  • 二、 在開發機執行echo test > /dev/ttyS0

  • 三、 觀察目標機是否打印test字樣;

深度解析KGDB調試Linux模塊和內核

深度解析KGDB調試Linux模塊和內核

2.2.2 準備調試代碼和目標二進制文件

調試代碼

因爲gdb調試須要源碼文件,所以須要把內核源碼拷貝到開發機。建議在目標機編譯前把整個源碼目錄拷貝到開發機,不然編譯後整個源碼目錄體積太大。

目標二進制文件

目標二進制文件就是要調試的文件,如vmlinux或xxx.ko,直接把目標機上編譯好的文件拷貝到開發機,建議放在內核源碼目錄下。

深度解析KGDB調試Linux模塊和內核

3 調試步驟

3.1調試內核vmlinux

以調試函數block層的函數get_request_wait爲例

一、 在目標機執行echo g > /proc/sysrq-trigger,會觸發目標機掛起以等待開發機輸入;

深度解析KGDB調試Linux模塊和內核

二、 在開發機啓動gdb:

深度解析KGDB調試Linux模塊和內核

三、 設置啓動遠程調試

在gdb界面輸入如下兩條命令,成功的話會顯示斷在kgdb_breakpoint函數:

  • set remotebaud 115200

  • target remote /dev/ttyS0

深度解析KGDB調試Linux模塊和內核

四、 輸入b get_request_wait爲咱們想調試的函數設置斷點(b表示breakpoint),而後執行c(continue)讓目標機繼續運行直到斷點;

深度解析KGDB調試Linux模塊和內核

五、 查看調用棧(bt)和單步調試(n)都是比較有用的手段;

查看函數get_request_wait的調用棧:

深度解析KGDB調試Linux模塊和內核

單步調試:

  • 下圖例子中代碼執行到rq = get_request(q, rw_flags, bio, GFP_NOIO);這行前;

  • 執行p rq打印指針變量rq的地址顯示value optimized out表示爲空;

  • 執行p *rq打印指針變量rq的內容顯示沒法訪問0x0地址;

  • 執行n讓rq = get_request(q, rw_flags, bio, GFP_NOIO);執行完;

  • 再次執行p rq成功打印出指針變量rq的地址;

  • 執行p *rq成功打印出指針變量rq的內容;

深度解析KGDB調試Linux模塊和內核

六、 調試完成後清除斷點讓目標機恢復正常運行;

  • 執行info b查看當前斷點;

  • 執行d breakpoint 1清除斷點1;

  • 執行c讓目標機恢復運行;

深度解析KGDB調試Linux模塊和內核

目標機以前掛起後網絡就中斷了,此時恢復後又可從新登陸:

深度解析KGDB調試Linux模塊和內核

3.2 調試模塊KO

以調試模塊scsi_mod.ko爲例:

一、先在目標機上查看模塊在內核中的偏移地址,而後掛起目標機:

深度解析KGDB調試Linux模塊和內核

二、在開發機啓動gdb,並執行add-symbol-file [模塊ko] [內核地址]加載模塊ko文件:

深度解析KGDB調試Linux模塊和內核

以後的步驟同調試內核vmlinux同樣:啓動遠程調試、設置斷點…

深度解析KGDB調試Linux模塊和內核

4 總結

使用KGDB,一方面能夠幫助閱讀內核代碼,實際觀察代碼執行的流程;另外一方面能夠幫助非自研模塊相關流程的問題定位,不須要反覆添加打印重編內核,提升問題定位效率。本文重點描述了KGDB環境搭建及啓動調試的步驟,更多gdb調試技巧請參考gdb手冊。

環境搭建重點在於更新內核,這塊也是整個過程當中最耗時和容易出錯的,項目組能夠組織分工進行各個版本、類型內核的KGDB更新(如SLES11 32位/64位、RHEL等等)並保存,後續使用時能夠直接拷貝。請搜索「ICT_Architect」加入微信公衆號「架構師技術聯盟」獲取更多精彩內容。

相關文章
相關標籤/搜索