1.学习链接
2.gdb的一些参数
GDB 调试主要有三种方式:
1. gdb filename 直接调试目标程序
2. gdb attach pid 附加进程
3. gdb filename corename 调试 core 文件
finish --执行完当前函数并回到函数调用点(如果在循环体内执行,则执行完整个循环,不一定会执行完当前函数)
return --停止执行当前函数并回到函数调用点
thread apply all bt 一次性答应出所有线程的信息(或thr app all bt)
3.gdb的TUI
GDB中的TUI的官方说明文档
4.GDB-COMMANDS
演示代码:
#include <stdio.h>
struct book {
// char a;
char *name;
int year;
int price;
}bk;
static int func(int n){
int sum = 0,i;
for(i = 0;i< n;i++)
{
sum += i;
}
return sum;
}
static void modify_book(void)
{
int i = 0;
while(1){
bk.name = "Linux device driver";
bk.year = i;
bk.price = i;
i++;
printf("%d\n",i);
sleep(1);
};
}
int main(int argc ,char **argv)
{
int i;
int result = 0;
for(i = 1;i<=100;i++)
{
result +=1;
}
printf("result[1-100]=%d \n ",result);
printf("result[1-250]=%d \n ",func(250));
modify_book();// 假设此行设置了断点且运行到此处停下来了,如果此时在此处如果敲s的话,会进入这个函数里面执行;如果敲n的话,会将这句话执行完.
return 0;
}
调试过程:
[root@localhost 0028-gdb]# gdb main.debug -q
Reading symbols from /home/muten/C/0028-gdb/main.debug...done.
(gdb) b 45
Breakpoint 1 at 0x401221: file 001-main.c, line 45.
(gdb) r
Starting program: /home/muten/C/0028-gdb/main.debug
result[1-100]=100
result[1-250]=31125
Breakpoint 1, main (argc=1, argv=0x7fffffffdb68) at 001-main.c:45
45 modify_book();// 假设此行设置了断点且运行到此处停下来了,如果此时在此处如果敲s的话,会进入这个函数里面执行;如果敲n的话,会将这句话执行完.
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64
(gdb) s【单步运行】
modify_book () at 001-main.c:23
(gdb) layout src
(gdb) bt【查看函数调用信息(堆栈)】
#0 modify_book () at 001-main.c:23
#1 0x0000000000401226 in main (argc=1, argv=0x7fffffffdb68) at 001-main.c:45
(gdb) p bk【查看bk的值】
$1 = {name = 0x0, year = 0, price = 0}
(gdb) p bk.year=2010【将bk.year的值改成2010】
$2 = 2010
(gdb) p bk【再次查看bk的值】
$3 = {name = 0x0, year = 2010, price = 0}
(gdb) p &bk【查看结构体的基地址】
$4 = (struct book *) 0x404050 <bk>
(gdb) x/3w 0x404050
0x404050 <bk>: 0 0 2010
(gdb) x/8w 0x404050
0x404050 <bk>: 0 0 2010 0
0x404060: 0 0 0 0
(gdb) x/16w 0x404050
0x404050 <bk>: 0 0 2010 0
0x404060: 0 0 0 0
0x404070: 0 0 0 0
0x404080: 0 0 0 0
(gdb) x/16x 0x404050【以16进制(x)看以0x404050为起始地址的16个word的地址】
0x404050 <bk>: 0x00000000 0x00000000 0x000007da 0x00000000
0x404060: 0x00000000 0x00000000 0x00000000 0x00000000
0x404070: 0x00000000 0x00000000 0x00000000 0x00000000
0x404080: 0x00000000 0x00000000 0x00000000 0x00000000
0x404050 <bk>: 0x00000000 0x00000000 0x000007da 0x00000000
0x404060: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) set *(int*)0x404058=2019【更改0x404058处对应的int类型的变量的值】
(gdb) p bk
$3 = {name = 0x0, year = 2019, price = 0}
继续运行,之后CTRL+C,TUI中看不到源码的时候说明函数进内核态了,TUI显示的代码是运行的代码,
此时运行bt
(gdb) bt Line: 24 PC: 0x4011c3
#0 0x00007ffff7ad2840 in __nanosleep_nocancel () from /lib64/libc.so.6
#1 0x00007ffff7ad26f4 in sleep () from /lib64/libc.so.6
#2 0x00000000004011c3 in modify_book () at 001-main.c:30
#3 0x0000000000401226 in main (argc=1, argv=0x7fffffffdb68) at 001-main.c:45
(gdb) finish【将#0运行完】
Run till exit from #0 0x00007ffff7ad2840 in __nanosleep_nocancel () from /lib64/libc.so.6
0x00007ffff7ad26f4 in sleep () from /lib64/libc.so.6
(gdb) finish【将#1运行完】
Run till exit from #0 0x00007ffff7ad26f4 in sleep () from /lib64/libc.so.6
modify_book () at 001-main.c:24
(gdb) bt
#0 modify_book () at 001-main.c:24
#1 0x0000000000401226 in main (argc=1, argv=0x7fffffffdb68) at 001-main.c:45
(gdb) watch bk.year
Hardware watchpoint 2: bk.year
一些图片:
5.strace+addr2line调试
strace+addr2line调试
strace 是一个集诊断、调试、统计与一体的工具,我们可以使用strace,对应用的系统调用和信号传递的跟踪结果,来对应用进行分析,以达到解决问题,或者是了解应用工作过程的目的。
strace 的简单的用法就是,执行一个指定的命令,在指定的命令结束之后,它也就退出了。
在命令执行的过程中,strace 会记录和解析命令进程的所有系统调用,以及这个进程所接收到的,所有的信号值。
-c ,统计每一系统调用的所执行的时间,次数和出错的次数等
-p ,指定进程pid
-i ,输出系统调用的入口指针
linux 下操作过程(省略部分加载信息):
strace -i ./a.out 找到段错误的地址
addr2line -e a.out 地址