experiment:Finding crash information using the MAP file on vs2005
最近的工程在用vs2005进行调试, 现在可以Attach到Release版带调试符号的目标程序进行调试, 但是在非开发机上就没这条件了.
看了以下几篇资料, 做个实验.
http://www.codeproject.com/KB/debug/mapfile.aspx?msg=1315494
Finding crash information using the MAP file <vc6版好使>
http://www.cppblog.com/Walker/articles/146153.html
调试Release发布版程序的Crash错误 (转)<这个资料说全了, 可以在vs2005中做事后调试>
自己写了一个demo, 进行了验证, 可行. 但是没有实战性, 准备找个实际的程序来验证.
我在CodeProject 找了一个扫雷程序:
http://www.codeproject.com/KB/cpp/Mine4Edu.aspx
<<Adapted WinMine Source for Teaching Win32 API Programming>>
本来想搞个数组越界的错误,人家的程序写的太坚固了,弄了数组越界操作,也不报错。
只好弄了一个除零错~
编译选项是Release版不优化带调试符号,为了根据转储信息定位到代码中的行, 设置了MAPInfo和COD文件.
在Win7上程序报错是有崩溃对话框的, 但是我的WinXp上崩溃对话框没出来,只有一个报错对话框, 没有转储信息.
安装系统自带的drwtsn32.exe作为调试工具.
http://support.microsoft.com/kb/188296/zh-cn
<<如何禁用或启用 Windows 的 Dr. Watson>>
默认调试器的注册表备份
Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="1"
"Debugger"="drwtsn32 -p %ld -e %ld -g"
设置华生医生转储选项
再运行程序时,程序报错后,直接崩溃消失了。到那时,就可以从非开发机(大部分情况是客户现场)拿到转储信息转到开发机进行分析.
如果drwtsn32.exe设置了"视觉通知", 当程序报错时,会有转储提示对话框弹出.如果错误不是每次必现或在客户现场运行不用设置"视觉通知"选项.
如果不设置 "视觉通知", 程序报错后,直接退出了.这时可以去取程序报错时的转储信息。
将转储对话框中的文本全选,复制弄回来.
发生应用程序意外错误:应用程序: D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe (pid=3528)时间: 2011-12-26 @ 00:51:45.265意外情况编号: c0000094 (除以零)*----> 系统信息 <----*计算机名: 20110616-2328用户名: Administrator终端会话 Id: 0处理器数量: 2处理器类型: x86 Family 6 Model 15 Stepping 6Windows 版本: 5.1当前内部版本号: 2600Service Pack: 3当前类型: Multiprocessor Free注册的单位: 微软中国注册的所有者: 微软用户*----> 任务列表 <----*0 System Process4 System840 smss.exe908 csrss.exe932 winlogon.exe976 services.exe988 lsass.exe
1192 nvsvc32.exe
1252 svchost.exe
1300 svchost.exe252 svchost.exe484 svchost.exe584 svchost.exe620 zhudongfangyu.exe
1620 spoolsv.exe
1852 Explorer.EXE
1932 RTHDCPL.EXE
1948 360Tray.exe
2000 bjcacertd_ft11.exe
2016 vmware-tray.exe
2024 ctfmon.exe128 360sd.exe184 263em.exe288 Snagit32.exe
1728 TSCHelp.exe368 SnagPriv.exe
2004 snagiteditor.exe
1336 GSvr.exe
1384 wdfmgr.exe
1432 vmware-usbarbitrator.exe364 vmnat.exe700 vmnetdhcp.exe
1468 vmware-authd.exe
2168 wmiprvse.exe
2224 vmware-hostd.exe
2568 alg.exe
4000 360rp.exe
4072 firefox.exe
3452 NOTEPAD.EXE
3652 drwtsn32.exe
4080 drwtsn32.exe
3528 WinMine.exe
3036 drwtsn32.exe*----> 模块清单 <----*
(0000000000400000 - 0000000000416000: D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
(0000000000920000 - 000000000098d000: C:\Program Files\360\360Safe\safemon\safemon.dll
(000000005d170000 - 000000005d20a000: C:\WINDOWS\system32\comctl32.dll
(0000000062c20000 - 0000000062c29000: C:\WINDOWS\system32\LPK.DLL
(0000000071a10000 - 0000000071a18000: C:\WINDOWS\system32\WS2HELP.dll
(0000000071a20000 - 0000000071a37000: C:\WINDOWS\system32\WS2_32.dll
(0000000073640000 - 000000007366e000: C:\WINDOWS\system32\msctfime.ime
(0000000073fa0000 - 000000007400b000: C:\WINDOWS\system32\USP10.dll
(0000000074680000 - 00000000746cc000: C:\WINDOWS\system32\MSCTF.dll
(0000000075ff0000 - 0000000076055000: C:\WINDOWS\system32\MSVCP60.dll
(0000000076300000 - 000000007631d000: C:\WINDOWS\system32\IMM32.DLL
(00000000765e0000 - 0000000076673000: C:\WINDOWS\system32\CRYPT32.dll
(0000000076680000 - 0000000076726000: C:\WINDOWS\system32\WININET.dll
(0000000076990000 - 0000000076ace000: C:\WINDOWS\system32\ole32.dll
(0000000076bc0000 - 0000000076bcb000: C:\WINDOWS\system32\PSAPI.DLL
(0000000076d70000 - 0000000076d92000: C:\WINDOWS\system32\Apphelp.dll
(0000000076db0000 - 0000000076dc2000: C:\WINDOWS\system32\MSASN1.dll
(00000000770f0000 - 000000007717b000: C:\WINDOWS\system32\OLEAUT32.dll
(0000000077180000 - 0000000077283000: C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll
(0000000077bd0000 - 0000000077bd8000: C:\WINDOWS\system32\VERSION.dll
(0000000077be0000 - 0000000077c38000: C:\WINDOWS\system32\msvcrt.dll
(0000000077d10000 - 0000000077da0000: C:\WINDOWS\system32\USER32.dll
(0000000077da0000 - 0000000077e49000: C:\WINDOWS\system32\ADVAPI32.dll
(0000000077e50000 - 0000000077ee3000: C:\WINDOWS\system32\RPCRT4.dll
(0000000077ef0000 - 0000000077f39000: C:\WINDOWS\system32\GDI32.dll
(0000000077f40000 - 0000000077fb6000: C:\WINDOWS\system32\SHLWAPI.dll
(0000000077fc0000 - 0000000077fd1000: C:\WINDOWS\system32\Secur32.dll
(000000007c800000 - 000000007c91e000: C:\WINDOWS\system32\kernel32.dll
(000000007c920000 - 000000007c9b6000: C:\WINDOWS\system32\ntdll.dll
(000000007d590000 - 000000007dd84000: C:\WINDOWS\system32\SHELL32.dll*----> 线程 ID 0xcc0 的状态转储 <----*eax=00000006 ebx=00000000 ecx=0012fd10 edx=00000000 esi=00401fd0 edi=0012fe3c
eip=00401761 esp=0012fd48 ebp=0012fd54 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216*** ERROR: Module load completed but symbols could not be loaded for D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
函数: WinMine00401749 7423 jz WinMine+0x176e (0040176e)0040174b 6a03 push 0x30040174d 8b450c mov eax,[ebp+0xc]00401750 50 push eax00401751 8b4d08 mov ecx,[ebp+0x8]00401754 51 push ecx00401755 e8b6060000 call WinMine+0x1e10 (00401e10)0040175a 83c40c add esp,0xc0040175d 8b4508 mov eax,[ebp+0x8]00401760 99 cdq
错误 ->00401761 f77d0c idiv dword ptr [ebp+0xc] ss:0023:0012fd60=0000000000401764 894508 mov [ebp+0x8],eax00401767 33c0 xor eax,eax00401769 e9be000000 jmp WinMine+0x182c (0040182c)0040176e 8b15e8c84000 mov edx,[WinMine+0xc8e8 (0040c8e8)]00401774 83c201 add edx,0x100401777 8915e8c84000 mov [WinMine+0xc8e8 (0040c8e8)],edx0040177d 8b450c mov eax,[ebp+0xc]00401780 50 push eax00401781 8b4d08 mov ecx,[ebp+0x8]00401784 51 push ecx*----> 堆栈反向跟踪 <---*
WARNING: Stack unwind information not available. Following frames may be wrong.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\USER32.dll -
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
ChildEBP RetAddr Args to Child
0012fd54 0040118f 00000006 00000000 00000006 WinMine+0x1761
0012fd74 004020d7 00000202 00a30012 000000ef WinMine+0x118f
0012fdd4 77d18734 00060648 00000202 00000000 WinMine+0x20d7
0012fe00 77d18816 00401fd0 00060648 00000202 USER32!GetDC+0x6d
0012fe68 77d189cd 00000000 00401fd0 00060648 USER32!GetDC+0x14f
0012fec8 77d18a10 0012ff0c 00000000 0012ff28 USER32!GetWindowLongW+0x127
0012fed8 00401fb4 0012ff0c 00000000 00401fd0 USER32!DispatchMessageW+0xf
0012ff28 00402e78 00400000 00000000 000207e0 WinMine+0x1fb4
0012ffc0 7c817077 0065002e 00650078 7ffdf000 WinMine+0x2e78
0012fff0 00000000 00402ee1 00000000 78746341 kernel32!RegisterWaitForInputIdle+0x49*----> 原始堆栈转储 <----*
000000000012fd48 bc 13 40 00 06 00 00 00 - 00 00 00 00 74 fd 12 00 ..@.........t...
000000000012fd58 8f 11 40 00 06 00 00 00 - 00 00 00 00 06 00 00 00 ..@.............
000000000012fd68 12 00 00 00 a3 00 00 00 - 00 00 00 00 d4 fd 12 00 ................
000000000012fd78 d7 20 40 00 02 02 00 00 - 12 00 a3 00 ef 00 00 00 . @.............
000000000012fd88 68 01 00 00 30 02 00 00 - 48 06 06 00 01 00 00 00 h...0...H.......
000000000012fd98 b0 fd 12 00 01 b4 d2 77 - 58 03 62 00 00 00 00 00 .......wX.b.....
000000000012fda8 00 00 00 00 01 00 00 00 - f4 fd 12 00 d4 13 69 74 ..............it
000000000012fdb8 ee 00 03 00 00 00 00 00 - 01 00 00 00 d9 13 69 74 ..............it
000000000012fdc8 00 00 00 00 00 e0 fd 7f - ac 98 96 db 00 fe 12 00 ................
000000000012fdd8 34 87 d1 77 48 06 06 00 - 02 02 00 00 00 00 00 00 4..wH...........
000000000012fde8 12 00 a3 00 d0 1f 40 00 - cd ab ba dc 00 00 00 00 ......@.........
000000000012fdf8 3c fe 12 00 d0 1f 40 00 - 68 fe 12 00 16 88 d1 77 <.....@.h......w
000000000012fe08 d0 1f 40 00 48 06 06 00 - 02 02 00 00 00 00 00 00 ..@.H...........
000000000012fe18 12 00 a3 00 14 ff 12 00 - 0c ff 12 00 a8 64 67 00 .............dg.
000000000012fe28 14 00 00 00 01 00 00 00 - 00 00 00 00 00 00 00 00 ................
000000000012fe38 10 00 00 00 00 00 00 00 - 8f 04 d4 77 00 00 00 00 ...........w....
000000000012fe48 00 00 00 00 00 00 00 00 - 1c fe 12 00 74 f9 12 00 ............t...
000000000012fe58 b8 fe 12 00 8f 04 d4 77 - 30 88 d1 77 00 00 00 00 .......w0..w....
000000000012fe68 c8 fe 12 00 cd 89 d1 77 - 00 00 00 00 d0 1f 40 00 .......w......@.
000000000012fe78 48 06 06 00 02 02 00 00 - 00 00 00 00 12 00 a3 00 H...............*----> 符号表 <----*
D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
在转储信息中,可以看到报错的地址.
错误 ->00401761 f77d0c idiv dword ptr [ebp+0xc] ss:0023:0012fd60=00000000
将编译这个程序时产生的.map文件,.cod文件,转储信息文件放在一起,都打开,分析代码错误行.
map文件中看到程序的基址 = 0x400000
Preferred load address is 00400000
报错地址0x401761附近的函数名称如下:
Address Publics by Value Rva+Base Lib:Object
0001:000004c0 _GameWon 004014c0 f MineGame.obj0001:00000570 _GameLost 00401570 f MineGame.obj0001:00000650 _CountMines 00401650 f MineGame.obj0001:000006f0 _StepBox 004016f0 f MineGame.obj0001:00000830 _FillRectStockBrush 00401830 f MinePaint.obj0001:00000870 _DrawMargin 00401870 f MinePaint.obj0001:000008b0 _DrawBorder 004018b0 f MinePaint.obj
计算包含0x401761地址的函数
_StepBox 0x400000 + 0x1000 + 0x6f0 = 0x4016f0
0x401761 报错的代码行
_FillRectStockBrush 0x400000 + 0x1000 + 0x830 = 0x401830
可以看到 0x401761地址在函数_StepBox和_FillRectStockBrush之间, 说明代码中出错的位置在_StepBox函数中~
从转储信息中计算出错位置离函数入口的偏移:
*** ERROR: Module load completed but symbols could not be loaded for D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
函数: WinMine00401749 7423 jz WinMine+0x176e (0040176e)0040174b 6a03 push 0x30040174d 8b450c mov eax,[ebp+0xc]00401750 50 push eax00401751 8b4d08 mov ecx,[ebp+0x8]00401754 51 push ecx00401755 e8b6060000 call WinMine+0x1e10 (00401e10)0040175a 83c40c add esp,0xc0040175d 8b4508 mov eax,[ebp+0x8]00401760 99 cdq
错误 ->00401761 f77d0c idiv dword ptr [ebp+0xc] ss:0023:0012fd60=0000000000401764 894508 mov [ebp+0x8],eax
出错位置离函数入口的偏移(报错地址-_StepBox入口地址) = 0x00401761 - 0x4016f0 = 0x71
从包含_StepBox函数的MineGame.cod中找到离_StepBox入口偏移为0x71的代码行:
_TranslateMouseMsg ENDP
_TEXT ENDS
PUBLIC _GameLost
PUBLIC _GameWon
PUBLIC _StepBox
; COMDAT _StepBox
_TEXT SEGMENT
_r$78102 = -12 ; size = 4
_c$78103 = -8 ; size = 4
_cMinesSurround$ = -4 ; size = 4
_row$ = 8 ; size = 4
_col$ = 12 ; size = 4
_StepBox PROC ; COMDAT; 282 : {00000 55 push ebp00001 8b ec mov ebp, esp00003 83 ec 0c sub esp, 12 ; 0000000cH; 283 : UINT cMinesSurround;
; 284 :
; 285 : if (board.Box[row][col].State != BS_INITIAL &&
; 286 : board.Box[row][col].State != BS_DICEY)00006 8b 45 08 mov eax, DWORD PTR _row$[ebp]00009 6b c0 78 imul eax, 120 ; 00000078H0000c 8b 4d 0c mov ecx, DWORD PTR _col$[ebp]0000f 8b 94 88 b8 0000 00 mov edx, DWORD PTR _board[eax+ecx*4+184]00016 c1 e2 1a shl edx, 26 ; 0000001aH00019 c1 fa 1b sar edx, 27 ; 0000001bH0001c 74 25 je SHORT $LN11@StepBox0001e 8b 45 08 mov eax, DWORD PTR _row$[ebp]00021 6b c0 78 imul eax, 120 ; 00000078H00024 8b 4d 0c mov ecx, DWORD PTR _col$[ebp]00027 8b 94 88 b8 0000 00 mov edx, DWORD PTR _board[eax+ecx*4+184]0002e c1 e2 1a shl edx, 26 ; 0000001aH00031 c1 fa 1b sar edx, 27 ; 0000001bH00034 83 fa 02 cmp edx, 200037 74 0a je SHORT $LN11@StepBox; 287 : {
; 288 : // previously stepped, must be safe, and no need to step second time
; 289 : return TRUE;00039 b8 01 00 00 00 mov eax, 10003e e9 f9 00 00 00 jmp $LN12@StepBox
$LN11@StepBox:; 290 : }
; 291 :
; 292 : if (board.Box[row][col].fMine)00043 8b 45 08 mov eax, DWORD PTR _row$[ebp]00046 6b c0 78 imul eax, 120 ; 00000078H00049 8b 4d 0c mov ecx, DWORD PTR _col$[ebp]0004c 8b 94 88 b8 0000 00 mov edx, DWORD PTR _board[eax+ecx*4+184]00053 c1 e2 1f shl edx, 31 ; 0000001fH00056 c1 fa 1f sar edx, 31 ; 0000001fH00059 74 23 je SHORT $LN10@StepBox; 293 : {
; 294 : // stepped on a mine!
; 295 : SetAndDispBoxState(row, col, BS_BLAST);0005b 6a 03 push 30005d 8b 45 0c mov eax, DWORD PTR _col$[ebp]00060 50 push eax00061 8b 4d 08 mov ecx, DWORD PTR _row$[ebp]00064 51 push ecx00065 e8 00 00 00 00 call _SetAndDispBoxState0006a 83 c4 0c add esp, 12 ; 0000000cH; 296 :
; 297 : /** 制造一个BUG, 踩了雷程序就报错, 数组越界
; 298 : * 程序编译选项不选优化, 否则这里制造的BUG就被干掉了
; 299 : */
; 300 : row = row / col;/**< 零列出现雷的时候报除零错 */0006d 8b 45 08 mov eax, DWORD PTR _row$[ebp]00070 99 cdq00071 f7 7d 0c idiv DWORD PTR _col$[ebp]00074 89 45 08 mov DWORD PTR _row$[ebp], eax; 301 :
; 302 : return FALSE;00077 33 c0 xor eax, eax00079 e9 be 00 00 00 jmp $LN12@StepBox
$LN10@StepBox:; 303 : }
; 304 :
离入口偏移为0x71的行找到了,果真是一句除零~.
00071 f7 7d 0c idiv DWORD PTR _col$[ebp]
这句汇编对应的代码上就在他的上面: row = row / col;/**< 零列出现雷的时候报除零错 */
; 300 : row = row / col;/**< 零列出现雷的时候报除零错 */0006d 8b 45 08 mov eax, DWORD PTR _row$[ebp]00070 99 cdq00071 f7 7d 0c idiv DWORD PTR _col$[ebp]00074 89 45 08 mov DWORD PTR _row$[ebp], eax
好, 已经找到报错的代码行了。
如果是在开发机上, 就直接可以在Release版不优化带调试符号的工程上单步了.
如果没有条件单步,在报错的代码上上,用调试日志记录关心的上下文,问题就能解决了。
这个扫雷游戏做的太坚固了,还没想到弄个别的非除零错之外的不明显的BUG来找找看.
以后在实际工程中再验证,那时就不会让drwtsn32这么容易的判断是什么具体错误~.
如果有崩溃对话框弹出, 连华生医生也不用了,那时也有转储信息. 可以用来了解客户那的操作系统信息, 当时运行的程序(有没有杀毒软件之类的程序).
experiment:Finding crash information using the MAP file on vs2005相关推荐
- iOS调优 | 深入理解Link Map File
Link Map File初识 我们编写的源码需要经过编译.链接,最终生成一个可执行文件.在编译阶段,每个类会生成对应的.o文件(目标文件).在链接阶段,会把.o文件和动态库链接在一起.Link Ma ...
- ArcIMS9.2新增地图服务时check your map file's layers and data source connections解决
ArcIMS9.2安装完毕后的配置可以参考网上的教程,很详细.其中配置Service时可能会出现以下报错: Error when trying to administer Service: check ...
- Echart报错: Map china not exists. You can download map file on.....的解决办法
Echart报错: Map china not exists. You can download map file on http://echarts.baidu.com/download-map.h ...
- 文件格式大全(A-H)
<前言> 经常有网友问什么什么扩展名的文件要用什么程序来打开,事实上,电脑上 面真正能表示文件的类型并且得到一致承认的扩展名并不是很多,而大多数扩展 名一般都是由使用该文件的软件的开发者定 ...
- auto make System.map to C header file
#!/bin/bash# auto make System.map to C header file # 说明: # 该脚本主要是将Linux内核生成的System.map文件中的符号.地址存入结构体 ...
- Crash Dump Analysis 崩溃转储分析-摘抄翻译自深入解析windows操作系统
Almost every Windows user has heard of, if not experienced, the infamous "blue screen of death. ...
- jQuery的jquery-1.10.2.min.map触发404(未找到)
本文翻译自:jQuery's jquery-1.10.2.min.map is triggering a 404 (Not Found) I'm seeing error messages about ...
- 问题-[Delphi]通过Map文件查找内存地址出错代码所在行
一 什么是MAP文件 什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持 ...
- ARM 之十 ARMCC(Keil) map 文件(映射文件)详解
在看这篇文章之前 需要对 ARM ELF 文件有一定的了解.了解什么是域(Region).节(Section,也称为节区).段(Segment).镜像(Image).镜像文件(Image File)等 ...
最新文章
- 使用css实现瀑布流的效果
- 使用sourceInsight 提高代码编写效率
- php sku添加,php – 在单个产品页面中显示SKU下的自定义字段值
- php 返回查询结果某个字段
- java修改文件的大小限制_Struts2修改上传文件大小限制方法解析
- Windows 技术篇-WPS关闭推送广告配置方法
- Spring Boot-场景启动器
- 更新系统时跳过某个软件包
- 你可能不知道的Docker资源限制
- mysql用in查询list_Mysql优化器对in list的处理
- macos实现输入文件输入结束符
- Eucalyptus-NC管理
- Win7安装RNDIS驱动
- 免费高清图片素材网站
- 抖音上热门精选技巧 小视频更改md5
- 通过aosp-latest下载Android源码
- Codeforces Round #521 (Div. 3) 	E - Thematic Contests (二分 + STL)
- 安霸Ambarella三款CV系列芯片对比--CV2S、CV22S、CV25S
- 制作NGUI动态字体
- docker 搭建frp内网穿透以及frp详细使用