It's our wits that make us men.

GDB(GNU Debugger)UNIX及UNIX-like下的调试工具

Posted on By tkly

功能 一般来说,GDB主要完成下面四个方面的功能: 1、启动程序,按照自定义的要求随心所欲的运行程序。 2、可让被调试的程序在指定的调试的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时程序中所发生的事。 4、可以改变程序,将一个BUG产生的影响修正从而测试其他BUG。

一、启动调试

调试C程序时需要在编译上加上-g参数

例如:

gcc -g helloworld.c -o helloworld

可以使用以下方式判断程序是否有调试信息

1、gdb “可执行文件”

例如:

$ gdb helloworld
Reading symbols from helloworld...(no debugging symbols found)...done.

可见此例没有调试信息,如果没有调试信息,会提示 no debugging symbols found.

如果提示信息如下,则说明程序有调试信息,可以使用GDB调试

Reading symbols from helloworld...done.

2、readelf查看段信息 例如:

$ readelf -S helloworld|grep debug
   [26] .debug_aranges    PROGBITS         0000000000000000  0000103a
   [27] .debug_info       PROGBITS         0000000000000000  0000106a
   [28] .debug_abbrev     PROGBITS         0000000000000000  00001387
   [29] .debug_line       PROGBITS         0000000000000000  00001469
   [30] .debug_str        PROGBITS         0000000000000000  00001540

如果没有任何debug信息,则不能使用GDB调试

3、file查看strip状态

$ file helloworld
helloworld: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, 
for GNU/Linux 3.2.0, BuildID[sha1]=69ee2ac21982f82c0b782bc03b8f1443bb22b2e9, with debug_info, not stripped

从最后的not stripped 可以看出,当前可执行文件helloworld有调试信息,可以调试(有not stripped并不能说明一定能调试) 当最后是stripped时,则说明该文件的符号表信息和调试信息已经被去除,不能使用gdb调试

调试时可以在程序尚未启动之前调试,也可以在程序运行时调试

1、启动调试(无参程序)

例如:

//helloworld.c
#include <stdio.h>

int main(void)
{
    printf("Hello World!\n");

	return 0;
}

先编译

$ gcc -g helloworld.c -o helloworld

然后使用gdb "可执行文件名"的方式启动调试

$ gdb helloworld

输入run命令,即可运行程序

$ run

2、启动调试(有参程序) 例如:

//helloworld.c
#include <stdio.h>

int main(int argc, char *argv[])
{
	if(1 >= argc)
	{
		printf("Usage:./helloworld [argument]\n");
		return 0;
	}
	else
	{
		printf("Hello World! %s!\n", argv[1]);
		return 0;
	}
}

先编译

$ gcc -g helloworld.c -o helloworld

然后使用gdb “可执行文件名”的方式启动调试

$ gdb helloworld

对于带参程序,此时如果要运行时,可采用如下两种方式:

1)、run “argument”

$ run tkly
(gdb) run tkly
Starting program: /mnt/c/Users/tkly/helloworld tkly
Hello World! tkly!
[Inferior 1 (process 7593) exited normally]
(gdb)

其中tkly为输入的参数

2)、在run之前,设置set args

$ set args tkly
(gdb) set args tkly
(gdb) run
Starting program: /mnt/c/Users/tkly/helloworld tkly
Hello World! tkly!
[Inferior 1 (process 7597) exited normally]

提前设置好参数,然后直接输入run启动调试

3、调试已经在运行的程序

先使用ps 命令找到程序对应的进程号

$ ps -ef | grep "进程名"

此时可以使用attach + 进程号的方式启动调试

$ gdb
(gdb) attach 7606

可能会有以下错误:

(gdb) attach 7606
Attaching to process 7606
Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.

解决方法: 切换到root用户: 将/etc/sysctl.d/10-ptrace.conf中的

kernel.yama.ptrace_scope = 1

修改为

kernel.yama.ptrace_scope = 1

4、直接调试程序对应的ID进程

可以使用gdb program pid的方式进行调试,如:

gdb helloworld 7606

或者

gdb helloworld --pid 7606

二、设置断点

1、查看已经设置的断点

info breakpoints

2、断点设置 ```c #include

int getNum() { int num; scanf(“%d”, &num); return num; }

void printNum(int num) { printf(“%d\n”, num); }

int main() { int num; num = getNum(); printNum(num);

return 0; }