GC가 시작되는 순간에 Hang 현상

High CPU현상이 아닌 상황에서 hang Dump 수집했는데, Lock 존재할 것이라고 생각했다.

 

0:100> !locks

 

CritSec +14ce60 at 0014ce60

WaiterWoken        No

LockCount          134

RecursionCount     1

OwningThread       162c

EntryCount         0

ContentionCount    86

*** Locked

 

CritSec +15d558 at 0015d558

WaiterWoken        No

LockCount          2

RecursionCount     1

OwningThread       8a4

EntryCount         0

ContentionCount    2

*** Locked

 

2개의 Lock 보이므로, 이것들이 서로서로 deadlock 유발하겠구나 하고 쉽게 생각했지만, 그렇지 않았다. 일단, 134개의 lock 잡고 있는 162c Thread GC Thread였다.

 

0:100> ~~[162c]s

eax=00000001 ebx=04fce8c0 ecx=002381e8 edx=7c96ed64 esi=04fce8c4 edi=7ffd4000

eip=7c96ed64 esp=04fce874 ebp=04fce91c iopl=0         nv up ei pl zr na pe nc

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

ntdll!KiFastSystemCallRet:

7c96ed64 c3              ret

0:014> kb

ChildEBP RetAddr  Args to Child             

04fce870 7c962104 7c82716b 00000002 04fce8c0 ntdll!KiFastSystemCallRet

04fce874 7c82716b 00000002 04fce8c0 00000001 ntdll!NtWaitForMultipleObjects+0xc

04fce91c 7c821095 00000002 04fcea5c 00000000 kernel32!WaitForMultipleObjectsEx+0x11a

04fce938 79248be3 00000002 04fcea5c 00000000 kernel32!WaitForMultipleObjects+0x18

04fceb70 791e0723 00000002 00000000 00000000 mscorwks!Thread::SysSuspendForGC+0x248

04fceb88 792144f9 00000001 00000000 00000000 mscorwks!GCHeap::SuspendEE+0xcf

04fceba4 7924199e 00000000 00000000 00000e44 mscorwks!GCHeap::GarbageCollectGeneration+0x103

04fcebd4 791b3868 00238a08 00000e44 00000000 mscorwks!gc_heap::allocate_more_space+0x13a

04fcedf8 791b300a 00238a08 00000e44 00000000 mscorwks!GCHeap::Alloc+0x5f

04fcee0c 791dd118 00000e44 00000000 00000000 mscorwks!Alloc+0x3a

04fcee2c 791dd0b9 00bd0088 0000071c 00000000 mscorwks!FastAllocatePrimitiveArray+0x45

04fceeac 00bc1336 00000000 0000071c 0c67ab58 mscorwks!JIT_NewArr1+0xbb

WARNING: Frame IP not in any known module. Following frames may be wrong.

00000000 00000000 00000000 00000000 00000000 0xbc1336

 

이것은 아마도 Memory Allocation중에 적정한 Size Memory 할당받지 못했나 보다. 하여, GC 수행되기 위해 EE Suspend 하고 있다. 만일, Thread 진행되지 않는 다면, 이는 Suspend 되지 않는 Thread 존재할 것이라 믿는 . 전에 대부분의 Thread 아래와 같은 Thread 동일한 형태였다.

 

0:014> ~100s

eax=000019d6 ebx=00000000 ecx=00000000 edx=630d5cb8 esi=0014ce60 edi=000005b8

eip=7c96ed64 esp=10c0f9bc ebp=10c0f9f8 iopl=0         nv up ei pl zr na pe nc

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

ntdll!KiFastSystemCallRet:

7c96ed64 c3              ret

0:100> kb

ChildEBP RetAddr  Args to Child             

10c0f9b8 7c962114 7c97972f 000005b8 00000000 ntdll!KiFastSystemCallRet

10c0f9bc 7c97972f 000005b8 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc

10c0f9f8 7c979640 00000000 00000004 0000000a ntdll!RtlpWaitOnCriticalSection+0x19c

10c0fa18 791b6ffc 0014ce60 10c0fa4c 79268960 ntdll!RtlEnterCriticalSection+0xa8

10c0fa24 79268960 0014ce60 00000000 0fdc43c8 mscorwks!EE_EnterCriticalSection+0xc

10c0fa38 791b48f8 7c828ce5 0fdc43c8 7c82bccd mscorwks!BaseCrst::Enter+0x8a

10c0fa4c 791d09e8 00000000 00000001 0fdc43c8 mscorwks!ThreadStore::LockThreadStore+0x9d

10c0fa60 791d0abb 0fdc43c8 00000000 7c82bbcd mscorwks!ThreadStore::AddThread+0xd

10c0fa88 7929c0de 0020de28 10c0fb48 7931712e mscorwks!SetupThread+0x103

10c0fa94 7931712e 00000000 0020de28 0020de28 mscorwks!SetupThreadPoolThread+0x15

10c0fb48 79317611 0017cd48 00000001 00000001 mscorwks!AddTimerCallbackEx+0x16

10c0fb5c 792eebc6 0017cd48 00000001 792eebb7 mscorwks!AddTimerCallback+0x10

10c0fb70 792ee6ca 0020de28 0512fe38 793fa170 mscorwks!ThreadpoolMgr::AsyncTimerCallbackCompletion+0xf

10c0fb84 792ee8c3 0512fe38 00000000 792ee79a mscorwks!ThreadpoolMgr::ExecuteWorkRequest+0x19

10c0fba4 792edfdb 00000000 00000014 10c0fbdc mscorwks!ThreadpoolMgr::WorkerThreadStart+0x129

10c0ffb8 7c8260b9 001a8488 00000000 00000000 mscorwks!ThreadpoolMgr::intermediateThreadProc+0x44

10c0ffec 00000000 792edf97 001a8488 00000000 kernel32!BaseThreadStart+0x34

0:100> dc 0014ce60

0014ce60  0014cf80 fffffde6 00000001 0000162c  ............,...

0014ce70  000005b8 00000000 0014cfa8 ffffffff  ................

0014ce80  00000000 00000000 00000000 00000000  ................

0014ce90  0015d610 0014ce90 00238a40 00000008  ........@.#.....

0014cea0  00000000 00000006 00000000 00000001  ................

0014ceb0  00000000 00000000 00000000 00000000  ................

0014cec0  00000000 002389d0 0000162c 00000111  ......#.,.......

0014ced0  00100010 000c01b6 003a0063 0077005c  ........c.:.\.w.

 

ntdll!RtlEnterCriticalSection Function 우리가 흔히 알고 있는 EnterCriticalSection 함수와 유사하다면, 첫번째 파라메터는 Critical Section Object 것이다. Binary 살펴보면, 0xc offset 162c 라는 값이 들어 온다. 이미 살펴 본봐 이는 !lock에서 보여주었던 GC Thread ThreadID 동일하다. 아마도, 해당 Critical Section Owner 보여주는 것으로 보인다.

 

결국, GC Thread Suspend Wait 하고 있는 이유를 밝히는 것이 중요하다. 아쉽게도 !lock에서 보여준 2번째 Thread Owner Orphan Thread임이 밝혀졌다.

 

0:100> ~~[8a4]d

             ^ Illegal thread error in '~~[8a4]d'

0:100> ~ <<< ALL thread 살펴볼 있으나, ThreadID 8a4 놈을 찾을 없다.

 

그리고, 중요한 것은 다음.

 

0:100> !threads

Loaded Son of Strike data table version 5 from "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"

ThreadCount: 8

UnstartedThread: 0

BackgroundThread: 6

PendingThread: 0

DeadThread: 1

                                  PreEmptive   GC Alloc                     Lock    

        ID  ThreadOBJ       State     GC       Context           Domain     Count APT Exception

  0 0x6928 0x0015d5a0      0xa020 Enabled  0x00000000:0x00000000 0x0014c130     0 MTA

  2  0x86c 0x00155508      0xb220 Enabled  0x00000000:0x00000000 0x0014c130     0 MTA (Finalizer)

  3  0x750 0x00194cf0      0x1220 Enabled  0x0c484a6c:0x0c486140 0x0014c130     0 Ukn

  5 0x70fc 0x001820d8   0x2001220 Enabled  0x00000000:0x00000000 0x0014c130     0 Ukn

 10 0x51f8 0x001a6c48    0x800222 Disabled 0x0c3a7c60:0x0c3a7c70 0x0014c130     0 MTA (Threadpool Completion Port)

XXX      0 0x001bbfc0    0x800820 Enabled  0x00000000:0x00000000 0x0014c130     1 MTA (Threadpool Completion Port)

 13 0x63e8 0x002381e8    0x800222 Disabled 0x0c489bf0:0x0c48a140 0x0014c130     0 MTA (Threadpool Completion Port)

 14 0x162c 0x002389d0    0x800220 Disabled 0x0c6ae3d8:0x0c6af044 0x0014c130     1 MTA (GC) (Threadpool Completion Port)

 

보면, PreEmptive GC Enabled 되지 않은 Thread GC Thread 포함해서 3개가 존재한다. 14 Thread GC Thread 다른 모든 Thread Suspend 때까지 기다릴 터이다. 그럼, 10, 13 Thread Disabled 인지 확인할 필요가 있다.

 

0:100> ~10s

eax=00003a24 ebx=00000000 ecx=00000000 edx=5dc101c9 esi=0015d558 edi=00000498

eip=7c96ed64 esp=0488df7c ebp=0488dfb8 iopl=0         nv up ei pl zr na pe nc

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

ntdll!KiFastSystemCallRet:

7c96ed64 c3              ret

0:010> kb

ChildEBP RetAddr  Args to Child              

0488df78 7c962114 7c97972f 00000498 00000000 ntdll!KiFastSystemCallRet

0488df7c 7c97972f 00000498 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc

0488dfb8 7c979640 00000000 00000004 0000000a ntdll!RtlpWaitOnCriticalSection+0x19c

0488dfd8 791b6ffc 0015d558 0488e008 79268960 ntdll!RtlEnterCriticalSection+0xa8

0488dfe4 79268960 0015d558 0488e15c 0488e15c mscorwks!EE_EnterCriticalSection+0xc

0488dff8 79254d88 0488e15c 0488e140 0488e044 mscorwks!BaseCrst::Enter+0x8a

0488e008 7921d09b 0488e140 0488e6b0 0488e15c mscorwks!CPFH_HandleManagedFault+0x61

0488e044 7921d135 0488e140 0488e6b0 0488e15c mscorwks!GetPrevSEHRecord+0x703

0488e05c 7c96eeca 0488e140 0488e6b0 0488e15c mscorwks!COMPlusFrameHandler+0x3d

0488e080 7c96ee9b 0488e140 0488e6b0 0488e15c ntdll!ExecuteHandler2+0x26

0488e128 7c96ecd6 04888000 0488e15c 0488e140 ntdll!ExecuteHandler+0x24

0488e128 04dece25 04888000 0488e15c 0488e140 ntdll!KiUserExceptionDispatcher+0xe

WARNING: Frame IP not in any known module. Following frames may be wrong.

0488e424 0488e650 0c3a7468 0c3a7504 0c3a4af8 0x4dece25

00000000 00000000 00000000 00000000 00000000 0x488e650

 

눈에 띄는 것은 KiUserExceptionDispatcher . (http://byung.egloos.com/4710539) 이것은 Exception 발생한 경우이다. 해당 함수의 Stack 살펴보면, 아래와 같은 몇몇 정보를 얻을 있다.

 

0:010> dc 0488e128

0488e128  0c3a7ac8 7c96ecd6 04888000 0488e15c  .z:....|....\...

0488e138  0488e140 0488e15c c0000005 00000000  @...\...........  <<< c0000005: Access Violation

0488e148  00000000 04dece25 00000002 00000000  ....%........... <<< 04dece25: Exception Address

0488e158  00000000 0001003f 00000000 00000000  ....?...........  <<< 1003f Context Flags

0488e168  00000000 00000000 00000000 00000000  ................

0488e178  ffff027f ffff4020 ffffffff 00bc4c08  .... @.......L..

0488e188  00ca001b 0488e6d8 ffff0023 00000000  ........#.......

0488e198  00000000 00000000 00000000 00000000  ................

 

결국, 해당 Thread 04dece25 에서 Access Violation 대한 Exception으로 인해 GC 의해 Suspend 되지 않은 것으로 보인다. 이는 Orphan Thread 관련이 있을 수도 있다. 임의의 Orphan Thread (Thread ID:8a4) Critical Section Lock 잡고 Terminated 되었기 때문에 해당 Exception Thread에서 Critical Section Lock 걸려있을 수도 있다. 그리고, 추가적으로 13 Thread 역시 10 Thread 동일한 Exception Thread이다.

 

0:013> kb

ChildEBP RetAddr  Args to Child             

00d4e5f0 7c962114 7c97972f 00000498 00000000 ntdll!KiFastSystemCallRet

00d4e5f4 7c97972f 00000498 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc

00d4e630 7c979640 00000000 00000004 0000000a ntdll!RtlpWaitOnCriticalSection+0x19c

00d4e650 791b6ffc 0015d558 00d4e680 79268960 ntdll!RtlEnterCriticalSection+0xa8

00d4e65c 79268960 0015d558 00d4e7d4 00d4e7d4 mscorwks!EE_EnterCriticalSection+0xc

00d4e670 79254d88 00d4e7d4 00d4e7b8 00d4e6bc mscorwks!BaseCrst::Enter+0x8a

00d4e680 7921d09b 00d4e7b8 00d4ed28 00d4e7d4 mscorwks!CPFH_HandleManagedFault+0x61

00d4e6bc 7921d135 00d4e7b8 00d4ed28 00d4e7d4 mscorwks!GetPrevSEHRecord+0x703

00d4e6d4 7c96eeca 00d4e7b8 00d4ed28 00d4e7d4 mscorwks!COMPlusFrameHandler+0x3d

00d4e6f8 7c96ee9b 00d4e7b8 00d4ed28 00d4e7d4 ntdll!ExecuteHandler2+0x26

00d4e7a0 7c96ecd6 00d4d000 00d4e7d4 00d4e7b8 ntdll!ExecuteHandler+0x24

00d4e7a0 04dece25 00d4d000 00d4e7d4 00d4e7b8 ntdll!KiUserExceptionDispatcher+0xe

WARNING: Frame IP not in any known module. Following frames may be wrong.

00d4ecc8 00e3b502 00d4ed10 00fbcda8 00d4ed28 0x4dece25

00000000 00000000 00000000 00000000 00000000 0xe3b502

 

0:013> dc 00d4e7a0

00d4e7a0  00d4ecc8 7c96ecd6 00d4d000 00d4e7d4  .......|........

00d4e7b0  00d4e7b8 00d4e7d4 c0000005 00000000  ................

00d4e7c0  00000000 04dece25 00000002 00000000  ....%...........  << Exception Address 10 Thread 동일한 위치!!

00d4e7d0  00000000 0001003f 00000000 00000000  ....?...........

00d4e7e0  00000000 00000000 00000000 00000000  ................

00d4e7f0  ffff027f ffff0000 ffffffff 00bc4c08  .............L..

00d4e800  00ca001b 00d4ecd8 ffff0023 00000000  ........#.......

00d4e810  00000000 00000000 00000000 00000000  ................

 

그러므로, Orphan Thread 역시 이와 같은 Exception 문제가 되는 것은 아닌 의심해 본다. 결국, 해당 GC suspend Hang Exception 대한 Fix 우선적으로 처리되는 것이 필요하며, Orphan Thread 위해 1st chance exception 대한 추가적인 메모리 덤프를 분석해 필요도 있을 모른다.


추가적으로
Exception Address Assembly code !u (해당 Thread managed thread stack 보여줬다.) 통해 확인해 필요가 있겠다. 여기서 또한, .cxr 이용하여 (Context Flags address pointer 이용) Context switch 하여 Exception 발생 Thread Stack으로 이동할 필요도 있을 것이다. 이하 생략한다. 단지, 해당 Process hang 상태를 확인하는 과정으로써 Thread Stack Pattern이나 분석 과정을 흩어보는 것으로 마무리 한다.

 

by 강세윤 | 2009/10/12 17:32 | Windows debugging | 트랙백 | 덧글(0)
Win7에서의 AppInit_DLLs

AppInit_DLLs 구조는 일반적으로 API hooking mechanism으로 사용되었던 구조이다. 해당 레지스트리 (AppInit_DLLs:REG_SZ) HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows 에서 확인할 수가 있는 , 이는 User32.dll DLL_PROCESS_ATTACH과정에서 LoadLibrary() 함수를 사용하여 load 된다. 그러므로, 해당 Registry 설정된 DLL path user32.dll 사용하는 모든 Application 의해서 load되므로, DLL injection 기능으로 사용되어 왔다. 이에 따라서 많은 malware 이러한 mechanism 사용하는 , Dead Lock이나 Crash 문제가 되었었고, performance에도 영향을 미치게 됨에 따라서 Win7에서는 일부 수정이 있게 되었다.

 

사실 Windows Vista 에서 부터 AppInit_DLLs 구조는 default disable 이다. 이러한 Default 설정은 Win7에서도 마찮가지이며, 이외에도 다음의 표와 같이 일부 수정된 기능이 존재한다.

 

Value

Description

Sample values

LoadAppInit_DLLs
(REG_DWORD)

Value that globally enables or disables AppInit_DLLs.

0x0 – AppInit_DLLs are disabled.
0x1 – AppInit_DLLs are enabled.

AppInit_DLLs
(REG_SZ)

Space -or comma-delimited list of DLLs to load. The complete path to the DLL should be specified by using short file names.

C:\PROGRA~1\Test\Test.dll

RequireSignedAppInit_DLLs
(REG_DWORD)

Require code-signed DLLs.

0x0 – Load any DLLs.
0x1 – Load only code-signed DLLs.

상위의 표를 보면 알겠지만, AppInit_DLLs 원천적으로 Disable 있다. 그리고, enable 된다 하더라도 Code-signed DLL만을 Load하게끔 구성할 있다. 이미 짐작하겠지만, AppInit_DLLs Application Compatibility 이유로 인하여 사용해야만 한다면, Recommendation으로는 code-signed DLLs만을 Load하도록 하는 것이 것이다.

 

DLL Code-sign하기 위해서는 Digital Signature Binary embedding 해야 것이며, 이는 아래와 같은 절차를 따르게 된다.

ü  /integritycheck linker option 가지고 DLL Link 한다. 이는 Visual Studio 2005/2008에서 지원한다. 이는 dumpbin /headers <dllname.dll> 통해 dumping data에서 Check integrity 포함되었는지를 확인함으로써 verify 있다.

ü  DLL /ph (page-hash) option 가지고 signed되어야 한다. 또한, /t (timestamp) option 가지고 sign함으로써 code signing certificate expiring 대해서 보호될 있다. 그리고, release시에는 반드시 /ac option 사용하여 cross-certificate 대한 참조가 가능하도록 한다. 이는 signing code path windows kernel 존재할 필요하다.

 

다음은 SignTool 이용하여 DLL sign 하는 예이다.

 

·         Test-signing example:

Signtool sign /v /ph /s My /n Contoso.com(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll DLLname.dll

 

·         Release-signing example:

Signtool sign /v /ph /ac MSCV-VSClass3.cer /s my /n contoso.com /t http://timestamp.verisign.com/scripts/timestamp.dll DLLname.dll

 

참조 발췌: http://www.microsoft.com/whdc/driver/install/AppInit-Win7.mspx

by 강세윤 | 2009/09/28 13:17 | 정리되지 않은 기술 | 트랙백 | 덧글(0)
advapi32!ReportEventW

이벤트로그에 오류라고 뜨면 일반적으로 Event ID 대상 프로그램의 이름 또는 관계된 Component , 그리고 Description 등을 확인할 있으며, 이를 가지고 Research 이뤄진다. 하지만, 간혹 Detail Debugging 위해 문제시점의 메모리 덤프를 얻어서 Callstack등을 확인할 경우가 필요하다. 경우에는 Event Log reporting 하는 Function advapi32!ReportEventW(또는 ReportEventA) Breakpoint 걸어서 메모리 덤프를 수집하는 것이 유용할 때가 있다. DebugDiag 사용하는 경우에 편리한데, 아래와 같이 Crash rule에서 추가적으로 지정해 주면 하다.

Debug Diag Crash Rule Advanced Configuration 있는 , 해당 설정 중에 Breakpoints... 라는 메뉴가 있다.

상위의 Configure Breakpoints 에서 Add Breakpoint... Click 하면, Configure Breakpoint Menu 상위와 같이 있으며, Breakpoint Expression "advapi32!ReportEventW" 입력하여 Action Type Full Userdump 설정하면 Event Log Event 기록될 Memory Dump 수집할 있다. 물론, 오류 뿐만이 아니라 해당 Process에서 날리는 Event마다 Dump 생성하는 것이므로, 적절한 시점에 설정하는 것이 필요할 하다.

by 강세윤 | 2009/09/24 14:13 | Windows debugging | 트랙백 | 덧글(0)
TypeLoadException

때때로 ClickOnce Application 경우, Binary Version 관리에 어려움을 겪을 때가 있다. 간혹, 잘못된 version packaging 됨에 따라 TypeLoadException 같은 오류를 만날 수도 있다. Fusion Log 확인해 보면, 아래와 같은 오류 메시지를 출력한다.

 

작업을 수행하지 못했습니다.

바인딩 결과: hr = 0x80070002. 지정된 파일을 찾을 수 없습니다.

 

다음 위치에서 어셈블리 관리자 로드:  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll

다음 실행 파일에서 실행:  C:\Documents and Settings\user\Local Settings\Apps\2.0\4OY0HKEP.MG6\BWRZ440C.JYB\clie..tion_074ec68f6f9bd5dd_0001.0000_2b9c0e62c20843f8\Client.exe

--- 자세한 오류 로그가 아래에 표시됩니다.

 

=== 미리 바인딩된 상태 정보 ===

로그: 사용자 = Test\user1

로그: DisplayName = CommonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=077d93da315deeea

 (Fully-specified)

로그: Appbase = file:///C:/Documents and Settings/user/Local Settings/Apps/2.0/4OY0HKEP.MG6/BWRZ440C.JYB/clie..tion_074ec68f6f9bd5dd_0001.0000_2b9c0e62c20843f8/

로그: 초기 PrivatePath = NULL

로그: 동적 베이스 = NULL

로그: 캐시 베이스 = NULL

로그: AppName = Client.exe

호출 어셈블리: Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.

===

로그: 네이티브 이미지 CommonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=077d93da315deeea() 바인딩하기 시작합니다.

경고: 일치하는 네이티브 이미지가 없습니다.

 

실제로 Fusion Log로는 해당 Client.exe Application CommonTest.dll 참조하고 있는 , 해당 DLL Load하지 못하는 것으로 보여준다. 이런 경우는 CommonTest.dll 종속성 때문에 종속적인 추가적인 DLL 존재하지 않거나 또는 해당 DLL 자체가 Client Machine 배포되지 않았을 경우에도 유사하게 보여준다. 하지만, 종속적인 추가적인 DLL 존재하지 않아서 문제가 된다면, 해당 종속 DLL 대한 FileNotFoundException 추가적으로 보이거나, 해당 DLL 배포되지 않았다면, Memory Dump에서 FileNotFoundException 확인할 있거나 또는 대상 Directory Check해보면, 권한 등의 오류에 의해서 실제로 DLL 존재하지 못하는 경우도 발생될 있다. 그런데, 간혹, Memory Dump 확인하였을 , TypeLoadException 같은 경우도 발생한다.

 

0:000> !do 0143bf08

Name: System.TypeLoadException

MethodTable: 7994b248

EEClass: 791710b4

Size: 88(0x58) bytes

GC Generation: 0

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

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

79330a00  40000b5        4        System.String  0 instance 00000000 _className

7932fe74  40000b6        8 ...ection.MethodBase  0 instance 00000000 _exceptionMethod

79330a00  40000b7        c        System.String  0 instance 00000000 _exceptionMethodString

79330a00  40000b8       10        System.String  0 instance 0143c2a8 _message

7932a35c  40000b9       14 ...tions.IDictionary  0 instance 00000000 _data

79330b94  40000ba       18     System.Exception  0 instance 00000000 _innerException

79330a00  40000bb       1c        System.String  0 instance 00000000 _helpURL

7933061c  40000bc       20        System.Object  0 instance 0143c48c _stackTrace

79330a00  40000bd       24        System.String  0 instance 00000000 _stackTraceString

79330a00  40000be       28        System.String  0 instance 00000000 _remoteStackTraceString

79332c4c  40000bf       34         System.Int32  0 instance        0 _remoteStackIndex

7933061c  40000c0       2c        System.Object  0 instance 00000000 _dynamicMethods

79332c4c  40000c1       38         System.Int32  0 instance -2146233054 _HResult

79330a00  40000c2       30        System.String  0 instance 00000000 _source

793332c8  40000c3       3c        System.IntPtr  0 instance        0 _xptrs

79332c4c  40000c4       40         System.Int32  0 instance -532459699 _xcode

79330a00  4000398       44        System.String  0 instance 0143be28 ClassName

79330a00  4000399       48        System.String  0 instance 0143be64 AssemblyName

79330a00  400039a       4c        System.String  0 instance 00000000 MessageArg

79332c4c  400039b       50         System.Int32  0 instance -2146233054 ResourceId

 

0:000> !do 0143be28

Name: System.String

MethodTable: 79330a00

EEClass: 790ed64c

Size: 60(0x3c) bytes

GC Generation: 0

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

String: CommonTest.FileWrapperClass

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

79332c4c  4000096        4         System.Int32  0 instance       22 m_arrayLength

79332c4c  4000097        8         System.Int32  0 instance       21 m_stringLength

793316e0  4000098        c          System.Char  0 instance       43 m_firstChar

79330a00  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  0015e850:01421198 <<

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

    >> Domain:Value  0015e850:014218f0 <<

 

0:000> !do 0143be64

Name: System.String

MethodTable: 79330a00

EEClass: 790ed64c

Size: 164(0xa4) bytes

GC Generation: 0

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

String: CommonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=077d93da315deeea

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

79332c4c  4000096        4         System.Int32  0 instance       74 m_arrayLength

79332c4c  4000097        8         System.Int32  0 instance       73 m_stringLength

793316e0  4000098        c          System.Char  0 instance       43 m_firstChar

79330a00  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  0015e850:01421198 <<

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

    >> Domain:Value  0015e850:014218f0 <<

 

메모리 덤프상에서 보면, CommonTest.dll Load되어 있는 것으로 보인다. 하지만, FileWrapperClass 라는 이름의 Class 호출할 , TypeLoadException 발생하는 것을 있다. 경우에는 CommonTest.dll 포함하고 있는 FileWrapperClass load 하지 못하는 경우이다. 일반적으로 해당 Class CommonTest.dll에서 제공하는 것이 맞는 지를 Check하는 것이 일감일 하다.

 

0:000> !dumpdomain

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

. . .

Assembly: 00229cd8 [C:\Documents and Settings\user\Local Settings\Apps\2.0\4OY0HKEP.MG6\BWRZ440C.JYB\clie..tion_074ec68f6f9bd5dd_0001.0000_2b9c0e62c20843f8\CommonTest.dll]

ClassLoader: 0020f0f0

SecurityDescriptor: 001c3060

  Module Name

00ad5c88 C:\Documents and Settings\user\Local Settings\Apps\2.0\4OY0HKEP.MG6\BWRZ440C.JYB\clie..tion_074ec68f6f9bd5dd_0001.0000_2b9c0e62c20843f8\CommonTest.dll

 

0:000> !dumpmodule -mt 00ad5c88

Name: C:\Documents and Settings\user\Local Settings\Apps\2.0\4OY0HKEP.MG6\BWRZ440C.JYB\clie..tion_074ec68f6f9bd5dd_0001.0000_2b9c0e62c20843f8\CommonTest.dll

Attributes: PEFile

Assembly: 00229cd8

LoaderHeap: 00000000

TypeDefToMethodTableMap: 037e325c

TypeRefToMethodTableMap: 037e3378

MethodDefToDescMap: 037e35f8

FieldDefToDescMap: 037e3bdc

MemberRefToDescMap: 037e3ee4

FileReferencesMap: 037e4370

AssemblyReferencesMap: 037e4374

MetaData start address: 03816048 (44216 bytes)

 

Types defined in this module

 

      MT    TypeDef Name

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

00ad6310 0x02000002 CommonTest.FileWrapperClassEx

00ad6c14 0x02000006 CommonTest.xxx

 

Types referenced in this module

 

      MT    TypeRef Name

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

7933061c 0x01000001 System.Object

7b21d954 0x01000003 System.Windows.Forms.Form

 

일단, 해당 모듈 CommonTest.dll에서는 FileWrapperClass 라는 Class 제공하지 않는 것으로 보인다. Name FileWrapperClassEx 있는 것으로 봐서는 뭔가 version 문제로 보인다. 확실하게 하기 위해서는 !SOS/SaveModule <address> <filepath>하여 Dump load되어 있는 CommonTest.dll Drop하는 것이 좋을 하다. 그리고, ildasm.exe 통해 해당 모듈의 metadata Check하여 로드되어 있는 CommonTest.dll FileWrapperClass Type으로 가지고 있는 Check하는 것이 좋을 하다.

by 강세윤 | 2009/09/22 13:44 | Windows debugging | 트랙백 | 덧글(0)
귀찮은 Charset (MLang API에 대해서)

예전에는 MultibyteToWideChar 인가 이런 것을 썼던 것 같은 데, Programming에서 절로 골치아픈것이 한글처리이다. 보통은 DBCS 체계(흔히 euc-kr)에서와 Unicode처리에서 고민하게 되는 데, MLang API가 색다르게 이런 문제를 해결해주기도 한다.

Visual Studio에서 C++ Programming 을 할 때 Project의 속성을 보면 Charset을 설정할 수 있다. 상위에 보면, MBCS(Multi-Byte Character Set)을 이용하는 것으로 되어 있다. 이 경우에 code editor에서 Text를 입력하면, 이는 한글일 경우, euc-kr format을 따른다.

 

보면, 0xb0, 0xa1 = ‘이렇게 되어 있다. 이것을 MLang APICreateConvertCharset, DoConversion을 이용하면, unicode로 변경할 수 있다.

  

물론, 그 반대도 가능하다. 만일, 속성의 CharsetUnicode 사용을 Check하면, Edit에 입력된 가나다abc”Unicode charset으로 저장된다. 이를 CreateConvertCharset Function을 통해서 1200(unicode) 20949(euc-kr) 로 변경되도록 수정하고, DoConversion Function을 통해서 변환해보면 된다. 코드는 상위 image에 나온 것이 전부이니.. 굳이

        CString str = "가나다abc" ;

 

        BYTE pbyte[100] ;

        memset(pbyte, '\0', 100) ;

        UINT s_b= str.GetLength () ;

        //s_b = 2*s_b+1 ;

        CopyMemory( pbyte, str.GetBuffer (s_b), s_b);

 

        IMultiLanguage2 *m = NULL ;

        IMLangConvertCharset* m_pMLCC = NULL;

        char d[1024] ;

 

        memset(d, 0x0, sizeof(d)) ;

 

HRESULT hr = CoCreateInstance(CLSID_CMultiLanguage, NULL,

        CLSCTX_INPROC_SERVER,

               IID_IMultiLanguage2, (void**) &m );

 

        //hr = m->CreateConvertCharset (1200, 20949, 0, &m_pMLCC) ;

        hr = m->CreateConvertCharset (20949, 1200, 0, &m_pMLCC) ;

       

        s_b = s_b*2+1 ;

        m_pMLCC->DoConversion (pbyte, &s_b, (BYTE*)d, &s_b) ;

by 강세윤 | 2009/09/18 13:48 | 정리되지 않은 기술 | 트랙백 | 덧글(1)
< 이전페이지 다음페이지 >