메시지(Window Message) 따라 디버깅

 

Message 기반의 Window에서 특히 MFC Application 같은, Debugging 시에 특정 Button Click 하면 Button Click에 대한 Function Call이 호출되고 어쩌구저쩌구 하는 경우, 간혹, 정확한 정보를 모르는 상태에서 Debugging을 하다 보면 난감할 때가 있다. 이런 경우, 가장 유용한 방법이 SPY Tool을 이용하는 것이다. 예를 들어, button하나 누르는 MFC Application을 가지고 살펴보면, 아래는 SPYmain window를 잡은 화면이다. 지금 하고자 하는 것은 button click하는 함수를 찾아 들어가는 것이다. (굳이 왜 이런 짓을 ..

SPY TOOL을 열어놓고, 메뉴의 Search 에서 Find Window 하여 MFC Application Main window drag하면 Windows1 화면에서 Highlighted Window가 바로 그놈 이다. 이름이 MfcBtnTest 라는 놈이다. 그리고, View 메뉴에서 속성을 확인하면 Property Inspector라는 창이 뜬다. 원하는 정보는 WinProc 이다. 여기에 5804f141 이라는 Address가 보인다. 이게 뭘까 …. WinDbg로 해당 Application에 걸면 WinProc Function이 보일 테이다. 아래와 같다. 아시다시피 AfxWndProcBase 이다. MFC Application의 기본적인 WinProc 이 되겠다. 보통 일반적인 Window Application 이라면, WindowProc (http://msdn.microsoft.com/en-us/library/ms633573(VS.85).aspx) 일 텐데..

 

0:001> ln 5b04f141

f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxstate.cpp(439)  ß아시다시피 해당 소스는 VS에서 구할 수 있다. C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src

(5b04f141)   mfc90u!AfxWndProcBase   |  (5b04f1c1)   mfc90u!AfxGetAppModuleState

Exact matches:

    mfc90u!AfxWndProcBase (struct HWND__ *, unsigned int, unsigned int, long)

 

조금은 복잡하게 됐다. 그리고, button click에 대한 Function을 쫓아 갈 차례다. WindowProc이건 AfcWndProcBase 건 간에 Message ID로 주고 받는 다. 이것도 역시 SPY로 정보를 얻을 수 있다. Main Window에서 Message Filtering을 하는 데, WM_COMMAND 를 잡으면 된다.

wID Msg 정보를 나타낸다. 1000(0x3e8) 이것이 Message 정보이다. 그러므로, Message Handler 0x3e8 이 처리되는 것이 바로 내가 원하는 Button Click 시의 Message 를 나타낸다. 간단하게는 WindowProc Assembly Code에서 0x3e8 Handling 하는 놈을 찾으면 되겠다. MFC에서는 _AfxDispatchCmdMsg 함수에서 0x3e8(두 번째 parameter) Handling 하여 원하는 Function으로 보낸다.

 

0:000> kp

ChildEBP RetAddr 

001af54c 5b080346 mfc90u!_AfxDispatchCmdMsg(class CCmdTarget * pTarget = 0x001afc20, unsigned int nID = 0x3e8, int nCode = 1766796, <function> * pfn = 0x01031440, void * pExtra = 0x00000000, unsigned int nSig = 0, struct AFX_CMDHANDLERINFO * pHandlerInfo = 0x00000000) [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp @ 54]

001af568 5b070e92 mfc90u!CCmdTarget::OnCmdMsg(unsigned int nID = 0x3e8, int nCode = 0, void * pExtra = 0x00000000, struct AFX_CMDHANDLERINFO * pHandlerInfo = 0x00000000)+0x124 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp @ 381]

. . .

 

0:000> ln 0x01031440

g:\codes\mfcbtntest\mfcbtntest\mfcbtntestdlg.cpp(154)

(01031440)   MfcBtnTest!CMfcBtnTestDlg::OnBnClickedButton1   |  (01031460)   MfcBtnTest!CDialog::Create

Exact matches:

    MfcBtnTest!CMfcBtnTestDlg::OnBnClickedButton1 (void)

 

0:000> uf 0x01031440

MfcBtnTest!CMfcBtnTestDlg::OnBnClickedButton1 [g:\codes\mfcbtntest\mfcbtntest\mfcbtntestdlg.cpp @ 154]:

  154 01031440 6a00            push    0

  156 01031442 68e0350301      push    offset MfcBtnTest!`string' (010335e0)

  156 01031447 68e0350301      push    offset MfcBtnTest!`string' (010335e0)

  156 0103144c 6a00            push    0

  156 0103144e ff15b8300301    call    dword ptr [MfcBtnTest!_imp__MessageBoxW (010330b8)]

157 01031454 c3              ret

 

아 왜 이런 쓸데없는 짓을 그냥 OnBnClickButton1 Break을 걸면 되지 않나.. 머 이럴수도 있겠다만, 맞는 말이다. 하지만, 여러 3rd party application Debugging 하다 보면, 복잡한 UI에서 도대체 Button Click 하면 어떤 Function으로 들어가는지 아무도 모르는 경우가 존재한다. 또 그런 Application Debugging 할 기회(?)도 존재한다. 그와 같은 때 유용하며, 이렇게 SPY WinDBG를 통해서 Message를 쫓아가는 경우는 여러 가지 응용도 가능하겠다.

by 강세윤 | 2009/07/01 16:43 | Windows debugging | 트랙백 | 덧글(0)
트랙백 주소 : http://byung.egloos.com/tb/5026885
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >