ReactOS  0.4.15-dev-1150-g593bcce
cmddbg.c
Go to the documentation of this file.
1 #include "precomp.h"
2 
3 #ifdef _DEBUG_MEM
4 
5 #define REDZONE_SIZE 32
6 #define REDZONE_LEFT 0x78
7 #define REDZONE_RIGHT 0x87
8 
9 typedef struct
10 {
11  size_t size;
13  const char *file;
14  int line;
15 } alloc_info, *palloc_info;
16 
17 static size_t allocations = 0;
18 static size_t allocated_memory = 0;
19 static LIST_ENTRY alloc_list_head = {&alloc_list_head, &alloc_list_head};
20 
21 static void *
22 get_base_ptr(void *ptr)
23 {
24  return (void *)((UINT_PTR)ptr - REDZONE_SIZE - sizeof(alloc_info));
25 }
26 
27 static void *
28 get_ptr_from_base(palloc_info info)
29 {
30  return (void*)((size_t)(info + 1) + REDZONE_SIZE);
31 }
32 
33 static void *
34 write_redzone(void *ptr, size_t size, const char *file, int line)
35 {
36  void *ret;
37  palloc_info info = (palloc_info)ptr;
38 
39  info->size = size;
40  info->file = file;
41  info->line = line;
42 
43  ptr = (void *)(info + 1);
44  memset(ptr, REDZONE_LEFT, REDZONE_SIZE);
45  ret = (void *)((size_t)ptr + REDZONE_SIZE);
46  ptr = (void *)((size_t)ret + size);
47  memset(ptr, REDZONE_RIGHT, REDZONE_SIZE);
48  return ret;
49 }
50 
51 static int
52 check_redzone_region(void *ptr, unsigned char sig, void **newptr)
53 {
54  unsigned char *p, *q;
55  int ret = 1;
56 
57  p = (unsigned char *)ptr;
58  q = p + REDZONE_SIZE;
59  while (p != q)
60  {
61  if (*(p++) != sig)
62  ret = 0;
63  }
64 
65  if (newptr != NULL)
66  *newptr = p;
67  return ret;
68 }
69 
70 static void
71 redzone_err(const char *msg, palloc_info info, void *ptr, const char *file, int line)
72 {
73  DbgPrint("CMD: %s\n", msg);
74  DbgPrint(" Block: 0x%p Size: %lu\n", ptr, info->size);
75  DbgPrint(" Allocated from %s:%d\n", info->file, info->line);
76  DbgPrint(" Detected at: %s:%d\n", file, line);
77  ASSERT(FALSE);
78  ExitProcess(1);
79 }
80 
81 static void
82 check_redzone(void *ptr, const char *file, int line)
83 {
84  palloc_info info = (palloc_info)ptr;
85  ptr = (void *)(info + 1);
86  if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr))
87  redzone_err("Detected buffer underflow!", info, ptr, file, line);
88  ptr = (void *)((UINT_PTR)ptr + info->size);
89  if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL))
90  redzone_err("Detected buffer overflow!", info, ptr, file, line);
91 }
92 
93 static size_t
94 calculate_size_with_redzone(size_t size)
95 {
96  return sizeof(alloc_info) + size + (2 * REDZONE_SIZE);
97 }
98 
99 static void
100 add_mem_to_list(void *ptr)
101 {
102  palloc_info info = (palloc_info)ptr;
103  InsertTailList(&alloc_list_head, &info->list_entry);
104 }
105 
106 static void
107 del_mem_from_list(void *ptr)
108 {
109  palloc_info info = (palloc_info)ptr;
110  RemoveEntryList(&info->list_entry);
111 }
112 
113 static void
114 dump_mem_list(void)
115 {
116  palloc_info info;
118  void *ptr;
119 
120  entry = alloc_list_head.Flink;
121  while (entry != &alloc_list_head)
122  {
123  info = CONTAINING_RECORD(entry, alloc_info, list_entry);
124 
125  DbgPrint(" * Block: 0x%p Size: %lu allocated from %s:%d\n", get_ptr_from_base(info), info->size, info->file, info->line);
126 
127  ptr = (void *)(info + 1);
128  if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr))
129  {
130  DbgPrint(" !!! Detected buffer underflow !!!\n");
131  }
132 
133  ptr = (void *)((UINT_PTR)ptr + info->size);
134  if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL))
135  {
136  DbgPrint(" !!! Detected buffer overflow !!!\n");
137  }
138 
139  entry = entry->Flink;
140  }
141 }
142 
143 void *
144 cmd_alloc_dbg(size_t size, const char *file, int line)
145 {
146  void *newptr = NULL;
147 
148  newptr = malloc(calculate_size_with_redzone(size));
149  if (newptr != NULL)
150  {
151  allocations++;
152  allocated_memory += size;
153  add_mem_to_list(newptr);
154  newptr = write_redzone(newptr, size, file, line);
155  }
156 
157  return newptr;
158 }
159 
160 void *
161 cmd_realloc_dbg(void *ptr, size_t size, const char *file, int line)
162 {
163  size_t prev_size;
164  void *newptr = NULL;
165 
166  if (ptr == NULL)
167  return cmd_alloc_dbg(size, file, line);
168  if (size == 0)
169  {
170  cmd_free_dbg(ptr, file, line);
171  return NULL;
172  }
173 
174  ptr = get_base_ptr(ptr);
175  prev_size = ((palloc_info)ptr)->size;
176  check_redzone(ptr, file, line);
177 
178  del_mem_from_list(ptr);
179  newptr = realloc(ptr, calculate_size_with_redzone(size));
180  if (newptr != NULL)
181  {
182  allocated_memory += size - prev_size;
183  add_mem_to_list(newptr);
184  newptr = write_redzone(newptr, size, file, line);
185  }
186  else
187  add_mem_to_list(ptr);
188 
189  return newptr;
190 }
191 
192 void
193 cmd_free_dbg(void *ptr, const char *file, int line)
194 {
195  if (ptr != NULL)
196  {
197  ptr = get_base_ptr(ptr);
198  check_redzone(ptr, file, line);
199  allocations--;
200  allocated_memory -= ((palloc_info)ptr)->size;
201  del_mem_from_list(ptr);
202  }
203 
204  free(ptr);
205 }
206 
207 TCHAR *
208 cmd_dup_dbg(const TCHAR *str, const char *file, int line)
209 {
210  TCHAR *ptr = NULL;
211 
212  if (str != NULL)
213  {
214  ptr = (TCHAR *)cmd_alloc_dbg((_tcslen(str) + 1) * sizeof(TCHAR), file, line);
215  if (ptr != NULL)
216  {
217  _tcscpy(ptr, str);
218  }
219  }
220 
221  return ptr;
222 }
223 
224 void
225 cmd_checkbuffer_dbg(void *ptr, const char *file, int line)
226 {
227  if (ptr != NULL)
228  {
229  ptr = get_base_ptr(ptr);
230  check_redzone(ptr, file, line);
231  }
232 }
233 
234 void
235 cmd_exit(int code)
236 {
237  if (allocations != 0 || allocated_memory != 0)
238  {
239  DbgPrint("CMD: Leaking %lu bytes of memory in %lu blocks! Exit code: %d\n", allocated_memory, allocations, code);
240  if (allocations != 0)
241  dump_mem_list();
242  }
243 
244  ExitProcess(code);
245 }
246 
247 #endif /* _DEBUG_MEM */
#define realloc
Definition: debug_ros.c:6
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
#define cmd_exit(code)
Definition: cmddbg.h:34
#define DbgPrint
Definition: loader.c:25
#define free
Definition: debug_ros.c:5
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
#define InsertTailList(ListHead, Entry)
#define REDZONE_SIZE(Block)
Definition: heap.c:30
#define list_entry(ptr, type, member)
Definition: list.h:185
struct _test_info info[]
Definition: SetCursorPos.c:19
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
static PVOID ptr
Definition: dispmode.c:27
const WCHAR * str
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
Definition: parser.c:48
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
__kernel_size_t size_t
Definition: linux.h:237
char TCHAR
Definition: xmlstorage.h:189
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLsizeiptr size
Definition: glext.h:5919
const char file[]
Definition: icontest.c:11
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
int ret
char line[200]
Definition: main.c:97
uint32_t entry
Definition: isohybrid.c:63
Definition: typedefs.h:119
Definition: inflate.c:139
Definition: list.h:27
#define msg(x)
Definition: auth_time.c:54
#define malloc
Definition: debug_ros.c:4
unsigned int line
Definition: notification.c:67
GLfloat GLfloat p
Definition: glext.h:8902
#define memset(x, y, z)
Definition: compat.h:39
Definition: fci.c:126