본문 바로가기
디버그

[x86 Windows debugging]Virtual Address Dump

by WeZZ 2011. 6. 14.

http://byung.egloos.com/4521186

Windows 32bit System 하에서 하나의 Process는 대략 2GB(~7fffffff address) Virtual Address 영역을 사용한다. 이는 사용자 모드에서 사용 가능한 가상메모리이며, 커널모드에서는 2GB를 따로 사용한다. (물론, 3gb option을 사용하면, bfffffff 까지 User mode에서 사용가능하고, 나머지 1GB kernel이 사용한다. Win32 2^32 arrange 를 갖는 다고 생각하면, 하나의 Process가 사용할 수 있는 Virtual Address layout 4GB이며, 이를 Kernel User mode에서 나눠 갖는 다고 생각하면 된다.) 이는 Physical Memory와 관련 없이 하나의 Process가 사용하는 가상메모리영역이다. 그러므로, Win32 System Windows 하에서 실행하는 임의의 User Mode Application 2GB에 이르기까지 메모리를 사용하고 있다면, 메모리부족오류가 발생할 수 있다.

해당 Application이 메모리관련오류, 특히 메모리누수와 같은 문제를 갖고 있다면, Process가 사용하는 Memory 상태를 확인하는 것은 중요하다. 여기서 메모리의 상태라는 것은 reserve, committed 그리고, Free 를 말한다. Virtual Memory는 성능 및 여러 가지 이유로 임의의 영역을 reserve 하고 나서 실제 사용시에 commit 한다. 물론, 다 사용하고 나면 free 시킬 수 있다. 임의의 Process Windbg Attach 하여 !vadump –v command를 실행하면, 연속된 가상메모리의 상태를 다음과 같이 확인할 수 있다.

BaseAddress: 533f0000

AllocationBase: 533f0000

AllocationProtect: 00000004 PAGE_READWRITE

RegionSize: 00001000

State: 00001000 MEM_COMMIT

Protect: 00000004 PAGE_READWRITE

Type: 00020000 MEM_PRIVATE

BaseAddress: 533f1000

AllocationBase: 00000000

RegionSize: 0000f000

State: 00010000 MEM_FREE

Protect: 00000001 PAGE_NOACCESS

BaseAddress: 53400000

AllocationBase: 53400000

AllocationProtect: 00000004 PAGE_READWRITE

RegionSize: 00001000

State: 00001000 MEM_COMMIT

Protect: 00000004 PAGE_READWRITE

Type: 00020000 MEM_PRIVATE

BaseAddress: 53401000

AllocationBase: 00000000

RegionSize: 0000f000

State: 00010000 MEM_FREE

Protect: 00000001 PAGE_NOACCESS

BaseAddress: 53410000

AllocationBase: 53410000

AllocationProtect: 00000004 PAGE_READWRITE

RegionSize: 00001000

State: 00001000 MEM_COMMIT

Protect: 00000004 PAGE_READWRITE

Type: 00020000 MEM_PRIVATE

메모리가 상당히 조각화되어 있다면, 해당 log는 상당한 양이 될 수도 있다. 반드시, .logopen 하여 file logging을 하도록 한 후에, 연속된 메모리의 상태를 차근차근히 살펴볼 필요가 있다. (하지만, 굉장히 짜증나는 작업이 될 수도 있다.) 그러면, 규칙적으로 Allocation되어 있는 데이타 Block을 찾거나, 메모리 곳곳에 마치 pinning되어 메모리조각화를 유발하는 메모리 block을 찾을 수도 있게 된다. (dc command를 통해 메모리영역에 Application개발자가 인식 가능한 데이터가 존재하는 지 확인해 볼 수 있으며, dds command를 통해 stack 영역인지 여부를 Check 할 수도 있다.

0:000> dds 533f0000

533f0000 533f0040

533f0004 00001000

533f0008 61447720 msdtcprx!UTLink<CMMPageInfo<CITransaction> *>::`vftable'

533f000c 533f0000

533f0010 53380008

533f0014 53400008

533f0018 00000001

533f001c 6149b778 msdtcprx!g_MemMgrCITransaction+0x20

533f0020 61431910 msdtcprx!UTStaticList<CITransaction *>::`vftable'

0:000> dds 53400000

53400000 53400040

53400004 00001000

53400008 61447720 msdtcprx!UTLink<CMMPageInfo<CITransaction> *>::`vftable'

5340000c 53400000

53400010 533f0008

53400014 533a0008

53400018 00000001

5340001c 6149b778 msdtcprx!g_MemMgrCITransaction+0x20

53400020 61431910 msdtcprx!UTStaticList<CITransaction *>::`vftable'

)

메모리 누수의 경우는 DebugDiag 와 같은 Tool이나, gflag에서 +ust option(create user mode stack database)를 이용한 UMDH.exe 를 이용하는 것이 API level에서 확인할 수 있는 가장 좋은 접근이지만, 이와 같은 접근 전에 전반적으로 메모리의 상태를 보고 이후에 좀 더 구체적으로 메모리 문제에 접근한다는 점에서 Virtual address dump는 유용할 수 있다.