ReactOS 0.4.15-dev-7918-g2a2556c
fxtagtracker.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxTagTracker.cpp
8
9Abstract:
10
11Author:
12
13Environment:
14
15 Both kernel and user mode
16
17Revision History:
18
19
20
21
22
23
24
25--*/
26
27#include "fxobjectpch.hpp"
28
29extern "C" {
30
31#if defined(EVENT_TRACING)
32#include "fxtagtracker.tmh"
33#endif
34
35#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
36//
37// rtlsupportapi.h causes problems in AMD64 and ARM builds.
38//
39extern
40_Success_(return != 0)
44 _In_ ULONG FramesToSkip,
48 );
49#endif
50
51}
52
54/*++
55
56Routine Description:
57 Destructor for this object. Will verify that the object is being freed
58 without any outstanding tags.
59
60Arguments:
61 None
62
63Return Value:
64 None
65
66 --*/
67{
68 KIRQL irql;
70
73
75
76 pExtension = GetDriverGlobals()->DebugExtension;
77
78 //
79 // Remove this tracker from the list of allocated trackers
80 //
81 pExtension->AllocatedTagTrackersLock.Acquire(&irql);
83 pExtension->AllocatedTagTrackersLock.Release(irql);
84 } else {
86 }
87
88 //
89 // Delete any outstanding tracking blocks.
90 //
91 m_SpinLock.Acquire(&irql);
92
94 m_Next = NULL;
95
96 while (current != NULL) {
97 next = current->Next;
98 delete current;
99 current = next;
100 }
101
102 m_SpinLock.Release(irql);
103}
104
105VOID
107 _Inout_ FxTagTrackingStackFrames** StackFrames,
108 _In_ USHORT NumFrames,
109 _In_reads_(NumFrames) PVOID* Frames
110 )
111{
113 FxTagTrackingStackFrames* stackFrames;
114
115 //
116 // FxTagHistory structs are stored in a circular buffer and reused,
117 // so we also reuse the FxTagTrackingStackFrames that each allocates.
118 //
119 stackFrames = *StackFrames;
120 if (stackFrames == NULL) {
123 if (stackFrames == NULL) {
124 return;
125 }
126
127 *StackFrames = stackFrames;
128 }
129
130 stackFrames->NumFrames = NumFrames;
131
132 for (int i = 0; i < NumFrames; i++) {
133 stackFrames->Frames[i] = (ULONG64)Frames[i];
134 }
135}
136
137VOID
139 __in PVOID Tag,
140 __in LONG Line,
142 __in FxTagRefType RefType,
143 __in ULONG RefCount
144 )
145/*++
146
147Routine Description:
148 Update tag history and either create or free an existing tag tracking block.
149
150Arguments:
151
152 Tag - Unique tag associated with the reference
153
154 Line - Line where the reference is referenced/released
155
156 File - Buffer containing the file name
157
158 RefType - Enumerated type ( AddRef or Release )
159
160 RefCount - Approximate current reference count (see FxTagHistory.RefCount comment)
161
162Return Value:
163
164 VOID
165
166--*/
167{
169 FxTagHistory* pTagHistory;
170 FxTagTrackingBlock* pBlock;
171 LONG pos;
172 KIRQL irql;
173 USHORT numFrames = 0;
174 PVOID frames[FRAMES_TO_CAPTURE];
175
177
180
181 //
182 // Prefast reports that m_CurRefHistory can be negative which can lead to
183 // underflow. But we know that m_CurRefHistory would never be negative.
184 // Hence we assert for the condition below and assume that it would be true.
185 //
187
188 pTagHistory = m_TagHistory + pos;
189
190 pTagHistory->RefType = RefType;
191 pTagHistory->RefCount = RefCount;
192 pTagHistory->Line = Line;
193 pTagHistory->Tag = Tag;
194 pTagHistory->File = File;
195
196 if (m_CaptureStack) {
199 frames,
200 NULL);
201 if (numFrames > 0) {
202 CopyStackFrames(&pTagHistory->StackFrames, numFrames, frames);
203 }
204 }
205
206 //
207 // We use the perf counter here and the tick count in the tracking block.
208 // Use the tick count here as well until we decide that correlating the
209 // perf counter to system time is not important.
210 //
211 // pTagHistory->Time = KeQueryPerformanceCounter(NULL);
212 Mx::MxQueryTickCount(&pTagHistory->Time);
213
214 if (RefType == TagAddRef) {
215
216 //
217 // Try to allocate some memory for the new block. If unsuccessful,
218 // fallback to a failed count increment.
219 //
221
222 if (pBlock == NULL) {
224 }
225 else {
226 m_SpinLock.Acquire(&irql);
227 pBlock->Next = m_Next;
228 m_Next = pBlock;
229 m_SpinLock.Release(irql);
230
231 if (m_CaptureStack && numFrames > 0) {
232 CopyStackFrames(&pBlock->StackFrames, numFrames, frames);
233 }
234 }
235 }
236 else {
237 FxTagTrackingBlock **prev;
238
239 //
240 // Walk the list of current blocks and attempt to find the tag being
241 // released. If not found, decrement the failed count. If no failed
242 // tags exists, ASSERT immediately.
243 //
244
245 m_SpinLock.Acquire(&irql);
246 prev = &m_Next;
247 pBlock = *prev;
248
249 while (pBlock != NULL) {
250 if (pBlock->Tag == Tag) {
251 *prev = pBlock->Next;
252 break;
253 }
254
255 prev = &pBlock->Next;
256 pBlock = pBlock->Next;
257 }
258
259 m_SpinLock.Release(irql);
260
261 if (pBlock == NULL) {
262 //
263 // Check to see if we have any credits in our Low Memory Count.
264 // In this fassion we can tell if we have acquired any locks without
265 // the memory for adding tracking blocks.
266 //
268 //
269 // We have just released a lock that neither had a corresponding
270 // tracking block, nor a credit in LowMemoryCount.
271 //
273
276 "releasing %s %p on object %p that was not acquired, !wdftagtracker %p",
277 m_TrackerType == FxTagTrackerTypePower ? "power tag" : "tag",
278 Tag,
280 this);
281
283 }
284 }
285 else {
286 delete pBlock;
287 pBlock = NULL;
288 }
289 }
290}
291
292VOID
294 VOID
295 )
296/*++
297
298Routine Description:
299 Iterates over any existing tags, dumping any existing tags to the debugger.
300 Will assert if there any outstanding tags (assumes that the caller wants
301 no current tags).
302
303Arguments:
304 None
305
306Return Value:
307 None
308
309 --*/
310{
313 LONG abandoned;
314 KIRQL irql;
315 BOOLEAN committed;
316
318
319 committed = m_OwningObject->IsCommitted();
320
321 //
322 // If the object was not committed, then it was an FxObject derived
323 // class that was *embedded* as a field in another structure or class.
324 // As such, we are allowing one outstanding reference at this time. We will
325 // catch > 1 outstanding references below in the while loop.
326 //
327 if (committed) {
328 if (m_Next != NULL || m_FailedCount != 0) {
330 "Dropped references on a tag tracker, "
331 "show references with: !wdftagtracker %p", this);
332 //
333 // If this ASSERT fails, look in the history .. you'll
334 // likely find that you released more references than you had
335 //
336 ASSERT(m_Next == NULL && m_FailedCount == 0);
337 }
338 }
339
340 m_SpinLock.Acquire(&irql);
341
342 current = m_Next;
343 abandoned = 0;
344
345 while (current != NULL) {
346 next = current->Next;
347
348 if (committed) {
350 "Abandonded ref on object %p tag %p (%s @ %d)",
351 m_OwningObject, current->Tag, current->File, current->Line);
352 abandoned++;
353 }
354
355 if (committed == FALSE) {
356 //
357 // The next time we encounter an abandoned reference, we will complain
358 // about it...we have used up our allowance of one leaked reference
359 // because the object is an embedded object.
360 //
361 // NOTE: we might be eating the real outstanding reference here
362 // and not tracing it and then tracing the initial creation
363 // reference as the leaked reference which will be confusing.
364 // This is b/c there is no way to distinguish what is the
365 // tracking block used to track the creatio of the object.
366 //
367 committed = TRUE;
368
370 "Possibly Abandonded ref on object %p tag %p (%s @ %d). "
371 "Is benign unless there are other outstanding leaked references.",
372 m_OwningObject, current->Tag, current->File, current->Line);
373 }
374
375 current = next;
376 }
377
378 m_SpinLock.Release(irql);
379
380 ASSERTMSG("Abandoned tags on ref\n", abandoned == 0);
381}
382
383
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
return
Definition: dirsup.c:529
Definition: File.h:16
BOOLEAN IsCommitted(VOID)
Definition: fxobject.hpp:1087
VOID CheckForAbandondedTags(VOID)
VOID CopyStackFrames(_Inout_ FxTagTrackingStackFrames **StackFrames, _In_ USHORT NumFrames, _In_reads_(NumFrames) PVOID *Frames)
FxTagTrackerType m_TrackerType
FxObject * m_OwningObject
BOOLEAN m_CaptureStack
FxTagHistory m_TagHistory[TAG_HISTORY_DEPTH]
VOID UpdateTagHistory(__in PVOID Tag, __in LONG Line, __in_opt PSTR File, __in FxTagRefType RefType, __in ULONG RefCount)
LIST_ENTRY m_TrackerEntry
FxTagTrackingBlock * m_Next
static __inline VOID MxQueryTickCount(__out PLARGE_INTEGER TickCount)
Definition: mxgeneralkm.h:116
#define __in
Definition: dbghelp.h:35
#define __in_opt
Definition: dbghelp.h:38
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
KIRQL irql
Definition: wave.h:1
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
UCHAR KIRQL
Definition: env_spec_w32.h:591
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
FxVerifierDbgBreakPoint(pFxDriverGlobals)
#define FX_ASSERT_AND_ASSUME_FOR_PREFAST(b)
Definition: fxmacros.hpp:284
_In_ ULONG FramesToCapture
_In_ ULONG _Out_opt_ PULONG BackTraceHash
@ FxTagTrackerTypePower
@ FxTagTrackerTypeHandle
FxTagRefType
@ TagAddRef
#define FRAMES_TO_CAPTURE
#define TAG_HISTORY_DEPTH
#define FRAMES_TO_SKIP
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
#define ASSERT(a)
Definition: mode.c:44
struct task_struct * current
Definition: linux.c:32
unsigned __int64 ULONG64
Definition: imports.h:198
#define _Out_opt_
Definition: ms_sal.h:346
#define _Success_(expr)
Definition: ms_sal.h:259
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define _Out_writes_to_(size, count)
Definition: ms_sal.h:355
#define _In_reads_(size)
Definition: ms_sal.h:319
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static unsigned __int64 next
Definition: rand_nt.c:6
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxTagTrackingStackFrames * StackFrames
LARGE_INTEGER Time
FxTagRefType RefType
FxTagTrackingStackFrames * StackFrames
struct FxTagTrackingBlock * Next
ULONG64 Frames[FRAMES_TO_CAPTURE]
Definition: ncftp.h:79
FxDriverGlobalsDebugExtension * DebugExtension
Definition: fxglobals.h:376
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
uint32_t ULONG
Definition: typedefs.h:59
#define STDCALL
Definition: wdf.h:45
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
NTSYSAPI USHORT NTAPI RtlCaptureStackBackTrace(_In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, _Out_writes_to_(FramesToCapture, return) PVOID *BackTrace, _Out_opt_ PULONG BackTraceHash)