首页 > 技术文章 > GDB程序调试工具

xcw0754 2018-10-19 11:09 原文

使用gcc/g++编译程序时加-g选项以方便调试。启动gdb时不打印提示信息可以加-q选项。

设置系统允许产生core文件:

$ulimit -c unlimited

调试由test程序产生的core文件:

$gdb ./test  core

设置输出信息时的分页功能相关命令

set pagination on    # 或者 set height <n>
set pagination off    # 等同 set height unlimited

show height   # 查看输出页面高度
show width    # 查看输出页面宽度

列出所有函数

info functions [regex]    # 不带regex的话输出数量一般很多
info functions foo    # 列出含有foo的函数名

打断点。

b <line>    # 在指定行打断点
b 12
b <func_name>    # 在指定函数打断点
b main
b <filename>:<line>    # 在指定源文件指定行打断点
b test.c:15
tb <line>    # 打临时断点,命中一次后失效
b 15 if i==0    # 打条件断点
info b    # 打印所有断点信息

在运行r之后会停留在断点处,如果断点都在同一个函数中,按n之后是不会进入其他函数的,只会直接执行。此时可以在执行函数的那一行按s来进入该函数。

如果按了s进入了某个不带调试信息的函数,那么接下来按n都会在该函数内逐行执行,可以通过敲finish快速运行完该函数。或者可以敲return <xxx>来快速跳过下面的代码行而直接返回。

在运行程序的过程中,可以直接调用某个函数,使用的是call或print指令

call foo(234)
print(foos("abc"))

打印当前域变量

p var    # var是变量名

打印所有堆栈或者指定的帧

bt    # 打印所有堆栈
frame <number>    # 打印并跳转到指定序号的帧
frame <addr>    # 打印并跳转到指定地址的帧
info frame    # 打印当前帧的信息

gdb调试活进程:

	1、加载程序
		gdb programe
	2、打断点
		b n							# 当前文件
		b file:n					# 指定文件
		b <func>					# 指定函数
		b file:<func>				# 指定文件及函数
		b +2						# 当前行的后两行
		break n thread n if a > b	# 条件断点,for内最佳
	3、查看所有断点
		info b
	4、删除所有断点
		delete
	4、禁用/使能某断点
		disable/enable b n
	5、监测变量(完事按c效果更佳)
		watch <expr>		# 变量发生变化时中断(写)
		rwatch <expr>		# 变量被读时中断
		awatch <expr>		# 变量值被读或被写时中断
		info watchpoints	# 打印所有监测点
	6、在main打个断点并开始运行
		start
	7、给程序指定运行参数
		r arg1 arg2 arg3 ...    # r表示run,其后可直接带程序参数
		set args arg1 arg2 arg3 ... # 只设置参数,但不运行
	8、锁定线程,只让当前线程运行,其他线程暂停。若停止在断点,所有线程会暂停,但是一旦继续当前线程,其他线程也可能会跑起来。
		set scheduler-locking on    # 已锁定
		set scheduler-locking off   # 已解锁

调试入门:

	c[ontinue]	继续运行程序直到下一个断点(类似于VS里的F5)
	n[ext]		逐过程步进,不会进入子函数(类似VS里的F10)
	s[etp]		逐语句步进,会进入子函数(类似VS里的F11)
	u[ntil]		运行至当前语句块结束
	finish		运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)

查看程序入口地址:

	1、readelf -h a.out 看Entry point address行
	2、info files
	2、用readelf -h 还可以看程序的大小端

gdb调试堆栈;

	1、加载
		gdb programe core 或者
		gdb core
	2、打印完整的栈
		bt
	3、切换到指定的栈
		frame n		# n从0开始到栈深
	4、打印当前栈的参数
		info args
	5、打印字符串变量(char *)
		x/s key
	6、打印变量所占空间大小
		p sizeof(key)
	7、打印当前函数的所有临时变量
		info locals
	8、把当前函数反汇编
		disassemble function
	9、打印某个变量的地址
		print &key
	10、查看所有线程
		info thread
	11、切换线程
		thread n
	12、查看当前函数的汇编
		disassemble
	13、查看当前寄存器值
		info reg
	14、查看所有线程的堆栈
		thread apply all bt
		thread apply 1-2 bt

如何调试python程序

http://www.brendangregg.com/blog/2016-08-09/gdb-example-ncurses.html

推荐阅读