Tag Archive for 'Heap'

[Heap] Page Heap Enabled 환경

일반적으로 heap에 메모리를 할당하게 되면 _HEAP 과 _HEAP_ENTRY가 기본적으로 생성됩니다. 하지만 Page Heap Enabled 환경에는 그외에 몇가지 추가 정보들을 가지게 됩니다.

일반 환경의 Heap Allocation

  • Create Heap -> _HEAP 생성
  • Allocate Heap -> _HEAP_ENTRY 생성

Page Heap Enabled 환경의 Heap Allocation

  • Create Heap -> _DPH_HEAP_ROOT 생성, _HEAP 생성
  • Allocate Heap -> _DPH_HEAP_BLOCK 생성, _DPH_BLOCK_INFORMATION 생성, _HEAP_ENTRY 생성

_DPH로 시작하는 구조체는 각  Heap 생성과 Free 시에 Stack Trace 정보, Memory의 Size, 실제 할당된 Virtual Memory의 Page ( 0×2000 사이즈.. )의 Address 등의 정보를 가지게 됩니다.

0:001> !heap -p -all
_DPH_HEAP_ROOT @ a1000
Freed and decommitted blocks
DPH_HEAP_BLOCK : VirtAddr VirtSize
000a3bdc : 022da000 00004000
000a39ac : 02368000 00002000
000a3e34 : 022ee000 00002000
000a4a3c : 02300000 00002000
000a48ac : 0239a000 00004000
000a3de4 : 02310000 00002000
000a3c7c : 02322000 00002000
000a4884 : 0239e000 00004000
000a3aec : 02360000 00003000
000a48fc : 023a2000 00004000
000a14f4 : 02314000 00002000
000a345c : 000fa000 00002000
000a4604 : 022de000 00002000
000a3ac4 : 0237a000 00004000
000a3f24 : 02350000 00002000
000a4334 : 02354000 00002000
000a3a24 : 02394000 00004000
000a35ec : 0236a000 00002000
000a4794 : 0238c000 00002000
000a46f4 : 023b2000 00002000
000a4c1c : 023c6000 00002000
000a3ccc : 0237e000 00002000
000a4bf4 : 023c4000 00002000
000a4ba4 : 023c0000 00002000
000a3a4c : 02378000 00002000
000a4b7c : 023be000 00002000
000a4b54 : 023bc000 00002000
000a39fc : 02366000 00002000
000a4b2c : 023ba000 00002000
000a4adc : 023b6000 00002000
000a2f0c : 000f6000 00002000
000a43fc : 0235e000 00002000
000a4ab4 : 023b4000 00002000
000a4c44 : 023c8000 00002000
Busy allocations
DPH_HEAP_BLOCK : UserAddr UserSize - VirtAddr VirtSize
000a38bc : 023cefe8 00000018 - 023ce000 00002000
000a3e5c : 023b0f88 00000074 - 023b0000 00002000
000a3a9c : 023aefd8 00000024 - 023ae000 00002000
000a4a14 : 023acf88 00000074 - 023ac000 00002000
000a3b14 : 02302f88 00000074 - 02302000 00002000
000a4a8c : 022fef88 00000074 - 022fe000 00002000
000a4a64 : 0234ef88 00000074 - 0234e000 00002000
000a47e4 : 02320f88 00000074 - 02320000 00002000
000a4b04 : 023b8f88 00000074 - 023b8000 00002000
000a48d4 : 02398f88 00000074 - 02398000 00002000
000a43ac : 0235afb8 00000044 - 0235a000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a3eac : 0231afb8 00000044 - 0231a000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a467c : 02316fb8 00000044 - 02316000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a44ec : 022f4fb8 00000044 - 022f4000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a3664 : 02282fb8 00000044 - 02282000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a2d2c : 02238fb8 00000044 - 02238000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a3bb4 : 022e2fb8 00000044 - 022e2000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a318c : 022e0fb8 00000044 - 022e0000 00002000
MSCTF!CProxyITfLangBarItemSink::`vftable’
000a476c : 0238afc8 00000038 - 0238a000 00002000
MSCTF!CStubITfLangBarItemButton::`vftable’
000a462c : 02344fc8 00000038 - 02344000 00002000
MSCTF!CStubITfLangBarItemButton::`vftable’
000a3d94 : 0230cfc8 00000038 - 0230c000 00002000
MSCTF!CStubITfLangBarItemButton::`vftable’
000a4834 : 023a6fc8 00000038 - 023a6000 00002000
MSCTF!CStubITfLangBarItemButton::`vftable’
000a4744 : 02388ff8 00000004 - 02388000 00002000
000a46a4 : 02380fd8 00000024 - 02380000 00002000
MSCTF!CSharedBlockNT::`vftable’
000a45dc : 02376ff0 00000010 - 02376000 00002000
MSCTF!CPtrArray<SYSTHREAD>::`vftable’
000a40dc : 02336ff0 00000010 - 02336000 00002000
000a4014 : 0232cf78 00000084 - 0232c000 00002000
MFC42!AFX_MODULE_THREAD_STATE::`vftable’
000a3c54 : 022d4f70 00001090 - 022d4000 00003000
MFC42!_AFX_BASE_MODULE_STATE::`vftable’
000a471c : 000f4fe0 00000020 - 000f4000 00002000
000a395c : 02364f78 00000084 - 02364000 00002000
MFC42!AFX_MODULE_THREAD_STATE::`vftable’
000a3f4c : 022fcfe0 00000020 - 022fc000 00002000
000a47bc : 02392fe0 00000020 - 02392000 00002000
000a421c : 02390fe0 00000020 - 02390000 00002000
000a42e4 : 0238efe0 00000020 - 0238e000 00002000
000a46cc : 02386fe0 00000020 - 02386000 00002000
000a4474 : 02384fe0 00000020 - 02384000 00002000
000a449c : 02382fe0 00000020 - 02382000 00002000
000a453c : 02372fe0 00000020 - 02372000 00002000
000a444c : 02370fe0 00000020 - 02370000 00002000

Windbg에서는 이러한 Page Heap Enabled 환경에서의 정보를 좀더 쉽게 볼수 있도록 !heap Extension Option을 제공하고 있습니다. ( !heap Extension에 관해서는 나중에 기회가되면 좀 정리하여 올리도록 하겠습니다. ) !heap -p 를 통해서 _DPH_HEAP_ROOT와 _DPH_HEAP_BLOCK으로 실제 할당된 메모리와 해제된 메모리의 추적이 가능합니다. 일단 _DPH_HEAP_ROOT의 실제 구조체를 살펴보죠.

0:001> dt ntdll!_DPH_HEAP_ROOT a1000
+0x000 Signature : 0xffeeddcc
+0x004 HeapFlags : 2
+0x008 HeapCritSect : 0x000a5000 _RTL_CRITICAL_SECTION
+0x00c nRemoteLockAcquired : 0
+0x010 pVirtualStorageListHead : 0x000a3894 _DPH_HEAP_BLOCK
+0x014 pVirtualStorageListTail : 0x000a10bc _DPH_HEAP_BLOCK
+0x018 nVirtualStorageRanges : 3
+0x01c nVirtualStorageBytes : 0x300000
+0×020 pBusyAllocationListHead : 0×000a38bc _DPH_HEAP_BLOCK
+0×024 pBusyAllocationListTail : 0×000a115c _DPH_HEAP_BLOCK
+0×028 nBusyAllocations : 0×14f
+0×02c nBusyAllocationBytesCommitted : 0×29f000

+0×030 pFreeAllocationListHead : 0×000a3bdc _DPH_HEAP_BLOCK
+0×034 pFreeAllocationListTail : 0×000a4c44 _DPH_HEAP_BLOCK
+0×038 nFreeAllocations : 0×22
+0×03c nFreeAllocationBytesCommitted : 0×51000

+0×040 pAvailableAllocationListHead : 0×000a480c _DPH_HEAP_BLOCK
+0×044 pAvailableAllocationListTail : 0×000a39d4 _DPH_HEAP_BLOCK
+0×048 nAvailableAllocations : 3
+0×04c nAvailableAllocationBytesCommitted : 0xa000

+0×050 pUnusedNodeListHead : 0×000a3934 _DPH_HEAP_BLOCK
+0×054 pUnusedNodeListTail : 0×000a4fb4 _DPH_HEAP_BLOCK
+0×058 nUnusedNodes : 0×1d
+0×05c nBusyAllocationBytesAccessible : 0×150000
+0×060 pNodePoolListHead : 0×000a1094 _DPH_HEAP_BLOCK
+0×064 pNodePoolListTail : 0×000a1094 _DPH_HEAP_BLOCK
+0×068 nNodePools : 1
+0×06c nNodePoolBytes : 0×4000
+0×070 pNextHeapRoot : 0×002b1000 _DPH_HEAP_ROOT
+0×074 pPrevHeapRoot : (null)
+0×078 nUnProtectionReferenceCount : 1
+0×07c InsideAllocateNode : 0
+0×080 ExtraFlags : 3
+0×084 Seed : 0×42752766
+0×088 NormalHeap : 0×001a0000
+0×08c CreateStackTrace : (null)
+0×090 FirstThread : 0×00000938

_DPH_HEAP_ROOT 구조체를 보면 현재 Busy 한 Heap Block과 Free한 Heap Block을 Linked List로 가지고 있는 것을 확인 할 수 있습니다. 이 링크를 통해서 _DPH_HEAP_BLOCK를 추적해 보죠.

0:001> dl 000a38bc
000a38bc 000a3e5c 023ce000 00002000 00001000
000a3e5c 000a3a9c 023b0000 00002000 00001000
000a3a9c 000a4a14 023ae000 00002000 00001000
000a4a14 000a3b14 023ac000 00002000 00001000
000a3b14 000a4a8c 02302000 00002000 00001000
000a4a8c 000a4a64 022fe000 00002000 00001000
000a4a64 000a47e4 0234e000 00002000 00001000
000a47e4 000a4b04 02320000 00002000 00001000
000a4b04 000a48d4 023b8000 00002000 00001000
000a48d4 000a43ac 02398000 00002000 00001000
000a43ac 000a3eac 0235a000 00002000 00001000
000a3eac 000a467c 0231a000 00002000 00001000
000a467c 000a44ec 02316000 00002000 00001000
000a44ec 000a3664 022f4000 00002000 00001000
000a3664 000a2d2c 02282000 00002000 00001000
000a2d2c 000a3bb4 02238000 00002000 00001000
000a3bb4 000a318c 022e2000 00002000 00001000
000a318c 000a476c 022e0000 00002000 00001000
000a476c 000a462c 0238a000 00002000 00001000
000a462c 000a3d94 02344000 00002000 00001000
000a3d94 000a4834 0230c000 00002000 00001000
000a4834 000a4744 023a6000 00002000 00001000
000a4744 000a46a4 02388000 00002000 00001000
000a46a4 000a45dc 02380000 00002000 00001000
000a45dc 000a40dc 02376000 00002000 00001000
000a40dc 000a4014 02336000 00002000 00001000
000a4014 000a3c54 0232c000 00002000 00001000
000a3c54 000a471c 022d4000 00003000 00002000
000a471c 000a395c 000f4000 00002000 00001000
000a395c 000a3f4c 02364000 00002000 00001000
000a3f4c 000a47bc 022fc000 00002000 00001000
000a47bc 000a421c 02392000 00002000 00001000

ntdll!_DPH_HEAP_BLOCK
+0x000 pNextAlloc : 0x000a3e5c _DPH_HEAP_BLOCK
+0x004 pVirtualBlock : 0x023ce000 ""
+0x008 nVirtualBlockSize : 0x2000
+0x00c nVirtualAccessSize : 0x1000
+0x010 pUserAllocation : 0x023cefe8 "???"
+0x014 nUserRequestedSize : 0x18
+0x018 nUserActualSize : 0x18
+0x01c UserValue : (null)
+0x020 UserFlags : 0
+0×024 StackTrace : 0×023e4efc _RTL_TRACE_BLOCK

상당히 많은 Block 들이 Double Linked List로 연결되어 있는 것을 확인 할 수 있습니다. 실제 가장 디버깅에 많이 사용되는 Stack Trace와 UserAllocation 부분 그리고 _DPH_BLOCK_INFORMATION을 확인해 보도록 하죠.

0:001> dt _RTL_TRACE_BLOCK 0x023e4efc
ntdll!_RTL_TRACE_BLOCK
+0x000 Magic : 0xabcdaaaa
+0x004 Count : 2
+0x008 Size : 0x10
+0x00c UserCount : 1
+0x010 UserSize : 0x18
+0x014 UserContext : 0x000a1000
+0x018 Next : (null)
+0×01c Trace : 0×023e4f1c -> 0×7c97bea7
0:001> dps 0×023e4f1c
023e4f1c 7c97bea7 ntdll!RtlReAllocateHeap+0×1de
023e4f20 7c830998 kernel32!LocalReAlloc+0×1b6
023e4f24 746a13cb MSCTF!cicMemReAlloc+0×13
023e4f28 7469346c MSCTF!CVoidPtrArray::CompactSize+0×1f
023e4f2c 746661b5 MSCTF!CVoidPtrArray::Remove+0×4f
023e4f30 7467c9f7 MSCTF!FreeMarshaledStubOfItem+0xe9
023e4f34 7467cfb1 MSCTF!CLangBarItemMgr::RemoveItem+0xc5
023e4f38 7467d649 MSCTF!CLangBarItemMgr::RemoveItem+0×42
023e4f3c 4b54c950 imekr61!CToolBar::Terminate+0xee
023e4f40 4b54a535 imekr61!CToolBar::`scalar deleting destructor’+0×7a
023e4f44 4b54a9df imekr61!SetIndicator+0×4a
023e4f48 4b54b6bf imekr61!UIPopupMenu+0×5e3
023e4f4c 77cf8734 USER32!InternalCallWinProc+0×28
023e4f50 77cf8816 USER32!UserCallWinProcCheckWow+0×150
023e4f54 77d0927b USER32!SendMessageWorker+0×4a5
023e4f58 77d4b875 USER32!SendMessageToUI+0×52

실제로 이 Block이 할당한 Stack을 확인 할 수 있습니다. 그럼 UserAllocation 부분과 _DPH_BLOCK_INFORMATION을 통해서 Stack Trace를 확인해 보도록 하죠.

0:001> dd 0x023cefe8-0x20
023cefc8 abcdbbbb 000a1000 00000018 00001000
023cefd8 019203b0 01926cdf 023e4f5c dcbabbbb
023cefe8 0234afc8 023a6fc8 0230cfc8 02344fc8
023ceff8 0238afc8 0235efc8 ???????? ????????
023cf008 ???????? ???????? ???????? ????????
023cf018 ???????? ???????? ???????? ????????
023cf028 ???????? ???????? ???????? ????????
023cf038 ???????? ???????? ???????? ????????

0:001> dt _DPH_BLOCK_INFORMATION 0x023cefe8-0x20
ntdll!_DPH_BLOCK_INFORMATION
+0x000 StartStamp : 0xabcdbbbb
+0x004 Heap : 0x000a1000
+0x008 RequestedSize : 0x18
+0x00c ActualSize : 0x1000
+0x010 FreeQueue : _LIST_ENTRY [ 0x19203b0 - 0x1926cdf ]
+0×010 TraceIndex : 0×3b0
+0×018 StackTrace : 0×023e4f5c
+0×01c EndStamp : 0xdcbabbbb

0:001> dps 0×023e4f5c
023e4f5c abcdaaaa
023e4f60 00000001
023e4f64 00000010
023e4f68 00000000
023e4f6c 00000000
023e4f70 00000000
023e4f74 00000000
023e4f78 023e4f7c
023e4f7c 7c99d27f ntdll!RtlDebugReAllocateHeap+0×30
023e4f80 7c97bea7 ntdll!RtlReAllocateHeap+0×1de
023e4f84 7c830998 kernel32!LocalReAlloc+0×1b6
023e4f88 746a13cb MSCTF!cicMemReAlloc+0×13
023e4f8c 7469346c MSCTF!CVoidPtrArray::CompactSize+0×1f
023e4f90 746661b5 MSCTF!CVoidPtrArray::Remove+0×4f
023e4f94 7467c9f7 MSCTF!FreeMarshaledStubOfItem+0xe9
023e4f98 7467cfb1 MSCTF!CLangBarItemMgr::RemoveItem+0xc5
023e4f9c 7467d649 MSCTF!CLangBarItemMgr::RemoveItem+0×42
023e4fa0 4b54c950 imekr61!CToolBar::Terminate+0xee
023e4fa4 4b54a535 imekr61!CToolBar::`scalar deleting destructor’+0×7a
023e4fa8 4b54a9df imekr61!SetIndicator+0×4a
023e4fac 4b54b6bf imekr61!UIPopupMenu+0×5e3
023e4fb0 77cf8734 USER32!InternalCallWinProc+0×28
023e4fb4 77cf8816 USER32!UserCallWinProcCheckWow+0×150
023e4fb8 77d0927b USER32!SendMessageWorker+0×4a5

여기서 특징적인 부분이라하면 _DPH_HEAP_BLOCK에 나타나는 StackTrace의 위치와  _DPH_BLOCK_INFORMATION에 나타나는 StackTrace의 위치가 다르다는 점입니다. 물론 그 내용은 동일 합니다. 좀더 효율적인 디버깅을 위해서 _DPH_BLOCK_INFORMATION과 _DPH_HEAP_BLOCK에 Stack Trace 정보를 따로 저장한것으로 생각됩니다.  Page Heap Enabled 환경의 경우 이러한 정보를 통해서 좀더 효율적인 Memory Debugging이 가능합니다. 예를 들면 Memory Leak 이나 Heap Curruption을 추적 같은 경우죠.

멋지게 한번 활용해 보시길 … Enjoy Debugging..^^

[blogging] HEAP / POOL / PAGED / NONPAGED

http://www.dumpanalysis.org/WDN/Windows-Debugging-Notebook-Sample-Chapter.pdf

 Dmitry Vostokov 의 Blog에 게시된 WDN의 Sample 인데 구조적인 부분을 UML로 표시하니 보기 좋군요.

 업무에 도입해 보고 싶은 생각이 마구 마구 드내요 ..