흐르는 시간의 블로그...

*** 이글은 스크랩 자료이므로 추가 스크랩을 하지 말아 주시기 바랍니다. ***

원본 출처는 http://byung.egloos.com/3938350입니다.

-----------------------------------------------------------------------------------------------------------------

Stack overflow: 사라진 Function 정보

WinDBG Debugging할 때 가장 많이 사용하는 command k command 입니다. 이유는 적어도 문제가 생긴 시점까지 진행된 Function을 확인해 보는 것이 중요할 것이고, 해당 Function들이 호출될 때 parameter들이 정상적으로 넘어 왔는지 한눈에 볼 수 있기 때문입니다.

0:000> kbL

ChildEBP RetAddr Args to Child

0012fd50 38373635 32313039 36353433 30393837 debuggingstuff!bar+0x7b

0012fe58 004115b5 0012ff40 00000000 00000000 0x38373635

0012ff48 00411bc6 00000001 008a2f50 008a1920 debuggingstuff!main+0x35

0012ff98 00411a0d 0012ffac 76a83833 7ffdf000 debuggingstuff!__tmainCRTStartup+0x1a6

0012ffa0 76a83833 7ffdf000 0012ffec 77d7a9bd debuggingstuff!mainCRTStartup+0xd

0012ffac 77d7a9bd 7ffdf000 0012fdbc 00000000 kernel32!BaseThreadInitThunk+0xe

0012ffec 00000000 00411127 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x23

적어도 상위의 callstack debuggingstuff.exe 에서 제공하는 main 함수 호출 후에 0x38373635라는 함수? 그리고, bar() 를 호출하여 문제가 발생한 것으로 보입니다. 한 눈에 보더라도 callstack이 깨진 것이 아닌가 의심하게 됩니다. 최상위 함수의 ebp 값을 통해 stack 상에 존재하는 데이터를 확인해 보면 아래와 같습니다. 보시는 바와 같이 알 수 없는 데이터로 인하여 stack overflow 된 것으로 보입니다. 이것을 Debugging 하는 방법은 stack이 깨지기 전의 callstack을 찾아서 그 위치에 break을 걸고 그 부분부터 문제가 발생한 시점까지 step by step debugging을 하여 문제를 찾아내는 것이 방법이며, 적어도 문제가 되는 함수를 review 하는 것도 방법일 수 있습니다.

0:000> dc 0012fd50

0012fd50 34333231 38373635 32313039 36353433 1234567890123456

0012fd60 30393837 34333231 38373635 32313039 7890123456789012

0012fd70 36353433 30393837 cccccc00 cccccccc 34567890........

0012fd80 cccccccc cccccccc cccccccc cccccccc ................

0012fd90 cccccccc cccccccc cccccccc cccccccc ................

0012fda0 cccccccc cccccccc cccccccc cccccccc ................

0012fdb0 cccccccc cccccccc cccccccc cccccccc ................

0012fdc0 cccccccc cccccccc cccccccc cccccccc ................

0012fdd0 cccccccc cccccccc cccccccc cccccccc ................

0012fde0 cccccccc cccccccc cccccccc cccccccc ................

0012fdf0 cccccccc cccccccc cccccccc cccccccc ................

0012fe00 cccccccc cccccccc cccccccc cccccccc ................

0012fe10 cccccccc cccccccc cccccccc cccccccc ................

0012fe20 cccccccc cccccccc cccccccc cccccccc ................

0012fe30 cccccccc cccccccc 01cccccc cccccccc ................

0012fe40 cccccccc 0000000a cccccccc cccccccc ................

0012fe50 00000000 cccccccc 0012ff48 004115b5 ........H.....A. ß-- 0012fe58 ebp값을 가지고 있을 지모른다.

0012fe60 0012ff40 00000000 00000000 7ffdf000 @...............

0012fe70 cccccccc cccccccc cccccccc cccccccc ................

0012fe80 cccccccc cccccccc cccccccc cccccccc ................

0012fe90 cccccccc cccccccc cccccccc cccccccc ................

0012fea0 cccccccc cccccccc cccccccc cccccccc ................

0012feb0 cccccccc cccccccc cccccccc cccccccc ................

0012fec0 cccccccc cccccccc cccccccc cccccccc ................

만일, 0012fe58 가리키는 0012ff48이 ebp라면, 004115b5 return address 임에 틀림없을 것입니다. 그러므로, raw stack에서 찾아낸 정보가 stack이 깨지기 전의 온전한 function call임을 확인해야 합니다.

0:000> ln 004115b5

c:\users\byungck\documents\visual studio 2005\projects\debuggingstuff\debuggingstuff\debuggingstuff.cpp(45)+0x9

(00411580) debuggingstuff!main+0x35 | (0041163c) debuggingstuff!malloc

해당 함수는 main 함수임을 확인할 수 있습니다. 그리고 나면, 다음과 같이 온전한 마지막 callstack을 볼 수 있습니다.

0:000> kbL=0012fe58 0012ff48 004115b5 ß- kbL=<ebp pointer> <ebp> <return address>

ChildEBP RetAddr Args to Child

0012fe58 004115b5 0012ff40 00000000 00000000 debuggingstuff!main+0x35

0012ff48 00411bc6 00000001 008a2f50 008a1920 debuggingstuff!main+0x35

0012ff98 00411a0d 0012ffac 76a83833 7ffdf000 debuggingstuff!__tmainCRTStartup+0x1a6

0012ffa0 76a83833 7ffdf000 0012ffec 77d7a9bd debuggingstuff!mainCRTStartup+0xd

0012ffac 77d7a9bd 7ffdf000 0012fdbc 00000000 kernel32!BaseThreadInitThunk+0xe

0012ffec 00000000 00411127 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x23

해당 함수에 대한 address start 00411580 입니다. 그리고 온전한 마지막 callstackoffset 0x35 이므로, 해당 instruction pointer004115b5 임이라는 것을 보여주죠.

0:000> ? 00411580 + 35

Evaluate expression: 4265397 = 004115b5

0:000> uf debuggingstuff!main

debuggingstuff!main [c:\users\byungck\documents\visual studio 2005\projects\debuggingstuff\debuggingstuff\debuggingstuff.cpp @ 41]:

41 00411580 55 push ebp

41 00411581 8bec mov ebp,esp

41 00411583 81ecd8000000 sub esp,0D8h

41 00411589 53 push ebx

41 0041158a 56 push esi

41 0041158b 57 push edi

41 0041158c 8dbd28ffffff lea edi,[ebp-0D8h]

41 00411592 b936000000 mov ecx,36h

41 00411597 b8cccccccc mov eax,0CCCCCCCCh

41 0041159c f3ab rep stos dword ptr es:[edi]

42 0041159e c745f800000000 mov dword ptr [ebp-8],0

43 004115a5 c745ec00000000 mov dword ptr [ebp-14h],0

45 004115ac 8d45f8 lea eax,[ebp-8]

45 004115af 50 push eax

45 004115b0 e864faffff call debuggingstuff!ILT+20(?fooYAJPAPADZ) (00411019)

45 004115b5 83c404 add esp,4

45 004115b8 8945ec mov dword ptr [ebp-14h],eax

47 004115bb 837df800 cmp dword ptr [ebp-8],0

47 004115bf 7416 je debuggingstuff!main+0x57 (004115d7)

. . .
. . .

그러므로, callstack에서 사라진 Functiondebuggingstuff!ILT+20(?fooYAJPAPADZ) foo function 입니다. (이것은 ebp frame 방식에서 보여주는 것이며, FPO형태에서는 적절하지 않을지 모릅니다.)