ReactOS 0.4.15-dev-7842-g558ab78
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
9typedef struct
10{
11 size_t size;
13 const char *file;
14 int line;
15} alloc_info, *palloc_info;
16
17static size_t allocations = 0;
18static size_t allocated_memory = 0;
19static LIST_ENTRY alloc_list_head = {&alloc_list_head, &alloc_list_head};
20
21static void *
22get_base_ptr(void *ptr)
23{
24 return (void *)((UINT_PTR)ptr - REDZONE_SIZE - sizeof(alloc_info));
25}
26
27static void *
28get_ptr_from_base(palloc_info info)
29{
30 return (void*)((size_t)(info + 1) + REDZONE_SIZE);
31}
32
33static void *
34write_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
51static int
52check_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
70static void
71redzone_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);
78 ExitProcess(1);
79}
80
81static void
82check_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
93static size_t
94calculate_size_with_redzone(size_t size)
95{
96 return sizeof(alloc_info) + size + (2 * REDZONE_SIZE);
97}
98
99static void
100add_mem_to_list(void *ptr)
101{
102 palloc_info info = (palloc_info)ptr;
103 InsertTailList(&alloc_list_head, &info->list_entry);
104}
105
106static void
107del_mem_from_list(void *ptr)
108{
109 palloc_info info = (palloc_info)ptr;
110 RemoveEntryList(&info->list_entry);
111}
112
113static void
114dump_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
143void *
144cmd_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
160void *
161cmd_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
192void
193cmd_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
207TCHAR *
208cmd_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
224void
225cmd_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
234void
235cmd_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
245}
246
247#endif /* _DEBUG_MEM */
#define msg(x)
Definition: auth_time.c:54
#define REDZONE_SIZE(Block)
Definition: heap.c:30
#define cmd_exit(code)
Definition: cmddbg.h:34
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
#define list_entry(ptr, type, member)
Definition: list.h:185
__kernel_size_t size_t
Definition: linux.h:237
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat p
Definition: glext.h:8902
#define DbgPrint
Definition: hal.h:12
#define _tcscpy
Definition: tchar.h:623
uint32_t entry
Definition: isohybrid.c:63
#define ASSERT(a)
Definition: mode.c:44
static PVOID ptr
Definition: dispmode.c:27
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
const WCHAR * str
#define memset(x, y, z)
Definition: compat.h:39
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: inflate.c:139
Definition: fci.c:127
unsigned int line
Definition: notification.c:67
Definition: parser.c:49
Definition: list.h:27
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
int ret
char TCHAR
Definition: xmlstorage.h:189
#define _tcslen
Definition: xmlstorage.h:198