编译器一般都用gcc,编译选项加-g,能生成调试信息在目标文件中。

调试目标文件,最主要的就是正确读取目标文件中的调试信息:

(比如指令地址对应的源代码哪一行,全局变量的地址是多少,局部变量存在哪个寄存器中还是栈中的哪个偏移位置,结构体长度多少如何怎样读取数据等,必须要这些调试信息,否则程序信息IDE一无所知(你说IDE自己分析源码?这个相当于自己实现一个编译器和生成调试信息了,不实际))

  GDB由三个部分组成:(这也是一个调试器必须要实现的3部分)

 (1)用户接口user interface,除支持传统的CLI接口还支持mi接口(ddd等工具使用)

 (2)符号处理层symbol handling,当gdb .xx目标文件 后GDB会读取文件的符号信息,之后的原代码,变量/函数/类型的显示都由该部分进行(everything you can do without live process,也就是不用把目标文件运行起来)。

 (3)目标系统处理层target system handling。包括执行控制,断点设置,单步执行,堆栈分析等操作都有该部分来进行。

最难的就是第二部分,但是第二部分会有一些库可以做的,但是也不简单。​

因此我们借助gdb的已有部分,合理的让我们适配它,会让我减小工作量。比自己去实现一套强。

接着调试信息部分的介绍,而这些调试信息都是有特定格式的(看我这篇文章​​​​​,对它们的解析是个大活。GDB调试器自己就是解析了里面的调试信息,发具体读写哪个地址内容,哪个寄存器这样的原始级别命令给目标机上的gdbserver(控制了被调试进程),然后一步一步操作。gdb在命令行发命令,这个叫cll接口。但是gdb跟gdbserver绑定得过紧,也就是不连接gdbserver,很多命令没法执行(但是我发现,即使不执行目标程序,还是可以看所有函数的局部变量地址等信息的,用info scope main varXX命令即可,真是太棒了)。gdb也考虑到了这一点,于是提供了libdbg库(应该是源代码库,gdb本身的实现就是基于这个),供别人调用。但是这个好像很久很久了,已经很少用了,gdb又做了两个给别人调用的接口,一个接口mi(可以看这个文章,还有个emacs编辑器版的接口,就是专门成为别人的IDE的后端的。

然后主流IDE可二次开发框架,eclipse,的CDT插件就是用的mi接口,实现利用gdb调试。codeblock用的也是另一个接口。

如果说我们调试裸板子,过程是怎样的呢,首先在pc机上,调试信息的解析,仍然不是一般能搞的,为了减小工作量,还是选择用gdb,但是目标板上没有gdbserver进程,所以没法单独工作,那怎么办呢,可以选择在板子上自己实现一个gdbserver,当然这个太麻烦。因此硬件调试器jlink等,就在调试器里自己实现了一个gdbserver(仿造Linux中的gdbserver),这样又可以让gdb工作啦。​

关于调试器和IDE的一些认识_gdb

如果说我们开发一个OS,也想具备应用程序调试功能。为了简便一些,就利用gdb作为后端来解析调试信息得了(当然自己可以调用已有调试信息解析库自己搞一个gdb出来,但是没必要了,有点复杂),OS中自己实现一个仿造的gdbserver,其中要能解决通信的匹配问题。

做IDE,用gdb的mi接口,作为后端调用,这个应该是最成熟的一种做法了。​

当然,也可以自己实现一个gdb,无法就是解析gcc生成的调试信息嘛,有很多库也可以做的。