Stack Overflow에 대한 Debugging Windows debugging

Program의 수행에서 CPU의 연산을 위해 Stack을 사용한다는 점에서 Stack Size가 제한되어 있다는 것은 개발자라면 항상 염두에 두고 있을 것이다. 그러므로, 무한 재귀 호출되는 Function이나 과도하게 Stack 상에다 Allocation한 후(일반적으로 Local variables parameters Stack에 저장된다.) Exception이나 비정상적인 operation으로 인하여 Stackunwind 되지 않는 다면, 예기치 않은 Stack overflow를 맞을 수 있다. 다음의 Stack overflow dump case를 예로 든다.

 

일단, 메모리덤프를 Open 하면, 대번 Stack Overflow임을 알 수 있다.

 

(24f8.f64): Stack overflow - code c00000fd (first/second chance not available)

eax=000900a0 ebx=00000000 ecx=08ac2bf0 edx=0e010026 esi=0e010024 edi=08aff134

eip=033f9577 esp=08afebe8 ebp=08afec1c iopl=0         nv up ei pl nz na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206

*** WARNING: Unable to verify checksum for ttt.dll

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ttt.dll -

ttt!DllUnregisterServer+0x33a4:

033f9577 8501            test    dword ptr [ecx],eax  ds:0023:08ac2bf0=00000000

 

Stack Size는 다음과 같이 Check 할 수 있다.

 

0:066> !teb

TEB at 7fefd000

    ExceptionList:        08afec10

    StackBase:            08b00000

    StackLimit:           08ac1000

    SubSystemTib:         00000000

    FiberData:            00001e00

    ArbitraryUserPointer: 00000000

    Self:                 7fefd000

    EnvironmentPointer:   00000000

    ClientId:             000024f8 . 00000f64

    RpcHandle:            00000000

    Tls Storage:          7fefd02c

    PEB Address:          7ffd8000

    LastErrorValue:       0

    LastStatusValue:      c0150008

    Count Owned Locks:    0

    HardErrorMode:        0

 

0:066> ? 08b00000 - 08ac1000

Evaluate expression: 258048 = 0003f000

 

실제, Max Allocation할 수 있는 Stack Size를 확인해 보면, 대략 256k임을 확인할 수 있다. 이는 아래와 같은 TEB Structure DeallocationStack 값을 확인하면 되며, 이는 http://msdn.microsoft.com/en-us/library/cc267849.aspx 문서를 참조하거나 debugging tools for windows help에서 참조할 수 있다.

 

typedef struct _TEB {
    NT_TIB NtTib;
    PVOID  EnvironmentPointer;
    CLIENT_ID ClientId;
    PVOID ActiveRpcHandle;
    PVOID ThreadLocalStoragePointer;
    PPEB ProcessEnvironmentBlock;
    ULONG LastErrorValue;
    .....
    PVOID DeallocationStack;
    .....
} TEB;

0:066> dd 7fefd000+e0c L1

7fefde0c  08ac0000

 

0:066> ? 08b00000 - 08ac0000

Evaluate expression: 262144 = 00040000  <---- 256k Max allocation size

 

그러므로, 현재 사용하는 Stack3f000 으로 Max Stack Size, 40000 에 도달하고 있음을 확인할 수 있다.

 

원인을 찾기 위해선 무엇보다도 먼저 재귀 호출이 있는 지 확인이 필요한데, 이는 Callstack을 확인하는 작업이 필요할 듯 하다. 일단, 해당 case에서는 안타깝게도 해당 모듈에 대한 Symbol이 정확하지 않아서 확인이 불가능했으며, 정확한 symbol이 존재한다면 아래의 Callstack에서 확인된 Function Check해야 한다.

 

0:066> kbL

ChildEBP RetAddr  Args to Child             

WARNING: Stack unwind information not available. Following frames may be wrong.

08afec1c 033f4de9 0df4002c 08aff0fc 0000fde9 ttt!DllUnregisterServer+0x33a4 <-- Symbol 맞지 않아서 이렇게 보이는 것임.

08aff118 033f40c8 0b056198 0b056228 00000000 ttt+0x4de9

08aff170 762e31eb 0b055f20 08aff124 08aff120 ttt+0x40c8

08aff198 7635184f 033f3e71 08aff3a0 00000005 rpcrt4!Invoke+0x2a

08aff5c4 7634fc79 09dae6f8 06afcbc8 018be228 rpcrt4!NdrStubCall2+0x27b

08aff614 760527f7 09dae6f8 018be228 06afcbc8 rpcrt4!CStdStubBuffer_Invoke+0xffffdd13

08aff638 76909759 09dae6f8 018be228 06afcbc8 oleaut32!CUnivStubWrapper::Invoke+0xc7

. . .

 

만일, Function의 무한 재귀호출에 의해서 Stack Overflow가 발생한 것이 아니라면, Stack allocation 패턴도 Check해야 한다.

 

0:066> dds esp

08afebe8  75f751ea kernel32!lstrlenW+0x56

08afebec  033f18c5 ttt+0x18c5

08afebf0  08aff134

08afebf4  0b0584a8

08afebf8  08aff148

08afebfc  01e62f00

08afec00  0b0584a8

08afec04  000cc09e

08afec08  08afec24

08afec0c  033f188b ttt+0x188b

08afec10  08aff10c

08afec14  0340c9f0 ttt!DllUnregisterServer+0x1681d

08afec18  00000000

08afec1c  08aff118

08afec20  033f4de9 ttt+0x4de9

08afec24  0df4002c

08afec28  08aff0fc

08afec2c  0000fde9

08afec30  0000007b

08afec34  0b055f20

08afec38  00000005

08afec3c  00000000

 

Callstack에서 문제가 발생한 시점이전의 최종 Return Address 33f4de9 인데, 그 이후에 Stack address(상위 raw stack에서의 회색 블럭)local variables 또는 parameters 등으로 사용되므로, 이들 중 Allocation 패턴이 overflow를 의심하게 하는 것이 있는 지 Check가 필요하다.

 

0:066> dc 0b0584a8

0b0584a8  0340e448 0b0500c4 00000000 00000000  H.@.............

0b0584b8  ee7ff470 08002142 00000001 0000261c  p...B!.......&..

0b0584c8  0000261c 000a000d 006f0043 0074006e  .&......C.o.n.t.

0b0584d8  006e0065 002d0074 00790054 00650070  e.n.t.-.T.y.p.e.

0b0584e8  0020003a 006d0069 00670061 002f0065  :. .i.m.a.g.e./.

0b0584f8  00690067 003b0066 006e0020 006d0061  g.i.f.;. .n.a.m.

0b058508  003d0065 00630022 0069006c 005f0070  e.=.".c.l.i.p._.

0b058518  006d0069 00670061 00300065 00330030  i.m.a.g.e.0.0.3.

 

0:066> du 0b0584c8+8

0b0584d0  "Content-Type: image/gif; name="c"

0b058510  "lip_image003.gif"..Content-ID: <"

0b058550  "20090223.44575.001@tagfree.com>."

0b058590  ".Content-Transfer-Encoding: base"

0b0585d0  "64..Content-Location: file:///C:"

0b058610  "/DOCUME~1/jkim/LOCALS~1/Temp/mso"

0b058650  "html1/01/clip_image003.gif....R0"

0b058690  "lGODlhKwHTAHcAMSH+GlNvZnR3YXJlOi"

0b0586d0  "BNaWNyb3NvZnQgT2ZmaWNlACH5BAEAAA"

0b058710  "AALBUACQAA..AcMAhgAAAAAAABoaTSYm"

0b058750  "czMzmWaAgIAzAICAAJaWlpm/v5/P/57O"

0b058790  "/53O/5zN/5vN/5rM/5nM/79N..AL/d/7"

0b0587d0  "7d/7zc/7vb/7ra/7na/73c/7jZ/7fZ/7"

0b058810  "bY/7XY/7TY/7PX/7LX/7DW/6/W/7TX/6"

0b058850  "/V/67V../63U/6vT/6rT/6nT/6jT/6zU"

0b058890  "/6vU/6fS/6bS/6bR/6XR/6TQ/6PQ/6LQ"

0b0588d0  "/6HP/6DP/8Tf/8Le/8He../8De/8Pf/8"

0b058910  "z//9/u/97t/93s/9zr/9vr/9rq/9nq/9"

0b058950  "jq/9rr/9bp/9Xo/9Tn/9fp/9Lm/9Hm/8"

0b058990  "/l../9Pn/87l/83k/9Dm/8zj/8vj/8ni"

0b0589d0  "/8ji/8fh/8bh/8Xg//9mAP//AP//zP7/"

0b058a10  "//7+//3+//z9//v9..//v8//r8//n8//"

0b058a50  "j7//f7//b6//X5//T4//P4//L4//H3//"

. . .<중략>

 

그러므로, 만일, 상위에서 보여주는 몇몇의 data가 과도한 Allocation이나 Allocation 패턴에 의해서 문제 상황을 가져오지는 않는 지는 최종적으로 Source Code를 통해서 확인해봐야 하며, 그러기 위해서는 정확한 Symbol match가 중요함을 잊지 말아야 한다.


트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://byung.egloos.com/tb/4809522 [도움말]
  • User mode 에서 Stack Overflow 2009/04/17 11:20 #

    Kernel mode 에서 정해진 Stack 보다 많은 Stack 을 사용하면 System 이 Crash 됩니다. 즉 x86 에서 12kb 의 kernel stack 보다 많은 메모리를... more

덧글

덧글 입력 영역