• Linux应用调试 :使用gdb和gdbserver进行远程调试


    一.引言

      在日常程序开发中不免遇到类似空指针操作导致程序崩溃的问题,所以需要一定的手段去定位bug,而断点调试是普遍使用的技巧,比如Windows中用VC++的debug模式进单步运行、断点调试等,而且是图形化操作界面很友好,但在Linux系统中使用的是没有图形界面的调试工具-GDB(听说eclipse支持GUI调试,暂未尝试),所以需要通过指令进行操作,下面逐步介绍gdb调试环境的搭建和使用方法。

    二.gdb调试环境搭建

    (1)下载gdb工具源码:http://www.gnu.org/software/gdb/download/

    选择下载最新版本:

    注:由于个人本地arm-linux-gcc版本较低(4.4.3)不支持 C++11,后面下载编译的是 gdb-7.12

    (2)解压

       解压tar.gz文件:tar -zxvf xxx.tar.gz

       解压tar.xz文件:先 xz -d xxx.tar.xz 将 xxx.tar.xz解压成 xxx.tar 然后,再用 tar xvf xxx.tar来解包。

    (3)编译安装

    --------①编译gdb(在Linux主机上运行的工具)

        ./configure --target=arm-linux   //配置要调试的目标为arm-Linux开发板(前提已经配置了arm-linux-gcc交叉编译环境)
        make
        make install //默认安装路径可以在Makefile中看到:prefix = /usr/local

      也可以指定安装目录,比如 : make install prefix=$PWD/tmp 

      环境变量添加该路径 或 复制arm-linux-gdb到/bin目录下后便可作为系统工具使用。

    错误1:

    location.c:527:19: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
           || *argp == ''

    解决方法:  || *argp == ''  修改为  || *argp == NULL

     

    错误2:

    make[5]: 进入目录“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc”
    /home/sheldon/work/linux_project/gdb-8.2/missing makeinfo --split-size=5000000 --split-size=5000000   -I ./../../readline/doc -I ./../mi -I . 
        -o gdb.info ./gdb.texinfo
    /home/sheldon/work/linux_project/gdb-8.2/missing: 81: /home/sheldon/work/linux_project/gdb-8.2/missing: makeinfo: not found
    WARNING: 'makeinfo' is missing on your system.
             You should only need it if you modified a '.texi' file, or
             any other file indirectly affecting the aspect of the manual.
             You might want to install the Texinfo package:
             <http://www.gnu.org/software/texinfo/>
             The spurious makeinfo call might also be the consequence of
             using a buggy 'make' (AIX, DU, IRIX), in which case you might
             want to install GNU make:
             <http://www.gnu.org/software/make/>
    make[5]: *** [gdb.info] 错误 127
    make[5]: 离开目录“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc”
    make[4]: *** [subdir_do] 错误 1
    make[4]: 离开目录“/home/sheldon/work/linux_project/gdb-8.2/gdb”
    make[3]: *** [install-only] 错误 2
    make[3]: 离开目录“/home/sheldon/work/linux_project/gdb-8.2/gdb”
    make[2]: *** [install] 错误 2
    make[2]: 离开目录“/home/sheldon/work/linux_project/gdb-8.2/gdb”
    make[1]: *** [install-gdb] 错误 2
    make[1]: 离开目录“/home/sheldon/work/linux_project/gdb-8.2”
    make: *** [install] 错误 2
    sheldon@sheldon-vm:~/work/linux_pro

    解决方法:sudo apt-get install texinfo (或者从GNU下载源码自行编译安装:http://ftp.gnu.org/gnu/texinfo/

     


    --------②编译gdbserver(在Linux开发板上作为父进程运行,启动加了gdb调试信息的应用程序)

        cd gdb/gdbserver/   //继续进入到gdbserver目录
        ./configure --host=arm-linux  //配置要运行的平台为arm-Linux开发板
        make
        make install prefix=../../tmp/gdbserver //指定安装到之前的tmp目录下

      将编译生成的gdbserver通过nfs或usb复制到开发板上,后面就可以开始远程gdb调试了!

    三.调试方法

    (1)编写测试程序:

    #include <stdio.h>
    
    void C(int *p)
    {
        *p = 0x12;
    }
    
    
    void B(int *p)
    {
        C(p);
    }
    
    void A(int *p)
    {
        B(p);
    }
    
    void A2(int *p)
    {
        C(p);
    }
    
    
    int main(int argc, char **argv)
    {
        int a;
        int *p = NULL;
    
        A2(&a);  // A2 > C
        printf("a = 0x%x
    ", a);
    
        A(p);    // A > B > C  故意操作空指针
    
        return 0;
    }

      编译生成可执行文件(-g选项增加gdb调试信息):

    arm-linux-gcc test_debug.c -g -o test_debug

    (2)发现在ARM板上运行test_debug后产生段错误,接下来就启动gdbserver来定位问题:

    gdbserver 192.168.1.17:2345 ./test_debug    //开发板通过gdbserver执行test_debug,并开启网络端口监听

    (3)在PC上执行

    /bin/arm-linux-gdb ./test_debug  //读取应用程序
    target remote 192.168.1.17:2345  //通过开发板监听的网络端口传输控制指令

    然后便可使用gdb命令来远程控制程序运行进行调试:


    示例①:main函数入口打个断点,然后继续运行:

      示例②:在代码的31行处打断点,然后继续运行:

      示例③:进入函数A2执行C(p),然后继续进入函数C到*p = 0x12(此时该语句还未执行),打印*p的随机值为33620,再继续执行赋值操作后打印值为赋值的0x12即十进制18:

      更详细的使用方法可参考如下指令自行调试:

    命令

    命令缩写

    命令说明

    list

    l

    显示多行源代码

    break

    b

    设置断点,程序运行到断点的位置会停下来

    info

    i

    描述程序的状态

    run

    r

    开始运行程序

    display

    disp

    跟踪查看某个变量,每次停下来都显示它的值

    step

    s

    执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句

    next

    n

    执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)

    print

    p

    打印内部变量值

    continue

    c

    继续程序的运行,直到遇到下一个断点

    set var name=v

     

    设置变量的值

    start

    st

    开始执行程序,main函数的第一条语句前面停下来

    file

     

    装入需要调试的程序

    kill

    k

    终止正在调试的程序

    watch

     

    监视变量值的变化

    backtrace

    bt

    产看函数调用信息(堆栈)

    frame

    f

    查看栈帧

    quit

    q

    退出GDB环境

      

      后面运行到操纵空指针处便打印了相关异常信息,这样就能大致定位出具体哪条语句处出现问题:

      

    四.另一种调试方法(非单步调试):

      让程序在开发板上直接运行,当它发生错误时,令它产生core dump文件,然后使用gdb根据core dump文件找到发生错误的地方,具体步骤如下:
      (1)在ARM板上进行如下操纵:

    ulimit -c unlimited  //一般Linux系统不会产生core dump文件(默认大小0),所以需要对core文件重新设置大小
    ./test_debug      //程序出错时会在当前目录下生成名为core的文件

      如下就是产生了core文件:

      (2)将core文件复制到PC上进行如下操纵:

    /bin/arm-linux-gdb ./test_debug ./core 

       执行后便可看到程序终止的信息并提示了具体出错位置:

      另外也可以通过 bt 指令打印函数调用信息(堆栈) main->A->B->C,然后到第6行异常终止:

       

    以上便是gdb调试的一般方法,更灵活的操作技巧需要多参考相关资料加以实践~

    -end-

  • 相关阅读:
    CF521D Shop
    AGC033D Complexity
    CF576D Flights for Regular Customers
    LG4781 【模板】拉格朗日插值
    洛谷3288 SCOI2014方伯伯运椰子(分数规划+spfa)
    洛谷4606 SDOI2018战略游戏(圆方树+虚树)
    洛谷4630APIO2018铁人两项(圆方树+dp)
    CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
    CF193D Two Segments (线段树+dp)(外加两个扩展题)
    洛谷4322 SHOI2014 三叉神经树(LCT+思维)
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/10462262.html
Copyright © 2020-2023  润新知