[Windows Debugging] 메모리에서 데이타를 보다

Application Crash가 발생하거나 혹은, Hang 현상이 발생할 경우에, Application Logic 만 가지고 추측하여 문제가 발생하는 지점을 찾아 Fix하는 것은 쉽지 않다. 만일, 그게 가능하다면, 사실 개발단계에서 그런 문제점을 고려하지 못했던 것을 탓해야 할 것이지만, 그렇지 못하기 때문에 대부분의 문제는 Application 운영 중 예상치 못한 시점에 발생한다. 이 경우에 Application에 대한 Debugging은 어떻게 접근하는 것이 좋을 까. 무엇보다도 문제 시점에 데이타를 보는 것이 빠른 접근이 아닐까 한다. Application은 일반적으로 logic에 따라 데이터의 흐름으로써 처리가 되며 그 결과를 보여주는 형태이다. 그러므로, 예상치 못한 시점의 예상치 못한 결과, Crash Hang이 발생했다면, 그 시점에 존재하는 연관된 데이타들은 Programmer가 예상한 시나리오에서의 올바른 데이터가 아니거나 고려하지 못한 흐름이라고 볼 수 있으며, 데이터와 logic을 보면서 verify 함으로써, logic의 수정이나 피치 못할 예외처리라든가 여러 가지 Application을 안정화하는 code를 추가할 수 있게 된다. 그러므로, Debugging은 전반적인 Logic을 보는 과정에 앞서서 문제 시점의 데이타를 분석하는 것이 우선이고 중요하다.

 

메모리 덤프는 Application Crash가 발생하거나 Hang이 발생하는 시점에 Debugging Tool을 이용하여 Application이 사용하는 메모리를 그대로 file Drop시킨 것이다. 그러므로, 그 시점에 register, heap memory assembly code등을 windbg.exe와 같은 tool을 이용하여 살펴볼 수 있는데, 메모리 덤프를 이용하여 Debugging하는 경우, 데이터 분석 시 가장 익숙하지 않고 어려운 부분은 Assembly code에 숨어 있는 데이터구조를 이해하는 것이 아닐까 한다. 예를 들어, array와 같은 Data Structure, linked list 그리고 Class와 같은 것들이다. 그러므로, 이들이 Memory Dump에서 어떻게 보여지고 이를 어떻게 해석해야 하는 지를 조금 언급해 볼까 한다.

 

먼저, 살펴볼 것은 array 구조에 대한 assembly code이다.

 

mov eax, DWORD PTR [ebp-20h]

mov ecx, DWORD PTR [ebp+eax*8-24h]

 

ebp-20h로부터 load eax 값은 array index 값이고, ebp-24h array base pointer이다. 여기서 *8 연산을 하는 것은 array의 저장된 item size(예를 들어, long ) eax , index에 곱해줘서 원하는 위치의 array item을 구하기 위한 offset 연산이 된다. 그리고, 동일하지만, shift 연산을 사용하는 다음과 같은 경우도 존재한다.

 

 mov eax, DWORD PTR [ebp-20h]

 shl eax, 2

 mov ecx, DWORD PTR [ebp+eax-24h]

 

이러한 patternarray 연산의 대표적인 형태이다.

다음은 Linked List 데이터 구조의 경우인데, 하나의 node Item Next node pointer를 갖고 있는 형태로 assembly code에서는 다음과 같이 처리된다.

 

 mov     eax,dword ptr [ebp+8]

 mov     ecx,dword ptr [eax]

 mov     edx,dword ptr [ecx]

 cmp     edx,dword ptr [ebp+0Ch]

 

보면, ebp+8 current node pointer이다. 그러므로, current node pointer ecx load 하고, 다시 해당 address edx load 한 후에 이를 ebp+0ch 값과 비교하는 것을 봐서 edx load된 값은 node structure의 첫 번째 item을 얻어 온 것이다.

 

                     if ((*n)->data == i)

                     { /* …  */

                     }

 

그리고, 연계하여,

 

  mov     eax,dword ptr [ebp+8]

  mov     ecx,dword ptr [eax]

  add     ecx,4

  mov     dword ptr [ebp+8],ecx

이것은 current node pointer ecx +4를 하는 것으로 보아 첫 번째 item int 와 같은 data type일 가능성이 있고, 4만큼 offset 이동하여 node struct의 두 번째 item을 얻어오는 것을 알 수 있다. 이는 Linked list 구조상 Next Pointer가 되는 데, 이를 current node pointer mov 하는 것이므로, Next node로 이동하는 다음과 같은 code 이다.

 

                     n = &(*n)->next;

 

이러한 pattern이 대표적인 Linked List 구조이다.

그리고, 다음에 언급할 구조는 class 구조이다.

 

High Level Language에서는 상위의 그림처럼 작성이 되지만, 메모리 layout은 좀 차이가 있다. 예를 들어, 상위의 C2 class의 경우는 아래와 같은 메모리 layout을 갖는 다.

 

0:000> dt rvsTest!C2

   +0x000 __VFN_table : Ptr32

   +0x004 b_m              : Int4B

   +0x008 c_m              : Int4B

   +0x00c c2_m             : Int4B

 

보면, Virtual Function Table public 하게 inherited fieldshierarchical 하게 메모리를 점유하고 있다. 그리고, Virtual function Table의 실제 memory layout을 살펴보면 다음과 같다.

 

 0:000> dt rvsTest!C2 0x00235e38

   +0x000 __VFN_table : 0x002e7768

   +0x004 b_m              : 1

   +0x008 c_m              : 2

   +0x00c c2_m             : 3

 

 0:000> dds 002e7768

002e7768  002e120d rvsTest!ILT+520(?b_vf1CUAEXXZ)

002e776c  002e11f9 rvsTest!ILT+500(?b_vf2CUAEXXZ)

002e7770  002e1073 rvsTest!ILT+110(?c_vf1C2UAEXXZ)

002e7774  00000000

002e7778  002e86d0 rvsTest!C::`RTTI Complete Object Locator'

002e777c  002e120d rvsTest!ILT+520(?b_vf1CUAEXXZ)

002e7780  002e11f9 rvsTest!ILT+500(?b_vf2CUAEXXZ)

002e7784  002e1217 rvsTest!ILT+530(?c_vf1CUAEXXZ)

002e7788  00000000

002e778c  002e86e8 rvsTest!B::`RTTI Complete Object Locator'

002e7790  002e11b8 rvsTest!ILT+435(?b_vf1BUAEXXZ)

002e7794  002e11a9 rvsTest!ILT+420(?b_vf2BUAEXXZ)

 

그러므로, 이러한 구조상에서 Virtual Function Call이 이뤄지게 된다. 다음의 assembly code를 보면,

 

   mov     eax,dword ptr [ebp-14h]

   mov     edx,dword ptr [eax]

   mov     esi,esp

   mov     ecx,dword ptr [ebp-14h]

   mov     eax,dword ptr [edx+8]

   call    eax

 

일반적인 Virtual Function Calling의 형태이다. Ebp-14 Class Object를 가리키고 있으며, edx는 상위에서 언급한 것처럼, Virtual Function Table Pointer이다. 그러므로, edx+8 002e7768+8=002e7770 , rvsTest!ILT+110(?c_vf1C2UAEXXZ)를 가리킨다. 그러므로, 다음은 Virtual Function disassembly code가 된다.

 

0:000> uf 002e1073

rvsTest!C2::c_vf1 [c:\codes\examples\rvstest\rvstest\rvstest.cpp @ 101]:

  101 002e1c30 55              push    ebp

  101 002e1c31 8bec            mov     ebp,esp

  101 002e1c33 81eccc000000    sub     esp,0CCh

  101 002e1c39 53              push    ebx

  101 002e1c3a 56              push    esi

  101 002e1c3b 57              push    edi

  101 002e1c3c 51              push    ecx

  101 002e1c3d 8dbd34ffffff    lea     edi,[ebp-0CCh]

  101 002e1c43 b933000000      mov     ecx,33h

  101 002e1c48 b8cccccccc      mov     eax,0CCCCCCCCh

  101 002e1c4d f3ab            rep stos dword ptr es:[edi]

  101 002e1c4f 59              pop     ecx

  101 002e1c50 894df8          mov     dword ptr [ebp-8],ecx

  102 002e1c53 8bf4            mov     esi,esp

  102 002e1c55 680c782e00      push    offset rvsTest!`string' (002e780c)

  102 002e1c5a ff15e4b22e00    call    dword ptr [rvsTest!_imp__printf (002eb2e4)]

  102 002e1c60 83c404          add     esp,4

  102 002e1c63 3bf4            cmp     esi,esp

  102 002e1c65 e821f5ffff      call    rvsTest!ILT+390(__RTC_CheckEsp) (002e118b)

  103 002e1c6a 5f              pop     edi

  103 002e1c6b 5e              pop     esi

  103 002e1c6c 5b              pop     ebx

  103 002e1c6d 81c4cc000000    add     esp,0CCh

  103 002e1c73 3bec            cmp     ebp,esp

  103 002e1c75 e811f5ffff      call    rvsTest!ILT+390(__RTC_CheckEsp) (002e118b)

  103 002e1c7a 8be5            mov     esp,ebp

  103 002e1c7c 5d              pop     ebp

  103 002e1c7d c3              ret

 

rvsTest!ILT+110(?c_vf1C2UAEXXZ):

002e1073 e9b80b0000      jmp     rvsTest!C2::c_vf1 (002e1c30)

by 강세윤 | 2008/10/10 09:37 | Windows debugging | 트랙백 | 덧글(0)
트랙백 주소 : http://byung.egloos.com/tb/4662336
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

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