GDB无法调试宏定义?一个小技巧一秒钟搞定

GDB调试时遇到宏怎么办?

我们知道,在C语言程序预编译阶段,所有的宏定义都会被展开在C源码文件中引用宏的地方。因此,一般编译过后的目标文件中,不存在关于宏定义的任何信息。如下面这段代码:

先编译一下:

gcc -g test.c -o test

然后用GDB调试:

尽管我们编译时加了“-g”选项,但当我们在GDB中查看MONDAY的值和使用MAX宏时,仍然会提示当前上行文中找不到这两个符号。

怎么解决呢?其实GCC已经给我们提供了解决方案。

GCC的调试选项 -g

我们知道,要想用GDB进行调试,必须在用GCC编译时加上“-g”选项。但很多童鞋可能不知道的是,和优化选项“-Ox”一样,调试选项“-g”也有几个等级可选:

  • -g 默认选项,同-g2
  • -g0 不生成任何调试信息,和编译时不加“-g”是一样的。
  • -g1 生成最少量的调试信息,这些信息足够用来通过backtrace查看调用栈符号信息。主要包括了函数声明、外部变量和行号等信息,但是不包含局部变量信息。这个选项比较少用。
  • -g2 生成足够多的调试信息,可以用GDB进行正常的程序调试,这个是默认选项。
  • -g3 在-g2的基础上产生更多的信息,如宏定义。

可见,我们编译时加的“-g”选项,其实等同于“-g2”,它产生了足够多的调试信息,我们可以用gdb查看调用栈、查看局部变量等。但是,要想查看宏定义,则必须要使用“-g3”选项。

使用-g3调试选项

重新编译一下:

gcc -g3 test.c -o test

用gdb重新调试:

用“-g3”选项重新编译之后,就可以在gdb中查看宏定义了。甚至还可以像调用函数一样,使用call命令来调用宏!

本来,到这里就该结束了,但是为了满足好奇心,我们看一下“-g2”和“-g3”对目标文件产生了什么影响。

“-g2”和“-g3”对目标文件的影响

我们先看一下“-g2”,重新编译一下,然后用readelf命令查看一下目标文件中的节区头部(section header)表:

gcc -g2 test.c -o test
readelf -S test

主要看一下和调试信息相关的节区:

GCC默认使用的调试信息存储格式叫做DWARF,gdb就是基于这个格式的规范,实现的源码级调试。

稍微解释一下:

  • .debug_aranges 地址范围信息
  • .debug_info 最核心的调试信息
  • .debug_abbrev 各编译单元的缩写表
  • .debug_line 行号信息
  • .debug_str 被“.debug_info”节区使用的字符串表

然后,再用“-g3”选项重新编译一下:

gcc -g3 test.c -o test
readelf -S test

再看下节区表:

跟“-g2”相比,“-g3”多了一个.debug_macro,这个节区就是主要用来存放宏定义的信息。

我们用下面这个命令来查看一下这个节区里面都存放了哪些信息:

readelf --debug-dump test

输出信息比较多,和“.debug_macro”有关的如下图所示:

测试程序中定义的两个宏MONDAY和MAX的信息都包含在这个节区中,包括文件信息、行号信息、以及宏定义具体内容等。


欢迎关注微信公众号:【原点技术】,分享真正有用的东西!

进技术交流群,欢迎添加作者微信:CreCoding

原创文章,未经允许禁止转载,转载请联系作者:CreCoding

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值