使用kgdb調試內核之模塊調試

        昨天搭建的kgdb調試環境,今天面臨的第一個問題就是調試我的模塊。調試內核根據上一篇文章的介紹已經夠了http://blog.csdn.net/zr_lang/article/details/8107015,但是調試模塊還需要一些額外的工作。下面針對用kgdb調試內核模塊的問題的重點部分簡要說明一下。

首先,有一個小技巧先說明一下,那就是如果你想在gdb沒有進入斷點的情況下從目標機運行中將主動權轉回給gdb的話(這個比較常用的),可以在命令行下這樣寫:

                echo g>/proc/sysrq-trigger

        這樣就可以切換回gdb主動控制了。(誰還有什麼辦法可以分享一下,我很想知道,謝謝)

        下面開始模塊的調試。

        1.   模塊的編譯。

        在目標機上 的模塊的編譯要藉助你編譯的這個已安裝內核的代碼,把它放到你指定的目錄下,然後在模塊編譯的時候指向這個目錄。需要注意的是,模塊的編譯需要加入-g選項。如果你是寫的Makefile,那麼可以在Makefile的開頭加入

                ccflags-y += -O -g
        這樣一句就會讓編譯時加入gdb調試所需的信息瞭如果你直接使用gcc那就不用我多說了。

        2.  模塊拷備。

        把你寫的模塊的源碼和編譯出的結果也放到調試機上,拷貝的地方要和在目標機上編譯的所在的路徑相同,這樣符號名才能完好的對應上,比如兩個系統的模塊源碼目錄都在/home/zrlang/mymodule/裏。

        3.  插入模塊。

        在目標機上插入模塊,在/home/zrlang/mymodule目錄下執行

                insmod ./mymodule.ko

        4.  查看已插入模塊的字段地址。

        因爲模塊插入後並調試機並不知道模塊的調試信息的符號表,所以在調試機需要手動插入/home/zrlang/mymodule/mymodule.ko的符號表,首先我們先查看mymodule.ko模塊插入後所在的內存地址,可以通過目標機的/sys/module/$module_name/sections/目錄中查看,$module_name就是模塊名稱,比如我們就查看/sys/module/mymodule/sections/目錄下的文件內容,其中.text文件代表.text字段的地址,也是這個模塊的起始地址,後面的.bss和.data也是比較重要的地址,至少要加入.text的地址,其次最好也寫入.bss和.data段的地址。如果你發現你的系統裏沒這個文件,那應該是你內核編譯選項的問題,一般這個默認都有,如果沒有請參考CONFIG_KALLSYMS編譯選項,這裏不多說了。

       5.  調試機插入模塊的符號表。

       先讓目標機把控制權交給gdb,在目標機執行上面說的echo g>/proc/sysrq-trigger,然後返回調試機就看到gdb重新獲得控制權。在gdb上使用add-symbol-file命令,命令的基本格式是:

              add-symbol-file  模塊所在路徑地址  要插入的內存地址  [ -s 字段名稱  內存地址]
       要插入的內存地址指上面的.text段的地址,最好在後面在接上.bss和.data地址等,這兩個地址是可選的,需要用-s選項接字段名稱接內存地址來指定。比如我們在目標機上查到的.text段地址是0xffffffffa00d0000,.bss段地址是0xffffffffa00d25c0,.data段的地址是0xffffffffa00d1d60。那麼我們就可以這樣寫:
              (gdb) add-symbol-fle  /home/zrlang/linx-mbc/linx_mbc.ko  0xffffffffa00d0000 -s .bss 0xffffffffa00d25c0 -s .data 0xffffffffa00d1d60
       回車,會讓你確認,寫y回車就行了。
       這樣就在調試機上插入了模塊的符號表,你就可以設置模塊裏面的斷點了。注意調試機上一定要有和目標機同目錄的一個模塊源碼即編譯後的目標文件的副本。
       爲了方便獲取地址信息,並構建出add-symbol-file命令,這裏有一個腳本供大家使用修改,如下:
#!/bin/bash
#
# usage: gdbline.sh module_name  module_path
#
# This script will outputs an add-symbol-file line suitable for pasting into gdb to examine
# a loaded module.
#
cd /sys/module/$1/sections
echo -n add-symbol-file $2 `/bin/cat .text`


for section in .[a-z]* *; do
    if [ $section != ".text" ]; then
echo  " \\"
echo -n " -s" $section `/bin/cat $section`
    fi
done

echo


       在目標機上執行這個簡單的腳本,給出內核模塊的名稱和內核模塊所在的路徑就可以構建一個add-symbol-file命令,直接在調試機上粘貼輸入就行了。比如我的這個模塊,我這樣使用這個腳本:
               ./gdbline.sh  linx_mbc  mymodule /home/zrlang/mymodule/mymodule.ko
然後就得到了如下輸出:
add-symbol-file /home/zrlang/mymodule/mymodule.ko 0xffffffffa00d0000 \
-s .bss 0xffffffffa00d25c0 \
-s .data 0xffffffffa00d1d60 \
-s .exit.text 0xffffffffa00d17c4 \
-s .gnu.linkonce.this_module 0xffffffffa00d2380 \
-s .init.text 0xffffffffa010d000 \
-s .note.gnu.build-id 0xffffffffa00d183c \
-s .rodata 0xffffffffa00d1860 \
-s .rodata.str1.1 0xffffffffa00d1c2d \
-s .rodata.str1.8 0xffffffffa00d19b0 \
-s .smp_locks 0xffffffffa00d1950 \
-s .strtab 0xffffffffa010dbb0 \
-s .symtab 0xffffffffa010d130 \
-s __bug_table 0xffffffffa00d1d4a
       你可以把這一堆一股腦都貼在調試機的gdb命令裏輸入,也可以只寫到.data或你認爲合適的地方。當然這裏面又寫字段在寫入的時候可能會報一些警告沒找到,如果不是關鍵問題就沒事。
       對於模塊符號表地址的獲取方法,誰還有更好的方法可以告訴我。
       如果你想刪除符號表,可以使用symbol-file,這樣就會把全部符號表都刪除包括內核的。所以最好記錄下內核的符號列表,以備重插。

       目前的遺留問題: 目前我沒找到用add-symbol-file重新插入模塊符號表的好方法(除了我上面說的把符號表都刪了重新插入),如果我以後找到解決方法會補上,如果誰有更好的方法可以告訴我。


參考文獻:
 [ 1 ] Linux 設備驅動程序(第三版) Jonathan corbet,alessandro rubini & Greg keroah-hartman 中國電力出版社

 [ 2 ] Debugging with GDB (Tenth Edition, for GDB version 7.3.92.20120112) Richard Stallman, Roland Pesch, Stan Shebs, et al.


發佈了31 篇原創文章 · 獲贊 75 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章