最近在做服务器,很是纠结崩溃信息获取,网上查了些资料,直指map文件信息分析
1、首先生成map cod 文件 直接上图
然后直接编译生成PokerPDKServer.map 和每一个cpp对已的TableFrameSink.cod文件 (生成位置)
PokerPDKServer
Timestamp is 5a80741f (Mon Feb 12 00:49:35 2018)
Preferred load address is 10000000
Start Length Name Class
0001:00000000 000079d8H .text CODE
0001:000079e0 0000040bH .text$x CODE
0001:00007df0 0000004eH .text$yc CODE
0001:00007e40 0000004bH .text$yd CODE
0002:00000000 000000f0H .idata$5 DATA
0002:000000f0 00000004H .CRT$XCA DATA
0002:000000f4 00000014H .CRT$XCU DATA
0002:00000108 00000004H .CRT$XCZ DATA
0002:0000010c 00000004H .CRT$XIA DATA
0002:00000110 00000004H .CRT$XIAA DATA
0002:00000114 00000004H .CRT$XIC DATA
0002:00000118 00000004H .CRT$XIZ DATA
0002:00000120 000004f8H .rdata DATA
0002:00000618 0000005cH .rdata$debug DATA
0002:00000674 00000448H .rdata$r DATA
0002:00000ac0 00000050H .rdata$sxdata DATA
0002:00000b10 00000004H .rtc$IAA DATA
0002:00000b14 00000004H .rtc$IZZ DATA
0002:00000b18 00000004H .rtc$TAA DATA
0002:00000b1c 00000004H .rtc$TZZ DATA
0002:00000b20 000006b4H .xdata$x DATA
0002:000011d4 00000000H ATL$__a DATA
0002:000011d4 00000000H ATL$__z DATA
0002:000011d4 00000064H .idata$2 DATA
0002:00001238 00000014H .idata$3 DATA
0002:0000124c 000000f0H .idata$4 DATA
0002:0000133c 00000424H .idata$6 DATA
0002:00001760 0000005eH .edata DATA
0003:00000000 00000204H .data DATA
0003:00000208 00000414H .bss DATA
0004:00000000 000000a0H .rsrc$01 DATA
0004:000000a0 00000528H .rsrc$02 DATA
Address Publics by Value Rva+Base Lib:Object
0000:00000014 ___safe_se_handler_count 00000014 <absolute>
0000:00000000 ___ImageBase 10000000 <linker-defined>
0001:00000000 ??$_Construct@V?$_Vector_iterator@V?$_Vector_val@U?$_Simple_types@E@std@@@std@@@std@@@?$vector@EV?$allocator@E@std@@@std@@QAEXV?$_Vector_iterator@V?$_Vector_val@U?$_Simple_types@E@std@@@std@@@1@0@Z 10001000 f i GameLogic.obj
...
0001:00003b50 ?OnActionUserOnReady@CTableFrameSink@@UAE_NGPAUIServerUserItem@@PAXG@Z 10004b50 f i TableFrameSink.obj
0001:00003b60 ?OnActionUserSitDown@CTableFrameSink@@UAE_NGPAUIServerUserItem@@_N@Z 10004b60 f TableFrameSink.obj
0001:00003b60 ?OnActionUserStandUp@CTableFrameSink@@UAE_NGPAUIServerUserItem@@_N@Z 10004b60 f TableFrameSink.obj
0001:00003b60 ?OnGameDataBase@CTableFrameSink@@UAE_NGPAXG@Z 10004b60 f TableFrameSink.obj
0001:00003b70 ?OnEventGameConclude@CTableFrameSink@@UAE_NGPAUIServerUserItem@@E@Z 10004b70 f TableFrameSink.obj
0001:000040c0 ?OnEventGameStart@CTableFrameSink@@UAE_NXZ 100050c0 f TableFrameSink.obj
0001:00004850 ?OnEventSendGameScene@CTableFrameSink@@UAE_NGPAUIServerUserItem@@E_N@Z 10005850 f TableFrameSink.obj
0001:00004b70 ?OnFrameMessage@CTableFrameSink@@UAE_NGPAXGPAUIServerUserItem@@@Z 10005b70 f TableFrameSink.obj
0001:00004b80 ?OnGameMessage@CTableFrameSink@@UAE_NGPAXGPAUIServerUserItem@@@Z 10005b80 f TableFrameSink.obj
0001:00004d20 ?OnTimerMessage@CTableFrameSink@@UAE_NKI@Z 10005d20 f TableFrameSink.obj
...
0003:00000618 ___onexitbegin 1000b618 <common>
entry point at 0001:0000744a
Static symbols
0000:ffff2000 .debug$S 10000000 kernel32:KERNEL32.dll
0000:ffff2000 .debug$S 10000000 KernelEngine:KernelEngine.dll
0000:ffff2000 .debug$S 10000000 msvcprt:MSVCP110.dll
...
0003:000002c8 _allocator_arg 1000b2c8 Stdafx.obj
0003:000002c9 _piecewise_construct 1000b2c9 Stdafx.obj
0003:000002dc ___proc_attached 1000b2dc msvcrt:crtdll.obj
0003:000002e0 _GS_ExceptionRecord 1000b2e0 msvcrt:gs_report.obj
0003:00000330 _GS_ContextRecord 1000b330 msvcrt:gs_report.obj
0003:000005fc _DebuggerWasPresent 1000b5fc msvcrt:gs_report.obj
0004:000000a0 $R000000 1000c0a0 GameServer.res
0004:000003a0 $R000300 1000c3a0 GameServer.res
2、其次确定崩溃地址信息,从计算机管理->事件查看器->Windows日志->应用程序 获得
从图中可以看到 错误偏移地址:0x000057ed
3、0x000057ed 拿到map文件里去对比
地址在100050c0-10005850 直接 10000000是起始地址
偏移地址-起始地址:0x000057ed -0x000050c0=72d (72d就是相对于OnEventGameStart函数的起始地址)
4、0x00000072d 在cod 文件里去对比(这里对比也有技巧,算出72d直接搜索即可,不然看闪眼)
; 174 : m_pITableFrame->KillGameTimer(IDI_START_GAME);
00701 8b 4f 6d mov ecx, DWORD PTR [edi+109]
00704 6a 01 push 1
00706 8b 01 mov eax, DWORD PTR [ecx]
00708 ff 90 84 00 00
00 call DWORD PTR [eax+132]
; 175 : m_pITableFrame->SetGameTimer(IDI_START_GAME,TIMER_START_GAME,1,0);
0070e 8b 4f 6d mov ecx, DWORD PTR [edi+109]
00711 6a 00 push 0
00713 8b 01 mov eax, DWORD PTR [ecx]
00715 6a 01 push 1
00717 68 a0 0f 00 00 push 4000 ; 00000fa0H
0071c 6a 01 push 1
0071e ff 90 80 00 00
00 call DWORD PTR [eax+128]
; 176 :
; 177 : char *p = NULL;
00724 33 c0 xor eax, eax
; 180 : return true;
00726 c7 45 fc ff ff
ff ff mov DWORD PTR __$EHRec$[ebp+8], -1
0072d c6 00 56 mov BYTE PTR [eax], 86 ; 00000056H
; File d:\program files\vs2012ultimate\vc\include\vector
; 1536 : if (this->_Myfirst != pointer())
00730 39 45 c8 cmp DWORD PTR _GameStart$[ebp+16], eax
00733 74 29 je SHORT $LN1512@OnEventGam
; 1537 : { // something to free, destroy and deallocate it
; 1538 : this->_Orphan_all();
5、0072d 上面一行就是 CTableFramSink.cpp 180行报错了,就可以去源代码看看上下文。
下面来实验下,到底是不是180崩溃,启动服务器,release调试
果然崩溃在180行,但是180行肯定不会引起崩溃,只能往上查找看汇编来判断具体哪一句。此处很明显是178行
说明:
1、线上发布release版本,要事先备份好项目,建议svn提交要检测应用的map和cod文件,这样就算改了项目源码,出了问题也可以根据svn版本来查看崩溃文件地址
2、运行的不确定性,很多问题都是不能确定,不然bug版本就已经发现问题了。很明显map和cod文件都是预先编译生成好的, 对于内存数据无法查看,所以只能根据上下文来检测有问题的代码段,它能给予的就是范围缩小,快速定位,这样已经很好完美了。如果有能精确定位,请告诉我
3、看看上图崩溃地址0x0F2757ED,一开始的时候一直在map文件里找这个地址,那真的是崩溃,没有!!!虽然网上没有查到,虽然不太明白,但是猜测0x0F270000是此刻程序加载基址,0x000057ED是出错偏移,有道行的人应该一眼就看的出,为什么是4位地址而不是5位6位呢,这个我也不太明白,PE文件代码启动地址0x00001000。这个方法不知道正不正确,还要经过大量测试,但是如图1定位偏移地址是没有问题的
转载:
https://www.cnblogs.com/ztercel/p/3485032.html