성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Windbg - 비정상 종료된 닷넷 프로그램의 StackTrace에서 보이는 offset 값 의미</h1> <p> 덤프 파일을 windbg로 열어서 예외 발생을 조사하는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000:x86> <span style='color: blue; font-weight: bold'>!threads</span> ThreadCount: 2 UnstartedThread: 0 BackgroundThread: 1 PendingThread: 0 DeadThread: 0 Hosted Runtime: no PreEmptive GC Alloc Lock ID OSID ThreadOBJ State GC Context Domain Count APT Exception 0 1 1020 00000000004c5af0 a020 Enabled 00000000027b1fc4:00000000027b1fe8 00000000004bc878 0 MTA <span style='color: blue; font-weight: bold'>System.OutOfMemoryException</span> (00000000027b1f1c) 2 2 1d38 00000000004d27c0 b220 Enabled 0000000000000000:0000000000000000 00000000004bc878 0 MTA (Finalizer) 0:000:x86> <span style='color: blue; font-weight: bold'>!pe</span> Exception object: 00000000027b1f1c Exception type: System.OutOfMemoryException Message: <none> InnerException: <none> StackTrace (generated): SP IP Function 0039F2F0 007A6D9C mscorlib!System.String.Concat(System.String, System.String, System.String)+0x7c 0039F308 006FDD3E <span style='color: blue; font-weight: bold'>ConsoleApplication1!ConsoleApplication1.Program.Main</span>(System.String[])<span style='color: blue; font-weight: bold'>+0x15e</span> StackTraceString: <none> HResult: 8007000e </pre> <br /> (HResult: 8007000e - Not enough storage is available to complete this operation.)<br /> <br /> 애석하게도 PDB 파일이 없는 관계로 소스 파일의 라인 번호가 아닌, "0x15e"라는 옵셋값만 출력됩니다. 다소 악조건의 상황이지만 이런 경우를 통해 windbg 사용법을 익혀 나가는 것 또한 그다지 나쁘지 않다는 긍정적인 판단하에 진행해 보았습니다.<br /> <br /> 우선, Main 메서드의 시작 위치를 알아야 합니다. 왜냐하면 실제로 예외가 발생한 System.String.Concat 메서드는 프레임워크 측의 코드이므로 그 위치를 알아낸다고 해서 그다지 크게 의미가 없습니다. 중요한 것은 "개발자가 작성한 코드"의 결함을 찾아내는 것이기 때문에 Concat 메서드를 부른 Main 메서드 내의 코드 위치를 알아내야 합니다. <br /> <br /> 이를 위해 name2ee 명령어로 다음과 같이 확인해 봐야겠지요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000:x86> <span style='color: blue; font-weight: bold'>!name2ee ConsoleApplication1!ConsoleApplication1.Program.Main</span> Module: 00000000001f2c70 (ConsoleApplication1.exe) Token: 0x0000000006000001 MethodDesc: 00000000001f3010 Name: ConsoleApplication1.Program.Main(System.String[]) <span style='color: blue; font-weight: bold'>JITTED Code Address: 00000000006fdbe0</span> </pre> <br /> 보는 바와 같이, 기계어로 번역된 Main 메서드의 코드 주소가 나옵니다. 이를 역어셈블 하기 위해 "!u" 명령어를 내려 볼까요?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000:x86> <span style='color: blue; font-weight: bold'>!u 00000000006fdbe0</span> Normal JIT generated code ConsoleApplication1.Program.Main(System.String[]) <span style='color: blue; font-weight: bold'>Begin 00000000006fdbe0, size 1a0</span> >>> 0033:006fdbe0 <Effective machine and debuggee state conflict, disassembly not possible> 0033:006fdbe1 <Effective machine and debuggee state conflict, disassembly not possible> ...[이하 반복되는 오류 메시지]... </pre> <br /> 아쉽지만 사후(Post-mortem) 디버깅을 하는 상태에서는 Full Dump 파일임에도 불구하고 !u 명령어를 통해 정상적으로 역어셈블되지 않습니다. (PDB 파일이 없어서일까요? 나중에 확인해 봐야겠습니다. ^^)<br /> <br /> 그래도, 다행히 !u 명령어를 통해 메서드의 크기가 출력되었기 때문에 SOS의 "!u" 명령어가 아닌 Windbg 자체의 "u" 명령어를 이용하여 역어셈블 결과를 어렵지 않게 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; height: 500px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000:x86> <span style='color: blue; font-weight: bold'>u 00000000006fdbe0 L1a0</span> 006fdbe0 55 push ebp 006fdbe1 8bec mov ebp,esp 006fdbe3 57 push edi 006fdbe4 56 push esi 006fdbe5 83ec70 sub esp,70h 006fdbe8 33c0 xor eax,eax 006fdbea 8945d8 mov dword ptr [ebp-28h],eax 006fdbed 8945dc mov dword ptr [ebp-24h],eax 006fdbf0 8945e0 mov dword ptr [ebp-20h],eax 006fdbf3 8945e4 mov dword ptr [ebp-1Ch],eax 006fdbf6 894df4 mov dword ptr [ebp-0Ch],ecx 006fdbf9 833d282e1f0000 cmp dword ptr ds:[1F2E28h],0 006fdc00 7405 je 006fdc07 006fdc02 e86a39cf6b call mscorwks!CorLaunchApplication+0xe99e (6c3f1571) 006fdc07 33d2 xor edx,edx 006fdc09 8955b0 mov dword ptr [ebp-50h],edx 006fdc0c 33d2 xor edx,edx 006fdc0e 8955f0 mov dword ptr [ebp-10h],edx 006fdc11 33d2 xor edx,edx 006fdc13 8955b8 mov dword ptr [ebp-48h],edx 006fdc16 c745d400000000 mov dword ptr [ebp-2Ch],0 006fdc1d c745e800000000 mov dword ptr [ebp-18h],0 006fdc24 c745ec00000000 mov dword ptr [ebp-14h],0 006fdc2b 33d2 xor edx,edx 006fdc2d 8955b4 mov dword ptr [ebp-4Ch],edx 006fdc30 90 nop 006fdc31 8b0db8217803 mov ecx,dword ptr ds:[37821B8h] 006fdc37 ff15e40e7600 call dword ptr ds:[760EE4h] 006fdc3d 90 nop 006fdc3e ff152c0e7600 call dword ptr ds:[760E2Ch] 006fdc44 90 nop 006fdc45 b934117600 mov ecx,761134h 006fdc4a e8cd43aeff call 001e201c 006fdc4f 8945ac mov dword ptr [ebp-54h],eax 006fdc52 8b4dac mov ecx,dword ptr [ebp-54h] 006fdc55 ff15dcda7100 call dword ptr ds:[71DADCh] 006fdc5b 8b45ac mov eax,dword ptr [ebp-54h] 006fdc5e 8945b8 mov dword ptr [ebp-48h],eax 006fdc61 8b0580207803 mov eax,dword ptr ds:[3782080h] 006fdc67 8945b4 mov dword ptr [ebp-4Ch],eax 006fdc6a 33d2 xor edx,edx 006fdc6c 8955f0 mov dword ptr [ebp-10h],edx 006fdc6f 90 nop 006fdc70 e9e9000000 jmp 006fdd5e 006fdc75 90 nop 006fdc76 33c9 xor ecx,ecx 006fdc78 ff15f8f67100 call dword ptr ds:[71F6F8h] 006fdc7e 8945cc mov dword ptr [ebp-34h],eax 006fdc81 8955d0 mov dword ptr [ebp-30h],edx 006fdc84 ff75d0 push dword ptr [ebp-30h] 006fdc87 ff75cc push dword ptr [ebp-34h] 006fdc8a 6a00 push 0 006fdc8c 6800040000 push 400h 006fdc91 e8df82a96b call mscorwks+0x25f75 (6c195f75) 006fdc96 8945e8 mov dword ptr [ebp-18h],eax 006fdc99 8955ec mov dword ptr [ebp-14h],edx 006fdc9c b9401e7100 mov ecx,711E40h 006fdca1 e87643aeff call 001e201c 006fdca6 8945a8 mov dword ptr [ebp-58h],eax 006fdca9 8b05bc217803 mov eax,dword ptr ds:[37821BCh] 006fdcaf 89458c mov dword ptr [ebp-74h],eax 006fdcb2 8b45a8 mov eax,dword ptr [ebp-58h] 006fdcb5 8b4de8 mov ecx,dword ptr [ebp-18h] 006fdcb8 8b55ec mov edx,dword ptr [ebp-14h] 006fdcbb 894804 mov dword ptr [eax+4],ecx 006fdcbe 895008 mov dword ptr [eax+8],edx 006fdcc1 8b45a8 mov eax,dword ptr [ebp-58h] 006fdcc4 894588 mov dword ptr [ebp-78h],eax 006fdcc7 ff35c0217803 push dword ptr ds:[37821C0h] 006fdccd 8b4d8c mov ecx,dword ptr [ebp-74h] 006fdcd0 8b5588 mov edx,dword ptr [ebp-78h] 006fdcd3 ff159c8e2900 call dword ptr ds:[298E9Ch] 006fdcd9 8945a4 mov dword ptr [ebp-5Ch],eax 006fdcdc 8b45a4 mov eax,dword ptr [ebp-5Ch] 006fdcdf 8945b0 mov dword ptr [ebp-50h],eax 006fdce2 8b45b8 mov eax,dword ptr [ebp-48h] 006fdce5 8945a0 mov dword ptr [ebp-60h],eax 006fdce8 8b45b0 mov eax,dword ptr [ebp-50h] 006fdceb 89459c mov dword ptr [ebp-64h],eax 006fdcee 8d4dbc lea ecx,[ebp-44h] 006fdcf1 ff1580967100 call dword ptr ds:[719680h] 006fdcf7 8d7dd8 lea edi,[ebp-28h] 006fdcfa 8d75bc lea esi,[ebp-44h] 006fdcfd f30f7e06 movq xmm0,mmword ptr [esi] 006fdd01 660fd607 movq mmword ptr [edi],xmm0 006fdd05 f30f7e4608 movq xmm0,mmword ptr [esi+8] 006fdd0a 660fd64708 movq mmword ptr [edi+8],xmm0 006fdd0f 8d4dd8 lea ecx,[ebp-28h] 006fdd12 ff15dc957100 call dword ptr ds:[7195DCh] 006fdd18 894598 mov dword ptr [ebp-68h],eax 006fdd1b 6800001000 push 100000h 006fdd20 ba43000000 mov edx,43h 006fdd25 33c9 xor ecx,ecx 006fdd27 e844820000 call 00705f70 006fdd2c 894594 mov dword ptr [ebp-6Ch],eax 006fdd2f ff7594 push dword ptr [ebp-6Ch] 006fdd32 8b5598 mov edx,dword ptr [ebp-68h] 006fdd35 8b4d9c mov ecx,dword ptr [ebp-64h] 006fdd38 ff15cc8e2900 call dword ptr ds:[298ECCh] 006fdd3e 894590 mov dword ptr [ebp-70h],eax 006fdd41 8b5590 mov edx,dword ptr [ebp-70h] 006fdd44 8b4da0 mov ecx,dword ptr [ebp-60h] 006fdd47 3909 cmp dword ptr [ecx],ecx 006fdd49 ff159cda7100 call dword ptr ds:[71DA9Ch] 006fdd4f 90 nop 006fdd50 8b4db0 mov ecx,dword ptr [ebp-50h] 006fdd53 ff15e40e7600 call dword ptr ds:[760EE4h] 006fdd59 90 nop 006fdd5a 90 nop 006fdd5b ff45f0 inc dword ptr [ebp-10h] 006fdd5e 817df0ffffff7f cmp dword ptr [ebp-10h],7FFFFFFFh 006fdd65 0f9cc0 setl al 006fdd68 0fb6c0 movzx eax,al 006fdd6b 8945d4 mov dword ptr [ebp-2Ch],eax 006fdd6e 837dd400 cmp dword ptr [ebp-2Ch],0 006fdd72 0f85fdfeffff jne 006fdc75 006fdd78 90 nop 006fdd79 8d65f8 lea esp,[ebp-8] 006fdd7c 5e pop esi 006fdd7d 5f pop edi 006fdd7e 5d pop ebp 006fdd7f c3 ret </pre> <br /> 이쯤에서 다시 처음으로 돌아가 "!pe" 결과로 출력된 옵셋값을 살펴보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > StackTrace (generated): SP IP Function 0039F308 <span style='color: blue; font-weight: bold'>006FDD3E</span> ConsoleApplication1!ConsoleApplication1.Program.Main(System.String[])+<span style='color: blue; font-weight: bold'>0x15e</span> </pre> <br /> 위의 의미는, Main 메서드의 최초 위치(006fdbe0)에서 0x15e 옵셋만큼 떨어진 기계어 코드를 가리키는 것임을 알 수 있습니다. 그 위치는 위의 결과에서 이미 IP(Instruction Pointer)로 출력된 "006FDD3E" 값과 동일합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ...[생략]... 006fdd2c 894594 mov dword ptr [ebp-6Ch],eax 006fdd2f ff7594 push dword ptr [ebp-6Ch] 006fdd32 8b5598 mov edx,dword ptr [ebp-68h] 006fdd35 8b4d9c mov ecx,dword ptr [ebp-64h] 006fdd38 ff15cc8e2900 call dword ptr ds:[298ECCh] <span style='color: blue; font-weight: bold'>006fdd3e 894590 mov dword ptr [ebp-70h],eax</span> 006fdd41 8b5590 mov edx,dword ptr [ebp-70h] 006fdd44 8b4da0 mov ecx,dword ptr [ebp-60h] 006fdd47 3909 cmp dword ptr [ecx],ecx 006fdd49 ff159cda7100 call dword ptr ds:[71DA9Ch] 006fdd4f 90 nop ...[생략]... </pre> <br /> 이렇게 해서, 일단 예외가 발생한 기계어 코드의 위치는 찾았지만, 닷넷 개발자 입장에서 위의 정보는 여전히 직접적인 도움이 되지 않습니다. 문제는, 위의 기계어 코드와 일치하는 실제 C# 소스 코드 위치를 알 수 있는 방법이 있느냐 하는 것인데요. 만약, 자동으로 알 수 있는 방법이 있었다면 windbg가 이미 보여줄 수 있었을 텐데, 보관해 둔 PDB 파일이 없으므로 '자동'으로 찾을 수 있는 방법은 포기해야 합니다.<br /> <br /> 우선, 수작업으로 찾는 방법이 2가지 정도 있습니다. 하나는 말 그대로 기계어를 보면서, Main 함수의 소스 코드를 같이 보면서 찾아들어갈 수 있습니다. 다른 방법으로는, 위의 오류가 발생한 머신과 비슷한 환경을 꾸미고 소스 코드가 갖춰진 개발자 컴퓨터에서 Visual Studio에서 디버거를 붙여서 실행 시킨 후 "역어셈블" 화면을 보면서 유사하게 생성된 기계어 패턴을 따라가면서 소스 코드 위치를 파악하는 것입니다.<br /> <br /> PDB 파일 보관을 제대로 하지 않았다면 이 정도 수고는 기꺼이 감수해야합니다. ^^<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8933
(왼쪽의 숫자를 입력해야 합니다.)