00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include "pipe/p_config.h"
00036
00037 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00038 #include <windows.h>
00039 #include <winddi.h>
00040 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00041 #include <wdm.h>
00042 #else
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #endif
00046
00047 #include "pipe/p_debug.h"
00048 #include "util/u_double_list.h"
00049
00050
00051 #define DEBUG_MEMORY_MAGIC 0x6e34090aU
00052
00053
00054 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && !defined(WINCE)
00055 #define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
00056 #define real_free(_ptr) EngFreeMem(_ptr)
00057 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00058 #define real_malloc(_size) ExAllocatePool(0, _size)
00059 #define real_free(_ptr) ExFreePool(_ptr)
00060 #else
00061 #define real_malloc(_size) malloc(_size)
00062 #define real_free(_ptr) free(_ptr)
00063 #endif
00064
00065
00066 struct debug_memory_header
00067 {
00068 struct list_head head;
00069
00070 unsigned long no;
00071 const char *file;
00072 unsigned line;
00073 const char *function;
00074 size_t size;
00075 unsigned magic;
00076 };
00077
00078 struct debug_memory_footer
00079 {
00080 unsigned magic;
00081 };
00082
00083
00084 static struct list_head list = { &list, &list };
00085
00086 static unsigned long last_no = 0;
00087
00088
00089 static INLINE struct debug_memory_header *
00090 header_from_data(void *data)
00091 {
00092 if(data)
00093 return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
00094 else
00095 return NULL;
00096 }
00097
00098 static INLINE void *
00099 data_from_header(struct debug_memory_header *hdr)
00100 {
00101 if(hdr)
00102 return (void *)((char *)hdr + sizeof(struct debug_memory_header));
00103 else
00104 return NULL;
00105 }
00106
00107 static INLINE struct debug_memory_footer *
00108 footer_from_header(struct debug_memory_header *hdr)
00109 {
00110 if(hdr)
00111 return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size);
00112 else
00113 return NULL;
00114 }
00115
00116
00117 void *
00118 debug_malloc(const char *file, unsigned line, const char *function,
00119 size_t size)
00120 {
00121 struct debug_memory_header *hdr;
00122 struct debug_memory_footer *ftr;
00123
00124 assert(size);
00125
00126 hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr));
00127 if(!hdr) {
00128 debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00129 file, line, function,
00130 (long unsigned)size);
00131 return NULL;
00132 }
00133
00134 hdr->no = last_no++;
00135 hdr->file = file;
00136 hdr->line = line;
00137 hdr->function = function;
00138 hdr->size = size;
00139 hdr->magic = DEBUG_MEMORY_MAGIC;
00140
00141 ftr = footer_from_header(hdr);
00142 ftr->magic = DEBUG_MEMORY_MAGIC;
00143
00144 LIST_ADDTAIL(&hdr->head, &list);
00145
00146 return data_from_header(hdr);
00147 }
00148
00149 void
00150 debug_free(const char *file, unsigned line, const char *function,
00151 void *ptr)
00152 {
00153 struct debug_memory_header *hdr;
00154 struct debug_memory_footer *ftr;
00155
00156 if(!ptr)
00157 return;
00158
00159 hdr = header_from_data(ptr);
00160 if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00161 debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
00162 file, line, function,
00163 ptr);
00164 debug_assert(0);
00165 return;
00166 }
00167
00168 ftr = footer_from_header(hdr);
00169 if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00170 debug_printf("%s:%u:%s: buffer overflow %p\n",
00171 hdr->file, hdr->line, hdr->function,
00172 ptr);
00173 debug_assert(0);
00174 }
00175
00176 LIST_DEL(&hdr->head);
00177 hdr->magic = 0;
00178 ftr->magic = 0;
00179
00180 real_free(hdr);
00181 }
00182
00183 void *
00184 debug_calloc(const char *file, unsigned line, const char *function,
00185 size_t count, size_t size )
00186 {
00187 void *ptr = debug_malloc( file, line, function, count * size );
00188 if( ptr )
00189 memset( ptr, 0, count * size );
00190 return ptr;
00191 }
00192
00193 void *
00194 debug_realloc(const char *file, unsigned line, const char *function,
00195 void *old_ptr, size_t old_size, size_t new_size )
00196 {
00197 struct debug_memory_header *old_hdr, *new_hdr;
00198 struct debug_memory_footer *old_ftr, *new_ftr;
00199 void *new_ptr;
00200
00201 if(!old_ptr)
00202 return debug_malloc( file, line, function, new_size );
00203
00204 if(!new_size) {
00205 debug_free( file, line, function, old_ptr );
00206 return NULL;
00207 }
00208
00209 old_hdr = header_from_data(old_ptr);
00210 if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
00211 debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
00212 file, line, function,
00213 old_ptr);
00214 debug_assert(0);
00215 return NULL;
00216 }
00217
00218 old_ftr = footer_from_header(old_hdr);
00219 if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
00220 debug_printf("%s:%u:%s: buffer overflow %p\n",
00221 old_hdr->file, old_hdr->line, old_hdr->function,
00222 old_ptr);
00223 debug_assert(0);
00224 }
00225
00226
00227 new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
00228 if(!new_hdr) {
00229 debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00230 file, line, function,
00231 (long unsigned)new_size);
00232 return NULL;
00233 }
00234 new_hdr->no = old_hdr->no;
00235 new_hdr->file = old_hdr->file;
00236 new_hdr->line = old_hdr->line;
00237 new_hdr->function = old_hdr->function;
00238 new_hdr->size = new_size;
00239 new_hdr->magic = DEBUG_MEMORY_MAGIC;
00240
00241 new_ftr = footer_from_header(new_hdr);
00242 new_ftr->magic = DEBUG_MEMORY_MAGIC;
00243
00244 LIST_REPLACE(&old_hdr->head, &new_hdr->head);
00245
00246
00247 new_ptr = data_from_header(new_hdr);
00248 memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
00249
00250
00251 old_hdr->magic = 0;
00252 old_ftr->magic = 0;
00253 real_free(old_hdr);
00254
00255 return new_ptr;
00256 }
00257
00258 unsigned long
00259 debug_memory_begin(void)
00260 {
00261 return last_no;
00262 }
00263
00264 void
00265 debug_memory_end(unsigned long start_no)
00266 {
00267 size_t total_size = 0;
00268 struct list_head *entry;
00269
00270 if(start_no == last_no)
00271 return;
00272
00273 entry = list.prev;
00274 for (; entry != &list; entry = entry->prev) {
00275 struct debug_memory_header *hdr;
00276 void *ptr;
00277 struct debug_memory_footer *ftr;
00278
00279 hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
00280 ptr = data_from_header(hdr);
00281 ftr = footer_from_header(hdr);
00282
00283 if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00284 debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
00285 hdr->file, hdr->line, hdr->function,
00286 ptr);
00287 debug_assert(0);
00288 }
00289
00290 if((start_no <= hdr->no && hdr->no < last_no) ||
00291 (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
00292 debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
00293 hdr->file, hdr->line, hdr->function,
00294 hdr->size, ptr);
00295 total_size += hdr->size;
00296 }
00297
00298 if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00299 debug_printf("%s:%u:%s: buffer overflow %p\n",
00300 hdr->file, hdr->line, hdr->function,
00301 ptr);
00302 debug_assert(0);
00303 }
00304 }
00305
00306 if(total_size) {
00307 debug_printf("Total of %u KB of system memory apparently leaked\n",
00308 (total_size + 1023)/1024);
00309 }
00310 else {
00311 debug_printf("No memory leaks detected.\n");
00312 }
00313 }