GDB调试用户态程序

GDB是Linux下非常好用且强大的调试工具。GDB可以调试C、C++、Go、java、 objective-c、PHP等语言。对于一名Linux下工作的c/c++程序员,GDB是必不可少的工具,本篇以C语言来调试。

一般来说,GDB主要帮助你完成下面四个方面的功能:

1、按照自定义的方式启动运行需要调试的程序。 2、可以使用指定位置和条件表达式的方式来设置断点。 3、程序暂停时的值的监视。 4、动态改变程序的执行环境。

基本命令的操作

image.png

gdb命令拥有较多内部命令。在gdb命令提示符“(gdb)”下输入“help”可以查看所有内部命令及使用说明。

判断文件是否带有调试信息

要调试C/C++的程序,首先在编译时,要使用gdb调试程序,在使用gcc编译源代码时必须加上“-g”参数。保留调试信息,否则不能使用GDB进行调试。

有一种情况,有一个编译好的二进制文件,你不确定是不是带有-g参数,执行下 gdb xxx

如果报错 :Reading symbols from /home/minger/share/tencent/gdb/main…(no debugging symbols found)…done.

如果出现:Reading symbols from /home/minger/share/tencent/gdb/main…done.

还有使用命令readlef查看可执行文件是否带有调试功能:

readelf -S xxxx|grep debug

调试方式启动运行程序

file xxx  选择调试文件
......    一般进行断点等设置(后面讲)
r   运行程序
r  xxx  带参数运行程序

调试core文件

Core Dump:Core的意思是内存,Dump的意思是扔出来,堆出来(段错误)。开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped),这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考,能够很大程序帮助我们定位问题。那怎么生成Core文件呢?

产生coredump的条件,首先需要确认当前会话的ulimit –c,若为0,则不会产生对应的coredump,需要进行修改和设置。

即便程序core dump了也不会有core文件留下。我们需要让core文件能够产生,设置core大小为无限:

 ulimit -c unlimied

更改core dump生成路径

因为core dump默认会生成在程序的工作目录,但是有些程序存在切换目录的情况,导致core dump生成的路径没有规律,

所以最好是自己建立一个文件夹,存放生成的core文件。

我建立一个 /data/coredump 文件夹,在根目录data里的coredump文件夹。

调用如下命令:

echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern

如果生成core文件 名字 叫 core.test.9527

gdb ./core.test.9527
bt 可以查看崩溃堆栈信息

或者可以

gdb       启动
core-file core的名字
敲命令bt可以查看准确信息。

断点设置与查看源码

通过行号设置断点

格式:break 文件名 : 行号

示例中的(gdb) b test.c:18是设置了断点。断点的位置是test.c文件的18行。**使用r命令执行脚本时,当运行到18行时就会暂停**。

通过函数设置断点

格式:break [函数名]

b xxx(函数名)

设置条件断点

break test.c:6 if num>0

查看断点

info breakpoints

删除断点

delete breakpoint   示例:delete 1 (1是info命令查出来的num号)

查看源码

断点设置完后,当程序运行到断点处就会暂停。暂停的时候,我们可以查看断点附近的代码。查看代码的子命令是list,缩写形式为l。

指定行号查看代码

list first,last
示例:要查看1-20行代码   list 1,20

列出指定文件的源码

list 【文件名加行号或函数名】

单步调试与查看变量


1、next命令(可简写为n)用于在程序断住后,继续执行下一条语句。

2、step命令(可简写为s),它可以单步跟踪到函数内部。

3、continue命令(可简写为c)或者fg,它会继续执行程序,直到再次遇到断点处。

4、跳过执行–skip skip function xxx

查看变量

现在你已经会设置断点,查看断点附近的代码,并可以单步执行和继续执行。接下来你可能会想知道程序运行的一些情况,如查看变量的值。print命令正好满足了你的需求。以帮助我们进一步定位问题。

print i

当然,多个函数或者多个文件会有同一个变量名,这个时候可以在前面加上文件名或者函数名来区分:
p 'testfile.c'::i
p 'sum'::i

指针变量

print buf
打印出地址
print *buf
打印出第一个值
print *buf@i
打印出前i个值

另外值得一提的是,$可表示上一个变量,在调试链表时时经常会用到的,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容,举例:

p *linkNode  #这里显示linkNode节点内容

p *$.next #这里显示linkNode节点下一个节点的内容

设置变量

使用print命令查看了变量的值,如果感觉这个值不符合预期,想修改下这个值,再看下执行效果。这种情况下,我们该怎么办呢?通常情况下,我们会修改代码,再重新执行代码。使用gdb的set命令,一切将变得更简单。

set命令可以直接修改变量的值。

设置观察点

设置观察点的作用就是:当被观察的变量发生变化后,程序就会暂停执行,并把变量的原值(Old)和新值(New)都会显示出来。设置观察点的命令是watch。

watch num

这个时候,让程序继续运行,如果num的值发生变化,则会打印相关内容,如:

Hardware watchpoint 3: num
Old value = 1
New value = 10

原文地址:https://blog.csdn.net/chen1415886044/article/details/105094688

你可能感兴趣的:(GDB调试用户态程序)