主要内容

最近比较多的调试linux上的应用程序, 用GDB也比较多, 这里就记录一些常用的gdb调试命令

解决问题

gdb a.out 使用gdb调试a.out, 执行后会进入gdb调试界面(a.out是编译出来的可执行程序)

$ gdb ./a.out
GNU gdb (GDB) 10.2
Copyright (C) 2021 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-pc-msys".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://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...
(gdb)

b main 设置断点

(gdb) b main
Breakpoint 1 at 0x410eec: file main.c, line 48.

b num 在当前C文件的num行设置断点

(gdb) b 100
Breakpoint 2 at 0xfc1c18: file main.c, line 106.

info b 查看断点设置情况

(gdb) info b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x00410eec in main at main.c:48
2       breakpoint     keep y   0x00fc1c18 in main at main.c:106

d num 删除断点num

(gdb) b main
Breakpoint 1 at 0x410eec: file main.c, line 48.
(gdb) d 1
(gdb) info b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x00fc1c18 in main at main.c:106

r a.wav 开始运行(a.wav为参数)

(gdb) r a.wav
Starting program: a.out a.wav

c 遇到断点时,继续运行

Thread 1 hit Breakpoint 4, main (argc=2, argv=0x1e12ee8) at main.c:48
48      {
(gdb) c
Continuing.

n 单步执行,不进入下层函数
s 单步执行,会进入下层函数
u 单步执行,自动跳出循环代码
finish 运行至跳出当前函数

p type 打印变量type

(gdb) p type
$1 = 3

p/x type 打印变量type(16进值显示)

(gdb) p/x type
$2 = 0x3

x/128xb 0xfd4100 打印内存数据(0xfd4100内存地址), 下面展示几种不同的输出方式

(gdb) x/128xb 0xfd4100
0xfd4100 <data0>:       0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfd4108 <data0+8>:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfd4110 <data0+16>:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

(gdb) x/128xw ac->frame->data[0]
0xfd4100 <data0>:       0x00000000      0x00000000      0x00000000      0x00000000
0xfd4110 <data0+16>:    0x00000000      0x00000000      0x00000000      0x00000000
0xfd4120 <data0+32>:    0x00000000      0x00000000      0x00000000      0x00000000

(gdb) x/128xs 0xfd4100
0xfd4100 <data0>:       ""
0xfd4101 <data0+1>:     ""
0xfd4102 <data0+2>:     ""

实际很多时候我们是用printf来debug程序, 有一点我们需要注意, linux 会buffer stdout 的数据, 会发现程序都执行完了, 还没打印出加的printf, 这里我们只要设置 stdbuf 的buf 就行了.

setbuf(stdout, NULL);

-ggdb/-g/-Og

-ggdb 优于 -g, 他们都是编译选项, 编译过程中加入更多的调试选项到目标文件中.
-Og 作为优化选项, 直接作用于具体函数的优化, 比如一些跳转, 循环都不会过度优化, 执行顺序基本保持和原函数相同, 方便单步调试
所以我们在编译的时候, 如果是调试版本, 最好 -ggdb -Og 都加上.

参考引用

https://github.com/me115/linuxtools_rst/blob/master/tool/gdb.rst
https://stackoverflow.com/questions/12970596/gcc-4-8-does-og-imply-g
https://stackoverflow.com/questions/10475040/gcc-g-vs-g3-gdb-flag-what-is-the-difference