gdb基础学习笔记

0. 前言

自古调试分两派,printf直接输出派 和 gdb调试派。

printf派直观暴力,但不全面。

gdb派全面却麻烦。

但为了更深入全面的学习,有必要了解gdb这款强大的调试工具。

1. gdb调试前准备

gcc -g -o hello hello.c

使用gcc编译时,一定要加上参数-g,不然生成的可执行文件hello不能调试,使用(gdb) file hellogdb hello时,会报错:No symbol table is loaded. Use the "file" command.

(这个结论尚且不准确。)

2. gdb指令

指令可Tab键补全,可上下键翻阅。

示例源程序如下:

#include<stdio.h>

int fun(int a, int b) {
    int val = 0;
    if (a > b) {
        val = a + b;
    } else {
        val = a - b;
    }
    return val;
}

int main() {
    printf("hello gdb!\n");

    int i;
    for (i=0; i<10; i++) {
        printf("what is gdb? %d\n", i);
    }

    int a = 1, b=3;
    printf("%d\n", fun(a, b));

    return 0;
}

file

格式:

  • file <可执行文件名>,加载要调试的可执行文件。

示例:

(gdb) file hello1
Reading symbols from hello1...done.

list

格式:

  • list <linenum>,显示程序第linenum行周围的源程序
  • list <function> ,显示函数名为function的函数的源程序
  • list,显示当前行周围的源程序(10行),多次list,会自动向后显示源程序
  • list -,向前显示源程序

简写:l

示例:

(gdb) l
warning: Source file is more recent than executable.
1       #include<stdio.h>
2
3       int fun(int a, int b) {
4                       int val = 0;
5                       if (a > b) {
6                                       val = a + b;
7                       } else {
8                                       val = a - b;
9                       }
10                      return val;
(gdb) l
11      }
12
13      int main() {
14                      printf("hello gdb!\n");
15                      int i;
16                      for (i=0; i<10; i++) {
17                                      printf("what is gdb? %d\n", i);
18                      }
19                      return 0;
20      }
(gdb) l -
1       #include<stdio.h>
2
3       int fun(int a, int b) {
4                       int val = 0;
5                       if (a > b) {
6                                       val = a + b;
7                       } else {
8                                       val = a - b;
9                       }
10                      return val;

start

说明:
开始执行程序,并在main函数的第一条语句前面停下来

示例:

(gdb) start
Temporary breakpoint 1 at 0x617: file hello1.c, line 14.
Starting program: /home/dounine/gdb/hello1

Temporary breakpoint 1, main () at hello1.c:14
14                      printf("hello gdb!\n");

run

说明:运行加载的程序。在run前,需先设定一个或多个断点,不然程序会运行直到结束。

简写:r

break

格式:

  • break <function>,在指定的函数入口处设置断点
  • break <linenum>,在指定的行号处设置断点
  • break *<address>,在指定地址对应的代码处(指令处)设置断点
  • break +<offset> / break -<offset>,在当前行的下offset行/上offset行,设置断点

简写:b

(gdb) start
Temporary breakpoint 1 at 0x617: file hello1.c, line 14.
Starting program: /home/dounine/gdb/hello1

Temporary breakpoint 1, main () at hello1.c:14
warning: Source file is more recent than executable.
14                      printf("hello gdb!\n");
(gdb) l
9                       }
10                      return val;
11      }
12
13      int main() {
14                      printf("hello gdb!\n");
15
16                      int i;
17                      for (i=0; i<10; i++) {
18                                      printf("what is gdb? %d\n", i);
(gdb) break 17
Breakpoint 2 at 0x400629: file hello1.c, line 17.
(gdb) break fun
Breakpoint 3 at 0x4005d0: file hello1.c, line 4.
(gdb) break *0x400630
Breakpoint 4 at 0x400630: file hello1.c, line 17.
(gdb) break +2
Note: breakpoint 2 also set at pc 0x400629.
Breakpoint 5 at 0x400629: file hello1.c, line 16.

break *<address> 在了解并查看汇编位置后再下断点。
break +2 在第16行设置了断点,是因为当前行在第14行。

continue

格式:

  • continue,当程序被停住后,可以使用该命令恢复程序的运行直到程序结束,或到达下一个断点
  • continue <ignore-count>,忽略ignore-count个断点

简写:c

next

格式:

  • next,执行下一步/下一个语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)
  • next <count>,执行后面的count条语句(不进入函数),然后再停住

简写:n

示例:

(gdb) break 22
Breakpoint 2 at 0x40065f: file hello1.c, line 22.
(gdb) c
Continuing.
hello gdb!
what is gdb? 0
what is gdb? 1
what is gdb? 2
what is gdb? 3
what is gdb? 4
what is gdb? 5
what is gdb? 6
what is gdb? 7
what is gdb? 8
what is gdb? 9

Breakpoint 2, main () at hello1.c:22
22                      printf("%d\n", fun(a, b));
(gdb) n
-2
24                      return 0;
(gdb) n
25      }

step

格式:

  • step,执行下一步/下一条语句,然后停住。如果该语句为函数调用,则进入函数执行其中的第一条语句
  • step <count>,执行后面的count条语句,然后再停住

简写:s

示例:

(gdb) start
Temporary breakpoint 1 at 0x617: file hello1.c, line 14.
Starting program: /home/dounine/gdb/hello1

Temporary breakpoint 1, main () at hello1.c:14
warning: Source file is more recent than executable.
14                      printf("hello gdb!\n");
(gdb) b 22
Breakpoint 2 at 0x40065f: file hello1.c, line 22.
(gdb) c
Continuing.
hello gdb!
what is gdb? 0
what is gdb? 1
what is gdb? 2
what is gdb? 3
what is gdb? 4
what is gdb? 5
what is gdb? 6
what is gdb? 7
what is gdb? 8
what is gdb? 9

Breakpoint 2, main () at hello1.c:22
22                      printf("%d\n", fun(a, b));
(gdb) s
fun (a=1, b=3) at hello1.c:4
4                       int val = 0;
(gdb) n
5                       if (a > b) {

注意:使用step命令会进入函数调用,而使用next显然不会。但是,如果一直使用step,那将会进入一些如printf之类的函数。

print

  • print <expr>,打印指定表达式的值(表达式可以是变量,也可以是地址)
  • print /<f> <expr>,将指定表达式的值以f格式输出

f的格式包括:

  • x 按十六进制格式显示变量。
  • d 按十进制格式显示变量。
  • u 按十六进制格式显示无符号整型。
  • o 按八进制格式显示变量。
  • t 按二进制格式显示变量。
  • a 按十六进制格式显示变量。
  • c 按字符格式显示变量。
  • f 按浮点数格式显示变量。

示例:

(gdb) print &i
$1 = (int *) 0xbffff46c
(gdb) print i
$2 = 2
(gdb) print i+=1
$3 = 3
(gdb) print i
$4 = 3
(gdb) start
Temporary breakpoint 1 at 0x5ac: file hello2.c, line 5.
Starting program: /home/dounine/gdb/hello2

Temporary breakpoint 1, main () at hello2.c:5
5               char *c = "hello world";
(gdb) p c
$1 = 0x400601 <__libc_csu_init+33> "\215\203\354\376\377\377)\306\301\376\002\205\366t%1\377\215\266"
(gdb) p /s c
$2 = 0x400601 <__libc_csu_init+33> "\215\203\354\376\377\377)\306\301\376\002\205\366t%1\377\215\266"
(gdb) p (char*)c
$3 = 0x400601 <__libc_csu_init+33> "\215\203\354\376\377\377)\306\301\376\002\205\366t%1\377\215\266"
(gdb) p *((char*)c)='H'
$4 = 72 'H'
(gdb) p c
$5 = 0x400601 <__libc_csu_init+33> "H\203\354\376\377\377)\306\301\376\002\205\366t%1\377\215\266"

注意:可以在print <expr>的时候,通过表达式设定某个变量的值

简写:p

examine

说明:用于打印某个地址所指向的内存中的内容,十分有用!!!

格式:x/nfu <addr>xexamine的缩写。

  • n:表示要显示的内存单元个数。取值为:1 2 3...

  • f:表示显示方式, 可取如下值:

    • x 按十六进制格式显示变量。
    • d 按十进制格式显示变量。
    • u 按十进制格式显示无符号整型。
    • o 按八进制格式显示变量。
    • t 按二进制格式显示变量。
    • i 指令地址格式
    • c 按字符格式显示变量。
    • f 按浮点数格式显示变量。
  • u:表示一个地址单元的长度,与n一起表示显示的地址长度。取值如下:

    • b 表示单字节,
    • h 表示双字节,
    • w 表示四字节,
    • g 表示八字节

示例:

# 显示0x7fffffffd708(这是个地址)处1个(n=1)单字节(u=b)的内容,以十六进制(f=x)表示;
(gdb)x/1xb  0x7fffffffd708
0x7fffffffd708: 0x26

也可以省略n f u参数:

(gdb) x/ 0x402470
0x402470:       0x00400f7c

display

  • display,跟踪查看某个变量,每次停下来都显示它的值

简写:disp

watch

  • watch,一般用来观察某个表达式(变量也是一种表达式)的值是否有变化。相当于,在每次该表达式值变化的地方,都设置一个断点。我们需要使用continue命令前进。

示例:

(gdb) start
Temporary breakpoint 1 at 0x617: file hello1.c, line 14.
Starting program: /home/dounine/gdb/hello1

Temporary breakpoint 1, main () at hello1.c:14
14                      printf("hello gdb!\n");
(gdb) watch i
Hardware watchpoint 2: i
(gdb) c
Continuing.
hello gdb!

Hardware watchpoint 2: i

Old value = 4196033
New value = 0
0x00400630 in main () at hello1.c:17
17                      for (i=0; i<10; i++) {
(gdb) c
Continuing.
what is gdb? 0

Hardware watchpoint 2: i

Old value = 0
New value = 1
0x0040064b in main () at hello1.c:17
17                      for (i=0; i<10; i++) {

info

说明:info命令可以在调试时用来查看寄存器、断点、观察点(watch)和信号等信息。

info可以查看的所有信息如下:

(gdb) info
"info" must be followed by the name of an info command.
List of info subcommands:

info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auto-load -- Print current status of auto-loaded files
info auxv -- Display the inferior's auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of specified breakpoints (all user-settable breakpoints if no argument)
info checkpoints -- IDs of currently known checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info exceptions -- List all Ada exception names
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info frame -- All about selected stack frame
info frame-filter -- List all registered Python frame-filters
info functions -- All function names
info guile -- Prefix command for Guile info displays
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of specified inferiors (all inferiors if no argument)
info line -- Core addresses of the code for a source line
info locals -- Local variables of current stack frame
info macro -- Show the definition of MACRO
info macros -- Show the definitions of all macros at LINESPEC
info mem -- Memory region attributes
info os -- Show OS data ARG
info pretty-printer -- GDB command to list all registered pretty-printers
info probes -- Show available static probes
info proc -- Show /proc process information about any running process
info program -- Execution status of the program
info record -- Info record options
info registers -- List of integer registers and their contents
info scope -- List the variables local to a scope
info selectors -- All Objective-C selectors
info set -- Show all GDB settings
info sharedlibrary -- Status of loaded shared object libraries
info signals -- What debugger does when program gets various signals
info skip -- Display the status of skips
info source -- Information about the current source file
info sources -- Source files in the program
info stack -- Backtrace of the stack
info static-tracepoint-markers -- List target static tracepoints markers
info symbol -- Describe what symbol is at location ADDR
info target -- Names of targets and files being debugged
info tasks -- Provide information about all known Ada tasks
info terminal -- Print inferior's saved terminal status
info threads -- Display currently known threads
info tracepoints -- Status of specified tracepoints (all tracepoints if no argument)
info tvariables -- Status of trace state variables and their values
info type-printers -- GDB command to list all registered type-printers
info types -- All type names
info unwinder -- GDB command to list unwinders
info variables -- All global and static variable names
info vector -- Print the status of the vector unit
info vtbl -- Show the virtual function table for a C++ object
info warranty -- Various kinds of warranty you do not have
info watchpoints -- Status of specified watchpoints (all watchpoints if no argument)
info win -- List of all displayed windows
info xmethod -- GDB command to list registered xmethod matchers

其中,常用的查看指令和作用如下:

  • info breakpoints,查看设置了所有断点的信息
  • info display,查看display命令监视的变量
  • info registers,查看寄存器中的值
  • info stack,查看栈(各函数栈帧)的信息
  • info watchpoints,查看watch命令监视的变量

delete

格式:

  • delete <breakpoints num>,删除断点编号所对应的断点,断点编号通过info breakpoints查看。
  • delete,删除所有断点。

示例:

(gdb) br 17
Breakpoint 2 at 0x400629: file hello1.c, line 17.
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x00400629 in main at hello1.c:17
(gdb) delete 2
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) br 16
Breakpoint 3 at 0x400629: file hello1.c, line 16.
(gdb) br 17
Note: breakpoint 3 also set at pc 0x400629.
Breakpoint 4 at 0x400629: file hello1.c, line 17.
(gdb) br 18
Breakpoint 5 at 0x400632: file hello1.c, line 18.
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
3       breakpoint     keep y   0x00400629 in main at hello1.c:16
4       breakpoint     keep y   0x00400629 in main at hello1.c:17
5       breakpoint     keep y   0x00400632 in main at hello1.c:18
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.

backtrace

说明:查看栈(各函数栈帧)信息,与info stack一样。

简写:bt

disassemble

说明:查看当前函数的反汇编代码。

quit

说明:退出gdb

简写:q

3. 安装peda插件

peda是用python开发的一款gdb插件,很受欢迎,github地址为https://github.com/longld/peda

3.1. 使用方法

git下载项目到本地,然后修改~/.gdbinit(当前用户的gdb配置目录)如下:

source xxx/peda/peda.py

修改后的效果是,每次启动gdb都会运行这条命令source xxx/peda/peda.py。这条命令的意思是:加载peda中的python脚本,xxx是peda的安装目录。

4. 使用自己python的脚本

在python中import gdb,就可以使用gdb模块了。

但是,import gdb直接运行会报错。

只有在gdbsource xxx.py时,才可以使用。

python中的gdb模块使用教程见官网:https://sourceware.org/gdb/onlinedocs/gdb/Python.html#Python

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容