调试利器GDB-中
Posted dengqiangjiayou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调试利器GDB-中相关的知识,希望对你有一定的参考价值。
GDB调试利器-中
-
数据断点
- GDB中支持数据断点的设置
- watch命令用于监视变量是否被改变(本质为硬件断点)
- watch命令的用法:watch var_name
-
GDB中的内存查看
- GDB中可以检查任意内存区域中的数据
- 命令语法:x /Nuf expression
- N - 需要打印的单元数
- u - 每个单元的大小
- f - 数据打印格式
比如: x /4bx 0x804a024 :打印出以0x804a024地址为首的连续4个byte,并且以16进制呈现
- x命令中参数u对应的单位
| 格式 | 打印方式 |
| ------------------------- |
| b | 单字节 |
|h | 双字节 |
| w | 四字节 |
| g | 八字节 | - GDB中的打印格式
| 格式 | 打印方式 |
| -------------------- |
| x | 十六进制 |
| d | 有符号十进制 |
| u | 无符号十进制 |
| o | 八进制 |
| t | 二进制 |
| a | 地址 |
| c | 字符 |
| f | 浮点数 |
-
使用watch查看数据
topeet@ubuntu:~/Desktop/Code$ ls func.c test.c test.c~ topeet@ubuntu:~/Desktop/Code$ gcc -g test.c -lpthread -o test.out topeet@ubuntu:~/Desktop/Code$ ./test.out g_var = 0 g_var = 0 g_var = 0 g_var = 0 g_var = 0 g_var = 1 g_var = 1 g_var = 1 g_var = 1 g_var = 1 topeet@ubuntu:~/Desktop/Code$ gdb test.out GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 Copyright (C) 2012 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 "x86_64-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/topeet/Desktop/Code/test.out...done. (gdb) start Temporary breakpoint 1 at 0x40062e: file test.c, line 16. Starting program: /home/topeet/Desktop/Code/test.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Temporary breakpoint 1, main () at test.c:16 16 int i = 0; (gdb) watch g_var Hardware watchpoint 2: g_var (gdb) info breakpoints Num Type Disp Enb Address What 2 hw watchpoint keep y g_var (gdb) continue Continuing. [New Thread 0x7ffff77f2700 (LWP 9615)] g_var = 0 g_var = 0 g_var = 0 g_var = 0 g_var = 0 [Switching to Thread 0x7ffff77f2700 (LWP 9615)] Hardware watchpoint 2: g_var Old value = 0 New value = 1 thread_func (args=0x0) at test.c:12 //执行到第12行时g_var被改写了 12 } (gdb) (gdb) print g_var $1 = 1 (gdb) print /a &g_var $2 = 0x601048 <g_var> (gdb) x /4bx 0x601048 0x601048 <g_var>: 0x01 0x00 0x00 0x00 //由以下判断系统的大小端 (gdb) x /1bx 0x601048 0x601048 <g_var>: 0x01 (gdb) x /1wx 0x601048 0x601048 <g_var>: 0x00000001 //(这里为了更严谨一点可以再定义一个变量看其地址是从高地址申请到低地址还是相反) (gdb)
-
函数调用栈的查看(backtrace和frame)
- backtrace
- 查看函数调用的顺序(函数调用栈的信息)
- frame N
- 切换到栈编号为N的上下文中
- info frame
- 查看当前函数调用的栈帧信息
- backtrace
-
栈帧信息(函数调用过程相关的记录)
参数 返回地址 Old ebp 寄存器信息 局部变量 其他数据信息 2个重要的寄存器:ebp、esp
- 深入info命令
| 命令 | 功能说明 |
| ------------- |
| info registers | 查看当前寄存器的值 |
| info args | 查看当前函数参数的值 |
| info locals | 查看当前局部变量的值 |
| info frame | 查看当前栈帧的详细信息 |
| info variable | 查看程序中的变量符号|
| info functions | 查看程序中的函数符号 |
- 深入info命令
topeet@ubuntu:~/Desktop/Code$ gdb test.out
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 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 "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/topeet/Desktop/Code/test.out...done.
(gdb) start
Temporary breakpoint 1 at 0x40054c: file test.c, line 19.
Starting program: /home/topeet/Desktop/Code/test.out
Temporary breakpoint 1, main () at test.c:19
19 int s = 0;
(gdb) continue
Continuing.
sum = 55
[Inferior 1 (process 9690) exited normally]
(gdb) break sum if n==0 //打一个条件断点
Breakpoint 2 at 0x40051f: file test.c, line 6.
(gdb) info breakpoints
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040051f in sum at test.c:6
stop only if n==0
(gdb) continue
The program is not being run.
(gdb) run
Starting program: /home/topeet/Desktop/Code/test.out
Breakpoint 2, sum (n=0) at test.c:6
6 int ret = 0;
(gdb) backtrace
#0 sum (n=0) at test.c:6
#1 0x0000000000400539 in sum (n=1) at test.c:10
#2 0x0000000000400539 in sum (n=2) at test.c:10
#3 0x0000000000400539 in sum (n=3) at test.c:10
#4 0x0000000000400539 in sum (n=4) at test.c:10
#5 0x0000000000400539 in sum (n=5) at test.c:10
#6 0x0000000000400539 in sum (n=6) at test.c:10
#7 0x0000000000400539 in sum (n=7) at test.c:10
#8 0x0000000000400539 in sum (n=8) at test.c:10
#9 0x0000000000400539 in sum (n=9) at test.c:10
#10 0x0000000000400539 in sum (n=10) at test.c:10
#11 0x000000000040055d in main () at test.c:21 //可以查看变量的调用情况当然也可以查看函数调用的过程/路径
(gdb) next
8 if( n > 0 )
(gdb) info args
n = 0
(gdb) frame 7 //切换栈帧
#7 0x0000000000400539 in sum (n=7) at test.c:10
10 ret = n + sum(n-1);
(gdb) info args
n = 7
(gdb)
(gdb) frame 0 //切换栈帧,继续分析
#0 sum (n=0) at test.c:8
8 if( n > 0 )
(gdb) info registers //打印出重要的寄存器信息
rax 0x0 0
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe2b8 140737488347832
rsi 0x7fffffffe2a8 140737488347816
rdi 0x0 0
rbp 0x7fffffffdfc0 0x7fffffffdfc0
rsp 0x7fffffffdfa0 0x7fffffffdfa0
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7dea600 140737351951872
r10 0x7fffffffe050 140737488347216
r11 0x7ffff7a32e50 140737348054608
r12 0x400450 4195408
r13 0x7fffffffe2a0 140737488347808
r14 0x0 0
r15 0x0 0
rip 0x400526 0x400526 <sum+18>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
(gdb) info frame //当前函数调用的详细信息,或者说栈帧的详细信息
Stack level 0, frame at 0x7fffffffdfd0:
rip = 0x400526 in sum (test.c:8); saved rip 0x400539
called by frame at 0x7fffffffe000
source language c.
Arglist at 0x7fffffffdfc0, args: n=0
Locals at 0x7fffffffdfc0, Previous frame's sp is 0x7fffffffdfd0 //sp指针的话应该是函数的执行流程指针,这段话的意思应该是 在这个函数调用之前sp的地址是0x7fffffffdfd0
Saved registers:
rbp at 0x7fffffffdfc0, rip at 0x7fffffffdfc8
(gdb)
(gdb) x /1wx 0x7fffffffdfc0
0x7fffffffdfc0: 0xffffdff0 //在这个函数调用之前rbp为首连续4个字节的数据是0xffffdff0(这个就先不验证了,对这些寄存器的概念还有点模糊)这个可以看上面的栈帧信息,一位在在返回地址下面有一个Old ebp,说明是previous old ebp 。
相关程序:
#include <stdio.h>
int sum(int n)
{
int ret = 0;
if( n > 0 )
{
ret = n + sum(n-1);
}
return ret;
}
int main()
{
int s = 0;
s = sum(10);
printf("sum = %d\\n", s);
return 0;
}
以上是关于调试利器GDB-中的主要内容,如果未能解决你的问题,请参考以下文章