Managed Debugging에서의 Method Parameters 값 확인에 대한 고민

Managed Debugging Native Debugging과는 다르다. 다음의 Callstack을 보자

 

0:010> kn

 # ChildEBP RetAddr 

00 042ad8ec 79f071ac kernel32!RaiseException+0x53

01 042ad94c 79f0a629 mscorwks!RaiseTheExceptionInternalOnly+0x2a8

02 042ada10 7963661a mscorwks!JIT_Throw+0xfc

03 07d40b60 79381dbe mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x2b466e

04 07d40b60 79381d16 mscorlib_ni!System.Security.Permissions.FileIOPermission.AddPathList(System.Security.Permissions.FileIOPermissionAccess, System.Security.AccessControl.AccessControlActions, System.String[], Boolean, Boolean, Boolean)+0x6a

05 07d3b3c0 0f2481d2 mscorlib_ni!System.Security.Permissions.FileIOPermission..ctor(System.Security.Permissions.FileIOPermissionAccess, System.String)+0x420:010> .frame 3

03 07d40b60 79381dbe mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x2b466e

...

0:010> dv /V

Integrated managed debugging does not support enumeration of local variables.

See http://dbg/managed.htm for more details.

Unable to enumerate locals, HRESULT 0x80004001

 

보다시피 Exception이 발생한 Callstack이다. 무심결에 Frame 3 locals, parameters를 확인하게 위해서 dv command를 실행하거나 kv command를 날려도 HRESULT 0x80004001만 보게 된다. 이유는 해당 callstack Managed Callstack 이기 때문이며, 이 경우는 SOS extension에서 제공하는 clrstack -a 를 통해서 보통 Parameters Locals를 얻을 수 있다고 한다. 그렇게 해서 살펴보면, 아래와 같다.

 

0:010> !clrstack -a

OS Thread Id: 0x1aa4 (10)

ESP       EIP    

042ad974 7c812aeb [HelperMethodFrame: 042ad974]

042ada18 7963661a System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)

    PARAMETERS:

        str = <no data>

        needFullPath = <no data>

    LOCALS:

        <no data>

        <no data>

        <no data>

        <no data>

        <no data>

 

042ada34 79381dbe System.Security.Permissions.FileIOPermission.AddPathList(System.Security.Permissions.FileIOPermissionAccess, System.Security.AccessControl.AccessControlActions, System.String[], Boolean, Boolean, Boolean)

    PARAMETERS:

        this = 0x07d40b3c

        access = 0x00000001

        control = 0x00000000

        pathListOrig = <no data>

        checkForDuplicates = 0x00000000

        needFullPath = <no data>

        copyPathList = <no data>

    LOCALS:

        <no data>

        <no data>

 

. . .

살펴보면, 어떤 Parameters Locals는 데이터가 보이는 데, 어떤 것들은 <no data> 라고 되어 있다. NULL 도 아니고 <no data> 라는 것이 좀 이상하다. 예를 들어, CreateListFromExpressions 함수의 2개의 parameters가 둘 다 <no data> 이다. 사실 해당 parameters값을 정확히 알지 못하고 Debugging 한다는 것은 무리일 듯 하여 이들을 살펴 봐야 하는데 과연, 이것은 무슨 의미일까? 이것은 아마도 GC에 의해서 Data가 소멸 되었거나 관련된 register의 값이 assembly 연산 중에 overwrite 가 되었기 때문이 아닐까 한다. 예를 들어, 해당 call시점의 GCInfo를 확인하면 다음과 같다.

 

0:010> !u -gcinfo 7963661a

preJIT generated code

System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)

Begin 79381fac, size 238

79381fac 57              push    edi

79381fad 56              push    esi

79381fae 53              push    ebx

79381faf 55              push    ebp

79381fb0 83ec08          sub     esp,8

79381fb3 891424          mov     dword ptr [esp],edx

79381fb6 8be9            mov     ebp,ecx

000C        reg EBP becoming live

79381fb8 85ed            test    ebp,ebp

79381fba 0f8494452b00    je      mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x2b45a8 (79636554)

79381fc0 b968431079      mov     ecx,offset mscorlib_ni+0x44368 (79104368) (MT: System.Collections.ArrayList)

79381fc5 e8c636af00      call    mscorwks!JIT_Writeable_Thunks_Buf+0x160 (79e75690) (JitHelp: CORINFO_HELP_NEWSFAST)

001E        reg EAX becoming live

79381fca 8bf8            mov     edi,eax

0020        reg EDI becoming live

79381fcc ba34020000      mov     edx,234h

79381fd1 b901000000      mov     ecx,1

79381fd6 e8ed36af00      call    mscorwks!JIT_Writeable_Thunks_Buf+0x198 (79e756c8) (JitHelp: CORINFO_HELP_GETSHARED_GCSTATIC_BASE)

002F        reg EAX becoming dead

002F        reg EAX becoming live (iptr)

79381fdb 8b80c0010000    mov     eax,dword ptr [eax+1C0h]

0035        reg EAX becoming dead

0035        reg EAX becoming live

79381fe1 8d5704          lea     edx,[edi+4]

0038        reg EDX becoming live (iptr)

79381fe4 e84735af00      call    mscorwks!JIT_Writeable_Thunks_Buf (79e75530)

003D        reg EDX becoming dead

79381fe9 33db            xor     ebx,ebx

79381feb 837d0400        cmp     dword ptr [ebp+4],0

79381fef 0f8e18010000    jle     mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x161 (7938210d)

0049        reg EAX becoming dead

79381ff5 3b5d04          cmp     ebx,dword ptr [ebp+4]

79381ff8 0f831d462b00    jae     mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x2b466f (7963661b)

79381ffe 837c9d0c00      cmp     dword ptr [ebp+ebx*4+0Ch],0

79382003 0f8477452b00    je      mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x2b45d4 (79636580)

79382009 8b749d0c        mov     esi,dword ptr [ebp+ebx*4+0Ch]

0061        reg ESI becoming live

7938200d ba66040000      mov     edx,466h

79382012 b901000000      mov     ecx,1

79382017 e8b436af00      call    mscorwks!JIT_Writeable_Thunks_Buf+0x1a0 (79e756d0) (JitHelp: CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE)

7938201c 89442404        mov     dword ptr [esp+4],eax

79382020 0fb7909c0a0000  movzx   edx,word ptr [eax+0A9Ch]

79382027 0fb788980a0000  movzx   ecx,word ptr [eax+0A98h]

7938202e 51              push    ecx

0083        push non-ptr (1)

7938202f 8bce            mov     ecx,esi

0085        reg ECX becoming live

79382031 3909            cmp     dword ptr [ecx],ecx

79382033 e8f2c6b200      call    mscorwks!COMString::Replace (79eae72a)

008C        reg EAX becoming live

008C        reg ECX becoming dead

008C        reg ESI becoming dead

. . .

 

살펴보면, 중간 중간에 ECX/EDX becoming dead, live 등의 marking된 정보를 볼 수 있는 데, Assembly의 연산에 따라서 각 Register의 값들의 변화에 따라서 live도 되고 dead도 되는 상태 표시이다. ECX/EDX registers parameters로 전달받은 Data라고 본다면(Managed Calling Convention에 따라), 기존의 값이 overwrite가 되거나 dead됨에 따라서 clrstack –a command에서 <no data> 라고 표시하게끔 하는 것으로 보인다.

그렇다면, 실질적인 parameters를 얻을 순 없을 까? 이러한 경우는 !dso command를 통해 해당 Thread stack에 살아있는 managed objects list up 하여 해당 Function logic과 함께 유추하거나 raw stack에서 parameters를 유추할 수 밖에 없다. !clrstack이나 !dumpstack –EE command는 해당 Call function(또는  Method) ESP ChildEBP 정보를 보여주기 때문에 해당 ESP 정보를 통해서 다음과 같이 raw stack을 확인할 수 있다.

 

0:010> dds 042ada18

042ada18  00000001

042ada1c  0a052010

042ada20  07d40b60

042ada24  07d40b60

042ada28  07d40b3c

042ada2c  00000001

042ada30  79381dbe mscorlib_ni!System.Security.Permissions.FileIOPermission.AddPathList(System.Security.Permissions.FileIOPermissionAccess, System.Security.AccessControl.AccessControlActions, System.String[], Boolean, Boolean, Boolean)+0x6a

042ada34  07d3b3c0  <- - - - str?

042ada38  00000001  <- - - - needFullPath?

042ada3c  07d40b60

042ada40  07d40b3c


<일단, 심증이 가는 놈들을 일일이 다 확인해 본다.>
 

0:010> !do 07d3b3c0

Name: System.String

MethodTable: 790fd8c4

EEClass: 790fd824

Size: 146(0x92) bytes

 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: http://70.11.89.156/iexplore.exe.config

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

79102290  4000096        4         System.Int32  1 instance       65 m_arrayLength

79102290  4000097        8         System.Int32  1 instance       39 m_stringLength

790ff328  4000098        c          System.Char  1 instance       68 m_firstChar

790fd8c4  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  057418f0:790d884c 0629a500:790d884c 062b2908:790d884c <<

7912dd40  400009a       14        System.Char[]  0   shared   static WhitespaceChars

    >> Domain:Value  057418f0:07be13e4 0629a500:07be7e18 062b2908:07c3f6e4 <<

 

0:010> !do 07d40b60   <- - - - locals??

Name: System.Object[]

MethodTable: 7912d8f8

EEClass: 7912de6c

Size: 20(0x14) bytes

Array: Rank 1, Number of elements 1, Type CLASS

Element Type: System.String

Fields:

None

 

0:010> !do 07d40b3c <- - - - locals??

Name: System.Security.Permissions.FileIOPermission

MethodTable: 79112b50

EEClass: 79112ae0

Size: 36(0x24) bytes

 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

79112c68  4001d04        4 ...ions.FileIOAccess  0 instance 00000000 m_read

79112c68  4001d05        8 ...ions.FileIOAccess  0 instance 00000000 m_write

79112c68  4001d06        c ...ions.FileIOAccess  0 instance 00000000 m_append

79112c68  4001d07       10 ...ions.FileIOAccess  0 instance 00000000 m_pathDiscovery

79112c68  4001d08       14 ...ions.FileIOAccess  0 instance 00000000 m_viewAcl

79112c68  4001d09       18 ...ions.FileIOAccess  0 instance 00000000 m_changeAcl

7910be50  4001d0a       1c       System.Boolean  1 instance        0 m_unrestricted

7912dd40  4001d0b      5bc        System.Char[]  0   shared   static m_illegalCharacters

    >> Domain:Value  057418f0:NotInit  0629a500:07c3eed8 062b2908:NotInit  <<


<아니면, !dso를 통해서 stack pointer address에 따른 살아있는 Object들을 확인 해본다.>
 

0:010> !dso

OS Thread Id: 0x1aa4 (10)

ESP/REG  Object   Name

042ad908 07d40bec System.ArgumentException

042ad954 07d40bec System.ArgumentException

042ad964 07d40b74 System.Collections.ArrayList

042ad968 07d40bec System.ArgumentException

042ad988 07d40b74 System.Collections.ArrayList

042ad998 07d40bec System.ArgumentException

042ad9a0 07d40bec System.ArgumentException

042ad9fc 07d40bec System.ArgumentException

042ada10 07d40b60 System.Object[]    (System.String[])

042ada20 07d40b60 System.Object[]    (System.String[])

042ada24 07d40b60 System.Object[]    (System.String[])

042ada28 07d40b3c System.Security.Permissions.FileIOPermission

042ada34 07d3b3c0 System.String    http://10.1.1.10/iexplore.exe.config

. . .


이와 같은 정보와 Managed Function의 Code를 review 하면서 해당 parameters를 추정 및 debugging을 전개해 나가면 된다.

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

:         :

:

비공개 덧글

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