2014-04-24 13 views
5

Come utilizzare e trarre vantaggio dall'impostazione GFlags Enable heap tagging by DLL?Come trarre vantaggio dalla codifica dell'heap dalla DLL?

So come attivare l'impostazione per un processo, ma non ho trovato informazioni utili nell'output di !heap -t in WinDbg. Mi aspettavo un po 'di output come questo:

0:000> !heap -t 
Index Address Allocated by 
1:  005c0000 MyDll.dll 
2:  006b0000 AnotherDll.dll 

in modo che possa identificare quale mucchio è stato creato con la quale DLL e poi per esempio identificare la fonte di una perdita di memoria.

Si tratta di un fraintendimento del termine "tagging heap da DLL" o sono necessari altri comandi per ottenere il risultato desiderato?

La mia ricerca finora:

  • Ho cercato su google per un tutorial su questo argomento, ma non riuscivo a trovare una descrizione dettagliata
  • ho letto WinDbg di .hh !heap ma non è lì spiegato in dettaglio come bene. Tag viene utilizzato solo in !heap -b

risposta

5

ancora una risposta molto tardi

di beneficiare di HeapTagging you need to create a tag prima nel codice.
per quanto ne so (cioè fino a xp-sp3) c'erano no Documented APIS to Create a tag

(io ho mai muck con il mucchio da allora in modo che io non sono a conoscenza di tutte le API in os> riscrive di Vista sono state fatte al gestore di heap quindi probabilmente molti dei ^^^features^^^ che i post di seguito potrebbero essere state corrette o migliorato o bug rimosso)

in XP-SP3 è possibile utilizzare senza documenti RtlCreateTagHeap per creare un nuovo tag a uno Process Heap o Private Heap

e dopo aver creato tha tag è necessario impostare la bandiera globale 8000 | 800

htg - Enable heap tagging 
htd - Enable heap tagging by DLL 

e theoratically all allocs and frees must get tagged.

ma practically only allocations > 512 kB gets tagged in XP-SP3 con questi passaggi fondamentali

esso sia un bug o di una caratteristica che limiti la codifica ad accantonamenti e libera> 512 kB
HeapAlloc goes through ZwAllocateVirtualMemory in caso di allocazioni> 512 kB nel processo a 32 bit refer HeapCreate/HeapAlloc Documentation in msdn

e come si può debuging aidpatch ntdll.dll su the fly to enable tagging per all Allocations and frees.

seguito è riportato un codice di esempio che illustra il tagging e come visualizzare il tutto in WinDbg

compilazione usando cl /Zi /analyze /W4 <src> /link /RELEASE

uso WinDbg per eseguire l'applicazione e guardare tagging con !heap * -t comando

#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(); 
} 

l'exe compilato da eseguire con windbg come sotto

di esecuzione predefinito ed ispezione
** a soli 50 tag saranno visibili tutti sono> 512 kB allocazioni

CDB -c "g; mucchio * t;! Q" newheaptag.exe | grep Tag **

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 

patch ntdll sul punto di interruzione del sistema dovrebbe rendere visibili tutti i tag

eb = scrittura byte di patch ed eseguire l'exe in uscita ispezionare cumuli con tag cdb -c "eb 7c94b8a1 + 3 00; g;! heap * -t; q" newheaptag.exe | grep Tag

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 
+0

E 'ok per attendere un tempo più lungo per le domande più difficili :-) Vado avanti e provare (Windows 7). Il concetto in sé non sembra così utile, perché qualcuno ha bisogno di pensare prima a taggare gli heap. Di solito sto pensando all'heap tagging solo nel caso in cui abbia già un problema. –

+0

il concetto è silenzioso ti rendi abituato a codificare robusto :) nel kernel sei costretto a farlo di default ..... ExAllocatePool è deprecato ti consigliamo di usare ExAllocatePoolWithTag e così tagghi in anticipo quale utilità helper usare a zero in quanto è tutto nel kernel è razionalizzato in modalità utente non è snellito eppure se lo provi su qualsiasi sistema operativo> xp upto win 8.1 a partire dalla data post back i risultati – blabb

Problemi correlati