• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            小默

            【轉】在VMware環境下使用KGDB調試Linux內核及內核模塊

            1:前言:
                最近幾天學習Linux-2.6平臺上的設備驅動,所以要建立內核及內核模塊的調試平臺.雖然網上有很多相關教程,但多是基于2.6.26以前的通過補丁安裝的,過程非常復雜,而且問題比較多.linux從 2.6.26開始已經集成了kgdb,只需要重新編譯2.6.26(或更高)內核即可.kgdb安裝及模塊調試過程也遇到不少問題,網上網下不斷的搜索與探索,才算調通.現在記錄下來,供朋友們參考.
                首先說一下,開始本打算安裝kdb進行內核調試,后來聽說kdb只能進行匯編級別的調試,所以放棄,改用kgdb.

            2: 系統環境:
            虛擬環境:   VMWare Workstation 5.5(英文版)
            操作系統:   CentOS-4.6-i386(原內核2.6.9,將會把內核升級至2.6.26)
            注:CentOS 是RedHat的一個社區版本.
                 (由于我們采用的linux kernel 2.6.26已經集成kgdb,kgdb再不需要單獨下載)

            3:系統的安裝:
            在VMWare中新建一臺計算機:

            點擊 Next
            選中Custom 點擊 Next
            選中 New-Workstation 5,點擊Next
            選中Linux ,Version選中Other Linux 2.6.x kernel 點擊Next
            Virtual machine name 輸入Client(Development) 點擊Next
            Processors 選中 One, 點擊Next
            Memory 輸入256,點擊Next
            Network connection 選中Use network address translation(NAT) (選第一個貌似也可以) 點擊Next
            I/O adapter types
            SCSI Adapters 選中默認的LSI Logic(這里如果你后面使用了SCSI格式的Disk,編譯內核時需要添加相應的驅動,我選擇的是IDE的硬盤,kernel默認就支持了)
            Disk 選中Create a new virtual disk 點擊Next
            Virtual Disk Type 選中IDE,點擊Next
            Disk capacity Disk size 輸入80G (下面的Allocate all disk space now不要選中,表示在真正使用才分配磁盤空間, Split disk into 2 GB files項,可不選,如果你的系統分區為fat32格式,最好選中) 點擊Next.
            Disk file ,輸入Disk的名稱,如:disk1.vmdk ,點擊Finish.完成
            安裝CentOS 4.6(過程略過)
            安裝完成后,關閉計算機,然后Clone一臺同樣的計算機.步驟如下:

            點擊VM->Clone
            選中默認的From current state,點擊Next
            選中Create a full clone, 點擊Next
            Virtual Machine name 輸入Server(Targe),將克隆的機器命令為目標機.
            說明一下,kgdb 需要兩臺計算機通過串口進行遠程調試,兩臺計算機分別為:
            Client(Development):開發機,也稱客戶機,將在該計算機上進行程序的開發,GDB將在本計算機上運行.用于輸入命令控制Server(target)的運行.
            Server(Target): 目標機,也稱服務器,就是被調試的計算機,在Development機上開發好的內核模塊程序將拷貝到Target上運行,其運行受到Development命令的控制.
            分別為兩個系統增加一個串口,以"Output to named pipe"方式,其中:

            Client端選擇"this end is the client", "the other end is a virtual machine"
            Server端選擇"this end is the server", "the other end is a virtual machine"
            備注: 兩個pipe的名稱要相同,并且選中下面的Connect at power on,及Advanced里面的Yield CPU on poll
            以后的部分,Server上的操作與Client上的操作將以不同的背景色顯示,輸入的命令將以不同的字體顏色并帶下劃線顯示.請注意:
            Server(Target) 輸入: cat /dev/ttyS0

            系統輸出的信息: hello Client(Development) 輸入: echo "hello" >/dev/ttuS0
            串口添加完成后,使用如果命令測試:
            在Server上cat /dev/ttyS0
            然后到Client上 echo "hello" > /dev/ttyS0
            這時回到Server上,如果能看到輸入的hello,說明串口通訊正常.
            4:升級內核2.6.26(添加關于KGDB的選項)
                  說明一下,這里是要升級Server的內核,因為kgdb是要Server上運行的,但是編譯需要在Client完成(或者你也可以在Server上編譯,之后再拷貝到Client上),因為調試時Client上的gdb會用到編譯的內核及源代碼.Client也需要升級,保證Client同Server上的內核一致,這樣Client上編譯的模塊拿到Server上加載就不會有什么問題.

            首先下載kernel 2.6.26
                  我習慣在windows上下載,然后共享,再到linux使用smbclient連接,拷貝到Linux上.你也可以直接在linux上下載.
                  smbclient用法 : smbclient //192.168.0.100/share -Uadministrator 回車后,會提示輸入admin的密碼.之后就可以通過get獲取了 192.168.0.100是我在windows主機的IP,share為共享名,-U后面是用戶名

            編譯Kernel2.6.26

            進入Client(Development)系統,將linux-2.6.26.tar.bz2拷貝到/usr/src目錄下:
            cd /usr/src
            tar jxvf linux-2.6.26.tar.bz2
            ln -s linux-2.6.26 linux
            cd linux
            make menuconfig
            File System --> 下面把ext3,ext2都編譯進內核(就是把前面的M變成*)
            Kernel Hacking -->
                  選中Compile the kernel with frame pointers
                  選中KGDB:kernel debugging with remote gdb
                  并確認以下兩項也是選中的(他們應該默認是選中的)
                  > kernel debugging
                  > Compile the kernel with debug info
            對于其它選項,請按實際情況,或你的要求定制.
            在其它網友的說明里面,會有Serial port number for KGDB等選項,但是我使用的版本未找到這些選項,所以忽略過.
            保存退出
            make -j10 bzImage
            -j10表示使用10個線程進行編譯.
            make modules
            編譯內核模塊
            make modules_install
            安裝內核模塊
            make install
            安裝內核
            將Client系統中的linux-2.6.26整個目錄同步到Server上.

            在Client系統上運行下列命令:
            cd /usr/src/linux  
            scp -r linux-2.6.26 root@Server(Target)IP:/usr/src/
                 系統會提示輸入root的密碼,輸入完了就會開始復制文件了,(這里要注意,如果原系統已經是2.6.26的內核,可以只拷貝arch/i386/boot/bzImage,及System.map文件到Server上,然后修改/boot/grub/grub.conf,但由于我是從2.6.9升級上來,所以需要將整個linux原代碼目錄拷貝到Server上進行升級)
            升級Srever系統的內核
            進入Server(Target)系統,usr/src目錄:
            ln -s linux-2.6.26 linux  
            cd linux  
            make modules_install
            安裝內核模塊
            make install
            安裝內核
            安裝完成后,在/boot/目錄下會有即個新添加的文件./boot/grub/grub.conf文件也會添加一個新的啟動項,我的如下(行號不是文件的一部分):
             1 # grub.conf generated by anaconda
             2 #
             3 # Note that you do not have to rerun grub after making changes to this file
             4 # NOTICE:  You have a /boot partition.  This means that
             5 #          all kernel and initrd paths are relative to /boot/, eg.
             6 #          root (hd0,0)
             7 #          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
             8 #          initrd /initrd-version.img
             9 #boot=/dev/hda
            10 default=0
            11 timeout=5
            12 splashimage=(hd0,0)/grub/splash.xpm.gz
            13 hiddenmenu
            14 title CentOS (2.6.26)
            15     root (hd0,0)
            16     kernel /vmlinuz-2.6.26 ro root=/dev/VolGroup00/LogVol00
            17     initrd /initrd-2.6.26.img
            18 title CentOS-4 i386 (2.6.9-67.ELsmp)
            19     root (hd0,0)
            20     kernel /vmlinuz-2.6.9-67.ELsmp ro root=/dev/VolGroup00/LogVol00
            21     initrd /initrd-2.6.9-67.ELsmp.img
             
                   注意里面的NOTICE說明,我的系統/boot是一個獨立的分區,所以下面配置的文件路徑都是相對于/boot/目錄的,像 /vmlinuz-2.6.26,實際到它的絕對位置應該是/boot/vmlinuz-2.6.26. 在你的系統上請根據實際情況處理.

            修改一下grub.conf,修改成下面這樣:
             1 # grub.conf generated by anaconda
             2 #
             3 # Note that you do not have to rerun grub after making changes to this file
             4 # NOTICE:  You have a /boot partition.  This means that
             5 #          all kernel and initrd paths are relative to /boot/, eg.
             6 #          root (hd0,0)
             7 #          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
             8 #          initrd /initrd-version.img
             9 #boot=/dev/hda
            10 default=0
            11 timeout=5
            12 splashimage=(hd0,0)/grub/splash.xpm.gz
            13 hiddenmenu
            14 title CentOS (2.6.26)
            15     root (hd0,0)
            16     kernel /vmlinuz-2.6.26 ro root=/dev/VolGroup00/LogVol00 kgdboc=ttyS0,115200
            17     initrd /initrd-2.6.26.img
            18 title CentOS (2.6.26) Wait...(kernel debug)
            19     root (hd0,0)
            20     kernel /vmlinuz-2.6.26 ro root=/dev/VolGroup00/LogVol00 kgdboc=ttyS0,115200 kgdbwait
            21     initrd /initrd-2.6.26.img
            22 title CentOS-4 i386 (2.6.9-67.ELsmp)
            23     root (hd0,0)
            24     kernel /vmlinuz-2.6.9-67.ELsmp ro root=/dev/VolGroup00/LogVol00
            25     initrd /initrd-2.6.9-67.ELsmp.img
             

            說明:

            第一個啟動項在原來的基礎上添加了kgdb的參數kgdboc=ttyS0,115200
            kgdboc 的意思是 kgdb over console,這里將kgdb連接的console設置為ttyS0,波特率為115200,如果不在內核啟動項中配置該參數,可以在進入系統后執行命令:
            echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc   
            第二個啟動項,同第一個使用同一個內核,只是添加了kgdbwait參數
            kgdbwait 使 kernel 在啟動過程中等待 gdb 的連接。

            我的啟動菜單如下:
            CentOS(2.6.26)
            CentOS(2.6.26)Wait...(kernel debug)
            CentOS-4 i386(2.6.9-67.ELsmp)
            調用內核模塊,就選擇第一個,如果要調試內核啟動過程,選擇第二個.
            5.內核調試
            重啟Server,通過啟動菜單第二項CentOS(2.6.26)Wait...(kernel debug)進入系統. 只到系統出現:

                 kgdb: Registered I/O driver kgdboc
                 kgdb: Waiting for connection from remote gdb  
            進入Client系統.

            cd /usr/src/linux  
            gdb vmlinux 
            啟動gdb開始準備調試:輸出大致如下:

            GNU gdb Red Hat Linux (6.3.0.0-1.153.el4rh)
            Copyright 2004 Free Software Foundation, Inc.
            GDB is free software, covered by the GNU General Public License, and you are
            welcome to change it and/or distribute copies of it under certain conditions.
            Type "show copying" to see the conditions.
            There is absolutely no warranty for GDB.  Type "show warranty" for details.
            This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db
            library "/lib/tls/libthread_db.so.1" (gdb) set remotebaud 115200
            (gdb) target remote /dev/ttyS0
            注意:有的文章講:因為vmware的named piped不能被gdb直接使用,需要使用 socat -d -d /tmp/com_1 /dev/ttyS0轉換,然后使用轉換后的設備. socat需要自己下載安裝. 但在我的環境中,直接使用并沒有出錯.
            執行該命令后輸出如下:
            Remote debugging using /dev/ttyS0
            kgdb_breakpoint () at kernel/kgdb.c:1674
            1674  wmb(); /*Sync point after breakpoint */
            warning: shared library handler failed to enable breakpoint看到上面的內容說明已經連接成功,但Server上依然是假死狀態,這時你可以像使用本地gdb一樣設置斷點(break),單步執行(step),或其它命令.
            (gdb) cont
            繼續執行,Server就繼續下面的系統初始化了.
            系統啟動完成后的內核調試:
                進入Server后,執行命令

            echo g > /proc/sysrq-trigger
            系統同樣會中斷,進入假死狀態,等待遠程gdb的連接.KGDB可能會輸出如下信息:
            SysRq: GDB    上面的命令(echo g > /proc/sysrq-trigger)可以有一個快捷鍵(ALT-SysRq-G)代替,當然前提是你編譯內核時需要選中相關選項,并且需要修改配置文件:/etc/sysctl.conf , 我用了一下,不太好用.因為有的桌面系統中PrintScreen/SysRq鍵是用于截屏的.所以還是直接用命令來的好!
            我在~/.bashrc中添加了一句(添加完保存后,要執行source ~/.bashrc應用該配置):
            alias debug='echo g > /proc/sysrq-trigger'
            之后就可以直接輸入debug來使內核進入調試狀態.
            Server進入調試狀態后,轉換到Client系統,重復上面的步驟.
            6. Linux內核模塊(設備驅動)的調試
            編寫內核模塊,及Makefile
                  我使用的例子是Linux Device Driver 3中的例子scull. 你可以從這里下載LDD3的所有例子程序.

            進入Client系統,解壓example.tar.gz,將其中的example/scull目錄拷貝到/root/scull
            然后執行:
            cd /root/scull  
            make 
            編譯應該會出錯,因為Linux Device Driver 3的例子程序是基于2.6.10內核的,請參靠下面的說明修改這些錯誤:
            編譯scull驅動,完成后,scull目錄應該多出了scull.ko及其它中間文件.
            scp scull.ko root@targetIp:/root/
            將scull.ko模塊文件拷貝到Server上.系統應該會提示輸入密碼:

            root@targetIp's password:輸入正確密碼后,應該能看到如下信息,表示復制成功了:
            scull.ko    100%  258k 258.0kb/s 00:00進入Server系統輸入:
            cd /root/  
            insmod scull.ko 
            加載scull模塊.
            cat /sys/module/globalmem/sections/.text 
            顯示scull模塊的.text段地址.運行該命令后,會返回一個16進制的地址,如:
            0xd099a000echo g > /proc/sysrq-trigger 
            現在Server系統變成等待狀態.
            再次進入Client系統:
            cd /usr/src/linux  
            gdb vmlinux  
            (gdb) set remotebaud 115200  
            (gdb) target remote /dev/ttyS0
            Remote debugging using /dev/ttyS0
            kgdb_breakpoint () at kernel/kgdb.c:1674
            1674  wmb(); /*Sync point after breakpoint */
            warning: shared library handler failed to enable breakpoint出現上面的信息表示連接成功,但此時還不可以設置斷點.我試了N次,現在設置端點后,無論Server上對scull做什么操作,Client上的gdb都不會停止.也有人說這是gdb的BUG,gdb無法正常解析內核模塊的符號信息. 說是下載kgdb網站上的gdbmod可以解決該問題,但我試了之后發現根本沒有用. 所以只能通過命令手動加載相關符號信息:
            (gdb) add-symbol-file /root/scull/scull.ko 0xd099a000
            注意: 0xd099a000地址是在上面獲取的,命令輸入完了,系統會有如下提示信息(第二行后面的y是自己輸入的:
            add symbol table from file "/root/scull/scull.ko" at .text_addr = 0xd099a000
            (y or n)y
            Reading symbols from /root/scull/scull.ko...done.        (gdb)break scull_write

            Breakpoint 1 at 0xd099a2d9: file /root/scull/main.c,line 338.(gdb)break scull_read

            Breakpoint 2 at 0xd099a1a2: file /root/scull/main.c,line 294(gdb)cont  

            ContinuingClient上的工作暫停,回到Server系統上:
            Server現在處于運行狀態,在Server上運行下面的命令:
            cat /proc/devices | grep "scull"
            查看scull模塊分配的major.我的系統中返回如下:
            253 scull
            253 scullp
            253 scullamknod /dev/scull c 253 0
            253是剛才查詢到的版本號.
            echo "this is a test " > /dev/scull
            測試輸入函數:scull_write. 該命令輸入完成后,進程應該會停下來, 請切換到Client系統.
            cat /dev/scull
            測試輸出函數:scull_read. 該命令輸入完成后,進程應該會停下來, 請切換到Client系統.
            回到Client系統,應該能看到gdb的輸出信息:

            Breakpoint 1, scull_write (filp=0xce5870c0,buf=0xb7f44000
                  "this is a test\nias | /usr/bin/which --tty-only --read-alias
                  --show-dot --show-tilde'\n",count=15,f_pos=0xce5c5f9c)
              at /root/scull/main.c:338
            338   {   
            (gdb)_  現在就可以像調試本地程序一樣調試scull.ko模塊了.
            以同樣的方法也可以調試其它函數.(初始化函數暫時沒想到辦法調試,因為使用這種方法需要先加載后,才可以進行調試)

            你可以自由使用和轉載本文檔,轉載時請注明出處. (jie123108@163.com)

            如果可以,我想寫一個腳本自動完成這個添加符號文件的過程,簡化調試過程.
             
            Linux Device Driver 3rd中的scull 例程在2.6.26上編譯出錯的問題
            1。scripts/Makefile.build:46: *** CFLAGS was changed in "examples/scull/Makefile". Fix it to use EXTRA_CFLAGS。 停止。
                解決方法:將 Makefile 中的 CFLAGS 改為 EXTRA_CFLAGS
            2. examples/scull/main.c:17:26: error: linux/config.h: 沒有該文件或目錄
                解決方法: 將 main.c 中的這條 include 語句注釋掉。
            3. examples/scull/access.c: 在函數‘scull_u_open’中:    examples/scull/access.c:107: 錯誤: 提領指向不完全類型的指針
                解決方法:access.c 中添加:#include <linux/sched.h>
            4. examples/scull/access.c: 在函數‘scull_access_setup’中:
                examples/scull/access.c:355: 警告: 格式字符串不是一個字面字符串而且沒有待格式化的實參
                解決方法:將  kobject_set_name(&dev->cdev.kobj,  devinfo->name); 改為:
                               kobject_set_name(&dev->cdev.kobj, "%s", devinfo->name);
            因為 kobject_set_name 有一個像 printf 一樣的參數表。
            補充 : 老外作的改動http://www.cs.fsu.edu/~baker/devices/lxr/source/2.6.25/ldd-examples/基本上已經可以編譯了
            摘錄自: <<Linux Device Driver 3 中的代碼在 2.6.27 中編譯不能通過的問題>>
            參考資料:
                    <<Using 2.6.26 Linux Kernel Debugger (KGDB) with VM>>
                    <<VMware環境下用kgdb調試內核>>
                    <<Using 2.6.26 Linux Kernel Debugger (KGDB) with VM>>
             


            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/jie12310/archive/2009/09/18/4564853.aspx

            posted on 2010-05-01 21:06 小默 閱讀(1826) 評論(1)  編輯 收藏 引用 所屬分類: Linux

            評論

            # re: 【轉】在VMware環境下使用KGDB調試Linux內核及內核模塊 2010-05-15 19:17

            精彩詳細  回復  更多評論   

            導航

            統計

            留言簿(13)

            隨筆分類(287)

            隨筆檔案(289)

            漏洞

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            色青青草原桃花久久综合| 麻豆精品久久久久久久99蜜桃 | 日日狠狠久久偷偷色综合96蜜桃| 国内精品久久久久久久影视麻豆| 日本久久中文字幕| 狠狠色噜噜色狠狠狠综合久久| 国产精品久久国产精麻豆99网站| 国产巨作麻豆欧美亚洲综合久久| 日韩人妻无码精品久久免费一| 久久精品这里热有精品| 囯产极品美女高潮无套久久久| 久久无码人妻一区二区三区 | 无码人妻久久一区二区三区免费| 激情五月综合综合久久69| 2021国内久久精品| 久久97久久97精品免视看| 婷婷综合久久中文字幕蜜桃三电影 | 人妻少妇精品久久| 2021国产成人精品久久| 国产一级做a爰片久久毛片| 久久亚洲精品无码AV红樱桃| 久久久久97国产精华液好用吗| 精品国产青草久久久久福利| 久久夜色精品国产噜噜麻豆| 亚洲国产精品综合久久网络| 婷婷久久综合| 久久av免费天堂小草播放| 久久国产精品77777| 国内精品久久久久| 国内精品伊人久久久久AV影院| 99久久精品午夜一区二区| 国内高清久久久久久| 怡红院日本一道日本久久| 97热久久免费频精品99| 精品久久久无码人妻中文字幕豆芽| 国产精品久久久久久久久久影院 | 欧美伊人久久大香线蕉综合69| 99久久国产免费福利| 国产99久久九九精品无码| 久久se精品一区二区影院 | 国产一区二区三区久久|