📄 sidebug.c
字号:
Return Value:
None.
--*/
{
PVOID Node;
while ((Node = Tree->TreeRoot) != NULL) {
SipDeleteElementTree(Tree, Node);
ExFreePool(Node);
}
}
typedef struct _SIS_COUNTING_MALLOC_CLASS_KEY {
POOL_TYPE poolType;
ULONG tag;
PCHAR file;
ULONG line;
} SIS_COUNTING_MALLOC_CLASS_KEY, *PSIS_COUNTING_MALLOC_CLASS_KEY;
typedef struct _SIS_COUNTING_MALLOC_CLASS_ENTRY {
RTL_SPLAY_LINKS;
SIS_COUNTING_MALLOC_CLASS_KEY;
ULONG numberOutstanding;
ULONG bytesOutstanding;
ULONG numberEverAllocated;
LONGLONG bytesEverAllocated;
struct _SIS_COUNTING_MALLOC_ENTRY *list;
struct _SIS_COUNTING_MALLOC_CLASS_ENTRY *prev, *next;
} SIS_COUNTING_MALLOC_CLASS_ENTRY, *PSIS_COUNTING_MALLOC_CLASS_ENTRY;
typedef struct _SIS_COUNTING_MALLOC_KEY {
PVOID p;
} SIS_COUNTING_MALLOC_KEY, *PSIS_COUNTING_MALLOC_KEY;
#define SIS_COUNTING_MALLOC_TRACE_DEPTH 8
typedef struct _SIS_COUNTING_MALLOC_ENTRY {
RTL_SPLAY_LINKS;
SIS_COUNTING_MALLOC_KEY;
PSIS_COUNTING_MALLOC_CLASS_ENTRY classEntry;
ULONG byteCount;
PVOID BackTrace[SIS_COUNTING_MALLOC_TRACE_DEPTH];
struct _SIS_COUNTING_MALLOC_ENTRY **prev, *next;
} SIS_COUNTING_MALLOC_ENTRY, *PSIS_COUNTING_MALLOC_ENTRY;
KSPIN_LOCK CountingMallocLock[1];
BOOLEAN CountingMallocInternalFailure = FALSE;
SIS_COUNTING_MALLOC_CLASS_ENTRY CountingMallocClassListHead[1];
SIS_TREE CountingMallocClassTree[1];
SIS_TREE CountingMallocTree[1];
LONG NTAPI
CountingMallocClassCompareRoutine(
PVOID Key,
PVOID Node)
{
PSIS_COUNTING_MALLOC_CLASS_KEY key = Key;
PSIS_COUNTING_MALLOC_CLASS_ENTRY entry = Node;
if (key->poolType > entry->poolType) return 1;
if (key->poolType < entry->poolType) return -1;
VRRASSERT(key->poolType == entry->poolType);
if (key->tag > entry->tag) return 1;
if (key->tag < entry->tag) return -1;
VRRASSERT(key->tag == entry->tag);
if (key->file > entry->file) return 1;
if (key->file < entry->file) return -1;
VRRASSERT(key->file == entry->file);
if (key->line > entry->line) return 1;
if (key->line < entry->line) return -1;
VRRASSERT(key->line == entry->line);
return 0;
}
LONG NTAPI
CountingMallocCompareRoutine(
PVOID Key,
PVOID Node)
{
PSIS_COUNTING_MALLOC_KEY key = Key;
PSIS_COUNTING_MALLOC_ENTRY entry = Node;
if (key->p < entry->p) return 1;
if (key->p > entry->p) return -1;
VRRASSERT(key->p == entry->p);
return 0;
}
VOID *
CountingExAllocatePoolWithTag(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag,
IN PCHAR File,
IN ULONG Line)
{
PVOID memoryFromExAllocate;
KIRQL OldIrql;
SIS_COUNTING_MALLOC_CLASS_KEY classKey[1];
PSIS_COUNTING_MALLOC_CLASS_ENTRY classEntry;
SIS_COUNTING_MALLOC_KEY key[1];
PSIS_COUNTING_MALLOC_ENTRY entry;
USHORT Frames;
//
// First do the actual malloc.
//
memoryFromExAllocate = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
if (NULL == memoryFromExAllocate) {
//
// We're out of memory. Punt.
//
return NULL;
}
KeAcquireSpinLock(CountingMallocLock, &OldIrql);
//
// See if we already have a class entry for this tag/poolType pair.
//
classKey->tag = Tag;
classKey->poolType = PoolType;
classKey->file = File;
classKey->line = Line;
classEntry = SipLookupElementTree(CountingMallocClassTree, classKey);
if (NULL == classEntry) {
//
// This is the first time we've seen a malloc of this class.
//
classEntry = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(SIS_COUNTING_MALLOC_CLASS_ENTRY), ' siS');
if (NULL == classEntry) {
CountingMallocInternalFailure = TRUE;
KeReleaseSpinLock(CountingMallocLock, OldIrql);
return memoryFromExAllocate;
}
//
// Fill in the new class entry.
//
classEntry->tag = Tag;
classEntry->poolType = PoolType;
classEntry->file = File;
classEntry->line = Line;
classEntry->numberOutstanding = 0;
classEntry->bytesOutstanding = 0;
classEntry->numberEverAllocated = 0;
classEntry->bytesEverAllocated = 0;
classEntry->list = NULL;
//
// Put it in the tree of classes.
//
SipInsertElementTree(CountingMallocClassTree, classEntry, classKey);
//
// And put it in the list of classes.
//
classEntry->prev = CountingMallocClassListHead;
classEntry->next = CountingMallocClassListHead->next;
classEntry->prev->next = classEntry->next->prev = classEntry;
}
//
// Roll up an entry for the pointer.
//
entry = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SIS_COUNTING_MALLOC_ENTRY), ' siS');
if (NULL == entry) {
CountingMallocInternalFailure = TRUE;
KeReleaseSpinLock(CountingMallocLock, OldIrql);
return memoryFromExAllocate;
}
//
// Update the stats in the class.
//
classEntry->numberOutstanding++;
classEntry->bytesOutstanding += NumberOfBytes;
classEntry->numberEverAllocated++;
classEntry->bytesEverAllocated += NumberOfBytes;
//
// Fill in the pointer entry.
//
entry->p = memoryFromExAllocate;
entry->classEntry = classEntry;
entry->byteCount = NumberOfBytes;
Frames = RtlCaptureStackBackTrace(1, SIS_COUNTING_MALLOC_TRACE_DEPTH,
entry->BackTrace, NULL);
for (; Frames < SIS_COUNTING_MALLOC_TRACE_DEPTH; Frames++)
entry->BackTrace[Frames] = NULL;
//
// Stick it in the tree.
//
key->p = memoryFromExAllocate;
SipInsertElementTree(CountingMallocTree, entry, key);
//
// Add it to the class list.
//
entry->next = classEntry->list;
entry->prev = &classEntry->list;
if (classEntry->list != NULL)
classEntry->list->prev = &entry->next;
classEntry->list = entry;
KeReleaseSpinLock(CountingMallocLock, OldIrql);
return memoryFromExAllocate;
}
VOID
CountingExFreePool(
PVOID p)
{
SIS_COUNTING_MALLOC_KEY key[1];
PSIS_COUNTING_MALLOC_ENTRY entry;
KIRQL OldIrql;
key->p = p;
KeAcquireSpinLock(CountingMallocLock, &OldIrql);
entry = SipLookupElementTree(CountingMallocTree, key);
if (NULL == entry) {
//
// We may have failed to allocate the entry because of an
// internal failure in the counting package, or else we're
// freeing memory that was allocated by another system
// component, like the SystemBuffer in an irp.
//
} else {
//
// Update the stats in the class.
//
VRRASSERT(entry->classEntry->numberOutstanding > 0);
entry->classEntry->numberOutstanding--;
VRRASSERT(entry->classEntry->bytesOutstanding >= entry->byteCount);
entry->classEntry->bytesOutstanding -= entry->byteCount;
//
// Remove the entry from the tree.
//
SipDeleteElementTree(CountingMallocTree, entry);
//
// Remove the entry from the class list.
//
*entry->prev = entry->next;
if (entry->next != NULL)
entry->next->prev = entry->prev;
//
// And free it.
//
ExFreePool(entry);
}
KeReleaseSpinLock(CountingMallocLock, OldIrql);
//
// Free the caller's memory.
//
ExFreePool(p);
}
VOID
InitCountingMalloc(void)
{
KeInitializeSpinLock(CountingMallocLock);
CountingMallocClassListHead->next =
CountingMallocClassListHead->prev = CountingMallocClassListHead;
SipInitializeTree(CountingMallocClassTree,
CountingMallocClassCompareRoutine);
SipInitializeTree(CountingMallocTree, CountingMallocCompareRoutine);
}
VOID
UnloadCountingMalloc(void)
{
PSIS_COUNTING_MALLOC_CLASS_ENTRY classEntry;
PSIS_COUNTING_MALLOC_ENTRY entry;
uint i;
int NoLeaks = TRUE;
for (classEntry = CountingMallocClassListHead->next;
classEntry != CountingMallocClassListHead;
classEntry = classEntry->next) {
for (entry = classEntry->list; entry != NULL; entry = entry->next) {
DbgPrint("Leaked alloc %p made at", entry->p);
for (i = 0; i < SIS_COUNTING_MALLOC_TRACE_DEPTH; i++)
DbgPrint(" %p", entry->BackTrace[i]);
DbgPrint("\n");
ExFreePool(entry->p);
NoLeaks = FALSE;
}
}
VRRASSERT(NoLeaks);
SipDeleteTree(CountingMallocTree);
SipDeleteTree(CountingMallocClassTree);
}
VOID
DumpCountingMallocStats(void)
{
PSIS_COUNTING_MALLOC_CLASS_ENTRY classEntry;
ULONG totalAllocated = 0;
ULONG totalEverAllocated = 0;
ULONG totalBytesAllocated = 0;
ULONG totalBytesEverAllocated = 0;
//
// Note that this function does NOT acquire CountingMallocLock,
// so there can be no concurrent allocations/frees happening.
// CountingMallocLock would raise to DPC irql,
// and the filename strings might be pageable.
//
DbgPrint("Tag\tFile\tLine\tPoolType\tCountOutstanding\tBytesOutstanding"
"\tTotalEverAllocated\tTotalBytesAllocated\n");
for (classEntry = CountingMallocClassListHead->next;
classEntry != CountingMallocClassListHead;
classEntry = classEntry->next) {
DbgPrint("%c%c%c%c\t%s\t%d\t%s\t%d\t%d\t%d\t%d\n",
(CHAR)(classEntry->tag),
(CHAR)(classEntry->tag >> 8),
(CHAR)(classEntry->tag >> 16),
(CHAR)(classEntry->tag >> 24),
classEntry->file,
classEntry->line,
(classEntry->poolType == NonPagedPool) ? "NonPagedPool"
: ((classEntry->poolType == PagedPool) ? "PagedPool"
: "Other"),
classEntry->numberOutstanding,
classEntry->bytesOutstanding,
classEntry->numberEverAllocated,
(ULONG)classEntry->bytesEverAllocated);
totalAllocated += classEntry->numberOutstanding;
totalEverAllocated += classEntry->numberEverAllocated;
totalBytesAllocated += classEntry->bytesOutstanding;
totalBytesEverAllocated += (ULONG)classEntry->bytesEverAllocated;
}
DbgPrint("%d objects, %d bytes currently allocated. "
"%d objects, %d bytes ever allocated.\n",
totalAllocated, totalBytesAllocated, totalEverAllocated,
totalBytesEverAllocated);
}
#endif // COUNTING_MALLOC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -