ReactOS  0.4.15-dev-3324-gda4e15f
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 
16 typedef struct SHIM_ALLOC_ENTRY
17 {
18  PVOID Address;
19  SIZE_T Size;
20  int Line;
21  const char* File;
22  PVOID Next;
23  PVOID Prev;
24 } SHIM_ALLOC_ENTRY, *PSHIM_ALLOC_ENTRY;
25 
26 static RTL_CRITICAL_SECTION g_SdbpAllocationLock;
27 static RTL_AVL_TABLE g_SdbpAllocationTable;
28 static 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 
43 static PVOID NTAPI ShimAllocAllocateRoutine(_In_ PRTL_AVL_TABLE Table, _In_ CLONG ByteSize)
44 {
45  return RtlAllocateHeap(g_PrivAllocationHeap, HEAP_ZERO_MEMORY, ByteSize);
46 }
47 
48 static VOID NTAPI ShimAllocFreeRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
49 {
50  RtlFreeHeap(g_PrivAllocationHeap, 0, Buffer);
51 }
52 
53 void 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 
67 void 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 
93 static 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 
100 void 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 
135 void SdbpDebugHeapInit(HANDLE privateHeapPtr)
136 {
137  g_PrivAllocationHeap = privateHeapPtr;
138 
139  RtlInitializeCriticalSection(&g_SdbpAllocationLock);
140  RtlInitializeGenericTableAvl(&g_SdbpAllocationTable, ShimAllocCompareRoutine,
141  ShimAllocAllocateRoutine, ShimAllocFreeRoutine, NULL);
142 }
143 
144 void 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
ASMGENDATA Table[]
Definition: genincdata.c:61
#define DbgPrint
Definition: hal.h:12
struct _Entry Entry
Definition: kefuncs.h:627
#define TRUE
Definition: types.h:120
WCHAR Second[]
Definition: FormatMessage.c:12
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static void Lookup(RTF_Info *, char *)
Definition: reader.c:2228
WCHAR First[]
Definition: FormatMessage.c:11
ULONG CLONG
Definition: umtypes.h:126
struct Line Line
Definition: wdfdevice.h:4081
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
static WCHAR Address[46]
Definition: ping.c:68
#define _In_
Definition: ms_sal.h:308
Definition: parser.c:48
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
GLsizeiptr size
Definition: glext.h:5919
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:383
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ BOOLEAN Restart)
ULONG NumberGenericTableElements
Definition: rtltypes.h:425
const char file[]
Definition: icontest.c:11
GLuint address
Definition: glext.h:9393
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:383
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
IN PCTCH line
Definition: pager.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define NULL
Definition: types.h:112
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID _In_ LONG _In_z_ PCHAR File
Definition: wdfdevice.h:4061
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:393
base of all file and directory entries
Definition: entries.h:82
Definition: fci.c:126