使用gdb调试当前运行的程序
来源:互联网 发布:python 使用 编辑:程序博客网 时间:2024/04/25 07:36
使用gdb调试当前运行的程序
http://wiki.ubuntu.org.cn/index.php?title=%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F&variant=zh-hans
http://blog.csdn.net/wfing/archive/2010/09/17/5890382.aspx
http://blog.csdn.net/chenglian_999/archive/2009/11/15/4813469.aspx
用gdb可以调试当前的程序的使用情况,读出他的参数。
以下用一个简单的程序做为例子:来说明gdb的调试。
第一步 编译一个死循环程序。
/* File name malloc.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getmem(void **p, int num){
*p = (void *)malloc(num);
}
void test(void){
char *str = NULL;
getmem((void **)&str, 100);
strcpy(str, "Hello");
printf("%s\n", str);
}
int main(void){
int i = 0;
while(1){
if (i == 1){
test();
return 1;
}
}
return 0;
}
我们可以看出,这个程序就是malloc一段内存空间,用来供strcpy使用,由于只是调试一下,就没有在test程序中加上一些关于strcpy的正确性判断语句。
函数的正常退出的情况是i==1,但是程序运行过程中根本无法使i==1成立。i的变量的值将会在使用gdb时用到。
开始编译
$gcc -g malloc.c
得用gdb,加上-g还是需要的。生成的可执行文件为a.out
第二步 让gdb连接到正在执行的进程上去
首先运行程序。
$./a.out
明显的,是一个死循环。
重新开一个shell
$ps -u
我的机器的运行情况如下所示:
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
wyc 7712 0.0 0.1 6092 3644 pts/8 Ss 10:24 0:00 bash
wyc 7880 0.0 0.1 6092 3608 pts/9 Ss 10:27 0:00 bash
wyc 7929 0.0 0.3 10848 6468 pts/9 S+ 10:28 0:00 gdb
wyc 8347 93.0 0.0 1652 284 pts/8 R+ 10:42 0:13 ./a.out
...
看到没有? ./a.out的进程号是8347。
现在启动gdb
$gdb
由于是调试运行的进程,不是可执行文件,后面不需要跟任何参数。在用 gdb调试运行状态下的程序时,最核心的就是gdb内部的attach命令
用法为
(gdb) attach
这是我的机器上的例子:
$ gdb
GNU gdb (GDB) 7.1.50.20100621
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i686-pc-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 8347
Attaching to process 8347
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$1 = 0
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) i=1
Undefined info command: "=1". Try "help info".
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) set var i=1
(gdb) l
14 }
15
16 int main(void){
17 int i = 0;
18 while(1){
19 if (i == 1){
20 test();
21 return 1;
22 }
23 }
(gdb) n
20 test();
(gdb)
21 return 1;
(gdb)
25 }
(gdb)
0xb7f47775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited with code 01.
(gdb)
在运行到第20行命令的时候,可以看一下到运行./a.out的那个shell,应该hello字符串在标准输出上了。当gdb中显示进程退出时,./a.out的shell应该结束了当前进程了。
在gdb中用set var i=1 来修改变量i的值(用set i=1不能识别命令),使程序能够正常退出。
在调试时,当前程序调用的所有库也全部都出来了。这个例子中的
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
是a.out程序所调用的全部库。可以用这种办法分析当前运行的程序的库的调用情况。
千万不要关掉gdb,以下调试更精彩:
第三步 在gdb中重启程序
在上面已经知道了程序正常退出了,但是gdb还没有退出,这时在gdb中运行run效果如何?
(gdb) run
Starting program: /home/wyc/desktop/my_program/review/a.out
下面是死循环了...
接下Ctrl+c,给gdb发个SIGINT的信号。
^C
Program received signal SIGINT, Interrupt.
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$2 = 0
(gdb) set var i=1
(gdb) n
20 test();
(gdb) n
Hello
21 return 1;
(gdb) n
25 }
(gdb) n
0xb7e7b775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited with code 01.
可以看出,用gdb连接进程后,他会找到运行这个进程所需的全部文件,当前进程关闭后,仍然可以在gdb中启动这个程序。
不得不佩服GDB的调试功能的强大
gdb中的其它命令,就看你分析程序时是否用到了,例如下面的一些简单的命令:
以下用一个简单的程序做为例子:来说明gdb的调试。
第一步 编译一个死循环程序。
/* File name malloc.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getmem(void **p, int num){
*p = (void *)malloc(num);
}
void test(void){
char *str = NULL;
getmem((void **)&str, 100);
strcpy(str, "Hello");
printf("%s\n", str);
}
int main(void){
int i = 0;
while(1){
if (i == 1){
test();
return 1;
}
}
return 0;
}
我们可以看出,这个程序就是malloc一段内存空间,用来供strcpy使用,由于只是调试一下,就没有在test程序中加上一些关于strcpy的正确性判断语句。
函数的正常退出的情况是i==1,但是程序运行过程中根本无法使i==1成立。i的变量的值将会在使用gdb时用到。
开始编译
$gcc -g malloc.c
得用gdb,加上-g还是需要的。生成的可执行文件为a.out
第二步 让gdb连接到正在执行的进程上去
首先运行程序。
$./a.out
明显的,是一个死循环。
重新开一个shell
$ps -u
我的机器的运行情况如下所示:
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
wyc 7712 0.0 0.1 6092 3644 pts/8 Ss 10:24 0:00 bash
wyc 7880 0.0 0.1 6092 3608 pts/9 Ss 10:27 0:00 bash
wyc 7929 0.0 0.3 10848 6468 pts/9 S+ 10:28 0:00 gdb
wyc 8347 93.0 0.0 1652 284 pts/8 R+ 10:42 0:13 ./a.out
...
看到没有? ./a.out的进程号是8347。
现在启动gdb
$gdb
由于是调试运行的进程,不是可执行文件,后面不需要跟任何参数。在用 gdb调试运行状态下的程序时,最核心的就是gdb内部的attach命令
用法为
(gdb) attach
这是我的机器上的例子:
$ gdb
GNU gdb (GDB) 7.1.50.20100621
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i686-pc-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 8347
Attaching to process 8347
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$1 = 0
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) i=1
Undefined info command: "=1". Try "help info".
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) set var i=1
(gdb) l
14 }
15
16 int main(void){
17 int i = 0;
18 while(1){
19 if (i == 1){
20 test();
21 return 1;
22 }
23 }
(gdb) n
20 test();
(gdb)
21 return 1;
(gdb)
25 }
(gdb)
0xb7f47775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited with code 01.
(gdb)
在运行到第20行命令的时候,可以看一下到运行./a.out的那个shell,应该hello字符串在标准输出上了。当gdb中显示进程退出时,./a.out的shell应该结束了当前进程了。
在gdb中用set var i=1 来修改变量i的值(用set i=1不能识别命令),使程序能够正常退出。
在调试时,当前程序调用的所有库也全部都出来了。这个例子中的
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
是a.out程序所调用的全部库。可以用这种办法分析当前运行的程序的库的调用情况。
千万不要关掉gdb,以下调试更精彩:
第三步 在gdb中重启程序
在上面已经知道了程序正常退出了,但是gdb还没有退出,这时在gdb中运行run效果如何?
(gdb) run
Starting program: /home/wyc/desktop/my_program/review/a.out
下面是死循环了...
接下Ctrl+c,给gdb发个SIGINT的信号。
^C
Program received signal SIGINT, Interrupt.
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$2 = 0
(gdb) set var i=1
(gdb) n
20 test();
(gdb) n
Hello
21 return 1;
(gdb) n
25 }
(gdb) n
0xb7e7b775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited with code 01.
可以看出,用gdb连接进程后,他会找到运行这个进程所需的全部文件,当前进程关闭后,仍然可以在gdb中启动这个程序。
不得不佩服GDB的调试功能的强大
gdb中的其它命令,就看你分析程序时是否用到了,例如下面的一些简单的命令:
常用的bt, p , p/x , setp, info registers, break , jump ......
- 使用gdb调试当前运行的程序
- 使用gdb调试当前运行的程序
- 使用gdb调试当前运行的程序
- 使用gdb调试当前运行的程序
- 使用gdb调试当前运行的程序
- gdb调试当前运行的程序
- 使用gdb调试正在运行的程序
- gdb调试运行的程序
- 使用arm-elf-gdb调试SkyEye上运行的程序
- 使用gdb调试运行时的程序小技巧
- 使用gdb调试运行时的程序小技巧
- 使用gdb调试运行时的程序小技巧
- 使用gdb调试运行时的程序小技巧
- 使用gdb调试运行时的程序小技巧
- 使用gdb调试运行时的程序小技巧 -转
- GDB调试程序的使用
- GDB调试(正在运行的程序)
- GDB怎么调试运行着的程序
- 【学习笔记三】最基本的JAVA基础[数据类型,运算符]
- MacBook上最简单的三系统安装教程
- [Javascript入门]Javascript之初体验1
- hadoop 0.20.2集群配置入门
- 各种平板电脑(IPAD2,chromebook)功耗大比拼
- 使用gdb调试当前运行的程序
- SGU 107
- 广州传智播客.Net训练营VS网页平面UI设计班——联谊篇
- 求子数组最大和的解决方法详解
- Effective Java 第 20 条: 类层次优于标签类
- 基于同态滤波器(Homomorphic Filtering)的运动目标检测算法
- fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "stdafx.h
- 开发者必备的6款源码搜索引擎
- zend framework2使用教程【二】–读取数据