(1).map文件:property->Configuration Properties->Linker->Debugging 中的Generate Map File选择Yes(/MAP);
(2).cod文件:property->Configuration Properties->C/C++->output Files中Assembler OutPut中选择Assembly,Maching Code and Source(/FAcs),生成机器,源代码。
程序崩溃时的绝对地址或者偏移地址
1. 假设异常偏移地址: 0x0001152f
计算异常的绝对地址
打开程序的map文件, 找到类似下行
Preferred load address is 00400000
00400000 是程序的基地址
异常的绝对地址为: 0x00400000+0x1152f=0x0041152f
2. 定位异常发生所在的函数, 打开map 文件
找到第一个接近0x0041152f,但小于0x0041152f的值,因为异常如果发生在某个函数中时,异常地址0x0041152f肯定高于函数的起始地址
所要找的列为Rva+Base,可以看出004114d0复合要求,那么异常就是发生在Test函数中
Address Publics by Value Rva+Base Lib:Object
0000:00000000 ___safe_se_handler_count 00000000
0000:00000000 ___safe_se_handler_table 00000000
0000:00000000 ___ImageBase 00400000
0001:00000000 __enc$textbss$begin 00401000
0001:00010000 __enc$textbss$end 00411000
0002:000004d0 ?Test@@YAXXZ 004114d0 f DumpTest1.obj
0002:00000570 _wmain 00411570 f DumpTest1.obj
3. 打开.cod文件,找到函数
?Test@@YAXXZ PROC ; Test, COMDAT
; 17 : {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec cc 00 00
00 sub esp, 204 ; 000000ccH
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 34 ff ff
ff lea edi, DWORD PTR [ebp-204]
00012 b9 33 00 00 00 mov ecx, 51 ; 00000033H
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; 18 : st *temp = (st *)malloc(sizeof(st));
第一行
其中"0000"表示相对于函数开始地址后的偏移,在debug版本中,这个数据为相对于函数起始地址的偏移(此时每个函数第一条语句相对偏移为0000);release版本中为相对于代码段第一条语句的偏移(即代码段第一条语句相对偏移为0000,而以后的每个函数第一条语句相对偏移就不为0000了)
"55"为编译后的机器代码," push ebp"为汇编代码。
从"cod"文件中我们可以看出,一条(c/c++)语句通常需要编译成数条汇编语句 。
此外有些汇编语句太长则会分两行显示如:
4. 确定错误的代码行
计算异常行的地址 = 异常绝对地址--函数起始地址==0x0041152f--00x004114d0==5f
异常发生在相对于函数首地址偏移5f的位置
; 23 :
; 24 : temp->age = 30;
0005c 8b 45 f8 mov eax, DWORD PTR _temp$[ebp]
0005f c7 40 0c 1e 00
00 00 mov DWORD PTR [eax+12], 30 ; 0000001eH
5. 只有崩溃的决定地址,找出Release版的奔溃处
对于release版的程序,如果崩溃的话,我查找对应源代码的办法是:
首先记下程序崩溃的地址,这个程序崩溃时windows会提示0X.......。
然后,把源程序加上 /FAcs 选项再重新编译一下,加上该选项可以生成一个源代码、汇编代码、机器码都含有的文件。
然后,用olydlg之类的反汇编软件找到崩溃地址对应的汇编代码和机器码,
用UE之类的文本编辑软件打开含有源代码、汇编代码、机器码都含有的文件,用搜索功能查找反汇编软件中崩溃地址附近的机器码也就是十六进制数,很快就可以找到位置了。
一般我几分钟就可以定位。
使用的人只要把崩溃地址告诉我,我就可以修改程序了。