源文件移动后gdb不显示代码的原因
源文件移动后gdb不显示代码的原因
问题
我们从一个最简单的C语言程序开始。源文件main.c在 用户目录gdb文件夹下。
florian@florian-pc:~/gdb$ cat main.c
int main()
{
return 0;
};
然后将源文件编译为main(需要调试选项-g),并将main.c移动到src/main.c下,然后对main进行调试。
florian@florian-pc:~/gdb$ gcc main.c -o main -g
florian@florian-pc:~/gdb$ mv main.c src/main.c
florian@florian-pc:~/gdb$ gdb main
(gdb) b main
Breakpoint 1 at 0x8048397: file main.c, line 3.
(gdb) list
1 main.c: 没有那个文件或目录.
in main.c
在gdb中,使用list命令查看源代码时,无法找到源文件main.c。
探究
由于对DWARF调试格式并不清晰,我本以为使用调试选项编译的可执行程序内部包含了源文件的内容,这样无论源码是否存在,可执行程序都可以被正常调试。但是,从上边的例子中可以看出,事实并非如此。
我们可以作一个简单的推测:由于移动源文件的位置后,gdb无法找到源文件的位置,估计可执行文件的调试段内保存的不是源文件的内容,而是路径信息。
将main.c移动回来,重新编译,生成目标文件main.o,并查看其段信息。
florian@florian-pc:~/gdb$ mv src/main.c main.c
florian@florian-pc:~/gdb$ gcc -c main.c -o main.o -g
florian@florian-pc:~/gdb$ objdump -s main.o
main.o: file format elf32-i386
Contents of section .text:
0000 5589e5b8 00000000 5dc3 U.......].
……
Contents of section .debug_str:
0000 6d61696e 2e63002f 686f6d65 2f666c6f main.c./home/flo
0010 7269616e 2f676462 00474e55 20432034 rian/gdb.GNU C 4
0020 2e342e35 006d6169 6e00 .4.5.main.
……
我们发现在.debug_str段内,有两个很明显的字符串信息。
(1)/home/florian/gdb:看起来很像源文件所在的绝对路径。
(2)main.c:显而易见,是源文件的名称。
验证
我们再把main.c移动到src目录下,再次编译,看看字符串的信息有何变化。
florian@florian-pc:~/gdb$ mv main.c src/main.c
florian@florian-pc:~/gdb$ gcc -c src/main.c -o main.o -g
florian@florian-pc:~/gdb$ objdump -s main.o
main.o: file format elf32-i386
Contents of section .text:
0000 5589e5b8 00000000 5dc3 U.......].
……
Contents of section .debug_str:
0000 2f686f6d 652f666c 6f726961 6e2f6764 /home/florian/gd
0010 6200474e 55204320 342e342e 35007372 b.GNU C 4.4.5.sr
0020 632f6d61 696e2e63 006d6169 6e00 c/main.c.main.
在.debug_str段内的两个字符串信息发生了变化。
(1)/home/florian/gdb:可见该字符串为执行gcc命令时的当前目录的绝对路径。
(2)src/main.c:该字符串为源文件相对于当前目录的相对路径。
将两个目录合并,便可以得到源文件的绝对路径:
/home/florian/gdb /src/main.c
结论
由此可见,使用调试选项编译生成的可执行文件内并非保存了源文件的内容,而是源文件的绝对路径信息。DWARF调试格式(详见这里)定义的其他debug段内保存了二进制代码与源文件行号的对应关系,这样gdb的list命令工作时,实际是读取可执行文件内的行号信息,并将源文件的代码内容显示出来。这也是为什么将源文件移动后,list命令信息无法找到源文件的原因。
从这里,我们也可以清楚一个事实:当源码目录的源文件路径发生变化后,如果需要对可执行文件进行调试,则必须重新编译。
类似的问题不仅仅在gdb的list命令中存在,objdump –S命令用于交叉显示反汇编代码与源代码,同样会受移动源文件的影响。
源文件移动后gdb不显示代码的原因的更多相关文章
- js DIV延时几秒后消失或显示代码
1.最常用的方法: 代码如下 复制代码 <script language='javascript' type='text/javascript'> $(function () { ...
- vue页面加载前显示{{代码}}的原因及解决办法
进入正题,简单说说自己对html中出现{{}}的原因及解决办法: 这样写的话,就会出现{{}}一闪的情况: 原因:html的加载顺序: 解析html结构 -> 加载外部脚本和样式表文件 -> ...
- 解决Button设置disabled后无法执行后台代码问题
一.开始调式下面的程序,发现Button在js中设置disabled后无法执行后台代码(btnsave_Click)问题 <asp:Button ID="btnsave" r ...
- C# Winform中DataGridView绑定后DataGridViewCheckBoxColumn无法显示的问题
在控件DataGridView绑定数据源后,发现DataGridViewCheckBoxColumn不能显示当前的check值.经过一番努力,现将完整代码奉献出来,仅供参考. 错误代码: /*禁止自动 ...
- 20145311利用gdb调试汇编代码
利用GDB调试汇编代码 首先编写c语言原代码,我使用的是同学分析过的代码 #include<stdio.h>short addend1 = 1;static int addend2 = 2 ...
- 如何通过VIM把代码格式化后生成HTML网页代码
本文转自http://wangxiaoyu.blog.51cto.com/922065/203471 需求及思路:演示需要,需要网站上嵌入一些代码,我的建议做法是根据代码文件,生成相应的HTML代码, ...
- tableview 选中一行后,不显示选中颜色
tableview 选中一行后,不显示选中颜色 千万不要将tableview的allowsSelection设置成NO,那样的话可能导致tableview不能响应点击动作. 应该使用:cell.sel ...
- C#读写Access数据库、表格datagridview窗体显示代码实例
C#读写Access数据库.表格datagridview窗体显示代码实例 最近项目中用到C#对于Access数据库表读写.mdb操作,学习了下相关的东西,这里先整理C#对于Access数据库的操作,对 ...
- 解决echart在IE中使用时,在div中加入postion后图表不显示问题
<!-- 为ECharts准备一个具备大小(宽高)的Dom --> <div id="main" style="height:400px;width:1 ...
随机推荐
- LWIP总结
介绍 Lwip,light weight IP:是由Adam Dunkels 开发的一个小型开源的TCP/IP协议栈:目前已经为全球共同开发的开源协议:支持TCPIP协议族的核心协议:包括:ARP/I ...
- 移动适配请使用比rem等更好的布局方案
移动端大行其道,rem/em.百分比.响应式方案更是层出不穷,看见周围的伙伴们都在对使用rem和百分比情有独钟,可我却偏不爱,之所以出现如此多的方法,其目的只有一个屏幕适配. 屏幕适配顾名思义 ...
- 动态SQL 学习
<select id="findUser" parameterType="Map" resultType="User"> ...
- Hadoop 学习资料集锦
Hadoop 资料 虾皮系列教程. Sqoop 资料 官方安装文档. 浪迹天涯博客. 瀚海星空博客. ……
- ViewPager取消左右滑动切换功能
ViewPager取消左右滑动切换功能 最近做项目要求某种情况下ViewPager不能滑动,那么我们只需要重写这个方法就可以禁止ViewPager滑动 IndexViewPager.java: imp ...
- Shader实例:NGUI制作网格样式血条
效果: 思路: 1.算出正确的uv去采样过滤图,上一篇文章说的很明白了.Shader实例:NGUI图集中的UISprite正确使用Shader的方法 2.用当前血量占总血量的百分比来设置shader中 ...
- 一张图系列——从CreateProcess到main函数的过程
整体过程如下: 需要说明两点: 1.在XP中,新进程主线程的启动,会先执行一个用户态的APC,会执行ntdll!LdrInitializeThunk进行程序执行前的一些列初始化操作.其中很重要任务就是 ...
- 踏上Salesforce的学习之路(一)
相信通过前面的学习,大家已经拥有了一个属于自己的Salesforce开发者账号,下面,我们将用这个账号正式踏上Salesforce的学习之路. 首先,点击网址:https://developer.sa ...
- js~~给网站图片添加水印~~~
因为朋友问我怎么加水印,引起了我的兴趣,没接触过也没想过要怎么写,所以试了试.写了一个简单的demo......
- es6转es5
一.在没有IDE情况下的转换 在"我的电脑->D盘”新建个文件夹es6,文件夹里新建一个文件es6.js. 打开命令行窗口 1.先全局安装babel-cli,输入命令 npm inst ...