您的位置:首页 > 其它

gdb学习step by step

2014-10-11 23:51 302 查看
gdb学习step by step lesson 1 : 显示代码内容
先贴一下我用来示范的程序,我们主要通过这段代码来step by step地学习gdb的使用.如果你想花15分钟学习,这不是你应该用的;如果你只是想对gdb有个简单的了解,这也不是你想要的; 如果你想对gdb有一个基本而全面的了解,这就是你想要的.

1 #include <stdio.h>
2
3 int func( int n )
4 {
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;
10 }
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;
20 for( i = 1; i <=100; i++ )
21 {
22 result += i;
23 }
24
25 printf( "result[1-100] = %d \n", result );
26 printf( "result[1-250] = %d \n", func( 250 ) );
27 }

然后执行如下命令: gcc -g test.c -o test , 生成test的可执行文件.
开始执行 gdb test

-------------------------------------------------------------------------------------------

GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".

(gdb)
-----------------------------------------------------------------------------------------

 list 显示代码内容

(1) help list  看一下系统的帮助
-----------------------------------------------------------------------------------------

(gdb) help list
List specified function or line.
With no argument, lists ten more lines after or around previous listing.
"list -" lists the ten lines before a previous ten-line listing.
One argument specifies a line, and ten lines are listed around that line.
Two arguments with comma between specify starting and ending lines to list.
Lines can be specified in these ways:
LINENUM, to list around that line in current file,
FILE:LINENUM, to list around that line in that file,
FUNCTION, to list around beginning of that function,
FILE:FUNCTION, to distinguish among like-named static functions.
*ADDRESS, to list around the line containing that address.
With two args if one is empty it stands for ten lines away from the other arg.

----------------------------------------------------------------------------------------------------------

上面说明: 
  list  显示上次显示的行的周围10行或后10行的代码.
list +  显示上次显示的行的后10行代码
  list -   显示上次显示的行的前10行代码  
  list后面带一个参数的话,是显示某一行附近的代码,带两个参数(中间要带一个逗号)的话,是显示两个数字之间的行的内容.

  参数的指定方式:  
一个数字 
文件名:数字

函数名

文件名:函数名
*内存地址  显示存在该内存地址处的代码的内容   
(2) list显示当前行的后10行或周围10行的代码
(gdb) list
10 }
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;

可以看到显示的是void main()前后的10行的代码

(3)list- 显示当前行的前10行代码
(gdb) list -
1 #include <stdio.h>
2
3 int func( int n )
4 {
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;

可以看到显示的是上面显示的10行代码的前面10行的代码

(4) list 数字

(gdb) list 10
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;
10 }
11
12 return sum;
13 }
14
可以看到显示的是10行附近的代码

(5) list 文件名:数字

(gdb) list test.c:15
10 }
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;
可以看到显示的是test.c文件中的15行代码

(6) list 函数名
(gdb) list func
1 #include <stdio.h>
2
3 int func( int n )
4 {
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;
10 }
可以看到显示的是func函数的开头部分

(7) 如果想接着看函数的后面部分,可以继续执行list
(gdb) list
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;
20 for( i = 1; i <=100; i++ )
可以看到显示的是上次10行的后10行的结果

(8) 现在看一下list +的效果
(gdb) list +
21 {
22 result += i;
23 }
24
25 printf( "result[1-100] = %d \n", result );
26 printf( "result[1-250] = %d \n", func( 250 ) );
27 }

(9) list 文件名:函数名
(gdb) list test.c:func
1 #include <stdio.h>
2
3 int func( int n )
4 {
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;
10 }

(10) 更改一次显示的行数
这个每次显示10行是可以调的,如果觉得10行太小,可以更改一下.
这个行数是通过listsize来调整的.

可以通过show listsize来看一次显示几次

(gdb) show listsize
Number of source lines gdb will list by default is 10.

可以通过set listsize <count>来设置每次显示的行数
(gdb) set listsize 20
(gdb) show listsize
Number of source lines gdb will list by default is 20.
(gdb) list func
1 #include <stdio.h>
2
3 int func( int n )
4 {
5 int sum = 0, i;
6
7 for( i = 0; i < n; i++ )
8 {
9 sum += i;
10 }
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;

20 for( i = 1; i <=100; i++ )
可以看到设置完后,通过show listsize和list func都可以看到我们的更改生效了.

(11) list *内存地址

既然是通过内存地址来显示代码内容就需要知道程序先跑起来,另外也需要提前知道某一段代码所在的内存位置,这个可以通过info line来查看

比如我们要看第20行代码的内存位置, info line 20; 也可以某一个函数的内存位置, info line func;
(gdb) info line 20
Line 20 of "test.c" starts at address 0x4004eb <main+16> and ends at 0x4004f8 <main+29>.
(gdb) list *0x4004eb
0x4004eb is in main (test.c:20).
10 }
11
12 return sum;
13 }
14
15
16 void main()
17 {
18 int i;
19 long result = 0;
20 for( i = 1; i <=100; i++ )
21 {
22 result += i;
23 }
24
25 printf( "result[1-100] = %d \n", result );
26 printf( "result[1-250] = %d \n", func( 250 ) );
27 }
上面先通过info line显示了20行代码的内存位置是0x4004eb, 然后通过list *0x4004eb来查看该 段代码的内容,可以看到显示的是20行代码,原因是因为之前设置的行数是20

至此list命令的学习结束了.
http://blog.csdn.net/lint2008/article/details/8039526

gdb学习step by step lesson 2 : breakpoint, wathpoint

一,先贴一下我们用来练习的代码
#include <stdio.h>

int func( int n )
{
int sum = 0, i;

for( i = 0; i < n; i++ )
{
sum += i;
}

return sum;
}

void initialize( int *num, int size, int value )
{
for( int i = 0; i < size; ++i )
{
num[ i ] = value;
}
}

void set_array( int *num, int size, int value )
{
for( int i = 0; i < size; ++i )
{
num[ i ] = value;
}
}

void print_value( int *num ,int size )
{
for( int i = 0; i < size; ++i )
{
printf( "%d\t", num[i] );
}
printf("\n" );
}

void main( )
{
int i;
long result = 0;
int num[10];

for( i = 1; i <=100; i++ )
{
result += i;
}

initialize( num, sizeof(num ), 0 );

set_array( num, sizeof(num), 10 );

print_value( num, sizeof(num) );

printf( "result[1-100] = %d \n", result );
printf( "result[1-250] = %d \n", func( 250 ) );
}
为了方便演示,这个代码里面加了一些数组相关的东西

二,先看一下系统自带的帮助

(gdb) help breakpoint
Making program stop at certain points.

List of commands:

awatch -- Set a watchpoint for an expression
break -- Set breakpoint at specified line or function
catch -- Set catchpoints to catch events
clear -- Clear breakpoint at specified line or function
commands -- Set commands to be executed when a breakpoint is hit
condition -- Specify breakpoint number N to break only if COND is true
delete -- Delete some breakpoints or auto-display expressions
disable -- Disable some breakpoints
enable -- Enable some breakpoints
hbreak -- Set a hardware assisted breakpoint
ignore -- Set ignore-count of breakpoint number N to COUNT
rbreak -- Set a breakpoint for all functions matching REGEXP
rwatch -- Set a read watchpoint for an expression
tbreak -- Set a temporary breakpoint
tcatch -- Set temporary catchpoints to catch events
thbreak -- Set a temporary hardware assisted breakpoint
watch -- Set a watchpoint for an expression

Type "help" followed by command name for full documentation.
Command name abbreviations are allowed if unambiguous.

做一个简单的翻译:
awatch 为一个表达式设置一个watchpoint, 当该表达式被读出或者值发生改变时触发

break 为某一行或者某个函数设置断点
catch   设置一个catchpoint去捕获事件
clear 清除某一行或者某个函数的断点
commands 设置当某个断点触发时要执行的命令
condition 设置当某一条件为真时断点才会被触发
delete 删除一些断点或者自动显示的表达式
disable 关掉一些断点,断点不生效,但是仍然仍在.
enable 与disable配合, 可以用来启用一些被disable掉的断点
hbreak  设置一个硬件支持断点, 这种断点需要硬件支持,这个命令的主要目的是用于对EPROM/ROM程序的调试。因为 这条命令可以在不改变代码的情况下设置断点。
这 可以同SPARCLite DSU 一起使用。当程序访问某些变量和代码时,DSU将设置“陷井”。注意: 你只能一次使用一个断点,在新设置断点时,先删除原断点。

ignore 只有断点被触发到一定次数时才会停下来.
rbreak 对所有的函数设置一个跟正则表达式关联的断点

rwatch 设置一个当某表达式被读出时才会触发的watchpoint
tbreak 设置一个临时的断点,只生效一次

tcatch 设置一个用来捕获事件的临时断点
thbreak 设置一个临时的硬件支持断点

watch 为一个表达式设置一个watchpoint, 当该表达式被读出或者值发生改变时触发, 这个与awatch类似

可以看到上面的东西有两部分 breakpoint和watchpoint. 我们分别来学习两部分的东西.

三, breakpoint 相关的东西
(1)  添加断点
添加断点的方式有以下几种:
  I break 函数名   在某个函数开始处设置断点
II break +行数   在程序的当前执行位置的前几行设置断点.
III break -行数   在程序的当前执行位置的后几行设置断点.
IV break 行号    在程序的第几行设置断点, 程序执行到当前行之前一行就会停止
  V break 文件名: 行号 在某一文件的某一行设置断点.
VI break 文件名:函数名 在某一文件中的某一函数的开始设置断点
  VII break *address 在当前地址上存储的代码位置处设置断点
  VIII break 'break'命令在当前执行到的程序运行栈中的下一条指令上设置一个断点。除了栈底以外,这个命令使 程序在一旦从当前函数返回时停止。
相似的命令是'finish',但'finish' 并不设置断点。这一点在循环语句中很有用.
IX break ... if conditon 当执行到某个断点时, 要先检查一下条件是否成立才决定是否要触发该断点
 
  这个break命令的使用方法跟之前的list方法是近似的, 都是一个命令+位置. 其中表示位置的方法是类似的, 所以就不具体贴贴图了.
我们只使用其中的几个加几个简单的断点.

(gdb) info break
No breakpoints or watchpoints.
(gdb) b print_
print_and_abort print_missing_version print_unresolved
print_header print_statistics print_value
(gdb) b print_value
Breakpoint 5 at 0x400566: file break.c, line 34.
(gdb) b 20
Breakpoint 6 at 0x4004f8: file break.c, line 20.
(gdb) b initial
initial initialize
(gdb) b initialize
Breakpoint 7 at 0x4004e9: file break.c, line 18.
(gdb) info break
Num Type Disp Enb Address What
5 breakpoint keep y 0x0000000000400566 in print_value at break.c:34
6 breakpoint keep y 0x00000000004004f8 in initialize at break.c:20
7 breakpoint keep y 0x00000000004004e9 in initialize at break.c:18

上面先用info break显示当前的断点为空,
然后给20行加一个代码, 给两个函数加了两个断点了.
这里有个提示 在写函数时,如果不知道有哪些函数,可以用info func来显示所有函数名. 然后在输入函数名的时候,可以输到一半时按两下TAB 来给出后缀提示.

(2)  显示数据相关的命令

四, watchpoint相关的东西
http://blog.csdn.net/lint2008/article/details/8039561
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: