利用map,cod文件定位崩溃代码行
利用vs2010 新建一个空的控制台项目,添加文件gtg.cpp,内容如下
void crash()
{
inti=1;
intj=0;
i/=j;
}
int main()
{
crash();
return0;
}
配置生成map及cod文件
项目-》属性-》连接器-》调试-》生成映射文件-》是 (/MAP)
项目-》属性-》c/c++-》输出文件-》汇编程序输出-》程序集、机器码和源代码 (/FAcs)
然后将增量编译关闭,否则会连接错误;
编译生成项目,运行,出现如下异常窗口
其中的故障模块名称及异常偏移是关键信息,
从异常模块名称 ddd.exe 我们知道问题代码应在ddd.map中
ddd
Timestamp is 5145d550 (Sun Mar 17 22:38:082013)
Preferred load address is 00400000
Start Length Name Class
0001:00000000 00001b3cH .text CODE
0002:00000000 000000e0H .idata$5 DATA
0002:000000e0 00000004H .CRT$XCA DATA
0002:000000e4 00000004H .CRT$XCAA DATA
0002:000000e8 00000004H .CRT$XCZ DATA
0002:000000ec 00000004H .CRT$XIA DATA
0002:000000f0 00000004H .CRT$XIAA DATA
0002:000000f4 00000004H .CRT$XIY DATA
0002:000000f8 00000004H .CRT$XIZ DATA
0002:00000100 000009d0H .rdata DATA
0002:00000ad0 00000036H .rdata$debug DATA
0002:00000b10 00000004H .rdata$sxdata DATA
0002:00000b14 00000004H .rtc$IAA DATA
0002:00000b18 00000004H .rtc$IMZ DATA
0002:00000b1c 00000004H .rtc$IZZ DATA
0002:00000b20 00000004H .rtc$TAA DATA
0002:00000b24 00000004H .rtc$TMZ DATA
0002:00000b28 00000004H .rtc$TZZ DATA
0002:00000b30 0000009cH .xdata$x DATA
0002:00000bcc 00000028H .idata$2 DATA
0002:00000bf4 00000014H .idata$3 DATA
0002:00000c08 000000e0H .idata$4 DATA
0002:00000ce8 000003c4H .idata$6 DATA
0002:000010ac 00000000H .edata DATA
0003:00000000 0000002cH .data DATA
0003:00000030 00000384H .bss DATA
Address Publics byValue Rva+Base Lib:Object
0000:00000001 ___safe_se_handler_count 00000001
0000:00000000 ___ImageBase 00400000
0001:00000000 ?crash@@YAXXZ 00401000 f gtg.obj
0001:00000040 _main 00401040 f gtg.obj
0001:00000080 __RTC_InitBase 00401080 f MSVCRTD:_init_.obj
………………………………省略……………………
entry point at 0001:00000380
Static symbols
0001:00000290 _pre_c_init 00401290 f MSVCRTD:crtexe.obj
0001:00000320 _pre_cpp_init 00401320 f MSVCRTD:crtexe.obj
0001:000003a0 ___tmainCRTStartup 004013a0 f MSVCRTD:crtexe.obj
0001:00000610 _check_managed_app 00401610 f MSVCRTD:crtexe.obj
0001:000007a0 ?failwithmessage@@YAXPAXHHPBD@Z 004017a0f MSVCRTD:_error_.obj
0001:000009c0 ?DebuggerProbe@@YAHK@Z 004019c0 f MSVCRTD:_error_.obj
0001:00000a50 ?DebuggerRuntime@@YAHKHPAXPB_W@Z00401a50 f MSVCRTD:_error_.obj
0001:00000d30 ?_getMemBlockDataString@@YAXPAD00I@Z00401d30 f MSVCRTD:_error_.obj
0001:00001750 ?GetPdbDll@@YAPAUHINSTANCE__@@XZ00402750 f MSVCRTD:_pdblkup_.obj
下面我们通过异常偏移信息定位出错位置所在函数:
崩溃偏移行地址=异常偏移-0x1000(其中0x1000因为一般的 PE 文件的代码段都是从 0x1000 偏移开始的在)
此例中为0x1030-0x1000=0x30;
在map文件中Address 列查找第一个大于ox30的数偏移地址,及绿色行,其上一行(红色)即为异常代码所在函数,可以看出此函数来自gtg.obj,的crash函数,下面计算异常代码在crash函数的偏移行
0x1030-0x1000-0x00000000=0x30,
打开gtg.cod内容如下:
; Listing generated by Microsoft (R)Optimizing Compiler Version 16.00.30319.01
TITLE E:\Projects\ddd\ddd\gtg.cpp
.686P
.XMM
includelisting.inc
.model flat
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
PUBLIC ?crash@@YAXXZ ;crash
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDATrtc$TMZ
; File e:\projects\ddd\ddd\gtg.cpp
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DDFLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDATrtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DDFLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT?crash@@YAXXZ
_TEXT SEGMENT
_j$ = -20 ;size = 4
_i$ = -8 ;size = 4
?crash@@YAXXZ PROC ; crash,COMDAT
; 2 : {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec d8 00 00
00 sub esp, 216 ;000000d8H
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 28 ff ff
ff lea edi, DWORD PTR [ebp-216]
00012 b9 36 00 00 00 mov ecx, 54 ; 00000036H
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; 3 : int i=1;
0001e c7 45 f8 01 00
0000 mov DWORD PTR _i$[ebp], 1
; 4 : int j=0;
00025 c7 45 ec 00 00
0000 mov DWORD PTR _j$[ebp], 0
; 5 : i/=j;
0002c 8b 45 f8 mov eax, DWORD PTR _i$[ebp]
0002f 99 cdq
00030 f7 7d ec idiv DWORD PTR _j$[ebp]
00033 89 45 f8 mov DWORD PTR _i$[ebp], eax
; 6 : }
00036 5f pop edi
00037 5e pop esi
00038 5b pop ebx
00039 8b e5 mov esp, ebp
0003b 5d pop ebp
0003c c3 ret 0
?crash@@YAXXZ ENDP ; crash
_TEXT ENDS
PUBLIC _main
EXTRN __RTC_CheckEsp:PROC
; Function compile flags: /Odtp /RTCsu /ZI
; COMDAT_main
_TEXT SEGMENT
_main PROC ;COMDAT
; 8 : {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec c0 00 00
00 sub esp, 192 ;000000c0H
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 40 ff ff
ff lea edi, DWORD PTR [ebp-192]
00012 b9 30 00 00 00 mov ecx, 48 ; 00000030H
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; 9 : crash();
0001e e8 00 00 00 00 call ?crash@@YAXXZ ; crash
; 10 : return 0;
00023 33 c0 xor eax, eax
; 11 : }
00025 5f pop edi
00026 5e pop esi
00027 5b pop ebx
00028 81 c4 c0 00 00
00 add esp, 192 ;000000c0H
0002e 3b ec cmp ebp, esp
00030 e8 00 00 00 00 call __RTC_CheckEsp
00035 8b e5 mov esp, ebp
00037 5d pop ebp
00038 c3 ret 0
_main ENDP
_TEXT ENDS
END
定位到crash函数,上文第一个红色行,然后根据偏移行定位到第三个红色行,向上查看定位到第二个红色行,最后定位到异常代码出现在gtg.Cpp的第五行,哈哈一个简单的异常定位就结束了
要想熟练使用还需要了解map及cod文件的格式
需要中意的是map文件中有static symbols 和export symbols 在定位行数时这些符号也需要考虑