]> git.lyx.org Git - lyx.git/blob - development/Win32/vld/src/vldint.h
add leak tool for msvc 'Visual Leak Detection' 1.9f: original files
[lyx.git] / development / Win32 / vld / src / vldint.h
1 ////////////////////////////////////////////////////////////////////////////////
2 //  $Id: vldint.h,v 1.45 2006/11/18 05:17:09 dmouldin Exp $
3 //
4 //  Visual Leak Detector - VisualLeakDetector Class Definition
5 //  Copyright (c) 2005-2006 Dan Moulding
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2.1 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 //
21 //  See COPYING.txt for the full terms of the GNU Lesser General Public License.
22 //
23 ////////////////////////////////////////////////////////////////////////////////
24
25 #pragma once
26
27 #ifndef VLDBUILD
28 #error \
29 "This header should only be included by Visual Leak Detector when building it from source. \
30 Applications should never include this header."
31 #endif
32
33 #include <cstdio>
34 #include <windows.h>
35 #include "callstack.h" // Provides a custom class for handling call stacks.
36 #include "map.h"       // Provides a custom STL-like map template.
37 #include "ntapi.h"     // Provides access to NT APIs.
38 #include "set.h"       // Provides a custom STL-like set template.
39 #include "utility.h"   // Provides miscellaneous utility functions.
40
41 #define MAXMODULELISTLENGTH 512     // Maximum module list length, in characters.
42 #define SELFTESTTEXTA       "Memory Leak Self-Test"
43 #define SELFTESTTEXTW       L"Memory Leak Self-Test"
44 #define VLDREGKEYPRODUCT    L"Software\\Visual Leak Detector"
45 #define VLDVERSION          L"1.9f"
46
47 // The Visual Leak Detector APIs.
48 extern "C" __declspec(dllexport) void VLDDisable ();
49 extern "C" __declspec(dllexport) void VLDEnable ();
50
51 // Data is collected for every block allocated from any heap in the process.
52 // The data is stored in this structure and these structures are stored in
53 // a BlockMap which maps each of these structures to its corresponding memory
54 // block.
55 typedef struct blockinfo_s {
56     CallStack *callstack;
57     SIZE_T     serialnumber;
58     SIZE_T     size;
59 } blockinfo_t;
60
61 // BlockMaps map memory blocks (via their addresses) to blockinfo_t structures.
62 typedef Map<LPCVOID, blockinfo_t*> BlockMap;
63
64 // Information about each heap in the process is kept in this map. Primarily
65 // this is used for mapping heaps to all of the blocks allocated from those
66 // heaps.
67 typedef struct heapinfo_s {
68     BlockMap blockmap;   // Map of all blocks allocated from this heap.
69     UINT32   flags;      // Heap status flags:
70 #define VLD_HEAP_CRT 0x1 //   If set, this heap is a CRT heap (i.e. the CRT uses it for new/malloc).
71 } heapinfo_t;
72
73 // HeapMaps map heaps (via their handles) to BlockMaps.
74 typedef Map<HANDLE, heapinfo_t*> HeapMap;
75
76 // This structure stores information, primarily the virtual address range, about
77 // a given module and can be used with the Set template because it supports the
78 // '<' operator (sorts by virtual address range).
79 typedef struct moduleinfo_s {
80     BOOL operator < (const struct moduleinfo_s &other) const
81     {
82         if (addrhigh < other.addrlow) {
83             return TRUE;
84         }
85         else {
86             return FALSE;
87         }
88     }
89
90     SIZE_T addrhigh;                 // Highest address within the module's virtual address space (i.e. base + size).
91     SIZE_T addrlow;                  // Lowest address within the module's virtual address space (i.e. base address).
92     UINT32 flags;                    // Module flags:
93 #define VLD_MODULE_EXCLUDED      0x1 //   If set, this module is excluded from leak detection.
94 #define VLD_MODULE_SYMBOLSLOADED 0x2 //   If set, this module's debug symbols have been loaded.
95     LPCSTR name;                     // The module's name (e.g. "kernel32.dll").
96     LPCSTR path;                     // The fully qualified path from where the module was loaded.
97 } moduleinfo_t;
98
99 // ModuleSets store information about modules loaded in the process.
100 typedef Set<moduleinfo_t> ModuleSet;
101
102 // Thread local storage structure. Every thread in the process gets its own copy
103 // of this structure. Thread specific information, such as the currentl leak
104 // detection status (enabled or disabled) and the address that initiated the
105 // current allocation is stored here.
106 typedef struct tls_s {
107     SIZE_T addrfp;           // Frame pointer at the first call that entered VLD's code for the current allocation.
108     UINT32 flags;            // Thread-local status flags:
109 #define VLD_TLS_CRTALLOC 0x1 //   If set, the current allocation is a CRT allocation.
110 #define VLD_TLS_DISABLED 0x2 //   If set, memory leak detection is disabled for the current thread.
111 #define VLD_TLS_ENABLED  0x4 //   If set, memory leak detection is enabled for the current thread.
112     DWORD  threadid;         // Thread ID of the thread that owns this TLS structure.
113 } tls_t;
114
115 // The TlsSet allows VLD to keep track of all thread local storage structures
116 // allocated in the process.
117 typedef Set<tls_t*> TlsSet;
118
119 ////////////////////////////////////////////////////////////////////////////////
120 //
121 // The VisualLeakDetector Class
122 //
123 //   One global instance of this class is instantiated. Upon construction it
124 //   patches the import address table (IAT) of every other module loaded in the
125 //   process (see the "patchimport" utility function) to allow key Windows heap
126 //   APIs to be patched through to, or redirected to, functions provided by VLD.
127 //   Patching the IATs in this manner allows VLD to be made aware of all
128 //   relevant heap activity, making it possible for VLD to detect and trace
129 //   memory leaks.
130 //
131 //   The one global instance of this class is constructed within the context of
132 //   the process' main thread during process initialization and is destroyed in
133 //   the same context during process termination.
134 //
135 //   When the VisualLeakDetector object is destroyed, it consults its internal
136 //   datastructures, looking for any memory that has not been freed. A memory
137 //   leak report is then generated, indicating any memory leaks that may have
138 //   been identified.
139 //
140 //   This class is derived from IMalloc so that it can provide an implementation
141 //   of the IMalloc COM interface in order to support detection of COM-based
142 //   memory leaks. However, this implementation of IMalloc is actually just a
143 //   thin wrapper around the system's implementation of IMalloc.
144 //
145 class VisualLeakDetector : public IMalloc
146 {
147 public:
148     VisualLeakDetector();
149     ~VisualLeakDetector();
150
151     // Public IMalloc methods - for support of COM-based memory leak detection.
152     ULONG __stdcall AddRef ();
153     LPVOID __stdcall Alloc (ULONG size);
154     INT __stdcall DidAlloc (LPVOID mem);
155     VOID __stdcall Free (LPVOID mem);
156     ULONG __stdcall GetSize (LPVOID mem);
157     VOID __stdcall HeapMinimize ();
158     HRESULT __stdcall QueryInterface (REFIID iid, LPVOID *object);
159     LPVOID __stdcall Realloc (LPVOID mem, ULONG size);
160     ULONG __stdcall Release ();
161
162 private:
163     // Import patching replacement functions - see each function definition for details.
164     static HRESULT __stdcall _CoGetMalloc (DWORD context, LPMALLOC *imalloc);
165     static LPVOID __stdcall _CoTaskMemAlloc (ULONG size);
166     static LPVOID __stdcall _CoTaskMemRealloc (LPVOID mem, ULONG size);
167     static void* __cdecl _crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line);
168     static void* __cdecl _crt80d__malloc_dbg (size_t size, int type, const char *file, int line);
169     static void* __cdecl _crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line);
170     static void* __cdecl _crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line);
171     static void* __cdecl _crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line);
172     static void* __cdecl _crt80d_calloc (size_t num, size_t size);
173     static void* __cdecl _crt80d_malloc (size_t size);
174     static void* __cdecl _crt80d_realloc (void *mem, size_t size);
175     static void* __cdecl _crt80d_scalar_new (unsigned int size);
176     static void* __cdecl _crt80d_vector_new (unsigned int size);
177     static void* __cdecl _crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line);
178     static void* __cdecl _crtd__malloc_dbg (size_t size, int type, const char *file, int line);
179     static void* __cdecl _crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line);
180     static void* __cdecl _crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line);
181     static void* __cdecl _crtd_calloc (size_t num, size_t size);
182     static void* __cdecl _crtd_malloc (size_t size);
183     static void* __cdecl _crtd_realloc (void *mem, size_t size);
184     static void* __cdecl _crtd_scalar_new (unsigned int size);
185     static FARPROC __stdcall _GetProcAddress(HMODULE module, LPCSTR procname);
186     static HANDLE __stdcall _HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize);
187     static BOOL __stdcall _HeapDestroy (HANDLE heap);
188     static NTSTATUS __stdcall _LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
189                                            PHANDLE modulehandle);
190     static void* __cdecl _mfc42d__scalar_new_dbg (unsigned int size, const char *file, int line);
191     static void* __cdecl _mfc42d_scalar_new (unsigned int size);
192     static void* __cdecl _mfc80d__scalar_new_dbg (unsigned int size, const char *file, int line);
193     static void* __cdecl _mfc80d__vector_new_dbg (unsigned int size, const char *file, int line);
194     static void* __cdecl _mfc80d_scalar_new (unsigned int size);
195     static void* __cdecl _mfc80d_vector_new (unsigned int size);
196     static LPVOID __stdcall _RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size);
197     static BOOL __stdcall _RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem);
198     static LPVOID __stdcall _RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size);
199
200     // Private functions - see each function definition for details.
201     static BOOL __stdcall addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
202     VOID attachtoloadedmodules (ModuleSet *newmodules);
203     LPWSTR buildsymbolsearchpath ();
204     VOID configure ();
205     static BOOL __stdcall detachfrommodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
206     BOOL enabled ();
207     SIZE_T eraseduplicates (const BlockMap::Iterator &element);
208     tls_t* gettls ();
209     VOID mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
210     VOID mapheap (HANDLE heap);
211     VOID remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
212     VOID reportconfig ();
213     VOID reportleaks (HANDLE heap);
214     VOID unmapblock (HANDLE heap, LPCVOID mem);
215     VOID unmapheap (HANDLE heap);
216
217     // Private data.
218     WCHAR                m_forcedmodulelist [MAXMODULELISTLENGTH]; // List of modules to be forcefully included in leak detection.
219     HeapMap             *m_heapmap;           // Map of all active heaps in the process.
220     IMalloc             *m_imalloc;           // Pointer to the system implementation of IMalloc.
221     SIZE_T               m_leaksfound;        // Total number of leaks found.
222     ModuleSet           *m_loadedmodules;     // Contains information about all modules loaded in the process.
223     CRITICAL_SECTION     m_loaderlock;        // Serializes the attachment of newly loaded modules.
224     CRITICAL_SECTION     m_maplock;           // Serializes access to the heap and block maps.
225     SIZE_T               m_maxdatadump;       // Maximum number of user-data bytes to dump for each leaked block.
226     UINT32               m_maxtraceframes;    // Maximum number of frames per stack trace for each leaked block.
227     CRITICAL_SECTION     m_moduleslock;       // Protects accesses to the "loaded modules" ModuleSet.
228     UINT32               m_options;           // Configuration options:
229 #define VLD_OPT_AGGREGATE_DUPLICATES    0x1   //   If set, aggregate duplicate leaks in the leak report.
230 #define VLD_OPT_MODULE_LIST_INCLUDE     0x2   //   If set, modules in the module list are included, all others are excluded.
231 #define VLD_OPT_REPORT_TO_DEBUGGER      0x4   //   If set, the memory leak report is sent to the debugger.
232 #define VLD_OPT_REPORT_TO_FILE          0x8   //   If set, the memory leak report is sent to a file.
233 #define VLD_OPT_SAFE_STACK_WALK         0x10  //   If set, the stack is walked using the "safe" method (StackWalk64).
234 #define VLD_OPT_SELF_TEST               0x20  //   If set, peform a self-test to verify memory leak self-checking.
235 #define VLD_OPT_SLOW_DEBUGGER_DUMP      0x40  //   If set, inserts a slight delay between sending output to the debugger.
236 #define VLD_OPT_START_DISABLED          0x80  //   If set, memory leak detection will initially disabled.
237 #define VLD_OPT_TRACE_INTERNAL_FRAMES   0x100 //   If set, include useless frames (e.g. internal to VLD) in call stacks.
238 #define VLD_OPT_UNICODE_REPORT          0x200 //   If set, the leak report will be encoded UTF-16 instead of ASCII.
239 #define VLD_OPT_VLDOFF                  0x400 //   If set, VLD will be completely deactivated. It will not attach to any modules.
240     static patchentry_t  m_patchtable [];     // Table of imports patched for attaching VLD to other modules.
241     FILE                *m_reportfile;        // File where the memory leak report may be sent to.
242     WCHAR                m_reportfilepath [MAX_PATH]; // Full path and name of file to send memory leak report to.
243     const char          *m_selftestfile;      // Filename where the memory leak self-test block is leaked.
244     int                  m_selftestline;      // Line number where the memory leak self-test block is leaked.
245     UINT32               m_status;            // Status flags:
246 #define VLD_STATUS_DBGHELPLINKED        0x1   //   If set, the explicit dynamic link to the Debug Help Library succeeded.
247 #define VLD_STATUS_INSTALLED            0x2   //   If set, VLD was successfully installed.
248 #define VLD_STATUS_NEVER_ENABLED        0x4   //   If set, VLD started disabled, and has not yet been manually enabled.
249 #define VLD_STATUS_FORCE_REPORT_TO_FILE 0x8   //   If set, the leak report is being forced to a file.
250     DWORD                m_tlsindex;          // Thread-local storage index.
251     CRITICAL_SECTION     m_tlslock;           // Protects accesses to the Set of TLS structures.
252     TlsSet              *m_tlsset;            // Set of all all thread-local storage structres for the process.
253     HMODULE              m_vldbase;           // Visual Leak Detector's own module handle (base address).
254
255     // The Visual Leak Detector APIs are our friends.
256     friend __declspec(dllexport) void VLDDisable ();
257     friend __declspec(dllexport) void VLDEnable ();
258 };
259
260 // Configuration option default values
261 #define VLD_DEFAULT_MAX_DATA_DUMP    0xffffffff
262 #define VLD_DEFAULT_MAX_TRACE_FRAMES 0xffffffff
263 #define VLD_DEFAULT_REPORT_FILE_NAME L".\\memory_leak_report.txt"