调试方法

应用bug分析示例

gdb调试示例

Openwrt加入gdb调试工具:

cd ssd2xx-openwrt/18.06
make menuconfig
#---Development
#------<*>gdb

演示代码:

#include <stdio.h>
#include <string.h>
#include <sys/resource.h>

typedef struct
{
    char *buffer;
    int len;
}S_USER_DATE;

void core_generate_conf(void)
{   
    struct rlimit limit;
 
    memset(&limit, 0, sizeof(limit));
    limit.rlim_cur = RLIM_INFINITY;
    limit.rlim_max = RLIM_INFINITY;
    setrlimit(RLIMIT_CORE, &limit);
}

void data_printf(S_USER_DATE *pdata)
{
    for(int i = 0; i < pdata->len; i++)
    {
        printf("input data[%d]: %d\n", i, pdata->buffer[i]);
    }
}

void err_ctrl(S_USER_DATE *pdata)
{
    pdata->buffer = NULL;
    pdata->len = 255;
}

int main(int argc, char *argv[])
{
    char data[5] = {1, 2, 3, 4, 5};
    S_USER_DATE s_cache = {
        .buffer = data,
        .len = sizeof(data)
    };

    core_generate_conf();
    err_ctrl(&s_cache);
    data_printf(&s_cache);

    return 0;
}

运行上述代码,目录下将生成包含core关键字的调试文件:

$gcc -g demo.c -o demo
$./demo
Segmentation fault (core dumped)
$ls
core-demo-82932-1652433788  demo  demo.c

下面使用gdb对core文件调试:

$gdb -c core-demo-82932-1652433788 demo
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from demo...done.
[New LWP 82932]

warning: Unexpected size of section `.reg-xstate/82932' in core file.
Core was generated by `./demo'.
Program terminated with signal SIGSEGV, Segmentation fault.

warning: Unexpected size of section `.reg-xstate/82932' in core file.
#0  0x00000000004006af in data_printf (pdata=0x7ffce1df1370) at demo.c:25
25	        printf("input data[%d]: %d\n", i, pdata->buffer[i]);
(gdb) 

错误追踪:

(gdb) bt #跟踪错误发生时的函数调用
#0  0x00000000004006af in data_printf (pdata=0x7ffce1df1370) at demo.c:25
#1  0x000000000040075b in main (argc=1, argv=0x7ffce1df1478) at demo.c:45
(gdb) f 0 #f命令(frame)选择0号栈帧然后再查看局部变量
#0  0x00000000004006af in data_printf (pdata=0x7ffce1df1370) at demo.c:25
25	        printf("input data[%d]: %d\n", i, pdata->buffer[i]);
(gdb) p 0 #p命令(print)打印变量值
(gdb) p pdata
$1 = (S_USER_DATE *) 0x7ffce1df1370
(gdb) p pdata->buffer #此处可观察到引发段错误为 操作了空指针pdata->buffer
$2 = 0x0

断点调试:

(gdb) b 44
Breakpoint 1 at 0x400743: file demo.c, line 44.
(gdb) b 45
Breakpoint 2 at 0x40074f: file demo.c, line 45.
(gdb) i b	#在使用s_cache的函数入口设置断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400743 in main at demo.c:44
2       breakpoint     keep y   0x000000000040074f in main at demo.c:45
(gdb) run
Starting program: /home/book/pro/gdb_debug/demo 

Breakpoint 1, main (argc=1, argv=0x7fffffffddb8) at demo.c:44
44	    err_ctrl(&s_cache);
(gdb) p s_cache #在进入err_ctrl函数前s_cache的值是正确
$1 = {buffer = 0x7fffffffdcc0 "\001\002\003\004\005\177", len = 5}
(gdb) n

Breakpoint 2, main (argc=1, argv=0x7fffffffddb8) at demo.c:45
45	    data_printf(&s_cache);
(gdb) p s_cache #在进入err_ctrl函数后s_cache发生改变
$2 = {buffer = 0x0, len = 255}
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00000000004006af in data_printf (pdata=0x7fffffffdcb0) at demo.c:25
25	        printf("input data[%d]: %d\n", i, pdata->buffer[i]);
(gdb) 

注意事项:使用Makefile编译的应用程序在调试时应注意编译过程关闭strip,strip 命令会从 XCOFF 对象文件中有选择地除去行号信息、重定位信息、调试段、typchk 段、注释段、文件头以及所有或部分符号表。