GDB调试报错 Source file is more recent than executable | 符号表与源代码文件对应错误

快速定位函数在调试程序链接的那个动态库中

问题的背景

今天在使用gdb调试程序, 在函数A处打断点, 在执行到断点时, 单步调试进入这个函数, 但是与预期的结果不同, 进入函数B中了, 没有进入到函数A中, 发截图给组内的大佬, 让仔细看 gdb 调试时输出的信息, 在查找后发现 gdb 中有出现如图中所出现的警告
a2M7kR.png

问题简单模拟复现

新建test目录, 在test目录下新建三个文件, main.c, hello.c, hello.h

内容如下
aRvNtA.png使用gcc hello.c main.c -o hello -g 编译生成可执行程序 hello

接下来对hello.c文件内容做如下修改

1 #include "hello.h"
2 #include <stdio.h>
3
4 int Add(int x, int y)
5 {
6 		return x + y;
7 }
8 
9 void PrintHello()
10 {
11 		printf("%s\n", "hello");
12 }

然后, 使用 gdb 调试 hello

在 main.c 第5行打断点, b main.c:5, r 启动程序调试运行到该断点, s 单步进入 PrintHello 函数, 这时我们会发现并没有如我们预期的进入 PrintHello 函数内, 而是进入到 Add 函数内,

aRzdL8.png
这是我们使用ll查看文件的最后修改时间
aRz7WR.png
由于对hello.c文件做了修改, 我们发现hello.c的最后修改时间时是要比hello的时间要新的。而我们没有重新编译生成程序, 导致 hello 可执行程序中的符号表保存的信息没有更新, 从而出现问题。 对比可以发现, 原来hello.c第6行对应的是 PrinHello 的定义, 而修改后hello.c对应的 Add 的定义, 进而会导致 gdb 调试出现问题, 这模拟的比较简单,只需要gcc编译, 在调试时就不会出现问题。

问题解决过程

然乎经过一番谷歌翻译, 意思是源文件比可执行文件要新, 那我们知道可执行程序中有要调试程序源代码文件的路径, 如果我们修改了程序的源文件, 没有重新编译程序, 直接调试就会导致程序符号表和源文件的函数对应出现错误, 而 gdb 这时会有警告Source is more recent than executable

我当时根据工程项目结构猜测出, 猜测可能是我调试的函数所在的文件和所在的目录结构及目录名字分析出, 程序依赖的某个动态库有问题, 重新编译该动态库后,问题就解决了。

那这个问题已经解决了, 但这不是通过分析,是通过猜测和运气解决的, 后面如果在遇到同样的问题, 我们如何快速解决呢。

我当时想到的是, Linux中ldd命令可以列举出程序链接的所有动态库, 但还是不知道出问题的函数在那个动态库中, 那这时有人可能会说可以把程序依赖的所有动态库更新, 这对于链接的动态库比较少的程序还是可以接受的, 但是我\如果比较多的呢, 我调试的那个程序有链接10多个动态库, 显然这种方法对链接动态库比较多的程序不可行的。

这时在组内大佬的提示下, 让回想整个问题的解决过程, 提示 gdb 或许可以帮助快速解决这个问题。

问题: 快速定位 一个函数在调试程序链接的那个动态库中

经过一番搜索, 百度没有我想要的答案, 这时我想或许看 gdb 的文档可以解决这个问题, 但是文档很长很多啊。在组内大佬的提示下, 用谷歌搜索通过关键词gdb function library进行搜索, 第一条搜索结果就是想要的答案。这是 stackoverflow 上一个问题的回答

aRXaEd.png

到这里, 这个问题应该是有了一个比较好的解决方案

解决方法总结

在gdb使用 info symbol可以打印函数所在动态库的名称

使用方法:

使用gdb 启动调试程序,在要查找的函数处打断点,然后执行到该断点处,在单步调试进入该函数,在使用info symbol fun_name就可以打印出函数的动态库名称

收获总结

  • stackoverflow 作为程序员专属的问答网站, 很多问题都可以找到解决方案。 (英文还是要好好学呀)

  • gdb 中可以查到查到函数在调试程序依赖的那个动态库及库的路径这个功能可以很多人都不知道, 一个经典强大的工具往往在很多方便都有完善的解决方案, 或许只是我们不知道。

  • gdb 作为一款经典的BUG 调试工具, 自己对 gdb 的了解还是太少了, 还是要通过官方文档完整了解一下 gdb 的功能

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值