一、前言
这篇文章来聊聊大名鼎鼎的GDB,它的豪门背景咱就不提了,和它的兄弟GCC一样是含着金钥匙出生的,在GNU的家族中的地位不可撼动。相信每位嵌入式开发工程师都使用过gdb来调试程序,如果你说没有用过,那只能说明你的开发经历还不够坎坷,还需要继续被 BUG吊打。
![7c9e9e918f30c9faf4cdfe645b091624.png](https://i-blog.csdnimg.cn/blog_migrate/a8c6dbb6a3b9bf1e04693aab11fa6ed0.png)
我们都知道,在使用gcc编译时,可以使用-g选项在可执行文件中嵌入更多的调试信息,那么具体嵌入了哪些调试信息?这些调试信息是如何与二进制的指令之间进行相互交互?在调试的时候,调试信息中是如何获取函数调用栈中的上下文信息?
针对上面这些疑惑,道哥用两篇文章把这些底层最深处的问题彻底描述清楚,让你一次看过瘾。
第一篇文章,就是当前这一篇,主要内容是介绍GDB的底层调试原理,我们来看一下GDB是通过什么机制来控制被调试程序的执行顺序。
第二篇文章,我们选择一个体积小巧、五脏俱全的LUA语言来进行剖析,从源代码分析到函数调用栈,从指令集到调试库的修改,一网打尽。
内容比较多,看完本文需要的时间可能长一些,为了您的健康,不建议在处于蹲姿的时候阅读这篇文章。
二、GDB调试模型
GDB调试包括2个程序:gdb程序和被调试程序。根据这2个程序是否运行在同一台电脑中,可以把GDB的调试模型分为2种:
- 本地调试
- 远程调试
本地调试:调试程序和被调试程序运行在同一台电脑中。
![0ab874f08ecb78671d5b32dc053522f3.png](https://i-blog.csdnimg.cn/blog_migrate/7b4d329d7c5d795340e50ca824a49858.png)
远程调试:调试程序运行在一台电脑中,被调试程序运行在另一台电脑中。
![507842b16dca12eeeca5aa240e1aa1b9.png](https://i-blog.csdnimg.cn/blog_migrate/3e25c8f216aba200ad453772f8b6076e.png)
关于可视化调试程序并不是重点,它只是一个用来封装GDB的外壳而已。我们既可以用黑乎乎的终端窗口来手动输入调试命令;也可以选择集成开发环境(IDE),这个IDE中已经嵌入了器调试,这样就可以使用各种button来代替手动输入调试命令了。
与本地调试相比,远程调试中多了一个GdbServer程序,它和目标程序都是运行在目标机中,可能是一台x86电脑或者是一个ARM板子。图中的红线表示GDB与GdbServer之间通过网络或者串口进行通讯。既然是通讯,那么肯定需要一套通讯协议:RSP协议,全称是:GDB Remote Serial Protocol(GDB远程通信协议)。
关于通讯协议的具体格式和内容,我们不需要关心,只需要知道:它们都是字符串,有固定的开始字符('$')和结束字符('#'),最后还有两个十六进制的ASCII字符作为校验和,了解这么多就足够了。至于更多的细节,如果实在闲的XX可以瞄几眼,其实