ff5a03095b19558d71df24ecd0be45ccd14978ef
[platform/upstream/multipath-tools.git] / libmultipath / memory.c
1 /*
2  * Part:        Memory management framework. This framework is used to
3  *              find any memory leak.
4  *
5  * Version:     $Id: memory.c,v 1.1.11 2005/03/01 01:22:13 acassen Exp $
6  *
7  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
8  *              Jan Holmberg, <jan@artech.net>
9  *
10  *              This program is distributed in the hope that it will be useful,
11  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *              See the GNU General Public License for more details.
14  *
15  *              This program is free software; you can redistribute it and/or
16  *              modify it under the terms of the GNU General Public License
17  *              as published by the Free Software Foundation; either version
18  *              2 of the License, or (at your option) any later version.
19  *
20  * Copyright (C) 2001-2005 Alexandre Cassen, <acassen@linux-vs.org>
21  */
22
23 #include <assert.h>
24 #include "memory.h"
25
26 /*
27  * Memory management. in debug mode,
28  * help finding eventual memory leak.
29  * Allocation memory types manipulated are :
30  *
31  * +type+--------meaning--------+
32  * ! 0  ! Free slot             !
33  * ! 1  ! Overrun               !
34  * ! 2  ! free null             !
35  * ! 3  ! realloc null          !
36  * ! 4  ! Not previus allocated !
37  * ! 8  ! Last free list        !
38  * ! 9  ! Allocated             !
39  * +----+-----------------------+
40  *
41  * global variabel debug bit 9 ( 512 ) used to
42  * flag some memory error.
43  *
44  */
45
46 #ifdef _DEBUG_
47
48 typedef struct {
49         int type;
50         int line;
51         char *func;
52         char *file;
53         void *ptr;
54         unsigned long size;
55         long csum;
56 } MEMCHECK;
57
58 /* Last free pointers */
59 static MEMCHECK free_list[256];
60
61 static MEMCHECK alloc_list[MAX_ALLOC_LIST];
62 static int number_alloc_list = 0;
63 static int n = 0;               /* Alloc list pointer */
64 static int f = 0;               /* Free list pointer */
65
66 void *
67 dbg_malloc(unsigned long size, char *file, char *function, int line)
68 {
69         void *buf;
70         int i = 0;
71         long check;
72
73         buf = zalloc(size + sizeof (long));
74
75         check = 0xa5a5 + size;
76         *(long *) ((char *) buf + size) = check;
77
78         while (i < number_alloc_list) {
79                 if (alloc_list[i].type == 0)
80                         break;
81                 i++;
82         }
83
84         if (i == number_alloc_list)
85                 number_alloc_list++;
86
87         assert(number_alloc_list < MAX_ALLOC_LIST);
88
89         alloc_list[i].ptr = buf;
90         alloc_list[i].size = size;
91         alloc_list[i].file = file;
92         alloc_list[i].func = function;
93         alloc_list[i].line = line;
94         alloc_list[i].csum = check;
95         alloc_list[i].type = 9;
96
97         if (debug & 1)
98                 printf("zalloc[%3d:%3d], %p, %4ld at %s, %3d, %s\n",
99                        i, number_alloc_list, buf, size, file, line,
100                        function);
101
102         n++;
103         return buf;
104 }
105
106 char *
107 dbg_strdup(char *str, char *file, char *function, int line)
108 {
109         void *buf;
110         int i = 0;
111         long check;
112         long size;
113
114         size = strlen(str) + 1;
115         buf = zalloc(size + sizeof (long));
116         strcat(buf, str);
117
118         check = 0xa5a5 + size;
119         *(long *) ((char *) buf + size) = check;
120
121         while (i < number_alloc_list) {
122                 if (alloc_list[i].type == 0)
123                         break;
124                 i++;
125         }
126
127         if (i == number_alloc_list)
128                 number_alloc_list++;
129
130         assert(number_alloc_list < MAX_ALLOC_LIST);
131
132         alloc_list[i].ptr = buf;
133         alloc_list[i].size = size;
134         alloc_list[i].file = file;
135         alloc_list[i].func = function;
136         alloc_list[i].line = line;
137         alloc_list[i].csum = check;
138         alloc_list[i].type = 9;
139
140         if (debug & 1)
141                 printf("strdup[%3d:%3d], %p, %4ld at %s, %3d, %s\n",
142                        i, number_alloc_list, buf, size, file, line,
143                        function);
144
145         n++;
146         return buf;
147 }
148
149
150
151 /* Display a buffer into a HEXA formatted output */
152 static void
153 dump_buffer(char *buff, int count)
154 {
155         int i, j, c;
156         int printnext = 1;
157
158         if (count % 16)
159                 c = count + (16 - count % 16);
160         else
161                 c = count;
162
163         for (i = 0; i < c; i++) {
164                 if (printnext) {
165                         printnext--;
166                         printf("%.4x ", i & 0xffff);
167                 }
168                 if (i < count)
169                         printf("%3.2x", buff[i] & 0xff);
170                 else
171                         printf("   ");
172                 if (!((i + 1) % 8)) {
173                         if ((i + 1) % 16)
174                                 printf(" -");
175                         else {
176                                 printf("   ");
177                                 for (j = i - 15; j <= i; j++)
178                                         if (j < count) {
179                                                 if ((buff[j] & 0xff) >= 0x20
180                                                     && (buff[j] & 0xff) <= 0x7e)
181                                                         printf("%c",
182                                                                buff[j] & 0xff);
183                                                 else
184                                                         printf(".");
185                                         } else
186                                                 printf(" ");
187                                 printf("\n");
188                                 printnext = 1;
189                         }
190                 }
191         }
192 }
193
194 int
195 dbg_free(void *buffer, char *file, char *function, int line)
196 {
197         int i = 0;
198         void *buf;
199
200         /* If nullpointer remember */
201         if (buffer == NULL) {
202                 i = number_alloc_list++;
203
204                 assert(number_alloc_list < MAX_ALLOC_LIST);
205
206                 alloc_list[i].ptr = buffer;
207                 alloc_list[i].size = 0;
208                 alloc_list[i].file = file;
209                 alloc_list[i].func = function;
210                 alloc_list[i].line = line;
211                 alloc_list[i].type = 2;
212                 if (debug & 1)
213                         printf("free NULL in %s, %3d, %s\n", file,
214                                line, function);
215
216                 debug |= 512;   /* Memory Error detect */
217
218                 return n;
219         } else
220                 buf = buffer;
221
222         while (i < number_alloc_list) {
223                 if (alloc_list[i].type == 9 && alloc_list[i].ptr == buf) {
224                         if (*
225                             ((long *) ((char *) alloc_list[i].ptr +
226                                        alloc_list[i].size)) ==
227                             alloc_list[i].csum)
228                                 alloc_list[i].type = 0; /* Release */
229                         else {
230                                 alloc_list[i].type = 1; /* Overrun */
231                                 if (debug & 1) {
232                                         printf("free corrupt, buffer overrun [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
233                                                i, number_alloc_list,
234                                                buf, alloc_list[i].size, file,
235                                                line, function);
236                                         dump_buffer(alloc_list[i].ptr,
237                                                     alloc_list[i].size + sizeof (long));
238                                         printf("Check_sum\n");
239                                         dump_buffer((char *) &alloc_list[i].csum,
240                                                     sizeof(long));
241
242                                         debug |= 512;   /* Memory Error detect */
243                                 }
244                         }
245                         break;
246                 }
247                 i++;
248         }
249
250         /*  Not found */
251         if (i == number_alloc_list) {
252                 printf("Free ERROR %p\n", buffer);
253                 number_alloc_list++;
254
255                 assert(number_alloc_list < MAX_ALLOC_LIST);
256
257                 alloc_list[i].ptr = buf;
258                 alloc_list[i].size = 0;
259                 alloc_list[i].file = file;
260                 alloc_list[i].func = function;
261                 alloc_list[i].line = line;
262                 alloc_list[i].type = 4;
263                 debug |= 512;
264
265                 return n;
266         }
267
268         if (buffer != NULL)
269                 xfree(buffer);
270
271         if (debug & 1)
272                 printf("free  [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
273                        i, number_alloc_list, buf,
274                        alloc_list[i].size, file, line, function);
275
276         free_list[f].file = file;
277         free_list[f].line = line;
278         free_list[f].func = function;
279         free_list[f].ptr = buffer;
280         free_list[f].type = 8;
281         free_list[f].csum = i;  /* Using this field for row id */
282
283         f++;
284         f &= 255;
285         n--;
286
287         return n;
288 }
289
290 void
291 dbg_free_final(char *banner)
292 {
293         unsigned int sum = 0, overrun = 0, badptr = 0;
294         int i, j;
295         i = 0;
296
297         printf("\n---[ Memory dump for (%s)]---\n\n", banner);
298
299         while (i < number_alloc_list) {
300                 switch (alloc_list[i].type) {
301                 case 3:
302                         badptr++;
303                         printf
304                             ("null pointer to realloc(nil,%ld)! at %s, %3d, %s\n",
305                              alloc_list[i].size, alloc_list[i].file,
306                              alloc_list[i].line, alloc_list[i].func);
307                         break;
308                 case 4:
309                         badptr++;
310                         printf
311                             ("pointer not found in table to free(%p) [%3d:%3d], at %s, %3d, %s\n",
312                              alloc_list[i].ptr, i, number_alloc_list,
313                              alloc_list[i].file, alloc_list[i].line,
314                              alloc_list[i].func);
315                         for (j = 0; j < 256; j++)
316                                 if (free_list[j].ptr == alloc_list[i].ptr)
317                                         if (free_list[j].type == 8)
318                                                 printf
319                                                     ("  -> pointer already released at [%3d:%3d], at %s, %3d, %s\n",
320                                                      (int) free_list[j].csum,
321                                                      number_alloc_list,
322                                                      free_list[j].file,
323                                                      free_list[j].line,
324                                                      free_list[j].func);
325                         break;
326                 case 2:
327                         badptr++;
328                         printf("null pointer to free(nil)! at %s, %3d, %s\n",
329                                alloc_list[i].file, alloc_list[i].line,
330                                alloc_list[i].func);
331                         break;
332                 case 1:
333                         overrun++;
334                         printf("%p [%3d:%3d], %4ld buffer overrun!:\n",
335                                alloc_list[i].ptr, i, number_alloc_list,
336                                alloc_list[i].size);
337                         printf(" --> source of malloc: %s, %3d, %s\n",
338                                alloc_list[i].file, alloc_list[i].line,
339                                alloc_list[i].func);
340                         break;
341                 case 9:
342                         sum += alloc_list[i].size;
343                         printf("%p [%3d:%3d], %4ld not released!:\n",
344                                alloc_list[i].ptr, i, number_alloc_list,
345                                alloc_list[i].size);
346                         printf(" --> source of malloc: %s, %3d, %s\n",
347                                alloc_list[i].file, alloc_list[i].line,
348                                alloc_list[i].func);
349                         break;
350                 }
351                 i++;
352         }
353
354         printf("\n\n---[ Memory dump summary for (%s) ]---\n", banner);
355         printf("Total number of bytes not freed...: %d\n", sum);
356         printf("Number of entries not freed.......: %d\n", n);
357         printf("Maximum allocated entries.........: %d\n", number_alloc_list);
358         printf("Number of bad entries.............: %d\n", badptr);
359         printf("Number of buffer overrun..........: %d\n\n", overrun);
360
361         if (sum || n || badptr || overrun)
362                 printf("=> Program seems to have some memory problem !!!\n\n");
363         else
364                 printf("=> Program seems to be memory allocation safe...\n\n");
365 }
366
367 void *
368 dbg_realloc(void *buffer, unsigned long size, char *file, char *function,
369                    int line)
370 {
371         int i = 0;
372         void *buf, *buf2;
373         long check;
374
375         if (buffer == NULL) {
376                 printf("realloc %p %s, %3d %s\n", buffer, file, line, function);
377                 i = number_alloc_list++;
378
379                 assert(number_alloc_list < MAX_ALLOC_LIST);
380
381                 alloc_list[i].ptr = NULL;
382                 alloc_list[i].size = 0;
383                 alloc_list[i].file = file;
384                 alloc_list[i].func = function;
385                 alloc_list[i].line = line;
386                 alloc_list[i].type = 3;
387                 return dbg_malloc(size, file, function, line);
388         }
389
390         buf = buffer;
391
392         while (i < number_alloc_list) {
393                 if (alloc_list[i].ptr == buf) {
394                         buf = alloc_list[i].ptr;
395                         break;
396                 }
397                 i++;
398         }
399
400         /* not found */
401         if (i == number_alloc_list) {
402                 printf("realloc ERROR no matching zalloc %p \n", buffer);
403                 number_alloc_list++;
404
405                 assert(number_alloc_list < MAX_ALLOC_LIST);
406
407                 alloc_list[i].ptr = buf;
408                 alloc_list[i].size = 0;
409                 alloc_list[i].file = file;
410                 alloc_list[i].func = function;
411                 alloc_list[i].line = line;
412                 alloc_list[i].type = 9;
413                 debug |= 512;   /* Memory Error detect */
414                 return NULL;
415         }
416
417         buf2 = ((char *) buf) + alloc_list[i].size;
418
419         if (*(long *) (buf2) != alloc_list[i].csum) {
420                 alloc_list[i].type = 1;
421                 debug |= 512;   /* Memory Error detect */
422         }
423         buf = realloc(buffer, size + sizeof (long));
424
425         check = 0xa5a5 + size;
426         *(long *) ((char *) buf + size) = check;
427         alloc_list[i].csum = check;
428
429         if (debug & 1)
430                 printf("realloc [%3d:%3d] %p, %4ld %s %d %s -> %p %4ld %s %d %s\n",
431                        i, number_alloc_list, alloc_list[i].ptr,
432                        alloc_list[i].size, alloc_list[i].file, alloc_list[i].line, alloc_list[i].func,
433                        buf, size, file, line, function);
434
435         alloc_list[i].ptr = buf;
436         alloc_list[i].size = size;
437         alloc_list[i].file = file;
438         alloc_list[i].line = line;
439         alloc_list[i].func = function;
440
441         return buf;
442 }
443
444 #endif