gdb 常用命令

1. 运行

 run/r 运行

运行带参数的可执行文件:r 后面接参数,例如:

$ gdb executablefile

(gdb) r arg1 arg2 arg3

continue/c 继续运行

next/n 单步运行

step/s 如果有函数则进入函数执行

finish 跳出当前的函数

jump/j 跳转到指定行/地址后继续执行,因此如果在跳转的目标行上如果没有设置断点,会继续往下执行

stop 停止运行

until xxx 可用于跳出循环

quit/ctrl+d 退出GDB

2. 打印

print/p var 打印变量的值

print/p &var 打印变量地址

printf/p *addr 打印地址的值

printf/p /x var 用16进制显示数据

x/(n,f,u为可选参数) 查看内存内容,与print不同的是,x后面接内存地址。
n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义
f:显示格式
    x(hex) 按十六进制格式显示变量。
    d(decimal) 按十进制格式显示变量。
    u(unsigned decimal) 按十进制格式显示无符号整型。
    o(octal) 按八进制格式显示变量。
    t(binary) 按二进制格式显示变量。
    a(address) 按十六进制格式显示变量。
    c(char) 按字符格式显示变量。
    f(float) 按浮点数格式显示变量    
u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示
    b:1 byte     h:2 bytes     w:4 bytes    g:8 bytes
    比如x/10xw 0x54320(4字节显示单位等同于x/10x 0x54320)表示从内存地址0x54320读取内容,w表示以4字节为单位,10表示输出10个内存单位,x表示按照十六进制显示。

x/50x $rsp 打印堆栈前50个内存单元的内容,每个单元默认占用4个字节

设置demangling:

set print asm-demangle on
set print demangle on

x/s <地址> 命令用于显示内存中的字符串,比如:

(gdb) p str
$1 = 0x601050 "Hello, GDB!"

(gdb) x/s str
0x601050:    "Hello, GDB!"

(gdb) x/s 0x601050
0x601050:    "Hello, GDB!"

x/i <地址> 命令用于显示内存中的指令,比如:

(gdb) x/i 0x4005d0
   0x4005d0:    callq  0x400570 <foo>

(gdb) x/i $pc
   0x4005d0:    callq  0x400570 <foo>

3. 设置断点

break/b xxx 在某行打断点

break/b fun 在某个函数处加断点

b xxx if (condition)条件断点,
例如:
b test.c:30 if n==100 //当变量n等于100的时候在test.c的30行处加断点.

b test_function if $_streq(my_arg1,"test1") //当字符串参数my_arg1等于"test1"的时候加断点
$_streq是gdb内置函数,具体参见参考文献。

break fileName:N 在某个文件的N行加断点

break fileName:func 在某个文件的某个函数加断点

info break/b [n] 查看断点,(注:n表示断点号,可选。info b列出所有断点信息)

clear N 删除N行断点

delete N 删除N号断点

delete 删除所有断点

disable xxx 失能断点

enable xxx 使能断点

info b 查看断点

watch xxx 设置监控点,在变量改变的时候停下来。(不可直接设置,先加断点在监测)

4. info 查看

info source 查看当前程序

info symbol查看地址对应的符号

info args  打印出当前函数的参数值。

info locals 打印出当前函数中所有局部变量值。

info registers/r 查看所有寄存器的值
info registers/r后面接寄存器名 查看某个寄存器的值
例如:
(gdb) info r rbp
rbp   0x7ff064d078c0   0x7ff064d078c0

info proc mappings 查看动态库(包含映射地址段)

# info line 可以从汇编指令找到对应的源代码行数,或者反过来,由源代码行数找到对应的汇编指令。

4.1 从汇编指令找源代码

info line *0xxxxx 查看地址对应的function,类似于addr2line
例如:
(gdb) info line *0x40ac8810
Line 66 of "../../../../../../my_test.cpp" starts at address 0x40ac8810 <test_port(void*)+352> and ends at 0x40ac8819 <test_port(void*)+361>.

4.2 从源代码找汇编指令

info line filename:linenum

pwd查看程序路径

ctrl+p 前一条命令

ctrl+n 下一条命令

ctrl+l可能layout会造成控制台花屏,使用ctrl+L清屏
 

5. disass/dissassemble反汇编

5.1  disass [function]

function是需要进行反汇编的函数名,例如

(gdb) disassemble main
Dump of assembler code for function main:
   0x4005d0 <+0>:    push   %rbp
   0x4005d1 <+1>:    mov    %rsp,%rbp
   0x4005d4 <+4>:    callq  0x400570 <foo>
   0x4005d9 <+9>:    pop    %rbp
   0x4005da <+10>:   retq   
End of assembler dump.

5.2 disass [address]

address是需要进行反汇编的地址。

5.3 disass [addr_start] [addr_end]

反汇编起始地址和结束地址之间的代码,例如

(gdb) disassemble 0x4005d0 0x4005e0
Dump of assembler code from 0x4005d0 to 0x4005e0:
   0x4005d0:    callq  0x400570 <foo>
   0x4005d5:    mov    %eax,%ebx
   0x4005d7:    add    $0x1,%ebx
   0x4005da:    retq   
End of assembler dump.

5.4 disass [addr_start],+[offset]

反汇编起始地址+偏移量之间的代码。例如

(gdb) disass 0x0000000000400937,+10
Dump of assembler code from 0x400937 to 0x400941:
   0x0000000000400937 <main()+49>:      mov    $0x601060,%edi
   0x000000000040093c <main()+54>:      callq  0x4007e0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt>
End of assembler dump.
(gdb) disass 0x0000000000400937,+1
Dump of assembler code from 0x400937 to 0x400938:
   0x0000000000400937 <main()+49>:      mov    $0x601060,%edi
End of assembler dump.

5.5 disass /m [addr]

结合源码查看汇编,比如:

(gdb) disass /m 0x00000000004005f6
Dump of assembler code for function main:
5       {
   0x00000000004005e6 <+0>:     push   %rbp
   0x00000000004005e7 <+1>:     mov    %rsp,%rbp
   0x00000000004005ea <+4>:     sub    $0x10,%rsp

6           char hi_ch[10] = {0};
=> 0x00000000004005ee <+8>:     movq   $0x0,-0xa(%rbp)
   0x00000000004005f6 <+16>:    movw   $0x0,-0x2(%rbp)

7               //int *hi_int = (int*)884097;
8               //printf("hi_int: %d\n", *hi_int);
9
10              printf("%.*s\n",2,"123");

6. 多线程

info threads 查看线程

thread apply all bt 查看所有线程back trace

thread 查看当前thread
例如:
(gdb) thread
[Current thread is 7 (Thread 1572)]

多线程下(禁止|允许|单步调试时禁止)线程切换:

set scheduler-locking on|off|step

show scheduler-locking: 查看gdb线程工作模式,默认为step, 即在调试的时候可以暂停其他线程的执行,以免线程混乱或者其他线程超时。

set scheduler-locking mode: 设置gdb工作模式,具体参考:

https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html

6.1 backtrace

bt 查看函数back trace

6.2 frame

frame + 帧号 切换栈帧

7. 设置变量

set variable variable = [expression]  设置变量的值,可以缩写为 set var ......

The variable to set.

If variable starts with a dollar sign ($) then it is either a predefined register name or a debugger variable, either a predefined variable or a user variable.

If variable does not start with a dollar sign ($), it is a variable in the program.

expression
    

The value for the variable.

例子:

(gdb)
                     print node->_data
2
(gdb)
                     set variable node->_data = 5
(gdb)
                     print node->_data
5

===========================================================

8. memory dump

两种方式:

1)参考

https://stackoverflow.com/questions/16095948/gdb-dump-memory-in-specific-region-save-formatted-output-into-a-file

例子:

从地址0x601580开始打印1000个四字节为单位的内存。

(gdb) set height 0
(gdb) set logging on
Copying output to gdb.txt.
(gdb) x/1000xw 0x601580
0x601580 <data>:        0x00000e23      0x00000865      0x0000000e      0x00000909

... ...

执行完以后,会dump到gdb.txt里面。

注意,上述打印出的值为大端表示。

2)使用gdb的dump命令:

关于dump的使用可以参考

示例:

(gdb) dump binary memory my.dump 0x601580 0x602ff0

包含内存dump的二进制文件my.dump可以在C的程序中读入,下面是一个例子:

#include <stdio.h>

int main(int argc , char* argv[])
{
    FILE *file;
    char data[100];
    int i;

    file = fopen("my.dump", "rb");

    fread(data, sizeof(data)-1, sizeof(char), file);

    for (i=0; i<100; i++)
    {
        printf("%02x", data[i]);
    }

    fclose(file);

    return 0;
}

输出结果为:

230e0000650800000e00000009090000

注意,上述输出为小端表示。(x86_64环境)

9. layout及代码查看

===========================================================

layout显示源码:
(gdb) layout src:显示源码窗口
(gdb) layout asm:显示汇编窗口
(gdb) layout regs:显示寄存器窗口
(gdb) layout split:显示源码和汇编窗口, 此时可以list filename:linenum同时查看源代码和汇编。
(gdb) layout next:显示下一个layout窗口
(gdb) layout prev:显示上一个layout窗口
Ctrl + L:刷新窗口
Ctrl + x,再按1:单窗口模式
Ctrl + x,再按2:双窗口模式
Ctrl + x,再按a:退出layout,回到执行layout之前的调试窗口。

===========================================================

list linenum:以linenum指定的行号为中心,显示10行

list function:以指定的函数为中心,显示10行

list:重复上一次的list指令,也可以直接按回车键,重复上次指令。

set listsize count:设置每次显示的行数。

show listsize:显示已设置的显示行数。

list first,last:显示指定起始行到结束结束行的源文件。

list ,last:显示以指定的last为结束行,显示10行。

list first,:以first为第一行,显示10行。

list +:以上次显示的结束行为起始行显示后10行

list –:以上次显示的起始行为结束行,显示前10行

9. core dump

gdb <executable_binary> <coredump_file>

 其中可执行文件为带有符号表的binary. 进入gdb以后执行bt命令查看函数调用。

10.  打印数据结构偏移

gdb 8.1以后,可以直接通过(gdb) ptype /o XXX 来查看XXX内的数据结构成员偏移。

如果是早些版本的GDB,可以通过变通的办法,例如:

struct A {
int a;
char b;
short c;
};

(gdb) print (int)&((struct A*)0)->a
$1 = 0
(gdb) print (int)&((struct A*)0)->b
$2 = 4
(gdb) print (int)&((struct A*)0)->c
$3 = 6

===========================================================

常见问题

1. print变量的时候出现<value optimized out>

gdb调试程序的时候打印变量值会出现<value optimized out> 情况,可以在gcc编译的时候加上 -O0参数项,意思是不进行编译优,发布项目的时候不要使用 -O0参数项,gcc 默认编译或加上-O2优化编译会提高程序运行速度.

2. 关于debuginfo

GDB有时会报错:Missing separate debuginfos, use: yum debuginfo-install libgcc-8.5.0-4.el8_5.x86_64 libstdc++-8.5.0-4.el8_5.x86_64

解决方法是先确保/etc/yum.repos.d/CentOS-Linux-Debuginfo.repo 中 enabled=1

然后按照GDB的指示安装debug info,执行:

yum debuginfo-install libgcc-8.5.0-4.el8_5.x86_64 libstdc++-8.5.0-4.el8_5.x86_64

参考文献:

https://blog.youkuaiyun.com/u014015972/article/details/51620694

http://scc.ustc.edu.cn/zlsc/chinagrid/intel/debugger/cl/GUID-BD46F547-7EFA-4066-96BB-7CB9EF415140.htm

https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html

https://sourceware.org/gdb/onlinedocs/gdb/Non_002dStop-Mode.html

https://www-zeuthen.desy.de/unix/unixguide/infohtml/gdb/All_002dStop-Mode.html

https://sourceware.org/gdb/onlinedocs/gdb/Convenience-Funs.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值