ReactOS 0.4.15-dev-7924-g5949c20
dbgheap.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Application compatibility module
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: SDB Debug heap functionality
5 * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#define WIN32_NO_STATUS
9#include "ntndk.h"
10
11
12#if SDBAPI_DEBUG_ALLOC
13
14#define TRACE_ALL_FREE_CALLS 1
15
16typedef struct SHIM_ALLOC_ENTRY
17{
20 int Line;
21 const char* File;
22 PVOID Next;
23 PVOID Prev;
24} SHIM_ALLOC_ENTRY, *PSHIM_ALLOC_ENTRY;
25
26static RTL_CRITICAL_SECTION g_SdbpAllocationLock;
27static RTL_AVL_TABLE g_SdbpAllocationTable;
28static HANDLE g_PrivAllocationHeap;
29
32{
33 PVOID First = ((PSHIM_ALLOC_ENTRY)FirstStruct)->Address;
34 PVOID Second = ((PSHIM_ALLOC_ENTRY)SecondStruct)->Address;
35
36 if (First < Second)
37 return GenericLessThan;
38 else if (First == Second)
39 return GenericEqual;
40 return GenericGreaterThan;
41}
42
43static PVOID NTAPI ShimAllocAllocateRoutine(_In_ PRTL_AVL_TABLE Table, _In_ CLONG ByteSize)
44{
45 return RtlAllocateHeap(g_PrivAllocationHeap, HEAP_ZERO_MEMORY, ByteSize);
46}
47
48static VOID NTAPI ShimAllocFreeRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
49{
50 RtlFreeHeap(g_PrivAllocationHeap, 0, Buffer);
51}
52
53void SdbpInsertAllocation(PVOID address, SIZE_T size, int line, const char* file)
54{
55 SHIM_ALLOC_ENTRY Entry = {0};
56
57 Entry.Address = address;
58 Entry.Size = size;
59 Entry.Line = line;
60 Entry.File = file;
61
62 RtlEnterCriticalSection(&g_SdbpAllocationLock);
63 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Entry, sizeof(Entry), NULL);
64 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
65}
66
67void SdbpUpdateAllocation(PVOID address, PVOID newaddress, SIZE_T size, int line, const char* file)
68{
69 SHIM_ALLOC_ENTRY Lookup = {0};
70 PSHIM_ALLOC_ENTRY Entry;
71 Lookup.Address = address;
72
73 RtlEnterCriticalSection(&g_SdbpAllocationLock);
74 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
75
76 if (address == newaddress)
77 {
78 Entry->Size = size;
79 }
80 else
81 {
82 Lookup.Address = newaddress;
83 Lookup.Size = size;
84 Lookup.Line = line;
85 Lookup.File = file;
86 Lookup.Prev = address;
87 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup, sizeof(Lookup), NULL);
88 Entry->Next = newaddress;
89 }
90 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
91}
92
93static void SdbpPrintSingleAllocation(PSHIM_ALLOC_ENTRY Entry)
94{
95 DbgPrint(" > %s(%d): %s%sAlloc( %d ) ==> %p\r\n", Entry->File, Entry->Line,
96 Entry->Next ? "Invalidated " : "", Entry->Prev ? "Re" : "", Entry->Size, Entry->Address);
97
98}
99
100void SdbpRemoveAllocation(PVOID address, int line, const char* file)
101{
102 SHIM_ALLOC_ENTRY Lookup = {0};
103 PSHIM_ALLOC_ENTRY Entry;
104
105#if TRACE_ALL_FREE_CALLS
106 DbgPrint("\r\n===============\r\n%s(%d): SdbpFree called, tracing alloc:\r\n", file, line);
107#endif
108
109 Lookup.Address = address;
110 RtlEnterCriticalSection(&g_SdbpAllocationLock);
111 while (Lookup.Address)
112 {
113 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
114 if (Entry)
115 {
116 Lookup = *Entry;
117 RtlDeleteElementGenericTableAvl(&g_SdbpAllocationTable, Entry);
118
119#if TRACE_ALL_FREE_CALLS
120 SdbpPrintSingleAllocation(&Lookup);
121#endif
122 Lookup.Address = Lookup.Prev;
123 }
124 else
125 {
126 Lookup.Address = NULL;
127 }
128 }
129 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
130#if TRACE_ALL_FREE_CALLS
131 DbgPrint("===============\r\n");
132#endif
133}
134
135void SdbpDebugHeapInit(HANDLE privateHeapPtr)
136{
137 g_PrivAllocationHeap = privateHeapPtr;
138
139 RtlInitializeCriticalSection(&g_SdbpAllocationLock);
140 RtlInitializeGenericTableAvl(&g_SdbpAllocationTable, ShimAllocCompareRoutine,
141 ShimAllocAllocateRoutine, ShimAllocFreeRoutine, NULL);
142}
143
144void SdbpDebugHeapDeinit(void)
145{
146 if (g_SdbpAllocationTable.NumberGenericTableElements != 0)
147 {
148 PSHIM_ALLOC_ENTRY Entry;
149
150 DbgPrint("\r\n===============\r\n===============\r\nSdbpHeapDeinit: Dumping leaks\r\n");
151 RtlEnterCriticalSection(&g_SdbpAllocationLock);
152 Entry = RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable, TRUE);
153
154 while (Entry)
155 {
156 SdbpPrintSingleAllocation(Entry);
157 Entry = RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable, FALSE);
158 }
159 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
160 DbgPrint("===============\r\n===============\r\n");
161 }
162 /*__debugbreak();*/
163 /*RtlDeleteCriticalSection(&g_SdbpAllocationLock);*/
164}
165
166#endif
WCHAR Second[]
Definition: FormatMessage.c:12
WCHAR First[]
Definition: FormatMessage.c:11
VOID NTAPI RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_AVL_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: avltable.c:26
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
Definition: bufpool.h:45
Definition: File.h:16
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static void Lookup(RTF_Info *, char *)
Definition: reader.c:2228
ASMGENDATA Table[]
Definition: genincdata.c:61
GLsizeiptr size
Definition: glext.h:5919
GLuint address
Definition: glext.h:9393
#define DbgPrint
Definition: hal.h:12
#define _In_
Definition: ms_sal.h:308
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
static WCHAR Address[46]
Definition: ping.c:68
base of all file and directory entries
Definition: entries.h:83
Definition: ncftp.h:79
ULONG NumberGenericTableElements
Definition: rtltypes.h:431
Definition: fci.c:127
Definition: parser.c:49
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG CLONG
Definition: umtypes.h:126
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ BOOLEAN Restart)
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:390
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:399
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:389
@ GenericLessThan
Definition: rtltypes.h:376
@ GenericEqual
Definition: rtltypes.h:378
@ GenericGreaterThan
Definition: rtltypes.h:377
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS