问题描述
我如何使用GFlags设置并从中受益通过DLL启用堆标记?
How do I use and benefit from the GFlags setting Enable heap tagging by DLL?
我知道如何激活进程的设置,但是在WinDbg中!heap -t
的输出中找不到有用的信息.我期待这样的输出:
I know how to activate the setting for a process, but I did not find useful information in the output of !heap -t
in WinDbg. I was expecting some output like this:
0:000> !heap -t
Index Address Allocated by
1: 005c0000 MyDll.dll
2: 006b0000 AnotherDll.dll
,这样我就可以确定哪个DLL是由哪个DLL创建的,然后例如确定内存泄漏的来源.
so that I can identify which heap was created by which DLL and then e.g. identify the source of a memory leak.
这是对通过DLL进行堆标记"一词的误解吗?还是我需要一些其他命令才能获得所需的结果?
Is this a misunderstanding of the term "heap tagging by DLL" or do I need some more commands to get to the desired result?
到目前为止我的研究:
- 我在Google上搜索了有关此主题的教程,但找不到详细的说明
- 我阅读了WinDbg的
.hh !heap
,但是这里也没有详细解释.标记仅在!heap -b
中使用
- I googled for a tutorial on this topic, but I couldn't find a detailed description
- I read WinDbg's
.hh !heap
but it's not explained there in detail as well. Tag is only used in!heap -b
推荐答案
又是一个很晚的答案
首先在代码中受益于HeapTagging you need to create a tag
.
据我所知(最多xp-sp3),有no Documented APIS to Create a tag
to benefit from HeapTagging you need to create a tag
first in your code.
as far as i know (that is upto xp-sp3) there were no Documented APIS to Create a tag
(此后我一直没有处理过堆,因此我不知道操作系统中的最新api> vista已对堆管理器进行了重写,因此我在下面发布的许多^^^features^^^
可能已得到纠正或改善,或已删除了错误)
(I havent mucked with heap since then so i am not aware of latest apis in os > vista Rewrites were done to heap manager so probably many of the ^^^features^^^
that i post below might have been corrected or bettered or bugs removed )
在xp-sp3中,您可以使用未公开的RtlCreateTagHeap
为Process Heap
或Private Heap
in xp-sp3 you can use undocumented RtlCreateTagHeap
to create a new tag to either Process Heap
or Private Heap
,在创建tha标签后,您需要设置全局标志8000 | 800
and after you create tha tag you need to set the global flag 8000 | 800
htg - Enable heap tagging
htd - Enable heap tagging by DLL
和theoratically all allocs and frees must get tagged
.
但在xp-sp3中practically only allocations > 512 kB gets tagged
具有这些基本步骤
but practically only allocations > 512 kB gets tagged
in xp-sp3 with these basic steps
它要么是错误,要么是将标记限制为分配并释放超过512 kB的功能HeapAlloc goes through ZwAllocateVirtualMemory
在32位进程中refer HeapCreate / HeapAlloc Documentation in msdn
it either is a bug or a feature that limits tagging to allocations and frees > 512 kBHeapAlloc goes through ZwAllocateVirtualMemory
in case of Allocations > 512 kB in 32 bit process refer HeapCreate / HeapAlloc Documentation in msdn
,并且作为debuging aid
,您可以在the fly to enable tagging
上的patch ntdll.dll
表示all Allocations and frees
.
and as a debuging aid
you can patch ntdll.dll
on the fly to enable tagging
for all Allocations and frees
.
下面是一个示例代码,演示了标记以及如何在windbg中查看所有标记
below is a sample code that demonstrates the tagging and how to view it all in windbg
使用cl /Zi /analyze /W4 <src> /link /RELEASE
使用windbg执行应用程序并使用!heap * -t
命令观看标记
use windbg to execute the app and watch tagging with !heap * -t
command
#include <windows.h>
#include <stdio.h>
//heaptags are kinda broken or they are intentionally
//given only to allocations > 512 kb // allocation > 512 kb
//go through VirtualAlloc Route for Heap created with maxsize
//set to 0 uncomment ALLOCSIZE 0xfdfd2 and recompile to watch
// tagging increase by 100% with ALLOCSIZE 0xfdfd1 only 50 allocs
// and frees that are > 512 kB will be tagged these magic numbers
// are related to comment in HeapCreate Documentation that state
// slightly less than 512 kB will be allocated for 32 bit process
// tagging can be dramatically increased by patching ntdll when
// stopped on system breakpoint patch 7c94b8a4 (xpsp3 ntdll.dll)
// use the below command in windbg for finding the offset of pattern
// command must be in single line no line breaks
// .foreach /pS 4 /ps 4 ( place { !grep -i -e call -c
// "# call*RtlpUpdateTagEntry 7c900000 l?20000" } ) { ub place }
// the instruction we are searching to patch is
//7c94b8a1 81e3ff0fffff and ebx,0FFFF0FFFh
// patch 0f to 00 at system breakpoint with eb 7c94b8a1+3 00
#define BUFFERSIZE 100
#define ALLOCSIZE 0xfdfd1
//#define ALLOCSIZE 0xfdfd2
typedef int ( __stdcall *g_RtlCreateTagHeap) (
HANDLE hHeap ,
void * unknown,
wchar_t * BaseString,
wchar_t * TagString
);
void HeapTagwithHeapAllocPrivate()
{
PCHAR pch[BUFFERSIZE] = {};
HANDLE hHeap = 0;
ULONG tag1 = 0;
ULONG tag2 = 0;
ULONG tag3 = 0;
ULONG tag4 = 0;
ULONG tag5 = 0;
g_RtlCreateTagHeap RtlCreateTagHeap = 0;
HMODULE hMod = LoadLibrary("ntdll.dll");
if(hMod)
{
RtlCreateTagHeap = (g_RtlCreateTagHeap)
GetProcAddress( hMod,"RtlCreateTagHeap");
}
if (hHeap == 0)
{
hHeap = HeapCreate(0,0,0);
if (RtlCreateTagHeap != NULL)
{
tag1 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag1");
tag2 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag2");
tag3 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag3");
tag4 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag4");
}
}
HANDLE DefHeap = GetProcessHeap();
if ( (RtlCreateTagHeap != NULL) && (DefHeap != NULL ))
{
tag5 = RtlCreateTagHeap (DefHeap,0,L"HeapTag!",L"MyTag5");
for ( int i = 0; i < BUFFERSIZE ; i++ )
{
pch[i]= (PCHAR) HeapAlloc( DefHeap,HEAP_ZERO_MEMORY| tag5, 1 );
HeapFree(DefHeap,NULL,pch[i]);
}
}
if(hHeap)
{
for ( int i = 0; i < BUFFERSIZE ; i++ )
{
pch[i]= (PCHAR) HeapAlloc( hHeap,HEAP_ZERO_MEMORY| tag1, 1 );
//lets leak all allocs patch ntdll to see the tagging details
//HeapFree(hHeap,NULL,pch[i]);
}
for ( int i = 0; i < BUFFERSIZE ; i++ )
{
pch[i]= (PCHAR) HeapAlloc( hHeap,HEAP_ZERO_MEMORY| tag2, 100 );
// lets leak 40% allocs patch ntdll to see the tagging details
if(i >= 40)
HeapFree(hHeap,NULL,pch[i]);
}
// slightly less than 512 kb no tagging
for ( int i = 0; i < BUFFERSIZE / 2 ; i++ )
{
pch[i]= (PCHAR) HeapAlloc(
hHeap,HEAP_ZERO_MEMORY| tag3, ALLOCSIZE / 2 );
}
// > 512 kb default tagging
for ( int i = BUFFERSIZE / 2; i < BUFFERSIZE ; i++ )
{
pch[i]= (PCHAR) HeapAlloc(
hHeap,HEAP_ZERO_MEMORY | tag4 ,ALLOCSIZE );
}
for (int i =0 ; i < BUFFERSIZE ; i++)
{
HeapFree(hHeap,NULL,pch[i]);
}
}
}
void _cdecl main()
{
HeapTagwithHeapAllocPrivate();
}
要与windbg一起运行的编译后的exe,如下所示
the compiled exe to be run with windbg as below
默认执行和检查
**只有50个标签可见,它们都是> 512 kB分配
DEFAULT execution and inspection
**only 50 tags will be visible all of them are > 512 kB Allocations
cdb -c"g;!heap * -t; q" newheaptag.exe | grep标签**
heaptag:\>cdb -c "g;!heap * -t;q" newheaptag.exe | grep Tag
Tag Name Allocs Frees Diff Allocated
Tag Name Allocs Frees Diff Allocated
Tag Name Allocs Frees Diff Allocated
0004: HeapTag!MyTag4 50 50 0 0
在系统断点上修补ntdll应该使所有标记可见
eb =写字节在带有标签的退出检查堆上修补并运行exe cdb -c"eb 7c94b8a1 + 3 00; g;!heap * -t; q" newheaptag.exe | grep标记
heaptag:\>cdb -c "eb 7c94b8a1+3 00;g;!heap * -t;q" newheaptag.exe | grep Tag
Tag Name Allocs Frees Diff Allocated
0012: HeapTag!MyTag5 100 100 0 0 <-our tag in process heap
Tag Name Allocs Frees Diff Allocated
Tag Name Allocs Frees Diff Allocated
0001: HeapTag!MyTag1 100 0 100 3200 <--- leak all
0002: HeapTag!MyTag2 100 60 40 5120 <--- leak 40 %
0003: HeapTag!MyTag3 50 50 0 0 <--- clean < 512 kB
0004: HeapTag!MyTag4 50 50 0 0 <----clean > 512 kB
这篇关于如何从DLL的堆标记中受益?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!