GDB调试相关教程

GDB调试相关教程

相关参考链接

  • https://wizardforcel.gitbooks.io/100-gdb-tips/content/set-step-mode-on.html
  • https://wizardforcel.gitbooks.io/100-gdb-tips/content/set-step-mode-on.html

设置程序运行参数

  • 命令set args 10 20 30 40

在这里插入图片描述

  • 使用show args显示设置好的运行参数

在这里插入图片描述

path 命令用于设置或显示当前的搜索路径列表。这些路径用于查找可执行文件、源文件和符号文件等。在调试过程中,GDB 会按照指定的路径顺序搜索这些文件。

  • show path或者show paths查看搜索路径

set environment varname [=value]命令用于设置或修改调试过程中使用的环境变量。此命令允许你在调试程序时指定特定的环境变量值,这些值会影响被调试程序的行为。

  • 例如set environment PATH = /usr/local/bin:/usr/bin:/bin修改PATH的值。

unset environment取消环境变量

  • unset environment LD_LIBRARY_PATH

show environment显示当前环境变量

工作目录

  • cd dir 进入指定目录
  • pwd 显示当前所在目录

程序的输入输出

  • info terminal 显示程序用到的终端的模式
  • 使用重定向控制程序输出 run > outfile
  • tty 命令用于指定被调试程序的输入和输出终端,将被调试程序的输入和输出重定向到一个特定的终端设备,从而与 GDB 的输入和输出分开。假设你有一个终端设备 /dev/pts/2,你希望被调试的程序使用这个终端设备进行输入和输出:(gdb) tty /dev/pts/2

暂停恢复程序运行

  • 在GDB中,有以下几种方式暂停:断点、观察点、捕捉点、信号、线程停止,如果要恢复程序运行,使用c或者continue命令。

设置断点

  • break function,在进入指定函数时停住,C++中可以使用class::function或者function(type, type)格式指定函数名。
  • break line指定行号停住。
  • break +offsetbreak -offset在在当前执行位置之后或者之前的几条指令处设置一个断点。
  • break filename:linenum在源文件filename的linenum处停住。
  • break filename:function在源文件filename的Function函数的入口处停住。
  • break *address在程序运行的内存地址处停住。
  • break没有参数表示在下一条指令处停住。
  • break ... if condition在满足条件时停住,比如循环过程中,break if i == 100表示i为100时停住。

查看断点

  • i[nfo] b[reakpoints] [n]查看断点信息,中括号表示可以不写,n表示断点号,不写表示查看所有断点。

在这里插入图片描述

设置观察点

  • 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,则马上停住。
  • watch expr为表达式expr设置一个观察点,一旦表达式有变化时,立马停住程序。
  • rwatch expr当表达式变量expr被读取时,停住程序。
  • awatch expr当表达式(变量)的值被读或者被写时,停住程序。
  • info watchpoints列出所有设置了的观察点。
  • 使用测试程序watch.cpp,编译命令g++ -g -o watch watch.cpp

在这里插入图片描述

  • 先删除watch断点2,添加rwatch断点,当变量x第一次被读取时,程序暂停执行并进入GDB

在这里插入图片描述

  • 先删除rwatch断点,添加awatch断点,当变量x第一次被读取或写入时,程序暂停执行并进入GDB。

在这里插入图片描述

  • 查看观察点信息。

在这里插入图片描述

设置捕捉点

  • 设置捕捉点来捕捉程序运行时的一些事件,如载入共享库、C++异常。
$gcc -g  catch.c -o catch
#gcc -g  child.c -o child
$ gdb catch
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 catch...
(gdb) set follow-fork-mode child
(gdb) catch exec
Catchpoint 1 (exec)
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/catch 
[Attaching after process 1409038 fork to child process 1409042]
[New inferior 2 (process 1409042)]
[Detaching after fork from parent process 1409038]
[Inferior 1 (process 1409038) detached]
process 1409042 is executing new program: /home/aaa/bbb/ccc/GDBDebug/test1/child
[Switching to process 1409042]Thread 2.1 "child" hit Catchpoint 1 (exec'd /home/aaa/bbb/ccc/GDBDebug/test1/child), 0x00007ffff7fd0100 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) b main
Breakpoint 2 at 0x555555555149: file child.c, line 7.
(gdb) l
1       #include <stdlib.h>
2       #include <stdio.h>
3       #include <unistd.h>
4
5       int my_print();
6       int main()
7       {
8           my_print();
9           return 0;
10      }
(gdb) b my_print 
Breakpoint 3 at 0x555555555162: file child.c, line 13.
(gdb) c
Continuing.Thread 2.1 "child" hit Breakpoint 2, main () at child.c:7
7       {
(gdb) l
2       #include <stdio.h>
3       #include <unistd.h>
4
5       int my_print();
6       int main()
7       {
8           my_print();
9           return 0;
10      }
11
(gdb) s
8           my_print();
(gdb) nThread 2.1 "child" hit Breakpoint 3, my_print () at child.c:13
13      {
(gdb) n
14          printf("hello world\n");
(gdb) n
hello world
15          return 0;
(gdb) n
16      }
(gdb) 
main () at child.c:9
9           return 0;
(gdb) 
10      }
(gdb) 
__libc_start_main (main=0x555555555149 <main>, argc=1, argv=0x7fffffffdd48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdd38) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
(gdb) 
[Inferior 2 (process 1409042) exited normally]
  • 上面的例子中,最重要的操作时catch exec这个事件。捕获到exec这个事件之后再往子进程的程序中打一个断点,然后执行continue操作。可以看到,此时程序就会进入到exec调用的子进程中了。

相关参考:
https://blog.csdn.net/www_dong/article/details/117304481

  • catch throw捕获C++抛出的异常
  • catch exec捕获系统调用exec时
  • catch fork捕获系统调用fork
  • catch vfork系统调用vfork时
  • catch load载入共享库时
  • catch unload卸载共享库时
  • tcatch <event>值设置一次捕捉点,当程序停住以后,应当自动删除

维护停止点

上面设置了停止点,如果需要取消停止点,可以使用deletecleardisableenable这几个命令来进行维护

  • clear清除所有已经定义的停止点
  • clear <function>clear <filename:function>清除指定函数上的停止点
  • clear <linenum>clear <filename:linenum>清除指定行上的停止点
  • delete [breakpoints] [range...]删除指定的断点,如果不指定断点,则表示删除所有的断点,range表示删除断点的范围,例如1-4
  • disable [breakpoints] [range...]disable所指定的停止点,breakpoints为停止点,如果不指定,表示disable所有的停止点,简写dis
  • enable [breakpoints] [rangs...]enable表示启动指定的停止点
  • enable [breakpoints] once range...enable指定的停止点一次,当程序停止后,该停止点自动disable
  • enable [breakpoints] delete ragne...enable所指定的停止点一次,当程序停止后,自动删除

停止条件维护

只有break和watch命令支持设置条件断点。

  • condition <bnum> <expression>修改断点号为bnum的停止条件为expression
  • condition <bnum>清除断点号为bnum的停止条件
  • ignore <bnum> <count>程序运行时,忽略某个断点count次

为断点设定运行命令

在断点停住时,可以让其运行一些别的命令。

  • command [bnum] ... command-list... end为断点指定一个命令列表,当程序在断点停住时,命令列表里面的命令依次被运行

使用如下程序代码进行测试:

// command.cpp
#include <iostream>void foo(int x)
{std::cout << "x = " << x << std::endl;
}int main()
{for (int i = 0; i < 5; ++i){foo(i);}return 0;
}

假设在调试希望每次调用foo函数时,都打印变量x的值,然后继续执行程序。
编译g++ command.cpp -o command -g,调试过程如下:

gdb command
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 command...
(gdb) b foo(int) 
Breakpoint 1 at 0x11c9: file command.cpp, line 4.
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>p x
>c
>end
(gdb) r
Starting program: /home/xxxx/GDBDebug/test1/command Breakpoint 1, foo (x=21845) at command.cpp:4
4       {
$1 = 21845
x = 0Breakpoint 1, foo (x=0) at command.cpp:4
4       {
$2 = 0
x = 1Breakpoint 1, foo (x=1) at command.cpp:4
4       {
$3 = 1
x = 2Breakpoint 1, foo (x=2) at command.cpp:4
4       {
$4 = 2
x = 3Breakpoint 1, foo (x=3) at command.cpp:4
4       {
--Type <RET> for more, q to quit, c to continue without paging--
$5 = 3
x = 4
[Inferior 1 (process 2436410) exited normally]
(gdb) b foo(int) if x > 0
Breakpoint 3 at 0x5555555551c9: file command.cpp, line 4.
(gdb) commands
Type commands for breakpoint(s) 3, one per line.
End with a line saying just "end".
>printf "x is %d\n", x
>c
>end
(gdb) r
Starting program: /home/xxx/GDBDebug/test1/command Breakpoint 3, foo (x=21845) at command.cpp:4
4       {
x is 21845
x = 0
x = 1Breakpoint 3, foo (x=1) at command.cpp:4
4       {
x is 1
x = 2Breakpoint 3, foo (x=2) at command.cpp:4
4       {
x is 2
x = 3Breakpoint 3, foo (x=3) at command.cpp:4
4       {
x is 3
x = 4
[Inferior 1 (process 2441936) exited normally]
  • 如果要清除断点上的命令,指定commands,然后在输出end即可

恢复程序运行和单步调试

  • continue命令继续执行程序,直到结束或者遇到下一个断点

  • step <count>单步执行,如果有函数则进入函数,进入函数的前提是该函数含有debug信息

  • next <count>单步调试,不会进入函数

  • set step-mode on / off我在做测试时,都可以进入到库函数的调用中,具体原因暂不详细,下面是例子

  • 所使用的代码

// step_mode.c
#include <stdio.h>void customFunction()
{printf("Inside customFunction\n");
}int main()
{printf("Hello, World!\n");customFunction();return 0;
}
  • 编译命令gcc -g step_mode.c -o step_mode -o0,执行过程如下:
(gdb) b main
Breakpoint 1 at 0x1160: file step_mode.c, line 9.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/step_mode Breakpoint 1, main () at step_mode.c:9
9       {
(gdb) set stemp-mode on
No symbol "stemp" in current context.
(gdb) set step-mode on
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/step_mode Breakpoint 1, main () at step_mode.c:9
9       {
(gdb) s
10          printf("Hello, World!\n");
(gdb) s
__GI__IO_puts (str=0x55555555601a "Hello, World!") at ioputs.c:33
33      ioputs.c: No such file or directory.
(gdb) finish
Run till exit from #0  __GI__IO_puts (str=0x55555555601a "Hello, World!") at ioputs.c:33
Hello, World!
main () at step_mode.c:11
11          customFunction();
Value returned is $1 = 14
(gdb) s
customFunction () at step_mode.c:4
4       {
(gdb) 
5           printf("Inside customFunction\n");
(gdb) 
__GI__IO_puts (str=0x555555556004 "Inside customFunction") at ioputs.c:33
33      ioputs.c: No such file or directory.
(gdb) finish
Run till exit from #0  __GI__IO_puts (str=0x555555556004 "Inside customFunction") at ioputs.c:33
Inside customFunction
customFunction () at step_mode.c:6
6       }
Value returned is $2 = 22
(gdb) s
main () at step_mode.c:12
12          return 0;
(gdb) s
13      }
(gdb) 
__libc_start_main (main=0x555555555160 <main>, argc=1, argv=0x7fffffffdd18, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdd08) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
(gdb) 
__GI_exit (status=0) at exit.c:138
138     exit.c: No such file or directory.
(gdb) 
139     in exit.c
(gdb) finish
warning: Function __GI_exit does not return normally.
Try to finish anyway? (y or n) y
Run till exit from #0  __GI_exit (status=0) at exit.c:139
[Inferior 1 (process 4103097) exited normally]
  • finish命令用于在调试过程中立即运行到当前函数的末尾,并返回调用该函数的地方。这在调试库函数或长时间运行的函数时特别有用,可以快速退出函数并查看返回值和调用者

  • 还是使用上面的step_mode.c代码,执行过程如下:

(gdb) b main
Breakpoint 1 at 0x1160: file step_mode.c, line 9.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/step_mode Breakpoint 1, main () at step_mode.c:9
9       {
(gdb) b cus
cuserid         cuserid.c       customFunction  
(gdb) b customFunction   ## customFunction 处断点
Breakpoint 2 at 0x555555555149: file step_mode.c, line 4.
(gdb) c   ## 运行到断点处
Continuing.
Hello, World!Breakpoint 2, customFunction () at step_mode.c:4
4       {
(gdb) s  ## 进入到断点
5           printf("Inside customFunction\n");
(gdb) finish  ## 执行finish
Run till exit from #0  customFunction () at step_mode.c:5
Inside customFunction
main () at step_mode.c:12
12          return 0;
(gdb) n
13      }
(gdb) 
__libc_start_main (main=0x555555555160 <main>, argc=1, argv=0x7fffffffdd18, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdd08) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
(gdb) 
[Inferior 1 (process 4123010) exited normally]
(gdb) 
The program is not being run.
  • until用于继续执行程序,直到当前函数或循环的结束。这在调试循环体或长时间运行的函数时特别有用,可以快速跳过剩余的循环迭代或函数代码,直接到达循环或函数的结束处
  • 示例代码:
// until.c
#include <stdio.h>void customFunction() {for (int i = 0; i < 5; i++) {printf("Loop iteration %d\n", i);}printf("End of customFunction\n");
}int main() {printf("Hello, World!\n");customFunction();return 0;
}
  • 调试过程如下:
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/until Breakpoint 1, main () at until.c:13
13      {
(gdb) n
14          printf("Hello, World!\n");
(gdb) n
Hello, World!
15          customFunction();
(gdb) s
customFunction () at until.c:4
4       {
(gdb) 
5           for (int i = 0; i < 5; i++)
(gdb) 
7               printf("Loop iteration %d\n", i);
(gdb) until
Loop iteration 0
5           for (int i = 0; i < 5; i++)
(gdb) until
Loop iteration 1
Loop iteration 2
Loop iteration 3
Loop iteration 4
9           printf("End of customFunction\n");
  • stepisinextini用于单步执行程序的汇编指令,而不是源代码行。
  • 使用调试代码如下:
// compilation.c
#include <stdio.h>
int main()
{int a = 5;int b = 10;int c = a + b;printf("Sum: %d\n", c);return 0;
}
  • 调试过程如下:
(gdb) b main
Breakpoint 1 at 0x1149: file compilation.c, line 4.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/compilation Breakpoint 1, main () at compilation.c:4
4       {
(gdb) layout asm

在这里插入图片描述

信号

  • handle命令用于指定 GDB 在接收到特定信号时应采取的动作。信号是操作系统向进程发送的异步通知,用于通知某些事件的发生,比如除零错误、非法内存访问等。使用 handle 命令,你可以告诉 GDB 如何处理这些信号,是继续程序执行、停止程序还是忽略信号。
  • handle命令基本语法:
handle signal [keywords...]
  • signal 是要处理的信号名称或者编号
  • keywords是GDB应该对信号执行的操作,可以是以下一个或多个关键字的组合:
  • nostop:当接收到该信号时,继续程序执行,不停下来
  • stop:当接收到该信号时,停止程序执行
  • nopass:当接收到该信号时,不把它传递给程序
  • pass:当接收到该信号时,把它传递给程序
  • print:当接收到该信号时,打印通知信息
  • noprint:当接收到该信号时,不打印通知信息
// signal.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>// 信号处理函数
void signal_handler(int signum)
{printf("Received signal: %d\n", signum);// 可以在信号处理函数中做一些处理,如记录日志或者进行特定操作
}int main()
{// 注册信号处理函数signal(SIGINT, signal_handler);  // 当收到 SIGINT (Ctrl+C) 时调用 signal_handlersignal(SIGSEGV, signal_handler); // 当收到 SIGSEGV (段错误) 时调用 signal_handler// 无限循环,模拟程序运行while (1){printf("Program running...\n");sleep(1);}return 0;
}
(gdb) b main
Breakpoint 1 at 0x11d1: file signal.c, line 14.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/signal Breakpoint 1, main () at signal.c:14
14      {
(gdb) handle SIGINT stop print  ## 设置处理动作
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal        Stop      Print   Pass to program Description
SIGINT        Yes       Yes     No              Interrupt
(gdb) handle SIGSEGV stop print  ## 设置处理动作
Signal        Stop      Print   Pass to program Description
SIGSEGV       Yes       Yes     Yes             Segmentation fault
(gdb) c
Continuing.
Program running...
Program running...
Program running...
Program running...
Program running...
Program running...
^C
Program received signal SIGINT, Interrupt.
0x00007ffff7e931b4 in __GI___clock_nanosleep (clock_id=<optimized out>, clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7fffffffdbf0, rem=rem@entry=0x7fffffffdbf0) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
78      ../sysdeps/unix/sysv/linux/clock_nanosleep.c: No such file or directory.
  • info signals查看信号
info signals
Signal        Stop      Print   Pass to program DescriptionSIGHUP        Yes       Yes     Yes             Hangup
SIGINT        Yes       Yes     No              Interrupt
SIGQUIT       Yes       Yes     Yes             Quit
SIGILL        Yes       Yes     Yes             Illegal instruction
SIGTRAP       Yes       Yes     No              Trace/breakpoint trap
SIGABRT       Yes       Yes     Yes             Aborted
SIGEMT        Yes       Yes     Yes             Emulation trap
SIGFPE        Yes       Yes     Yes             Arithmetic exception
SIGKILL       Yes       Yes     Yes             Killed
SIGBUS        Yes       Yes     Yes             Bus error
SIGSEGV       Yes       Yes     Yes             Segmentation fault
SIGSYS        Yes       Yes     Yes             Bad system call
SIGPIPE       Yes       Yes     Yes             Broken pipe
SIGALRM       No        No      Yes             Alarm clock
SIGTERM       Yes       Yes     Yes             Terminated
SIGURG        No        No      Yes             Urgent I/O condition
SIGSTOP       Yes       Yes     Yes             Stopped (signal)
SIGTSTP       Yes       Yes     Yes             Stopped (user)
SIGCONT       Yes       Yes     Yes             Continued
SIGCHLD       No        No      Yes             Child status changed
SIGTTIN       Yes       Yes     Yes             Stopped (tty input)
SIGTTOU       Yes       Yes     Yes             Stopped (tty output)
SIGIO         No        No      Yes             I/O possible
SIGXCPU       Yes       Yes     Yes             CPU time limit exceeded
SIGXFSZ       Yes       Yes     Yes             File size limit exceeded
SIGVTALRM     No        No      Yes             Virtual timer expired
SIGPROF       No        No      Yes             Profiling timer expired
  • info handle查看哪些信号在GDB中被检测
info handle
Signal        Stop      Print   Pass to program DescriptionSIGHUP        Yes       Yes     Yes             Hangup
SIGINT        Yes       Yes     No              Interrupt
SIGQUIT       Yes       Yes     Yes             Quit
SIGILL        Yes       Yes     Yes             Illegal instruction
SIGTRAP       Yes       Yes     No              Trace/breakpoint trap
SIGABRT       Yes       Yes     Yes             Aborted
SIGEMT        Yes       Yes     Yes             Emulation trap
SIGFPE        Yes       Yes     Yes             Arithmetic exception
SIGKILL       Yes       Yes     Yes             Killed
SIGBUS        Yes       Yes     Yes             Bus error
SIGSEGV       Yes       Yes     Yes             Segmentation fault
SIGSYS        Yes       Yes     Yes             Bad system call
SIGPIPE       Yes       Yes     Yes             Broken pipe
SIGALRM       No        No      Yes             Alarm clock
SIGTERM       Yes       Yes     Yes             Terminated
SIGURG        No        No      Yes             Urgent I/O condition
SIGSTOP       Yes       Yes     Yes             Stopped (signal)
SIGTSTP       Yes       Yes     Yes             Stopped (user)
SIGCONT       Yes       Yes     Yes             Continued
SIGCHLD       No        No      Yes             Child status changed
SIGTTIN       Yes       Yes     Yes             Stopped (tty input)
SIGTTOU       Yes       Yes     Yes             Stopped (tty output)
SIGIO         No        No      Yes             I/O possible
SIGXCPU       Yes       Yes     Yes             CPU time limit exceeded
SIGXFSZ       Yes       Yes     Yes             File size limit exceeded
SIGVTALRM     No        No      Yes             Virtual timer expired
SIGPROF       No        No      Yes             Profiling timer expired

线程

  • break <linespec> thread <threadno>
  • break <linespec> thread <threadno> if ...
  • info threads查看线程信息
  • 使用程序:
// thread_test.cpp
#include <iostream>
#include <thread>
#include <chrono>void task1()
{for (int i = 0; i < 5; ++i){std::cout << "Task 1 running... " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}
}void task2()
{for (int i = 0; i < 5; ++i){std::cout << "Task 2 running... " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));}
}int main()
{std::thread t1(task1);std::thread t2(task2);t1.join();t2.join();return 0;
}
  • 运行结果如下所示:
(gdb) b task1
Breakpoint 1 at 0x1309
(gdb) b task2
Breakpoint 2 at 0x13ac
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/thread 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7a41700 (LWP 61886)]
[New Thread 0x7ffff7240700 (LWP 61887)]
[Switching to Thread 0x7ffff7a41700 (LWP 61886)]Thread 2 "thread" hit Breakpoint 1, 0x0000555555555309 in task1() ()
(gdb) info threadsId   Target Id                                  Frame 1    Thread 0x7ffff7a42740 (LWP 61872) "thread" __pthread_clockjoin_ex (threadid=140737348114176, thread_return=0x0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>) at pthread_join_common.c:145
* 2    Thread 0x7ffff7a41700 (LWP 61886) "thread" 0x0000555555555309 in task1() ()3    Thread 0x7ffff7240700 (LWP 61887) "thread" 0x00005555555553ac in task2() ()
(gdb) b thread.cpp:7 thread 2
No source file named thread.cpp.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) b ./thread.cpp:7 thread 2
No source file named ./thread.cpp.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) pwd

查看栈信息

  • backtrace或者bt
  • backtrace <n>表示只打印栈顶上n层栈信息
  • backtrace <-n>表示只打印栈底层的n层信息
  • 切换栈,程序停止时,最顶的栈就是当前栈,使用frame <n>进行切换
  • up <n>表示向栈的上面移动n层,不写n表示1层
  • down <n>表示向栈的下面移动n层,不写n表示1层
(gdb) bt
#0  0x0000555555555309 in task1() ()
#1  0x0000555555556276 in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) ()
#2  0x000055555555620e in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) ()
#3  0x00005555555561a0 in void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) ()
#4  0x000055555555615d in std::thread::_Invoker<std::tuple<void (*)()> >::operator()() ()
#5  0x000055555555612e in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() ()
#6  0x00007ffff7e79df4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff7f8d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8  0x00007ffff7cb5353 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) f  ## 表示当前栈
#0  0x0000555555555309 in task1() ()
(gdb) info f  ## 查看当前栈信息
Stack level 0, frame at 0x7ffff7a40e20:rip = 0x555555555309 in task1(); saved rip = 0x555555556276called by frame at 0x7ffff7a40e40Arglist at 0x7ffff7a40e10, args: Locals at 0x7ffff7a40e10, Previous frame's sp is 0x7ffff7a40e20Saved registers:rip at 0x7ffff7a40e18
  • info args打印当前函数的参数名及其值
  • info locals打印当前函数的局部变量和值
  • info catch打印函数中的异常处理信息

显示源代码

  • 编译时加入-g选项,才可以查看源代码,当GDB停下时,会报告在哪个文件的第几行上
  • list <linenum>显示linenum周围的源程序
  • list <function>显示函数名为function的函数的源程序
  • list或者l显示当前行后面的源程序
  • list -显示当前行前面的源程序
  • set listsize <count>设置一次显示源代码的行数
  • show listsize查看当前listsize的设置
  • list <first>, <last>显示从first行到last行之间的源代码
  • list , <last>显示从当前行到last行之间的源代码
  • list +往后显示源代码,一般可以在list后面跟以下参数:
  • <linenum>行号
  • <+offset>当前行号的正偏移量
  • <-offset>当前行号的负偏移量
  • <filename:linenum>哪个文件的哪一行
  • <function>函数名
  • <filename:function>哪个文件中的哪个函数
  • <*address>程序运行时的语句在内存中的地址

搜索源代码

  • forward-search <regexp>向前搜索
  • search <regexp>向后搜索
  • reverse-search <regexp>反向搜索
  • 使用thread_test.cpp源代码
(gdb) forward-search task
26          std::thread t2(task2);
(gdb) 
Expression not found
(gdb) 
Expression not found
(gdb) reverse-search task
25          std::thread t1(task1);
(gdb) 
14      void task2()
(gdb) 
5       void task1()
(gdb) 
Expression not found
(gdb) reverse-search task
Expression not found
(gdb) 
Expression not found
(gdb) search task
14      void task2()
(gdb) 
25          std::thread t1(task1);
(gdb) 
26          std::thread t2(task2);
(gdb) 
Expression not found

指定源文件路径

  • directory 命令用于添加或更改 GDB 查找源文件的目录列表。这个命令可以帮助 GDB 在调试时找到你的源代码,特别是当源代码不在当前工作目录中时。
  • 使用示例
// File: /home/aaa/bbb/ccc/GDBDebug/test1/src/directory.cpps
#include <iostream>int main() {std::cout << "Hello, GDB!" << std::endl;return 0;
}
  • 编译时将生成的可执行文件放入test1文件夹下:g++ test1/src/directory.cpp -o test1/directory -g,和源文件不放入一个文件夹中
  • 调试过程如下:
$ gdb test1/directory  ## 启动要调试的程序
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/directory...
(gdb) directory /home/aaa/bbb/ccc/GDBDebug/test1/src/   ## 添加目录
Source directories searched: /home/aaa/bbb/ccc/GDBDebug/test1/src/:$cdir:$cwd
(gdb) b directory.cpp:5   ## 添加断点
Breakpoint 1 at 0x11a9: file test1/src/directory.cpp, line 5.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/directory Breakpoint 1, main () at test1/src/directory.cpp:5  ## 可以正确的找到源文件
5       {
(gdb) show directories  ## 显示目录
Source directories searched: /home/aaa/bbb/ccc/GDBDebug/test1/src:$cdir:$cwd
  • 添加多个目录时,使用空格隔开,其中在 Windows 下添加多个目录,假设你有两个目录 C:\Projects\Source1 和 C:\Projects\Source2,则使用(gdb) directory C:\\Projects\\Source1 C:\\Projects\\Source2或者(gdb) directory C:/Projects/Source1 C:/Projects/Source2,在 Linux 下添加多个目录,假设你有两个目录 /home/user/projects/source1 和 /home/user/projects/source2,使用(gdb) directory /home/user/projects/source1 /home/user/projects/source2

  • 清除所有的自定义的源文件搜索路径信息directory

  • 显示定义了的源文件搜索路径show directories

源代码的内存

  • info line directory.cpp:main查看main函数的地址
  • info line命令后面可以是行号,函数名,文件名:行号,文件名:函数名
  • disassemble func查看函数func的汇编代码
  • 执行结果如下:
(gdb) info line directory.cpp:main
Line 5 of "test1/src/directory.cpp" starts at address 0x11a9 <main()> and ends at 0x11b1 <main()+8>.
(gdb) disassemble main
Dump of assembler code for function main():0x00000000000011a9 <+0>:     endbr64 0x00000000000011ad <+4>:     push   %rbp0x00000000000011ae <+5>:     mov    %rsp,%rbp0x00000000000011b1 <+8>:     lea    0xe4d(%rip),%rsi        # 0x20050x00000000000011b8 <+15>:    lea    0x2e81(%rip),%rdi        # 0x4040 <_ZSt4cout@@GLIBCXX_3.4>0x00000000000011bf <+22>:    callq  0x1090 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>0x00000000000011c4 <+27>:    mov    %rax,%rdx0x00000000000011c7 <+30>:    mov    0x2e02(%rip),%rax        # 0x3fd00x00000000000011ce <+37>:    mov    %rax,%rsi0x00000000000011d1 <+40>:    mov    %rdx,%rdi0x00000000000011d4 <+43>:    callq  0x10a0 <_ZNSolsEPFRSoS_E@plt>0x00000000000011d9 <+48>:    mov    $0x0,%eax0x00000000000011de <+53>:    pop    %rbp0x00000000000011df <+54>:    retq   
End of assembler dump.

查看运行时数据

  • p[rint] <expr>或者p[rint] /<f> <expr>输出,<f>指定输出格式
  • 打印变量值p val
  • 打印表达式的值p val1 + val2
  • 打印指针的值和指向的内容p ptr,p *ptr
  • 打印结构体成员p struct_val.member
  • 打印数组内容p array,p array[0]@10,打印array的地址和array的前10个元素
  • 打印对象p object
  • 打印内存地址的内容p *(char*)0x601050
  • 格式化输出:
(gdb) print /x var   # 以十六进制格式输出
(gdb) print /d var   # 以十进制格式输出
(gdb) print /c var   # 以字符格式输出
(gdb) print /s var   # 以字符串格式输出
(gdb) print /t var   # 按二进制类型显示
(gdb) print /u var   # 按十六进制显示无符号整型
(gdb) print /o var   # 八进制显示变量
(gdb) print /a var   # 十六进制显示变量
(gdb) print /f val   # 浮点数显示变量
  • 测试代码
#include <iostream>
#include <vector>struct Point {int x, y;
};int main() {int a = 10;int b = 20;int *ptr = &a;Point p = {3, 4};std::vector<int> vec = {1, 2, 3, 4, 5};std::cout << "Hello, GDB!" << std::endl;return 0;
}
  • 运行结果如下:
$ gdb test1/print_test 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/print_test...
(gdb) b main
Breakpoint 1 at 0x1289: file test1/print_test.cpp, line 10.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/print_test Breakpoint 1, main () at test1/print_test.cpp:10
10      {
(gdb) p a
$1 = 1
(gdb) n
11          int a = 10;
(gdb) n
12          int b = 20;
(gdb) p a
$2 = 10
(gdb) b print_test.cpp:18
Breakpoint 2 at 0x555555555362: file test1/print_test.cpp, line 18.
(gdb) c
Continuing.
Hello, GDB!Breakpoint 2, main () at test1/print_test.cpp:18
18          return 0;
(gdb) p b
$3 = 20
(gdb) p ptr
$4 = (int *) 0x7fffffffdb88
(gdb) p *ptr
$5 = 10
(gdb) p p
$6 = {x = 3, y = 4}
(gdb) p vec
$7 = std::vector of length 5, capacity 5 = {1, 2, 3, 4, 5}
(gdb) p vec[0]@5
$8 = {1, 2, 3, 4, 5}
(gdb) p /x a
$9 = 0xa
(gdb) p /d a
$10 = 10
(gdb) p vec@4
$11 = {std::vector of length 5, capacity 5 = {1, 2, 3, 4, 5}, std::vector of length -23454100575501, capacity -23451953091852 = {267633501, 1213594142, -2092374647, -1991765780, -1958152067, -1991706555, 18933959, -913309696, 267620547, 1213594142, -2092374647, -1991765780, -1958152067, -1991706555, 17885383, -913309696, 267620547, 1213594142, 1213457801, 1211690115, 1222147465, -1991708535, -225883946, -1069184696, -933918392, -800224952, 76236900, 10277, 1166624768, 1220555240, 1222133131, 1221612939, -1991715191, 16050375, -1924661248, -1991720891, 24832199, -1991770112, 1166887107, -947304256, 87528, -1047967744, -666531000, 1222281544, -1991717239, 26273991, 518717440, -98693133, 1220774216, 1222133131, -639055991, 1207959552, -1991714679, -58660665, -1958150145, 1214572613, 673514547, 1946157056, -63117307, -2092367873, 1566259396, 267620547, 1213594142, -2092374647, -1991765780, -1958152067, -1991706555, 32303303, -1991770112, 1166756034, 1217087736, 1166755848, 9128184, 1221495112, -504838263, 1207959553, 1224230283, 1843971977, -1879048192, 267633609, 1213594142, -1991711351, 1569781885, 267620547, 1213594142, -1991711351, 1569781885, 267620547, 1213594142, -2092374647, -1991765780, -1958152067, -1991706555, -22484793, -913244161, 267620547, 1213594142, -2092374647, -1991765780, -1991706499, -1958154123, -1958152123, -1991708587, -947304234, 104936, -1010200576, -98693133, -443987883, 283935560, -125990584, -129660088, 273713992, -129660088, 1207995208, -1991720407, -121550640, -1031190526, -129660088, 1208519496, 1224230283, -1991717239, 25880775, -1958215680, -1991706555, -9901881, -913244161, 267620547, 1213594142, -1991711351, -1958152067, -1958152123, -1866244864, -98693133, -443987883, -326940589, 2106148888, 1166756072, -947304216, -12824, -1014413057, -398095544, -389576376, 370, 48283976, 1222115656, 1528349827, 267633501, 1213594142, 1213457801, 1211690115, 1222147465, 1221621129, 1221088649, 1221088651, 1221608843, -1991715191, 21948615, -1991770112, -1958156219, -1958160291, -1991714747, 7661767, -1991770112, 1166756034, -695645976, -389576376, 384, 1220970824, -68624503, 1207959553, 1222137227, -1958215031, -1958160315, 1435191296, -490649368, -1040103422, -666531000, 273713480, -666531000, -389576376, 42, 1220643144, 1222133131, -1958211445, -1958164363, -1991716795, 32237767, -1958215680, -1991714731, 1217398850, 1530446979, 267633501, 1213594142, -1991711351, -1958152067, -1017251771, -98693133, -443987883, 552371016, -125990584...}, std::vector of length 346103213422400382, capacity -35183298347009 = {<error reading variable>
(gdb) p vec[0]@4
$12 = {1, 2, 3, 4}

表达式

  • @符号主要用来打印数组的内容,(gdb) print array[0]@10
  • ::符号主要用于标识 C++ 程序中的类和命名空间作用域
  • 访问类的静态成员变量和静态成员函数
  • 测试代码
// region.cpp
#include <iostream>
using namespace std;class MyClass
{
public:static int staticVar;static void staticFunc(){// some codestd::cout << "Hello, GDB!" << std::endl;}
};int MyClass::staticVar = 42;int main()
{MyClass::staticFunc();return 0;
}
  • 调试过程如下:
$ gdb test1/region 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/region...
(gdb) b region.cpp:29
Breakpoint 1 at 0x11e9: file test1/region.cpp, line 29.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/region 
Hello, GDB!Breakpoint 1, main () at test1/region.cpp:29
29          return 0;
(gdb) p MyClass::staticVar  ## 通过作用域访问类中的静态变量
$1 = 42
(gdb) p MyNamespace::var  ## 通过作用域访问命名空间中的变量
$2 = 5
(gdb) call MyClass::staticFunc()  ## 通过作用域调用类中的静态函数
Hello, GDB!
(gdb) call MyNamespace::func()  ## 通过作用域调用命名空间中的函数
MyNamespace::func() called. Hello, GDB!

程序变量

  • 在GDB中,可以随时查看全局变量(所有文件可见)、静态全局变量(当前文件可见的)、局部变量(当前范围可见的)
  • 如果全局变量和局部变量名称相同,则可以使用作用域限定符,file::var,func::var

数组

  • 调试过程中,想要查看连续内存空间的值,或是动态分配数据的大小,可以使用上面讲到的@符号,左边放第一个内存地址,右边放想要查看的内存的长度,例如,有下面代码int * array = (int*)malloc(len * sizeof(int));,可以使用如下命令进行查看,p *array@len,如果是静态数组的话,可以直接p 数组名

查看内存

  • examine/<n><f><u> <addr>查看内存中的值,examine可以简写为x
  • n是一个正整数,表示显示内存的长度,也就是从当前地址向后显示几个地址的内容
  • <f>:显示格式(显示数据的格式,可以是 x(十六进制)、d(十进制)、u(无符号十进制)、o(八进制)、t(二进制)、f(浮点数)、a(地址)、c(字符)或 s(字符串))
  • <u>:单位大小(显示内存单元的大小,可以是 b(字节)、h(半字)、w(字)或 g(巨字,即 8 字节))
  • <address>:要检查的内存地址
  • 显示单个字节的十六进制值:x/1xb <address>
  • 显示四个字节的十六进制值:x/4xw <address>
  • 显示四个字节的十进制值:x/4dw <address>
  • 显示内存中的字符串:x/s <address>
  • 显示十个无符号十进制数:x/10uw <address>
  • 测试程序如下:
// examine.cpp
#include <iostream>int main()
{int numbers[4] = {10, 20, 30, 40};char message[] = "Hello, GDB!";std::cout << "Debugging example" << std::endl;return 0;
}
  • 调试过程如下:
$ gdb test1/examine 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/examine...
(gdb) b main
Breakpoint 1 at 0x11c9: file test1/examine.cpp, line 4.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/examine Breakpoint 1, main () at test1/examine.cpp:4
4       {
(gdb) p numbers  ## 未运行到该初始化代码时,为乱值
$1 = {-136555800, 32767, 1431655104, 21845}
(gdb) n
5           int numbers[4] = {10, 20, 30, 40};
(gdb) n
6           char message[] = "Hello, GDB!";
(gdb) p numbers   ## 初始化之后的值
$2 = {10, 20, 30, 40}
(gdb) p &numbers  ## 打印地址
$3 = (int (*)[4]) 0x7fffffffdbd0
(gdb) x/4dw 0x7fffffffdbd0 ## 将改地址解释为4个十进制数,每个数值为一个w(字)
0x7fffffffdbd0: 10      20      30      40
(gdb) n
7           std::cout << "Debugging example" << std::endl;
(gdb) p &message 
$4 = (char (*)[12]) 0x7fffffffdbec
(gdb) x/s 0xfffffffdbec  ## 将该地址输出为一个字符串
0xfffffffdbec:  <error: Cannot access memory at address 0xfffffffdbec>
(gdb) x/s 0x7fffffffdbec  ## 将该地址输出为一个字符串
0x7fffffffdbec: "Hello, GDB!" 
(gdb) x/16xb 0x7fffffffdbd0  ## 将该地址输出为16个16进制的数,每个数一个字节,也就是每个字节输出为一个十六进制
0x7fffffffdbd0: 0x0a    0x00    0x00    0x00    0x14    0x00    0x00    0x00
0x7fffffffdbd8: 0x1e    0x00    0x00    0x00    0x28    0x00    0x00    0x00
(gdb) x/12cb 0x7fffffffdbec  ## 显示 message 的每个字符
0x7fffffffdbec: 72 'H'  101 'e' 108 'l' 108 'l' 111 'o' 44 ','  32 ' '  71 'G'
0x7fffffffdbf4: 68 'D'  66 'B'  33 '!'  0 '\000'

自动显示

  • display命令用于在程序运行期间自动显示表达式的值。每次程序停止时,GDB 会自动显示指定表达式的当前值,这在调试时非常有用
  • 设置自动显示display <expression>
  • 查看所有自动显示的表达式info display
  • 删除自动显示的表达式undisplay <display-number>
  • 禁用自动显示disable display <display-number>
  • 启用自动显示enable display <display-number>
  • 清除所有自动显示的表达式delete display
  • 使用测试代码:
// display.cpp
#include <iostream>int main()
{int i = 0;for (i = 0; i < 5; ++i){std::cout << "i = " << i << std::endl;}float f = 3.14;char c = 'A';const char *str = "Hello, GDB!";int arr[] = {1, 2, 3, 4, 5};return 0;
}
  • 调试过程如下:
$ gdb test1/display 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/display...
(gdb) b display.cpp:6
Breakpoint 1 at 0x120b: file test1/display.cpp, line 6.
(gdb) b display.cpp:14
Breakpoint 2 at 0x1295: file test1/display.cpp, line 14.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/display Breakpoint 1, main () at test1/display.cpp:6
6           for (i = 0; i < 5; ++i)
(gdb) display i
1: i = 0
(gdb) display /f f
2: /f f = 4.59163468e-41
(gdb) display /c c
3: /c c = 0 '\000'
(gdb) display /s str
4: x/s str  0x555555555320 <__libc_csu_init>:   "\363\017\036\372AWL\215=;*"
(gdb) display /x arr
5: /x arr = {0x0, 0x0, 0x55555100, 0x5555, 0xffffdcf0}
(gdb) display /d arr[0]
6: /d arr[0] = 0
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
1:   y  i
2:   y  /f f
3:   y  /c c
4:   y  /1bs str
5:   y  /x arr
6:   y  /d arr[0]
(gdb) c
Continuing.
i = 0
i = 1
i = 2
i = 3
i = 4Breakpoint 2, main () at test1/display.cpp:14
14          return 0;
1: i = 5
2: /f f = 3.1400001
3: /c c = 65 'A'
4: x/s str  0x55555555600a:     "Hello, GDB!"
5: /x arr = {0x1, 0x2, 0x3, 0x4, 0x5}
6: /d arr[0] = 1
(gdb) disable display 1
(gdb) b display.cpp:15
Breakpoint 3 at 0x55555555529a: display.cpp:15. (3 locations)
(gdb) nBreakpoint 3, main () at test1/display.cpp:15
15      }
2: /f f = 3.1400001
3: /c c = 65 'A'
4: x/s str  0x55555555600a:     "Hello, GDB!"
5: /x arr = {0x1, 0x2, 0x3, 0x4, 0x5}
6: /d arr[0] = 1
  • display /i $pc用于显示程序计数器当前指向的汇编指令
  • 测试代码如下:
// display1.cpp
#include <stdio.h>int main() {int a = 5;int b = 10;int c = a + b;printf("Sum: %d\n", c);return 0;
}
  • 调试过程如下:
$ gdb test1/display1 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/display1...
(gdb) display /i $pc
1: x/i $pc
<error: No registers.>
(gdb) b main
Breakpoint 1 at 0x1149: file test1/display1.cpp, line 4.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/display1 Breakpoint 1, main () at test1/display1.cpp:4
4       {
1: x/i $pc
=> 0x555555555149 <main()>:     endbr64 
(gdb) n
5           int a = 5;
1: x/i $pc
=> 0x555555555155 <main()+12>:  movl   $0x5,-0xc(%rbp)
(gdb) 
6           int b = 10;
1: x/i $pc
=> 0x55555555515c <main()+19>:  movl   $0xa,-0x8(%rbp)
(gdb) 
7           int c = a + b;
1: x/i $pc
=> 0x555555555163 <main()+26>:  mov    -0xc(%rbp),%edx
(gdb) 
8           printf("Sum: %d\n", c);
1: x/i $pc
=> 0x55555555516e <main()+37>:  mov    -0x4(%rbp),%eax
(gdb) 
Sum: 15
9           return 0;
1: x/i $pc
=> 0x555555555184 <main()+59>:  mov    $0x0,%eax
(gdb) 
10      }
1: x/i $pc
=> 0x555555555189 <main()+64>:  leaveq 
(gdb) 
__libc_start_main (main=0x555555555149 <main()>, argc=1, argv=0x7fffffffdcf8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdce8) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
1: x/i $pc
=> 0x7ffff7dda083 <__libc_start_main+243>:      mov    %eax,%edi
(gdb) 
[Inferior 1 (process 3316307) exited normally]

设置显示选项

  • set print address on/off打开/关闭地址输出,当程序显示函数时,GDB会显出函数的参数地址,默认打开
  • show print address查看当前地址显示选项是否打开
  • set print array on/off打开/关闭数组显示,分行显示或是一行内显示,默认关闭
  • show print array查看数组显示是否打开
  • set print elements <number-of-elements>设置显示数组的最大长度
  • show print elements,默认200
  • set print null-stop <on/off>打开表示显示字符串时,遇到结束符就停止显示,默认off
  • set print pretty on格式化显示结构体,默认关闭,一行内显示结构体
  • set print sevenbit-strings <on/off>是否按\nnn格式显示字符或字符串,默认关闭
  • set print union <on/off>设置显示结构体时,是否显示其内部的联合体数据
  • 测试代码如下:
#include <stdio.h>typedef union
{int i;float f;char str[20];
} Data;typedef enum
{Tree,Bug
} Species;
typedef enum
{Big_tree,Acorn,Seedling
} Tree_forms;
typedef enum
{Caterpillar,Cocoon,Butterfly
} Bug_forms;
struct thing
{Species it;union{Tree_forms tree;Bug_forms bug;} form;
};int main()
{Data data;data.i = 10;printf("data.i = %d\n", data.i);printf("data.f = %f\n", data.f);printf("data.str = %s\n", data.str);struct thing foo = {Tree, {Acorn}};printf("foo.it = %d\n", foo.it);printf("foo.form.tree = %d\n", foo.form.tree);return 0;
}
  • 调试过程如下:
$ gdb test1/union 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/union...
(gdb) show print union
Printing of unions interior to structures is on.
(gdb) b union.cpp:48
Breakpoint 1 at 0x120d: file test1/union.cpp, line 48.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/union 
data.i = 10
data.f = 0.000000
data.str = foo.it = 0
foo.form.tree = 1Breakpoint 1, main () at test1/union.cpp:48
48          return 0;
(gdb) p data
$1 = {i = 10, f = 1.40129846e-44, str = "\n\000\000\000\000\000\000\000\200PUUUU\000\000\360\334\377\377"}
(gdb) p foo  ## 结构体里面的联合体被详细展示出来
$2 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}
(gdb) set print union off  ## 关闭
(gdb) show print union  
Printing of unions interior to structures is off.
(gdb) p data  ## 联合体完整展示
$3 = {i = 10, f = 1.40129846e-44, str = "\n\000\000\000\000\000\000\000\200PUUUU\000\000\360\334\377\377"}
(gdb) p foo
$4 = {it = Tree, form = {...}}  ## 设置为off之后,结构体里面的联合体不在详细展示
  • set print object <on/off>C++如果一个对象指针指向其派生类,打开此选项,GDB会自动按照虚方法调用的规则显示输出,如果关闭此选项,GDB就不管虚函数表,默认是off
  • 测试代码:
// object.cpp
#include <iostream>class Base
{
public:virtual void show(){std::cout << "Base::show()" << std::endl;}virtual ~Base() = default;
};class Derived : public Base
{
public:void show() override{std::cout << "Derived::show()" << std::endl;}
};int main()
{Base *b = new Derived();b->show();delete b;return 0;
}
  • 调试过程如下:
$ gdb test1/object 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/object...
(gdb) b object.cpp:26
Breakpoint 1 at 0x1229: file test1/object.cpp, line 26.
(gdb) show print object
Printing of object's derived type based on vtable info is off.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/object 
Derived::show()Breakpoint 1, main () at test1/object.cpp:26
26          delete b;
(gdb) p b
$1 = (Base *) 0x55555556aeb0
(gdb) p *b
$2 = {_vptr.Base = 0x555555557d18 <vtable for Derived+16>}
(gdb) set print object on
(gdb) show print object 
Printing of object's derived type based on vtable info is on.
(gdb) p b
$3 = (Derived *) 0x55555556aeb0
(gdb) p *b
$4 = (Derived) {<Base> = {_vptr.Base = 0x555555557d18 <vtable for Derived+16>}, <No data fields>}
  • 输出(Derived) {<Base> = {_vptr.Base = 0x555555557d18 <vtable for Derived+16>}, <No data fields>}解释如下:

  • (Derived):表示这个对象的实际类型是 Derived 类。

  • {<Base> = ...}:表示这个对象包含一个 Base 类的子对象。由于 Derived 继承自 Base,所以它包含一个 Base 的子对象。

  • _vptr.Base:这是 Base 类的虚函数表指针。这个指针指向虚函数表(vtable)的地址。

  • 0x555555557d18:这是虚函数表的地址。

  • <vtable for Derived+16>:表示这个虚函数表实际上是 Derived 类的虚函数表,地址偏移为 +16。

  • set print static-members <on/off>当显示一个C++对象中的内容时,是否显示其中的静态数据成员,默认是on

  • show print static-members查看静态数据成员的选项设置

  • set print vtbl <on/off>打开时,GDB将用比较规整的格式来显示虚函数表,默认off

  • show print vtbl查看虚函数显示格式的选项

历史记录

  • 使用print查看程序数据时,GDB会对输出的数据编号为$1,$2,可以通过编号访问以前的数据

GDB环境变量

  • set $foo = *object_ptr,可以给环境变量定义任何类型
  • show convenience查看当前所设置的所有的环境变量
(gdb) set $foo = *b  ## 设置环境变量
(gdb) show convenience  ## 查看所有环境变量
$foo = {_vptr.Base = 0x555555557d18 <vtable for Derived+16>}
$bpnum = 1
$_gdb_minor = 2
$_gdb_major = 9
$_any_caller_matches = <internal function _any_caller_matches>
$_any_caller_is = <internal function _any_caller_is>
$_caller_matches = <internal function _caller_matches>
$_caller_is = <internal function _caller_is>
$_regex = <internal function _regex>
$_streq = <internal function _streq>
$_strlen = <internal function _strlen>
$_memeq = <internal function _memeq>
$_as_string = <internal function _as_string>
$_inferior = 1
$_gdb_maint_setting = <internal function _gdb_maint_setting>
$_gdb_maint_setting_str = <internal function _gdb_maint_setting_str>
$_gdb_setting = <internal function _gdb_setting>
$_gdb_setting_str = <internal function _gdb_setting_str>
$_cimag = <internal function _cimag>
$_creal = <internal function _creal>
$_isvoid = <internal function _isvoid>
$_sdata = void
$_gthread = 1
$_thread = 1
$_probe_arg11 = <error: No probe at PC 0x0000555555555229>
$_probe_arg10 = <error: No probe at PC 0x0000555555555229>
$_probe_arg9 = <error: No probe at PC 0x0000555555555229>
$_probe_arg8 = <error: No probe at PC 0x0000555555555229>
$_probe_arg7 = <error: No probe at PC 0x0000555555555229>
$_probe_arg6 = <error: No probe at PC 0x0000555555555229>
$_probe_arg5 = <error: No probe at PC 0x0000555555555229>
$_probe_arg4 = <error: No probe at PC 0x0000555555555229>
$_probe_arg3 = <error: No probe at PC 0x0000555555555229>
$_probe_arg2 = <error: No probe at PC 0x0000555555555229>
  • 使用示例,要循环输出一个变量时,可以设置环境变量$i,然后循环输出set $i = 0,print bar[$i++],循环执行后面的语句就可以顺序输出结果

查看寄存器

  • info registers查看寄存器的情况,除浮点寄存器外
  • info all-registers查看所有寄存器
  • info registers <regname...>查看指定的寄存器情况
  • 使用示例
(gdb) info registers
rax            0x555555558040      93824992247872
rbx            0x55555556aeb0      93824992325296
rcx            0x7ffff7ce2297      140737350869655
rdx            0x0                 0
rsi            0x0                 0
rdi            0x7ffff7dc27e0      140737351788512
rbp            0x7fffffffdc00      0x7fffffffdc00
rsp            0x7fffffffdbe0      0x7fffffffdbe0
r8             0x0                 0
r9             0x0                 0
r10            0xfffffffffffff04a  -4022
r11            0x7ffff7c56340      140737350296384
r12            0x555555555100      93824992235776
r13            0x7fffffffdcf0      140737488346352
r14            0x0                 0
r15            0x0                 0
rip            0x555555555229      0x555555555229 <main()+64>
eflags         0x213               [ CF AF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
k0             0x0                 0
k1             0x0                 0
k2             0x0                 0
k3             0x0                 0
k4             0x0                 0
k5             0x0                 0
k6             0x0                 0
k7             0x0                 0
(gdb) info all-registers
rax            0x555555558040      93824992247872
rbx            0x55555556aeb0      93824992325296
rcx            0x7ffff7ce2297      140737350869655
rdx            0x0                 0
rsi            0x0                 0
rdi            0x7ffff7dc27e0      140737351788512
rbp            0x7fffffffdc00      0x7fffffffdc00
rsp            0x7fffffffdbe0      0x7fffffffdbe0
r8             0x0                 0
r9             0x0                 0
r10            0xfffffffffffff04a  -4022
r11            0x7ffff7c56340      140737350296384
r12            0x555555555100      93824992235776
r13            0x7fffffffdcf0      140737488346352
r14            0x0                 0
r15            0x0                 0
rip            0x555555555229      0x555555555229 <main()+64>
eflags         0x213               [ CF AF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
st0            0                   (raw 0x00000000000000000000)
st1            0                   (raw 0x00000000000000000000)
st2            0                   (raw 0x00000000000000000000)
st3            0                   (raw 0x00000000000000000000)
st4            0                   (raw 0x00000000000000000000)
st5            0                   (raw 0x00000000000000000000)
st6            0                   (raw 0x00000000000000000000)
st7            0                   (raw 0x00000000000000000000)
fctrl          0x37f               895
fstat          0x0                 0
--Type <RET> for more, q to quit, c to continue without paging--
ftag           0xffff              65535
fiseg          0x0                 0
fioff          0x0                 0
foseg          0x0                 0
fooff          0x0                 0
fop            0x0                 0
mxcsr          0x1f80              [ IM DM ZM OM UM PM ]
bndcfgu        {raw = 0x0, config = {base = 0x0, reserved = 0x0, preserved = 0x0, enabled = 0x0}} {raw = 0x0, config = {base = 0, reserved = 0, preserved = 0, enabled = 0}}
bndstatus      {raw = 0x0, status = {bde = 0x0, error = 0x0}} {raw = 0x0, status = {bde = 0, error = 0}}
k0             0x0                 0
k1             0x0                 0
k2             0x0                 0
k3             0x0                 0
k4             0x0                 0
k5             0x0                 0
k6             0x0                 0
k7             0x0                 0
pkru           0x55555554          1431655764
zmm0           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm1           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm2           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm3           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm4           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm5           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff,--Type <RET> for more, q to quit, c to continue without paging--0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm6           {v16_float = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x7fffffffffffffff, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xff <repeats 16 times>, 0x0 <repeats 48 times>}, v32_int16 = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0 <repeats 24 times>}, v16_int32 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0 <repeats 12 times>}, v8_int64 = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xffffffffffffffffffffffffffffffff, 0x0, 0x0, 0x0}}
zmm7           {v16_float = {0x0, 0x0, 0x0, 0xffffffff, 0x0 <repeats 12 times>}, v8_double = {0x8000000000000000, 0x7fffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x0 <repeats 48 times>}, v32_int16 = {0xf1f0, 0xf3f2, 0xf5f4, 0xf7f6, 0xf9f8, 0xfbfa, 0xfdfc, 0xfffe, 0x0 <repeats 24 times>}, v16_int32 = {0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8, 0xfffefdfc, 0x0 <repeats 12 times>}, v8_int64 = {0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0xfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0, 0x0, 0x0, 0x0}}
zmm8           {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm9           {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm10          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm11          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm12          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm13          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm14          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm15          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm16          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm17          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm18          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm19          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
zmm20          {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x0, 0x0, 0x0, 0x0}}
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) info registers rax
rax            0x555555558040      93824992247872
(gdb) p $rax  ## 使用print 查看寄存器
$1 = 93824992247872

改变程序的执行

  • 使用GDB调试程序时,可以根据自己的思路动态更改当前调试程序的运行线路或者变量的值

修改变量值

  • print x = 4修改为4
  • set var var_name=xxx设置变量值

跳转执行

  • jump <linespec>指定下一条语句的运行点,<linespec>可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式
  • jump <address>跳到指定地址
  • 注意,jump命令不会改变当前程序栈中的内容,所以,从一个函数跳到另外一个函数时,函数运行完返回时进行弹栈操作必然会发生错误,所以最好还是在同一个函数中进行跳转,jump主要是改变了指令寄存器中的值
  • 测试程序
//jump.cpp
#include <iostream>int main()
{int x = 0;int y = 1;int z = 2;std::cout << "Before jump: x = " << x << ", y = " << y << ", z = " << z << std::endl;z = x + y;std::cout << "After jump: x = " << x << ", y = " << y << ", z = " << z << std::endl;return 0;
}
  • 调试过程
$ gdb test1/jump 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/jump...
(gdb) b main
Breakpoint 1 at 0x11c9: file test1/jump.cpp, line 4.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/jump Breakpoint 1, main () at test1/jump.cpp:4
4       {
(gdb) n
5           int x = 0;
(gdb) 
6           int y = 1;
(gdb) 
7           int z = 2;
(gdb) jump 10
Continuing at 0x55555555526b.
After jump: x = 0, y = 1, z = 0  ## z的值没有被修改
[Inferior 1 (process 132450) exited normally]

产生信号量

  • signal <signal>发送信号
  • 常见信号:SIGINT (2): 终止进程(通常由 Ctrl+C 触发)、SIGKILL (9): 强制终止进程、SIGTERM (15): 请求终止进程、SIGSEGV (11): 无效内存引用、SIGABRT (6): 异常终止进程
  • 使用程序
// signal1.cpp
#include <stdio.h>
#include <signal.h>
#include <unistd.h>void handle_signal(int signal)
{printf("Received signal: %d\n", signal);
}int main()
{signal(SIGINT, handle_signal);printf("waiting for signal...\n");while (1){sleep(1);}return 0;
}
  • 调试结果
$ gdb test1/signal1 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/signal1...
(gdb) signal SIGINT
The program is not being run.
(gdb) b main
Breakpoint 1 at 0x11d1: file test1/signal1.cpp, line 11.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/signal1 Breakpoint 1, main () at test1/signal1.cpp:11
11      {
(gdb) n
12          signal(SIGINT, handle_signal);
(gdb) n
13          printf("waiting for signal...\n");
(gdb) n
waiting for signal...
16              sleep(1);
(gdb) signal SIGINT
Continuing with signal SIGINT.
Received signal: 2

强制函数返回

  • 如果在调试过程中,某个函数还没有执行完,可以使用return命令强制函数忽略还没有执行完的语句并返回
  • return <expression>
  • 使用程序
// return.cpp
#include <stdio.h>int add(int a, int b) {return a + b;
}int main() {int result = add(3, 4);printf("Result: %d\n", result);return 0;
}
  • 调试过程
$ gdb test1/return 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 test1/return...
(gdb) b add
Breakpoint 1 at 0x1149: file test1/return.cpp, line 4.
(gdb) r
Starting program: /home/aaa/bbb/ccc/GDBDebug/test1/return Breakpoint 1, add (a=21845, b=1431654816) at test1/return.cpp:4
4       {
(gdb) n
5           return a + b;
(gdb) p a
$1 = 3
(gdb) p b
$2 = 4
(gdb) return 10
Make add(int, int) return now? (y or n) y
#0  0x000055555555517c in main () at test1/return.cpp:10
10          int result = add(3, 4);
(gdb) n
11          printf("Result: %d\n", result);
(gdb) n
Result: 10
12          return 0;

强制函数调用

  • call <expr>或者print func(a, b)
  • 使用上面的程序
(gdb) call add(1, 2)
$1 = 3
(gdb) print add(5, 6)
$2 = 11
(gdb) 
  • 查看当前调试的语言环境show language
  • info frame查看当前栈信息
  • info source查看当前文件的程序语言
(gdb) info source
Current source file is test1/return.cpp
Compilation directory is /home/aaa/bbb/ccc/GDBDebug
Located in /home/aaa/bbb/ccc/GDBDebug/test1/return.cpp
Contains 13 lines.
Source language is c++.
Producer is GNU C++14 9.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.

GDB启动的方式

  • gdb program启动可执行文件
  • gdb program core启动可执行文件和core dump文件
  • gdb pid 如果调试服务程序,可以指定pid,GDB会自动attach

GDB启动时常用开关

  • -symbols [file](-s) 读取文件中的符号表
  • -exec [file](-e) 调试一个可执行文件
  • -se [file] 上二者的缩写
  • -core [file] (-c) 读入一个core dump文件
  • -pid number (-p) 启动attach模式
  • -directory [directory] (-d)添加源码扫描路径
  • -readnow (-r)一次读取完所有的符号表
  • -quite -silent -q安静模式,启动GDB将不显示版权页
  • -windows -w 启动GUI
  • -nowindows -nw 如果GDB编入GUI的话,这个选项会关掉它
  • -cd [directory] 切换工作目录为directory而不是现在的目录
  • -tty [device] (-t) 指定device为标准输出
  • --args 这个参数要当做命令的最后一个参数,其后的参数都会变成调试程序参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/29426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python __call__(实例化对象的时候返回一个函数,调用这个函数的时候会执行__call__)(将类实例用作回调函数)(类装饰器)

文章目录 Python中的__call__方法深入解析__call__方法简介定义和基本用法为什么要使用__call__方法 __call__方法的高级用法在装饰器中使用__call__&#xff08;类装饰器&#xff1a;在类中保持状态或进行状态管理&#xff09;将类实例用作回调函数 结论 Python中的__call__方…

ComfyUI 完全入门:ControlNet 使用教程

今天继续给大家分享 ComfyUI 的入门必备技能&#xff1a;ControlNet。 ControlNet 提供了十几种生成图片的控制方式&#xff0c;有的可以控制画面的结构&#xff0c;有的可以控制人物的姿势&#xff0c;还有的可以控制图片的画风&#xff0c;这对于提高 AI 绘画的质量特别有用…

谷粒商城实战(042集群学习-mysql集群-主从同步)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第361p-第p363的内容 集群 集群的基础形式 MySQL集群 MMM机制 这里使用了vip虚拟ip方式&#xff08;如192.168.0.101&#xff0c;192.168.0.102&…

深入理解计算机系统 CSAPP 家庭作业6.40

这书真是会绕. A:16*16*4 B:256 ,第一个for 50%不命中 0.5*16*16.第二个for 每两个循环1次不命中 也就是128次 C:0.25

网上书店商城项目采用SpringBoot+Vue前后端分离技术(商家端、移动端、PC端)

项目简介&#xff1a; 本项目基于SpringBootVue2技术设计并实现了一个网上书店商城系统。系统的数据采用MYSQL数据库进行存储&#xff0c;开发工具选择为IDEA或VSCode工具。本商城系统具有前台购物功能和后台相应的信息管理。前台用户登陆注册后可以进行商品浏览、添加购物车、…

茶艺师服务师傅小程序APP源码(APP+小程序+公众号+H5)

&#x1f375;茶艺师服务小程序&#xff1a;品味生活的茶艺新体验&#x1f331; &#x1f33f;一、引言&#xff1a;茶艺师服务小程序&#xff0c;让生活更有味 在繁忙的生活中&#xff0c;品一杯香茗&#xff0c;感受茶文化的韵味&#xff0c;是许多人向往的休闲方式。然而&…

汇编语言程序设计 - 新建一个文件:d:\abc.txt,从键盘输入文件的内容(不超过100个字符)

80x86汇编习题 题目描述&#xff1a;编写一个程序&#xff0c;新建一个文件&#xff1a;d:\abc.txt&#xff0c;从键盘输入文件的内容&#xff08;不超过100个字符&#xff09; 思路&#xff1a; 1&#xff0c;定义好文件名&#xff0c;记得末尾0 2&#xff0c;定义好缓冲区…

高考分数限制下,选好专业还是选好学校?

高考分数限制下&#xff0c;选好专业还是选好学校&#xff1f; 高考作为每年一度的盛大考试&#xff0c;不仅关乎学生们的未来&#xff0c;更承载了家庭的期望。2004年高考刚刚结束&#xff0c;许多考生和家长已经开始为填报志愿而焦虑。选好学校和专业&#xff0c;直接关系到…

windows如何查看硬盘类型(查看磁盘类型)(查看是固态硬盘ssd还是机械硬盘hdd)(Windows优化驱动器——媒体类型)

文章目录 方法&#xff1a;使用Windows优化驱动器1、在任务栏搜索框中输入“优化驱动器”并打开它。2、在优化驱动器的窗口中&#xff0c;查看每个驱动器旁边的“媒体类型”。3、如果列出的是“固态驱动器”&#xff0c;那么它是SSD&#xff1b;如果是“硬盘驱动器”&#xff0…

图像分割——U-Net论文介绍+代码(PyTorch)

0、概要 原理大致介绍了一下&#xff0c;后续会不断精进改的更加详细&#xff0c;然后就是代码可以对自己的数据集进行一个训练&#xff0c;还会不断完善&#xff0c;相应其他代码可以私信我。 一、论文内容总结 摘要&#xff1a;人们普遍认为&#xff0c;深度网络成功需要数…

Ansible离线部署 之 Zabbix

Ansible介绍 Ansible 是一个自动化平台&#xff0c;用于 IT 自动化&#xff0c;如配置管理、应用部署、任务自动化等。Ansible 使用 SSH 来连接到远程机器&#xff0c;并执行预定义的任务。Ansible 的主要特点是其简单性、易用性和强大的功能集。 以下是 Ansible 的一些关键特…

vs2022配置openvino环境(无需修改系统环境变量)

openvino版本&#xff1a;2022.3.0 opencv版本&#xff1a;4.8.0 配置openvino Release版本 &#xff08;一&#xff09;右键打开项目的属性 &#xff08;二&#xff09;配置opencv和openvino的环境&#xff08;路径根据自己的安装路径进行修改&#xff09;

禁用/屏蔽 Chrome 默认快捷键

Chrome 有一些内置的快捷键&#xff0c;但是它并没有像其他软件一样提供管理快捷键的界面。在某些时候&#xff0c;当我们因为个人需求希望禁用 Chrome 某些快捷键时&#xff0c;又无从下手。 好在有开发者开发了 Chrome 插件&#xff0c;可以禁用 Chrome 快捷键的插件&#x…

文心一言 VS 讯飞星火 VS chatgpt (284)-- 算法导论21.2 2题

二、对定理 21.1 的整体证明进行改造&#xff0c;得到使用链表表示和加权合并启发式策略下的 MAKE-SET 和 FIND-SET 的摊还时间上界为 O(1)&#xff0c;以及 UNION 的摊还时间上界为 O(lgn)。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 在Go语言中实现使用链…

红黑树插入数据的底层详解

红黑树定义 1. 每个结点不是红色就是黑色 2. 根节点是黑色的 3. 如果一个节点是红色的&#xff0c;则它的两个孩子结点是黑色的 4. 对于每个结点&#xff0c;从该结点到其所有后代叶结点的简单路径上&#xff0c;均 包含相同数目的黑色节点 5. 每个叶子结点都是黑色的(此…

大模型下一步在哪里?王小川、杨植麟等给出回答 “苹果智能”何时可用?

大模型下一步在哪里 AI大模型是正在进行的新一轮技术革命&#xff0c;它最终能否通向AGI&#xff0c;在技术研发和商业落地之间该如何权衡&#xff0c;这是当下需要厘清的核心议题。 6月14日&#xff0c;在2024北京智源大会上&#xff0c;百川智能CEO王小川、智谱AI CEO张鹏、…

具身智能的视觉-语言-动作模型综合综述论文

近期arXiv公开了关于具身智能&#xff08;Embodied AI&#xff09;中的视觉-语言-动作模型&#xff08;Vision-Language-Action Models&#xff0c;简称VLAs&#xff09;的综合综述论文。介绍了VLAs的概念&#xff0c;它们是为了处理多模态输入而设计的模型&#xff0c;包括视觉…

Linux UFW防火墙设置、案例教程及注意事项

背景 远程连接服务器时&#xff0c;发现SSH远程登录服务器失败&#xff0c;但是又可以Ping通&#xff0c;故服务器的是开启的。 sudo systemctl status sshd查看sshd的状态发现其是active&#xff0c;所以为什么一直SSH失败呢&#xff1f; 最后知道是有人启动了防火墙&#x…

氢气传感器:呼吸疾病的隐形向导

​ ​​在医学领域&#xff0c;每一次技术革新都可能成为疾病诊断与治疗的新曙光。氢气传感器&#xff0c;这一看似不起眼的装置&#xff0c;正逐渐成为辅助诊断呼吸系统疾病的关键工具。它如同一位精准的侦探&#xff0c;穿梭于呼吸的微风中&#xff0c;捕捉着那些可能预示…

示例:WPF中在没有MouseDoubleClick的控件中如何识别双击

一、目的&#xff1a;由于MouseDoubleClick控件是在Control中实现&#xff0c;那么在底层控件如Grid中想要类似功能如何实现&#xff0c;这里通过MouseDown的事MouseButtonEventArgs参数去实现 二、实现 定义Grid并注册Grid的MouseDown事件 <Grid Background"Transpa…