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