GDB调试系列之了解GDB
想要熟练利用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 进入调试器,一般启动时会显示如下信息
GNU gdb (GDB) 8.3
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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-apple-darwin18.5.0".
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".
(gdb)
显示信息
如果不想显示这些信息,可以通过 -q 参数将其关掉
cv-MacBook-Pro:~ cv$ gdb -q
(gdb)
3.2 在调试过程中,任何时候如果想查看 GDB 版本信息
(gdb) show version
GNU gdb (GDB) 8.3
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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-apple-darwin18.5.0".
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".
(gdb) show version
3.3 如果想查看 GDB 版权相关信息
(gdb) show copying
GNU GENERAL PUBLIC LICENSE
Version , June Copyright (C) Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for
software and other kinds of works. The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too. When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
--Type <RET> for more, q to quit, c to continue without paging--
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights. Developers that use the GNU GPL protect your rights with two steps:
() assert copyright on the software, and () offer you this License
giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
--Type <RET> for more, q to quit, c to continue without paging--
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
......
(gdb) show copying
或者
(gdb) show warranty
. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. . Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
......
(gdb) show warranty
3.4 当 gdb 输出信息较多时会暂停输出,并打印 “---Type <return> to continue, or q <return> to quit---” 这样的提示信息
如果想要让其中间不暂停,输出全部内容,设置
cv-MacBook-Pro:~ cv$ gdb
(gdb) set pagination off
或者
cv-MacBook-Pro:~ cv$ gdb
(gdb) set height
附录A
A.i 在大多 Linux 系统如 Ubuntu16.04 中 ptrace 系统调用原型如下
- 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 显示如下
#include <sys/types.h>
#include <sys/ptrace.h> int
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的更多相关文章
- gdb调试器的使用
想要使用gdb调试程序的话,首先需要gcc -g main.c -o test 然后运行gdb test对程序进行调试 l (小写的l,是list的首字母),用以列出程序 回车 是运行上一个命令 ...
- 赵文豪 GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 使用gdb调 ...
- gdb调试基本命令(常用)
gdb调试命令 1>. 启动gdb gdb 可执行程序的名字 2>. 查看代码 l -- 查看当前文件 -- 默认main函数 2. 查看其它文件: l 文件名:行号, 显示指定行号的上下 ...
- Linux下GDB调试
GDB 是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行 序列,形成脚本.UNIX 下的软件全是命令行的,这给程序开发提供了极大的便利,命令行 软件的优势在于, 他们可以非常容 ...
- 20145219 gdb调试汇编堆栈分析
20145219 gdb调试汇编堆栈分析 代码gdbdemo.c int g(int x) { return x+19; } int f(int x) { return g(x); } int mai ...
- GDB调试器
/*this project used for gdb debug c programs*//*At first,using compile command turn out the executab ...
- 比较全面的gdb调试命令 (转载)
转自http://blog.csdn.net/dadalan/article/details/3758025 用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形 ...
- 使用GDB调试器(一)
使用GDB调试器 GDB概要---- GDB是GNU开源组织公布的一个强大的UNIX下的程序调试工具.也许,各位比較喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但假设你是在UNIX平台下做软 ...
- Nginx学习之十四-GDB调试Nginx初试
本文的测试环境: Win7+虚拟机VMWareVMware-workstation-full-7.1.4-385536+Ubuntu12.04 Nginx-1.4.0 要想有效的研究Nginx源码,必 ...
随机推荐
- 14 微服务电商【黑马乐优商城】:day02-springcloud(搭建Eureka注册中心)
本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...
- NOIP2013D1T3货车运输 (生成树+树链剖分)
给出一个图,询问图上两点间路径上最小边权的最大值. 先跑一次最大生成树. 树剖维护路径最小边权. 树剖又双叒叕写挂了. #include<cstring> #include<cstd ...
- [LC] 117. Populating Next Right Pointers in Each Node II
Given a binary tree struct Node { int val; Node *left; Node *right; Node *next; } Populate each next ...
- 对Java8新的日期时间类的学习(一)
引用自Java译站http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.html 除 ...
- FastDFS安装部署
博主本人平和谦逊,热爱学习,读者阅读过程中发现错误的地方,请帮忙指出,感激不尽 服务器信息: Storage:192.168.247.20 Traker:192.168.247.21 一.搭建环境准备 ...
- 路由配置(route IP
转载于:http://blog.csdn.net/chenlycly/article/details/52141854 使用下面的 route 命令可以查看 Linux 内核路由表. # route ...
- 如何使用Outlook 客户端配置其他邮箱客户端收发邮件
本文介绍Outlook2016客户端配置QQ邮箱收发邮件 1.打开Outlook客户端,文件->信息->-添加账户 2.输入需要添加的邮箱账户,点击连接 3.输入密码并连接 4.打开QQ邮 ...
- 深入JVM内核--JVM运行机制
JVM启动流程 JVM基本结构 PC寄存器 每个线程拥有一个PC寄存器 在线程创建时 创建 指向下一条指令的地址 执行本地方法时,PC的值为undefined 方法区 保存装载的类信息 类型的常量池 ...
- verilog求倒数-ROM实现方法
采用线性逼近法结合32段线性查找表的方式来实现1/z的计算. 首先将1/32-1/64的定点化数据存放到ROM中,ROM中存放的是扩大了2^20 次方的数字四舍五入后的整数部分.n值越大,精度越大,误 ...
- 为什么jdk1.8 HashMap的容量一定要是2的n次幂
一.jdk1.8中,对“HashMap的容量一定要是2的n次幂”做了严格控制 1.默认初始容量: [Java] 纯文本查看 复制代码 ? 1 2 3 4 /** * The default init ...