如何使用map和cod文件定位程序崩溃位置
目的
程序或者dll在别的电脑上运行的时候发生崩溃,很难定位位置。我所知道的有两种方法可以快速定位,一种靠dump和pdb文件,另一种靠map和cod文件。这里讲第二种方法。
步骤
这里简单写一段会崩溃的代码。工程名为sample。
class Test{
public:
void say(){
int a = 0;
int b = 10 / a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test t;
t.say();
return 0;
}
1.生成map和cod文件
设置工程属性,以便生成cod文件。
设置工程属性,以便生成map文件。
运行后可在sample\sample\Debug下发现sample.cod文件。
sample\Debug下发现sample.map文件。
2.获取崩溃信息
双击运行sample.exe文件,会立即崩溃,出现这个弹窗。
关键信息是异常偏移:113f0。
假如错过了这个弹窗,可以通过控制面板-》系统和安全-》管理工具.查看事件日志-》自定义视图下的管理事件查看。根据大概时间和程序名字就可以找到相关信息。
3.查找map文件
打开map文件,开头可以看到这部分。
Preferred load address是该模块的首选加载地址。00400000+000113f0=004113f0,这是具体崩溃的代码的地址。
往下看可以看到这些。
Address表示分段地址,0000、0001、0002是段号,后面的是段内偏移地址。
具体分析一段。
这里_wmain的Rva+Base为00411410,Base为前面说到的Preferred load address,也就是00400000。
Rva为Relative Virtual Address,称为相对虚拟地址。Rva=00411410-00400000=00011410。也就是说相对于基地址的偏移为00011410。
也就是说Address0002:00000410=00011410。由此可知0002段的起始地址为00011410-00000410=00011000。
f说明是函数信息。sample.obj说明这个函数来自sample.obj,由它链接成.exe文件。
前面知道崩溃地址是004113f0,我们找Rva+Base中第一个比004113f0大的那一行,它的前一行就是崩溃的函数。
也就是004113c0。我们知道这个函数来自于sample.obj文件,它由sample.pp编译成,所以我们下一步查看sample.cod文件。
4.查找cod文件
004113f0-004113c0=30。
我们搜函数的名字aaa@qq.com@@QAEXXZ,定位到这个地方
这里的00001、00003表示偏移量,10:void say()表示这段代码的行号为10。这段代码会被处理为下面的汇编命令。我们只要找偏移量为30的,
前面的那段代码int b=10/a就是崩溃的代码了,行号是12。
参考:
1.map 文件的使用
2.vs生成的map文件详解
3.VS 2005/2008使用map文件查找程序崩溃原因