|
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에 대한 추가적인 메모리 덤프를 분석해 볼 필요도 있을 지 모른다.
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에서도 마찮가지이며, 이외에도 다음의 표와 같이 일부 수정된 기능이 존재한다.
상위의 표를 보면 알겠지만, 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 이벤트로그에 오류라고 뜨면 일반적으로 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... 라는 메뉴가 있다.
작업을 수행하지 못했습니다. 바인딩 결과: 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하는 것이 좋을 듯 하다. 예전에는 MultibyteToWideChar 인가 이런 것을 썼던 것 같은 데, Programming에서 절로 골치아픈것이 한글처리이다. 보통은 DBCS 체계(흔히 euc-kr)에서와 Unicode처리에서 고민하게 되는 데, MLang API가 색다르게 이런 문제를 해결해주기도 한다.
보면, 0xb0, 0xa1 = ‘가’ 이렇게 되어 있다. 이것을 MLang API인 CreateConvertCharset, DoConversion을 이용하면, unicode로 변경할 수 있다.
물론, 그 반대도 가능하다. 만일, 속성의 Charset에 Unicode 사용을 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) ;
|
카테고리
이글루링크
최근 등록된 덧글
17번부터 어떻게 접는지..
by tykim0131 at 10/28 ATL이나 MFC를 이용하.. by 김명신 at 09/24 복원되었군요.. 제 RSS.. by 강세윤 at 09/24 허걱, 하고 있는 것으로.. by 강세윤 at 09/15 RSS 주소 서비스는 안 .. by 정성태 at 09/15 다시 보고 싶군요. by 강세윤 at 09/14 마악하임 ㄱ-;;; ㅋㅋㅋ.. by ㅋㅋㅋ at 09/13 17번막혀17번막혀17번막혀.. by 17번막혀 at 09/06 번역줌해줬으면... by 김용우 at 09/02 11번부터막힌다 by 김용우 at 09/02 이글루 파인더
| |||||||||||||||