峥嵘岁月

joshua_yu的网络空间

俞峥ID:joshua_yu
103604次访问,排名850好友6人,关注者15
人生总有些阶段,新的起点,新的心情,没有好也没有坏,生活总是辩证而真实地存在,感谢所有人!
joshua_yu的文章
原创 44 篇
翻译 2 篇
转载 42 篇
评论 30 篇
joshua的公告
联系方式: QQ:404271575 MSN:joshua_yu@263.net
最近评论
wBlf_www:请问我在过滤函数中截获所有收发数据包,会否有漏包的现象,我发现通过web发邮件,截获的数据不能恢复出邮件发出的状态(邮件包括内容和多个附件)。
wBlf_www:请问我在过滤函数中截获所有收发数据包,会否有漏包的现象,我发现通过web发邮件,截获的数据不能恢复出邮件发出的状态(邮件包括内容和多个附件)。
ohyeath:在你的工程文件里面设置一下就可以了,project->setting->c/c++->preprosessor->addtional include headers 添加你的sdk路径,
ohyeath:在你的工程文件里面设置一下就可以了,project->setting->c/c++->preprosessor->addtional include headers 添加你的sdk路径,
ohyeath:在你的工程文件里面设置一下就可以了,project->setting->c/c++->preprosessor->addtional include headers 添加你的sdk路径,
文章分类
收藏
    相册
    08年第一期儿子照片
    过年
    交大新面貌
    我的可爱儿子
    周末烧烤之众生相
    关注的Blog
    EVA的回收站
    joyfire的space
    Kendiv的专栏
    PJF的Blog
    WebCrazy的Blog
    孟言的blog
    野路子(http://wulujia.com)
    铁卷大成天下
    网络收藏夹
    China CISSP论坛(文档保护)
    China Uniix
    developerWorks Linux 专栏
    docshow
    linux伊甸园
    OSR在线论坛
    PKI论坛
    reactos
    rootkit论坛
    Sysinternals论坛
    中国Linux公社
    中国Linux论坛
    协议分析网论坛
    安全焦点
    看雪技术学院论坛
    驱动开发网
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 (转载)使用kgdb调试linux内核及内核模块收藏

    新一篇: 基于 linux 平台的 libpcap 源代码分析 | 旧一篇: (转载)Linux 调试技术

    使用kgdb调试linux内核及内核模块

    创建时间:2005-09-09
    文章属性:原创
    文章提交:xcspy (xcspy.com_at_gmail.com)

    作者:xcspy成员 ladybug
    E-mail:xcspy.com@gmail.com
    主页:www.xcspy.com

    1. 几种内核调试工具比较

    kdb:只能在汇编代码级进行调试;
         优点是不需要两台机器进行调试。

    gdb:在调试模块时缺少一些至关重要的功能,它可用来查看内核的运行情况,包括反汇编内
    核函数。

    kgdb:能很方便的在源码级对内核进行调试,缺点是kgdb只能进行远程调试,它需要一根串
    口线及两台机器来调试内核(也可以是在同一台主机上用vmware软件运行两个操作系统来调试
    )

    使用kdb和gdb调试内核的方法相对比较简单,这里只描述如何使用kgdb来调试内核。

    2.软硬件准备

    环境:
    一台开发机developer(192.168.16.5 com1),一台测试机target(192.168.16.30 com2),都
    预装redhat 9;一根串口线

    下载以下软件包:
    linux内核2.4.23         linux-2.4.23.tar.bz2
    kgdb内核补丁1.9版       linux-2.4.23-kgdb-1.9.patch
    可调试内核模块的gdb     gdbmod-1.9.bz2

    3.ok,开始

    3.1 测试串口线
    物理连接好串口线后,使用一下命令进行测试,stty可以对串口参数进行设置

    在developer上执行:
    stty ispeed 115200 ospeed 115200 -F /dev/ttyS0
    echo hello > /dev/ttyS0
    在target上执行:
    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配置项中将以下三项编译进内核
    KGDB: Remote (serial) kernel debugging with gdb
    KGDB: Thread analysis
    KGDB: Console messages through gdb

    注意在编译内核的时候需要加上-g选项
    #make dep;make bzImage

    使用scp进行将相关文件拷贝到target上(当然也可以使用其它的网络工具)
    #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提供的一个工具,用于激活内核钩子,使内核处于调试状态

    3.2.2 配置

    *在developer机器上

    在内核源码目录下编辑一文件.gdbinit(该文件用以对gdb进行初始化),内容如下:
    #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,内容如下:
    #vi debug
    #!/bin/bash
    gdbstart -s 115200 -t /dev/ttyS1 <<EOF

    EOF
    #chmod +x debugkernel
    这个脚本主要是调用gdbstart程序设置target机上使用的串口及其速率,并使内核处于调试
    状态

    3.3 开始调试

    target上的内核或内核模块处于调试状态时,可以查看其变量、设置断点、查看堆栈等,并
    且是源码级的调试,和用gdb调试用户程序一样

    3.3.1 内核启动后调试

    *在target机器上

    重启系统,选择以 2.4.23-kgdb内核启动,启动完成后运行debugkenel,
    这时内核将停止运行,在控制台屏幕上显示信息,并等待来自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"...

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

    这时target上的内核处于调试状态,可以查看其变量、设置断点、查看堆栈等,和用gdb调试
    用户程序一样

    查看堆栈
    (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上的内核继续运行,执行continue命令
    (gdb) continue
    Continuing.

    3.3.2 内核在引导时调试

    kgdb可以在内核引导时就对其进行调试,但并不是所有引导过程都是可调试的,如在kgdb 1
    .9版中,它在init/main.c的start_kernel()函数中插入以下代码:
    start_kernel()
    {
        ......
            smp_init();
    #ifdef CONFIG_KGDB
            if (gdb_enter) {
                    gdb_hook();             /* right at boot time */
            }
    #endif
        ......
    }

    所以在smp_init()之前的初始化引导过程是不能调试的。

    另外要想让target的内核在引导时就处于调试状态,需要修改其/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=115
    200

    *在target机器上

    引导2.4.23-kgdb内核,内核将在短暂的运行后暂停并进入调试状态,打印如下信息:
    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"...

    执行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函数处设置断点,并让内核恢复运行
    (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));

    内核在do_basic_setup断点处停止运行后查看当前堆栈
    (gdb) bt
    #0  do_basic_setup () at current.h:9
    (gdb)

    3.3.3 内核模块调试调试

    要想调试内核模块,需要相应的gdb支持,kgdb的主页上提供了一个工具gdbmod,它修正了g
    db 6.0在解析模块地址时的错误,可以用来正确的调试内核模块

    *在developer机器上

    写了个测试用的内核模块orig,如下:
    void xcspy_func()
    {
        printk("<1>xcspy_func\n");
        printk("<1>aaaaaaaaaaa\n");
    }

    int xcspy_init()
    {
        printk("<1>xcspy_init_module\n");
           
        return 0;
    }

    void xcspy_exit()
    {
        printk("<1>xcspy_cleanup_module\n");
    }

    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

    开始调试:
    # 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

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

    设置断点使得可以调试内核模块的init函数,查内核源码可知,内核是通过module.c文件的
    第566行(sys_init_module函数中)mod->init来调用模块的init函数的
    (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机器上执行insmod orig.o,developer则相应的在断点处被暂停,如下
                                                                                   
                                             
    Breakpoint 1, sys_init_module (name_user=0xc03401bc "\001",
    mod_user=0x80904d8) at module.c:566
    566             if (mod->init && (error = mod->init()) != 0) {

    使用step命令进入模块的init函数
    (gdb) step
    xcspy_init () at orig.c:12
    12              printk("<1>xcspy_init_module\n");
    (gdb) n
    15      }
    (gdb)

    说明:
    调试内核模块的非init函数相对比较简单,只要先在target上执行insmod orig.o,这时由于
    模块的符号被加载,可以直接在developer的gdb中对想调试的模块函数设置断点,如bt xcs
    py_func,后面当xcspy_func被调用时就进入了调试状态。
    如果想调试内核模块的init函数,由于在执行insmod之前模块的符号还没有被加载,不能直
    接对模块的init函数设置断点,所以相对来说要困难一些。可以采用两种变通的方法:1,采
    用上面介绍的在内核调用模块的init函数被调用之前的某处插入断点,如bt sys_init_modu
    le()或bt module.c:566;2,在developer上让内核处于运行状态,在target上先执行一遍in
    smod orig.o,这时orig.o的符号已经被加载到内存中,可以直接在developer的gdb中对模块
    的init函数设置断点,如bt xcspy_init,然后在target上rmmod orig.o,当下次在target上
    重新加载orig.o时就进入了调试状态,developer在xcspy_init处被暂停。

    发表于 @ 2006年02月03日 22:23:00|评论(loading...)|编辑|收藏

    新一篇: 基于 linux 平台的 libpcap 源代码分析 | 旧一篇: (转载)Linux 调试技术

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © joshua