Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

Windbg - 비정상 종료된 닷넷 프로그램의 StackTrace에서 보이는 offset 값 의미

덤프 파일을 windbg로 열어서 예외 발생을 조사하는데,

0:000:x86> !threads
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 System.OutOfMemoryException (00000000027b1f1c)
   2    2 1d38 00000000004d27c0      b220 Enabled  0000000000000000:0000000000000000 00000000004bc878     0 MTA (Finalizer)

0:000:x86> !pe
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 ConsoleApplication1!ConsoleApplication1.Program.Main(System.String[])+0x15e

StackTraceString: <none>
HResult: 8007000e

(HResult: 8007000e - Not enough storage is available to complete this operation.)

애석하게도 PDB 파일이 없는 관계로 소스 파일의 라인 번호가 아닌, "0x15e"라는 옵셋값만 출력됩니다. 다소 악조건의 상황이지만 이런 경우를 통해 windbg 사용법을 익혀 나가는 것 또한 그다지 나쁘지 않다는 긍정적인 판단하에 진행해 보았습니다.

우선, Main 메서드의 시작 위치를 알아야 합니다. 왜냐하면 실제로 예외가 발생한 System.String.Concat 메서드는 프레임워크 측의 코드이므로 그 위치를 알아낸다고 해서 그다지 크게 의미가 없습니다. 중요한 것은 "개발자가 작성한 코드"의 결함을 찾아내는 것이기 때문에 Concat 메서드를 부른 Main 메서드 내의 코드 위치를 알아내야 합니다.

이를 위해 name2ee 명령어로 다음과 같이 확인해 봐야겠지요. ^^

0:000:x86> !name2ee ConsoleApplication1!ConsoleApplication1.Program.Main
Module: 00000000001f2c70 (ConsoleApplication1.exe)
Token: 0x0000000006000001
MethodDesc: 00000000001f3010
Name: ConsoleApplication1.Program.Main(System.String[])
JITTED Code Address: 00000000006fdbe0

보는 바와 같이, 기계어로 번역된 Main 메서드의 코드 주소가 나옵니다. 이를 역어셈블 하기 위해 "!u" 명령어를 내려 볼까요?

0:000:x86> !u 00000000006fdbe0
Normal JIT generated code
ConsoleApplication1.Program.Main(System.String[])
Begin 00000000006fdbe0, size 1a0
>>> 0033:006fdbe0 <Effective machine and debuggee state conflict, disassembly not possible>
0033:006fdbe1 <Effective machine and debuggee state conflict, disassembly not possible>
...[이하 반복되는 오류 메시지]...

아쉽지만 사후(Post-mortem) 디버깅을 하는 상태에서는 Full Dump 파일임에도 불구하고 !u 명령어를 통해 정상적으로 역어셈블되지 않습니다. (PDB 파일이 없어서일까요? 나중에 확인해 봐야겠습니다. ^^)

그래도, 다행히 !u 명령어를 통해 메서드의 크기가 출력되었기 때문에 SOS의 "!u" 명령어가 아닌 Windbg 자체의 "u" 명령어를 이용하여 역어셈블 결과를 어렵지 않게 구할 수 있습니다.

0:000:x86> u 00000000006fdbe0 L1a0
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

이쯤에서 다시 처음으로 돌아가 "!pe" 결과로 출력된 옵셋값을 살펴보면,

StackTrace (generated):
    SP       IP       Function
    0039F308 006FDD3E ConsoleApplication1!ConsoleApplication1.Program.Main(System.String[])+0x15e

위의 의미는, Main 메서드의 최초 위치(006fdbe0)에서 0x15e 옵셋만큼 떨어진 기계어 코드를 가리키는 것임을 알 수 있습니다. 그 위치는 위의 결과에서 이미 IP(Instruction Pointer)로 출력된 "006FDD3E" 값과 동일합니다.

...[생략]...
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
...[생략]...

이렇게 해서, 일단 예외가 발생한 기계어 코드의 위치는 찾았지만, 닷넷 개발자 입장에서 위의 정보는 여전히 직접적인 도움이 되지 않습니다. 문제는, 위의 기계어 코드와 일치하는 실제 C# 소스 코드 위치를 알 수 있는 방법이 있느냐 하는 것인데요. 만약, 자동으로 알 수 있는 방법이 있었다면 windbg가 이미 보여줄 수 있었을 텐데, 보관해 둔 PDB 파일이 없으므로 '자동'으로 찾을 수 있는 방법은 포기해야 합니다.

우선, 수작업으로 찾는 방법이 2가지 정도 있습니다. 하나는 말 그대로 기계어를 보면서, Main 함수의 소스 코드를 같이 보면서 찾아들어갈 수 있습니다. 다른 방법으로는, 위의 오류가 발생한 머신과 비슷한 환경을 꾸미고 소스 코드가 갖춰진 개발자 컴퓨터에서 Visual Studio에서 디버거를 붙여서 실행 시킨 후 "역어셈블" 화면을 보면서 유사하게 생성된 기계어 패턴을 따라가면서 소스 코드 위치를 파악하는 것입니다.

PDB 파일 보관을 제대로 하지 않았다면 이 정도 수고는 기꺼이 감수해야합니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 8/3/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  [3]  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13567정성태2/27/20241836오류 유형: 898. .NET Framework 3.5 이하에서 mscoree.tlb 참조 시 System.BadImageFormatException파일 다운로드1
13566정성태2/27/20241892오류 유형: 897. Windows 7 SDK 설치 시 ".NET Development" 옵션이 비활성으로 선택이 안 되는 경우
13565정성태2/23/20241734닷넷: 2219. .NET CLR2 보안 모델에서의 개별 System.Security.Permissions 제어
13564정성태2/22/20241978Windows: 259. Hyper-V Generation 1 유형의 VM을 Generation 2 유형으로 바꾸는 방법
13563정성태2/21/20241961디버깅 기술: 196. windbg - async/await 비동기인 경우 메모리 덤프 분석의 어려움
13562정성태2/21/20242007오류 유형: 896. ASP.NET - .NET Framework 기본 예제에서 System.Web에 대한 System.IO.FileNotFoundException 예외 발생
13561정성태2/20/20242083닷넷: 2218. C# - (예를 들어, Socket) 비동기 I/O에 대한 await 호출 시 CancellationToken을 이용한 취소파일 다운로드1
13560정성태2/19/20242129디버깅 기술: 195. windbg 분석 사례 - Semaphore 잠금으로 인한 Hang 현상 (닷넷)
13559정성태2/19/20242954오류 유형: 895. ASP.NET - System.Security.SecurityException: 'Requested registry access is not allowed.'
13558정성태2/18/20242206닷넷: 2217. C# - 최댓값이 1인 SemaphoreSlim 보다 Mutex 또는 lock(obj)를 선택하는 것이 나은 이유
13557정성태2/18/20241941Windows: 258. Task Scheduler의 Author 속성 값을 변경하는 방법
13556정성태2/17/20242002Windows: 257. Windows - Symbolic (hard/soft) Link 및 Junction 차이점
13555정성태2/15/20242152닷넷: 2216. C# - SemaphoreSlim 사용 시 주의점
13554정성태2/15/20241875VS.NET IDE: 189. Visual Studio - 닷넷 소스코드 디컴파일 찾기가 안 될 때
13553정성태2/14/20241967닷넷: 2215. windbg - thin/fat lock 없이 동작하는 Monitor.Wait + Pulse
13552정성태2/13/20241916닷넷: 2214. windbg - Monitor.Enter의 thin lock과 fat lock
13551정성태2/12/20242107닷넷: 2213. ASP.NET/Core 웹 응용 프로그램 - 2차 스레드의 예외로 인한 비정상 종료
13550정성태2/11/20242271Windows: 256. C# - Server socket이 닫히면 Accept 시켰던 자식 소켓이 닫힐까요?
13549정성태2/3/20242732개발 환경 구성: 706. C# - 컨테이너에서 실행하기 위한 (소켓) 콘솔 프로젝트 구성
13548정성태2/1/20242532개발 환경 구성: 705. "Docker Desktop for Windows" - ASP.NET Core 응용 프로그램의 소켓 주소 바인딩(IPv4/IPv6 loopback, Any)
13547정성태1/31/20242317개발 환경 구성: 704. Visual Studio - .NET 8 프로젝트부터 dockerfile에 추가된 "USER app" 설정
13546정성태1/30/20242157Windows: 255. (디버거의 영향 등으로) 대상 프로세스가 멈추면 Socket KeepAlive로 연결이 끊길까요?
13545정성태1/30/20242007닷넷: 2212. ASP.NET Core - 우선순위에 따른 HTTP/HTTPS 호스트:포트 바인딩 방법
13544정성태1/30/20242033오류 유형: 894. Microsoft.Data.SqlClient - Could not load file or assembly 'System.Security.Permissions, ...'
13543정성태1/30/20242065Windows: 254. Windows - 기본 사용 중인 5357 포트 비활성화는 방법
13542정성태1/30/20242084오류 유형: 893. Visual Studio - Web Application을 실행하지 못하는 IISExpress - 두 번째 이야기
1  2  [3]  4  5  6  7  8  9  10  11  12  13  14  15  ...