码迷,mamicode.com
首页 > 数据库 > 详细

Linux系统调试--gdb

时间:2015-02-01 01:51:55      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

GDB是一个强大的GNU Project调试器。通过gdb你能够查看另一个程序的执行过程,或者当程序崩溃时正在做什么事情。

GDB主要通过以下4个方面来帮助你找出程序中的bug:  

  • 运行你的程序,设置所有能够影响程序运行的东西   
  • 能够使你的程序在指定的条件下停止
  • 当你程序停止时,你能够检查发生了什么
  • 改变你的程序(如改变当前变量的值),这样你可以试着去改正由bug产生的问题

现在,GDB可以调试用Ada, C, C++, Objective-C, Pascal等语言编写的程序。而且GDB支持本机(native)调试和远程(remote)调试。

一. gdb的基本使用

首先通过一个例子来介绍gdb的使用和命令:

程序名:main.c

#include <stdlib.h>                                                             
#include <stdio.h>

void fa() 
{
    int a = 0;
    int loop = 10; 
    while(loop--){
        sleep(1);
        printf("a = %d\n", a++);
    }   
}

void fb() 
{
    fa();
}

int main(int argc, char **argv)
{
    int m;
    char *str="hello world\n";
    printf("%s",str);
    m = 1;
    m = 2;
    fb();
    return 0;
}

 

编译时必须加-g选项,否则编译出来的可执行文件没有debug符号,我们在debug时候就看不到源代码了。

编译命令: gcc -g main.c 

编译出来的可执行文件默认命名为a.out

1. 开始调试

一般情况下,直接通过指定可执行程序作为gdb的参数来启动调试:

  $gdb program  

或者在gdb启动后,使用file 可执行程序 来加载被调试程序

  (gdb)file program

也可以直接调试指定的进程:

  $gdb -p process_id

 

[root@ubuntu:~]$ gdb a.out

GNU gdb (Ubuntu 7.7-0ubuntu3.1) 7.7
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
(gdb)

2. 添加断点

break:(可简写为 b)

  

break [function name]         给某个函数设置断点

break [line number]         给某一行添加断点

break [+offset / -offset]       给当前行号的正/负偏移添加端点

break [filename: line number]     在某个文件的那行添加端点

break [*address]           在程序中的某个地址设置端点

break ... if [condition]        当condition满足时,程序停止

    

例如

(gdb) b main
Breakpoint 1 at 0x80484ad: file main.c, line 22.
(gdb) b 6

(gdb) b *0x8048497
Breakpoint 2 at 0x8048497: file main.c, line 15.

(gdb) break fb if loop=90   //断点设置在fb函数中,当loop==90时,程序停止

 

3. 查看断点

info b

(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x080484ad in main at main.c:22
2 breakpoint keep y 0x08048453 in a at main.c:6

4. 运行

run

  运行程序,知道遇到断点停止

c

  当程序停止时,执行c继续运行程序

next

  单步执行程序,遇到函数会直接执行过该函数,不会进入

step

  单步执行程序,遇到函数会进入函数执行

until

  Execute until the program reaches a source line greater than the current

  or a specified location (same args as break command) within the current frame.

finish

  运行直到当前的栈返回。一般用于跳出当前执行的函数

5. 显示原码 list

list [line number]

list [filename: line number]

list [+offset]

list [-offset]

list [function]

list [filename: function]

list [*address]

 

6.watchpoint

watchpoint用来指定表达式或变量在程序执行过程中是否有变动,如果有变动则程序停止。

watch
  为表达式中的变量设置一个watchpoint
rwatch
  当表达式中变量被读时,程序停止
awatch
  当表达式中变量被读或被写时,程序停止
info watchpoints
  列出当前设置的所有watchpoint

 

例如:

(gdb) awatch m
Hardware access (read/write) watchpoint 2: m

7. bt

查看程序运行是的栈信息

(gdb) bt

#0 0xb7fdd424 in __kernel_vsyscall ()
#1 0xb7ec9340 in __nanosleep_nocancel ()
at ../sysdeps/unix/syscall-template.S:81
#2 0xb7ec910d in __sleep (seconds=0) at ../sysdeps/unix/sysv/linux/sleep.c:137
#3 0x0804846f in fa () at main.c:9
#4 0x080484a2 in fb () at main.c:16
#5 0x080484de in main (argc=1, argv=0xbffff6b4) at main.c:26

8. 打印

打印输出变量的值

print val  

9. 输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:
x 按十六进制格式显示变量。 显示0x
d 按十进制格式显示变量 。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 ‘e‘
(gdb) p/f i
$24 = 1.41531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101
 
10. 查看数组
有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“@”操作符,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:
int *array = (int *) malloc (len * sizeof (int));
于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
p *array@len
@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子的:
(gdb) p *array@len
$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}
如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。
 
11.查看内存
可以使用examine命令(简写是x)来查看内存地址中的值。x命令的格式如下所示:
 
x/[n/f/u] [addr]
 
n, f, u是可选的参数。
 
[n]是一个正整数,表示需要显示的内存单元的个数, 也就是说从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义。
 
f表示输出格式,参见下面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
输出格式
  一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进 制来查看这个整型变量 的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:
 
  x 按十六进制格式显示变量。
  d 按十进制格式显示变量。
  u 按十六进制格式显示无符号整型。
  o 按八进制格式显示变量。
  t 按二进制格式显示变量。
  a 按十六进制格式显示变量。
  c 按字符格式显示变量。
  f 按浮点数格式显示变量。  
 
[u]表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字 节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
 
[addr]表示一个内存地址。
 
注意:严格区分n 和u的关系,n表示单元个数,u表示每个单元的大小。
 
n/f/u三个参数可以一起使用。例如:
1. x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示输出三个单位,u表示按十六进制显示。
2. x/100uh pBuf  //查看pBuf数组所在地址的数据,输出100个双字节单位,按十六进制显示
3. x/100c pBuf //查看pBuf地址的100个字符   
 
 
 

Linux系统调试--gdb

标签:

原文地址:http://www.cnblogs.com/veryon/p/4264977.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!