色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 使用kgdb調(diào)試linux內(nèi)核及內(nèi)核模塊

          使用kgdb調(diào)試linux內(nèi)核及內(nèi)核模塊

          ——
          作者:xcspy 時間:2008-01-11 來源:電子產(chǎn)品世界 收藏

          1. 幾種內(nèi)核調(diào)試工具比較

          kdb:只能在匯編代碼級進行調(diào)試;
               優(yōu)點是不需要兩臺機器進行調(diào)試。

          gdb:在調(diào)試模塊時缺少一些至關重要的功能,它可用來查看內(nèi)核的運行情況,包括反匯編內(nèi)核函數(shù)。

          kgdb:能很方便的在源碼級對內(nèi)核進行調(diào)試,缺點是kgdb只能進行遠程調(diào)試,它需要一根串口線及兩臺機器來調(diào)試內(nèi)核(也可以是在同一臺主機上用vmware軟件運行兩個操作系統(tǒng)來調(diào)試)

          使用kdb和gdb調(diào)試內(nèi)核的方法相對比較簡單,這里只描述如何使用kgdb來調(diào)試內(nèi)核。

          2.軟硬件準備

          環(huán)境:
          一臺開發(fā)機developer(192.168.16.5 com1),一臺測試機target(192.168.16.30 com2),都預裝redhat 9;一根串口線

          下載以下軟件包:
          linux內(nèi)核2.4.23         linux-2.4.23.tar.bz2
          kgdb內(nèi)核補丁1.9版       linux-2.4.23-kgdb-1.9.patch
          可調(diào)試內(nèi)核模塊的gdb     gdbmod-1.9.bz2

          3.ok,開始

          3.1 測試串口線
          物理連接好串口線后,使用一下命令進行測試,stty可以對串口參數(shù)進行設置

          在developer上執(zhí)行:
          stty ispeed 115200 ospeed 115200 -F /dev/ttyS0
          echo hello > /dev/ttyS0
          在target上執(zhí)行:
          stty ispeed 115200 ospeed 115200 -F /dev/ttyS1
          cat /dev/ttyS1

          串口線沒問題的話在target的屏幕上顯示hello

          3.2 安裝與配置

          3.2.1 安裝

          下載linux-2.4.23.tar.bz2,linux-2.4.23-kgdb-1.9.patch,gdbmod-1.9.bz2到developer的/home/liangjian目錄

          *在developer機器上

          #cd /home/liangjian
          #bunzip2 linux-2.4.23.tar.bz2
          #tar -xvf linux-2.4.23.tar
          #bunzip2 gdbmod-1.9.bz2
          #cp gdbmod-1.9 /usr/local/bin
          #cd linux-2.4.23
          #patch -p1 < ../linux-2.4.23-kgdb-1.9.patch
          #make menuconfig

          在Kernel hacking配置項中將以下三項編譯進內(nèi)核
          KGDB: Remote (serial) kernel debugging with gdb
          KGDB: Thread analysis
          KGDB: Console messages through gdb

          注意在編譯內(nèi)核的時候需要加上-g選項
          #make dep;make bzImage

          使用scp進行將相關文件拷貝到target上(當然也可以使用其它的網(wǎng)絡工具)
          #scp arch/i386/boot/bzImage root@192.168.16.30:/boot/vmlinuz-2.4.23-kgdb
          #scp System.map root@192.168.16.30:/boot/System.map-2.4.23-kgdb
          #scp arch/i386/kernel/gdbstart  root@192.168.16.30:/sbin
          gdbstart為kgdb提供的一個工具,用于激活內(nèi)核鉤子,使內(nèi)核處于調(diào)試狀態(tài)

          {{分頁}}

          3.2.2 配置

          *在developer機器上

          在內(nèi)核源碼目錄下編輯一文件.gdbinit(該文件用以對gdb進行初始化),內(nèi)容如下:
          #vi .gdbinit
          define rmt
          set remotebaud 115200
          target remote /dev/ttyS0
          end
          #
          以上在.gdbinit中定義了一個宏rmt,該宏主要是設置使用的串口號和速率

          *在target機器上

          編輯/etc/grub.conf文件,加入以下行:
          #vi /etc/grub.conf
          title Red Hat Linux (2.4.23-kgdb)
              root (hd0,0)
              kernel /boot/vmlinuz-2.4.23-kgdb ro root=/dev/hda1
          #

          在root目錄下建立一個腳本文件debugkernel,內(nèi)容如下:
          #vi debug
          #!/bin/bash
          gdbstart -s 115200 -t /dev/ttyS1 <<EOF

          EOF
          #chmod +x debugkernel
          這個腳本主要是調(diào)用gdbstart程序設置target機上使用的串口及其速率,并使內(nèi)核處于調(diào)試狀態(tài)

          3.3 開始調(diào)試

          target上的內(nèi)核或內(nèi)核模塊處于調(diào)試狀態(tài)時,可以查看其變量、設置斷點、查看堆棧等,并且是源碼級的調(diào)試,和用gdb調(diào)試用戶程序一樣

          3.3.1 內(nèi)核啟動后調(diào)試

          *在target機器上

          重啟系統(tǒng),選擇以 2.4.23-kgdb內(nèi)核啟動,啟動完成后運行debugkenel,
          這時內(nèi)核將停止運行,在控制臺屏幕上顯示信息,并等待來自developer的
          串口連接

          #./debug
          About to activate GDB stub in the kernel on /dev/ttyS1
          Waiting for connection from remote gdb...

          *在developer機器上

          #cd /home/liangjian/linux-2.4.23
          # gdb vmlinux
          GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
          Copyright 2003 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"...

          執(zhí)行rmt宏
          (gdb) rmt
          breakpoint () at kgdbstub.c:1005
          1005                    atomic_set(&kgdb_setting_breakpoint, 0);

          這時target上的內(nèi)核處于調(diào)試狀態(tài),可以查看其變量、設置斷點、查看堆棧等,和用gdb調(diào)試用戶程序一樣

          查看堆棧
          (gdb) bt
          #0  breakpoint () at kgdbstub.c:1005
          #1  0xc0387f48 in init_task_union ()
          #2  0xc01bc867 in gdb_interrupt (irq=3, dev_id=0x0, regs=0xc0387f98) at
          gdbserial.c:158
          #3  0xc010937b in handle_IRQ_event (irq=3, regs=0xc0387f98, action=0xce5a9860)
          at irq.c:452
          #4  0xc0109597 in do_IRQ (regs=
                {ebx = -1072671776, ecx = -1, edx = -1070047232, esi = -1070047232, edi
          = -1070047232, ebp = -1070039092, eax = 0, xds
          = -1070071784, xes = -1070071784, orig_eax = -253, eip = -1072671729, xcs =
          16, eflags = 582, esp = -1070039072, xss = -1072671582}) at irq.c:639
          #5  0xc010c0e8 in call_do_IRQ ()

          查看jiffies變量的值
          (gdb) p jiffies
          $1 = 76153

          如果想讓target上的內(nèi)核繼續(xù)運行,執(zhí)行continue命令
          (gdb) continue
          Continuing.

          3.3.2 內(nèi)核在引導時調(diào)試

          kgdb可以在內(nèi)核引導時就對其進行調(diào)試,但并不是所有引導過程都是可調(diào)試的,如在kgdb 1.9版中,它在init/main.c的start_kernel()函數(shù)中插入以下代碼:
          start_kernel()
          {
              ......
                  smp_init();
          #ifdef CONFIG_KGDB
                  if (gdb_enter) {
                          gdb_hook();             /* right at boot time */
                  }
          #endif
              ......
          }

          所以在smp_init()之前的初始化引導過程是不能調(diào)試的。

          {{分頁}}

          另外要想讓target的內(nèi)核在引導時就處于調(diào)試狀態(tài),需要修改其/etc/grub.conf文件為如下形式:
          title Red Hat Linux (2.4.23-kgdb)
              root (hd0,0)
              kernel /boot/vmlinuz-2.4.23-kgdb ro root=/dev/hda1 gdb gdbttyS=1 gdbbaud=115200

          *在target機器上

          引導2.4.23-kgdb內(nèi)核,內(nèi)核將在短暫的運行后暫停并進入調(diào)試狀態(tài),打印如下信息:
          Waiting for connection from remote gdb...

          *在developer機器上

          #cd /home/liangjian/linux-2.4.23
          # gdb vmlinux
          GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
          Copyright 2003 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"...

          執(zhí)行rmt宏
          (gdb) rmt
          breakpoint () at kgdbstub.c:1005
          1005                    atomic_set(&kgdb_setting_breakpoint, 0);

          查看當前堆棧
          (gdb) bt
          #0  breakpoint () at kgdbstub.c:1005
          #1  0xc0387fe0 in init_task_union ()
          #2  0xc01bc984 in gdb_hook () at gdbserial.c:250
          #3  0xc0388898 in start_kernel () at init/main.c:443

          在do_basic_setup函數(shù)處設置斷點,并讓內(nèi)核恢復運行
          (gdb) b do_basic_setup
          Breakpoint 1 at 0xc0388913: file current.h, line 9.
          (gdb) continue
          Continuing.
          [New Thread 1]
          [Switching to Thread 1]

          Breakpoint 1, do_basic_setup () at current.h:9
          9               __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));

          內(nèi)核在do_basic_setup斷點處停止運行后查看當前堆棧
          (gdb) bt
          #0  do_basic_setup () at current.h:9
          (gdb)

           

          3.3.3 內(nèi)核模塊調(diào)試調(diào)試

          要想調(diào)試內(nèi)核模塊,需要相應的gdb支持,kgdb的主頁上提供了一個工具gdbmod,它修正了gdb 6.0在解析模塊地址時的錯誤,可以用來正確的調(diào)試內(nèi)核模塊

          *在developer機器上

          寫了個測試用的內(nèi)核模塊orig,如下:
          void xcspy_func()
          {
              printk("<1>xcspy_funcn");
              printk("<1>aaaaaaaaaaan");
          }

          int xcspy_init()
          {
              printk("<1>xcspy_init_modulen");
                 
              return 0;
          }

          void xcspy_exit()
          {
              printk("<1>xcspy_cleanup_modulen");
          }

          module_init(xcspy_init);
          module_exit(xcspy_exit);

          {{分頁}}

          編譯該模塊:
          #cd /home/liangjian/lkm
          #gcc -D__KERNEL__ -DMODULE -I/home/liangjian/linux-2.4.23/include -O -Wall -g -c -o orig.o orig.c
          #scp orig.o root@192.168.16.30:/root

          開始調(diào)試:
          # gdbmod vmlinux
          GNU gdb 6.0
          Copyright 2003 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 "i686-pc-linux-gnu"...

          設置符號文件的搜索路徑
          (gdb) set solib-search-path /home/liangjian/lkm

          執(zhí)行rmt宏
          (gdb) rmt
          breakpoint () at kgdbstub.c:1005
          1005                    atomic_set(&kgdb_setting_breakpoint, 0);

          設置斷點使得可以調(diào)試內(nèi)核模塊的init函數(shù),查內(nèi)核源碼可知,內(nèi)核是通過module.c文件的第566行(sys_init_module函數(shù)中)mod->init來調(diào)用模塊的init函數(shù)的
          (gdb) b module.c:566
          Breakpoint 1 at 0xc011cd83: file module.c, line 566.
          (gdb) c
          Continuing.
          [New Thread 1352]
          [Switching to Thread 1352]

          這時在target機器上執(zhí)行insmod orig.o,developer則相應的在斷點處被暫停,如下
                                                                                                                                   
          Breakpoint 1, sys_init_module (name_user=0xc03401bc "