想要熟练利用GDB进行程序调试,首先要了解什么是GDB。

1. 什么是GDB

GDB (the GNU Project Debugger) 是一个可以运行在大多数常见的UNIX架构、Windows、Mac OSX等系统上的跨平台调试器,允许我们查看另一个程序在运行过程中内部发生了什么——或者另一个程序崩溃时在做什么。

具体而言,GDB能做以下四种事情[1],以帮助我们定位运行中的Bug:

  • 让程序开始运行,指定任何可能影响其行为的内容。
  • 让程序在特定条件下停止运行。
  • 检查程序停止运行时发生了什么。
  • 在程序中改变一些变量或条件,修复当前的Bug使其正常执行,继续检查下一个。

根据官网介绍,GDB (9.1版本) 支持 Ada/Assembly/C/C++/D/Fortran/Go/Objective-C/OpenCL/Modula-2/Pascal/Rust 等编程语言的调试。

2. 调试原理

那么 GDB 是如何调试程序,其实现的原理是什么呢?为什么它可以控制程序执行、中断、访问内存甚至改变程序流程呢?

这就要从一个强大的系统调用 ptrace() 说起了。

2.1 系统调用 ptrace

简单来说,ptrace 系统调用提供了一种方法,让父进程可以观察和控制其它进程的执行,检查和改变其核心映像和寄存器。主要用来实现断点调试和系统调用跟踪。

GDB 的跟踪调试允许设置程序断点 break point,父进程通过 ptrace 接管子进程除了 SIGKILL 之外的所有信号。子进程(就是我们调试的程序)在发送 break point 或者单步调试时,会产生一个信号 SIGTRAP,被父进程(这里的GDB)捕获到,这时用户就可以通过 GDB 实时观察到当前子进程的状态。

2.2 三种调试方式

2.2.1 gdb executable_file

运行并调试一个新的进程。

首先通过fork()系统调用创建一个新进程,在新创建的子进程中调用 ptrace(PTRACE_TRACEME, 0, 0, 0),在子进程中通过execv()系统调用加载用户指定的可执行文件。

2.2.2 gdb executable_file corefile

如果程序发生了 core dump,出现段错误 (segment fault) 等,该命令可用于查看 coredump 文件信息,定位coredump产生原因、触发源。

2.2.3 gdb attach pid

调试一个已经运行的进程,如服务器进程等,同 gdb -p pid

首先需要确定待调试进程的进程 id,可利用 ps 指令获取 pid;然后运行 gdb attch pid,gdb 将对指定进程执行如下操作:ptrace (PTRACE_ATTACH, pid, 0, 0)

3. 信息显示

以 MacOS Mojave 10.14.6 系统为例

3.1 终端输入 gdb 进入调试器,一般启动时会显示如下信息

  1. GNU gdb (GDB) 8.3
  2. Copyright (C) Free Software Foundation, Inc.
  3. License GPLv3+: GNU GPL version or later <http://gnu.org/licenses/gpl.html>
  4. This is free software: you are free to change and redistribute it.
  5. There is NO WARRANTY, to the extent permitted by law.
  6. Type "show copying" and "show warranty" for details.
  7. This GDB was configured as "x86_64-apple-darwin18.5.0".
  8. Type "show configuration" for configuration details.
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>.
  11. Find the GDB manual and other documentation resources online at:
  12. <http://www.gnu.org/software/gdb/documentation/>.
  13.  
  14. For help, type "help".
  15. Type "apropos word" to search for commands related to "word".
  16. (gdb)

显示信息

如果不想显示这些信息,可以通过 -q 参数将其关掉

  1. cv-MacBook-Pro:~ cv$ gdb -q
  2. (gdb)

3.2 在调试过程中,任何时候如果想查看 GDB 版本信息

  1. (gdb) show version
  1. GNU gdb (GDB) 8.3
  2. Copyright (C) Free Software Foundation, Inc.
  3. License GPLv3+: GNU GPL version or later <http://gnu.org/licenses/gpl.html>
  4. This is free software: you are free to change and redistribute it.
  5. There is NO WARRANTY, to the extent permitted by law.
  6. Type "show copying" and "show warranty" for details.
  7. This GDB was configured as "x86_64-apple-darwin18.5.0".
  8. Type "show configuration" for configuration details.
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>.
  11. Find the GDB manual and other documentation resources online at:
  12. <http://www.gnu.org/software/gdb/documentation/>.
  13.  
  14. For help, type "help".
  15. Type "apropos word" to search for commands related to "word".

(gdb) show version

3.3 如果想查看 GDB 版权相关信息

  1. (gdb) show copying
  1. GNU GENERAL PUBLIC LICENSE
  2. Version , June
  3.  
  4. Copyright (C) Free Software Foundation, Inc. <http://fsf.org/>
  5. Everyone is permitted to copy and distribute verbatim copies
  6. of this license document, but changing it is not allowed.
  7.  
  8. Preamble
  9.  
  10. The GNU General Public License is a free, copyleft license for
  11. software and other kinds of works.
  12.  
  13. The licenses for most software and other practical works are designed
  14. to take away your freedom to share and change the works. By contrast,
  15. the GNU General Public License is intended to guarantee your freedom to
  16. share and change all versions of a program--to make sure it remains free
  17. software for all its users. We, the Free Software Foundation, use the
  18. GNU General Public License for most of our software; it applies also to
  19. any other work released this way by its authors. You can apply it to
  20. your programs, too.
  21.  
  22. When we speak of free software, we are referring to freedom, not
  23. price. Our General Public Licenses are designed to make sure that you
  24. --Type <RET> for more, q to quit, c to continue without paging--
  25. have the freedom to distribute copies of free software (and charge for
  26. them if you wish), that you receive source code or can get it if you
  27. want it, that you can change the software or use pieces of it in new
  28. free programs, and that you know you can do these things.
  29.  
  30. To protect your rights, we need to prevent others from denying you
  31. these rights or asking you to surrender the rights. Therefore, you have
  32. certain responsibilities if you distribute copies of the software, or if
  33. you modify it: responsibilities to respect the freedom of others.
  34.  
  35. For example, if you distribute copies of such a program, whether
  36. gratis or for a fee, you must pass on to the recipients the same
  37. freedoms that you received. You must make sure that they, too, receive
  38. or can get the source code. And you must show them these terms so they
  39. know their rights.
  40.  
  41. Developers that use the GNU GPL protect your rights with two steps:
  42. () assert copyright on the software, and () offer you this License
  43. giving you legal permission to copy, distribute and/or modify it.
  44.  
  45. For the developers' and authors' protection, the GPL clearly explains
  46. that there is no warranty for this free software. For both users' and
  47. authors' sake, the GPL requires that modified versions be marked as
  48. --Type <RET> for more, q to quit, c to continue without paging--
  49. changed, so that their problems will not be attributed erroneously to
  50. authors of previous versions.
  51. ......

(gdb) show copying

或者

  1. (gdb) show warranty
  1. . Disclaimer of Warranty.
  2.  
  3. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
  4. APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
  5. HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
  6. OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
  7. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  8. PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
  9. IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
  10. ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  11.  
  12. . Limitation of Liability.
  13.  
  14. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  15. WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
  16. THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
  17. GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  18. USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
  19. DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
  20. PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
  21. EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
  22. SUCH DAMAGES.
  23. ......

(gdb) show warranty

3.4 当 gdb 输出信息较多时会暂停输出,并打印 “---Type <return> to continue, or q <return> to quit---” 这样的提示信息

如果想要让其中间不暂停,输出全部内容,设置

  1. cv-MacBook-Pro:~ cv$ gdb
  2. (gdb) set pagination off

或者

  1. cv-MacBook-Pro:~ cv$ gdb
  2. (gdb) set height

附录A

A.i 在大多 Linux 系统如 Ubuntu16.04 中 ptrace 系统调用原型如下

ptrace definition
  • enum __ptrace_request request  指示ptrace要执行的命令。
  • pid_t pid  指示ptrace要跟踪的进程。
  • void *addr  指示要监控的内存地址。
  • void *data  存放读取出的或者要写入的数据。

request 的主要选项

  • PTRACE_TRACEME 由子进程调用,表示本进程将被其父进程跟踪,交付给这个进程的所有信号,即使信号是忽略处理的(SIGKILL 除外),都会使其停止,父进程通过 wait() 获知这一情况
  • PTRACE_ATTACH 指attach到一个指定的进程,使其成为当前进程跟踪的子进程,而子进程的行为等同于它进行了一次 PTRACE_TRACEME 操作。但要注意的是,虽然当前进程成为被跟踪进程的父进程,但是子进程使用 getppid() 得到的仍是其原始父进程的 pid。当在 GDB 中使用 attach 命令来跟踪一个指定进程/线程时,GDB 就自动成为该进程的父进程,而被跟踪的进程则使用了一次 PTRACE_TRACEME,GDB 也就顺理成章接管这个进程。
  • PTRACE_CONT 继续运行之前停止的子进程。可同时向子进程交付指定的信号。

A.ii 在 MacOS Mojave 10.14.6 系统中通过 man ptrace 显示如下

  1. #include <sys/types.h>
  2. #include <sys/ptrace.h>
  3.  
  4. int
  5. ptrace(int request, pid_t pid, caddr_t addr, int data);

其中 request 有以下几个主要设置选项

  • PT_TRACE_ME

此请求是被跟踪进程使用的两个请求之一,声明当前进程将被其父进程跟踪。所有其它参数都会被忽略。当一个进程使用了这个请求并调用execve(2)或其上构建的任何例程时,它将在执行新映像的第一条指令前停止。此外在可执行文件执行过程中,任何 setuid 或 setgid 位都会被忽略。

  • PT_ATTACH/PT_ATTACHEXC

此请求允许进程获得对其它无关进程的控制并开始对其跟踪。不需要被跟踪进程的任何配合。此情况下,pid 指定将被跟踪的进程的进程 ID,其余两个参数被忽略。此请求要求目标进程与跟踪进程必须具有相同的真实UID,并且它不能执行 setuid 或 setgid 可执行文件。跟踪进程将感知到新跟踪的进程的停止,然后可以像一直跟踪一样控制它。注意此调用不同于先前的调用(PT_ATTACH),因为来自子调用的信号作为Mach异常传递给父调用。

  • PT_STEP

单步执行被跟踪的进程。参数与传给 PT_CONTINUE 的相同。

  • PT_CONTINUE

被跟踪的进程继续执行。addr指向即将被执行的进程的地址,或者为 1 表示从之前停止的地方开始继续执行。data提供在跟踪进程恢复执行时传递给跟踪进程的信号值,不发送信号则为 0。

  • PT_DETACH

该请求与 PT_CONTINUE 基本相同,除了不允许在另一个备用位置继续执行,在它成功之后,被跟踪的进程将不再被跟踪,并且正常继续执行。


参考资料

[1] GDB: The GNU Project Debugger

[2] 100个gdb小技巧之信息显示

[3] GDB实现原理和使用范例

[4] 比较全面的gdb调试命令

[5] GDB使用记录

GDB调试系列之了解GDB的更多相关文章

  1. gdb调试器的使用

    想要使用gdb调试程序的话,首先需要gcc -g main.c -o test 然后运行gdb test对程序进行调试 l (小写的l,是list的首字母),用以列出程序 回车    是运行上一个命令 ...

  2. 赵文豪 GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 使用gdb调 ...

  3. gdb调试基本命令(常用)

    gdb调试命令 1>. 启动gdb gdb 可执行程序的名字 2>. 查看代码 l -- 查看当前文件 -- 默认main函数 2. 查看其它文件: l 文件名:行号, 显示指定行号的上下 ...

  4. Linux下GDB调试

    GDB 是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行 序列,形成脚本.UNIX 下的软件全是命令行的,这给程序开发提供了极大的便利,命令行 软件的优势在于, 他们可以非常容 ...

  5. 20145219 gdb调试汇编堆栈分析

    20145219 gdb调试汇编堆栈分析 代码gdbdemo.c int g(int x) { return x+19; } int f(int x) { return g(x); } int mai ...

  6. GDB调试器

    /*this project used for gdb debug c programs*//*At first,using compile command turn out the executab ...

  7. 比较全面的gdb调试命令 (转载)

    转自http://blog.csdn.net/dadalan/article/details/3758025 用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形 ...

  8. 使用GDB调试器(一)

    使用GDB调试器 GDB概要---- GDB是GNU开源组织公布的一个强大的UNIX下的程序调试工具.也许,各位比較喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但假设你是在UNIX平台下做软 ...

  9. Nginx学习之十四-GDB调试Nginx初试

    本文的测试环境: Win7+虚拟机VMWareVMware-workstation-full-7.1.4-385536+Ubuntu12.04 Nginx-1.4.0 要想有效的研究Nginx源码,必 ...

随机推荐

  1. TPO1-3Timberline Vegetabtion on Mountain|have the advantage over

    The upper timberline, like the snow line, is highest in the tropics and lowest in the Polar Regions. ...

  2. Java中Arrays详解

    一.Arrays类的定义 Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法 使用时导包:import java.util.Arrays 二.Arrays常用函数(都是静态的) ...

  3. [学习笔记]set的使用

    set默认进行升序排列,通过结构体可以改. 维护一个比主人公分数高的set 降序排列,比主人公高就进入set 比主人公低就不进去,或者在删除操作里删掉. 然后血的教训 https://blog.csd ...

  4. hibernate 持久化对象 save

    hibernate 持久化对象 save new出来的user对象是游离状态的对象,执行session.save()方法保存后,user对象就变为持久化了,持久化的对象跟数据库表双向绑定的意思, 对象 ...

  5. VSFTP服务搭建

    title date tags layout CentOS6.5 Vsftp服务安装与配置 2018-09-04 Centos6.5服务器搭建 post 1.安装vsftp服务 [root@local ...

  6. 六、linux-mysql的mysql字符集问题

    一.什么是字符集? 字符集是用来定义mysql数据字符串的存储方式,而校对规则则是定义比较字符串的方式.mysql字符集包含字符集和校对规则. 二.字符集的选择 常见的字符集中,中英混合环境建议用UT ...

  7. MTSP问题

    问题描述:m个旅行商去旅游 n个城市,规定都必须从同一个出发点出发,而且返回原出发点,需要将所有的城市遍历完毕,每个城市只能游历一次,但是为了路径最短可以路过这个城市多次.这个就是多旅行商问题.是在T ...

  8. Linux基础篇八:VIM

    新知识: 普通模式光标跳转: G     ##光标跳转到末端  (shift +g) gg   ##光标跳转到开端 Ngg 15gg  ##光标跳转到当前文本中的15行 $     ##光标移动到当前 ...

  9. linux清除cache的方法

    1  Linux下内存占用多的原因 当linux第一次读取一个文件运行时,一份放到一片内存中cache起来,另一份放入运行程序的内存中,正常运行,当程序运行完,关闭了,cache中的那一分却没有释放, ...

  10. python学习笔记(16)hashlib.md5摘要算法(哈希算法)

    一.摘要算法格式 import hashlib #导入hashlib模块 md = hashlib.md5() #获取一个md5加密算法对象 md.update('how to use md5 in ...