]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/smartall.c
kes Prepare to add JS_Warnings termination status.
[bacula/bacula] / bacula / src / lib / smartall.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29
30                          S M A R T A L L O C
31                         Smart Memory Allocator
32
33         Evolved   over   several  years,  starting  with  the  initial
34         SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
35         Watchbreaker,  John  Walker.  Isolated in this general-purpose
36         form in  September  of  1989.   Updated  with  be  more  POSIX
37         compliant  and  to  include Web-friendly HTML documentation in
38         October  of  1998  by  the  same  culprit.    For   additional
39         information and the current version visit the Web page:
40
41                   http://www.fourmilab.ch/smartall/
42
43
44          Version $Id$
45
46 */
47
48 #define _LOCKMGR_COMPLIANT
49
50 #include "bacula.h"
51 /* Use the real routines here */
52 #undef realloc
53 #undef calloc
54 #undef malloc
55 #undef free
56
57 /* We normally turn off debugging here.
58  *  If you want it, simply #ifdef all the
59  *  following off.
60  */
61 #undef Dmsg1
62 #undef Dmsg2
63 #undef Dmsg3
64 #undef Dmsg4
65 #define Dmsg1(l,f,a1)
66 #define Dmsg2(l,f,a1,a2)
67 #define Dmsg3(l,f,a1,a2,a3)
68 #define Dmsg4(l,f,a1,a2,a3,a4)
69
70
71 uint64_t sm_max_bytes = 0;
72 uint64_t sm_bytes = 0;
73 uint32_t sm_max_buffers = 0;
74 uint32_t sm_buffers = 0;
75
76 #ifdef SMARTALLOC
77
78 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
79
80 extern char my_name[];                /* daemon name */
81
82 typedef unsigned short sm_ushort;
83
84 #define EOS      '\0'              /* End of string sentinel */
85 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
86
87 /*  Queue data structures  */
88
89 /*  Memory allocation control structures and storage.  */
90
91 struct abufhead {
92    struct b_queue abq;         /* Links on allocated queue */
93    unsigned ablen;             /* Buffer length in bytes */
94    const char *abfname;        /* File name pointer */
95    sm_ushort ablineno;         /* Line number of allocation */
96    bool abin_use;              /* set when malloced and cleared when free */
97 };
98
99 static struct b_queue abqueue = {    /* Allocated buffer queue */
100    &abqueue, &abqueue
101 };
102
103
104 static bool bufimode = false;   /* Buffers not tracked when True */
105
106 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
107
108
109 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
110                  tracking list.  */
111
112 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
113 {
114    char *buf;
115
116    /* Note:  Unix  MALLOC  actually  permits  a zero length to be
117       passed and allocates a valid block with  zero  user  bytes.
118       Such  a  block  can  later  be expanded with realloc().  We
119       disallow this based on the belief that it's better to  make
120       a  special case and allocate one byte in the rare case this
121       is desired than to miss all the erroneous occurrences where
122       buffer length calculation code results in a zero.  */
123
124    ASSERT(nbytes > 0);
125
126    nbytes += HEAD_SIZE + 1;
127    if ((buf = (char *)malloc(nbytes)) != NULL) {
128       struct abufhead *head = (struct abufhead *)buf;
129       P(mutex);
130       /* Enqueue buffer on allocated list */
131       qinsert(&abqueue, (struct b_queue *) buf);
132       head->ablen = nbytes;
133       head->abfname = bufimode ? NULL : fname;
134       head->ablineno = (sm_ushort)lineno;
135       head->abin_use = true;
136       /* Emplace end-clobber detector at end of buffer */
137       buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
138       buf += HEAD_SIZE;  /* Increment to user data start */
139       if (++sm_buffers > sm_max_buffers) {
140          sm_max_buffers = sm_buffers;
141       }
142       sm_bytes += nbytes;
143       if (sm_bytes > sm_max_bytes) {
144          sm_max_bytes = sm_bytes;
145       }
146       V(mutex);
147    } else {
148       Emsg0(M_ABORT, 0, _("Out of memory\n"));
149    }
150    Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
151 #if    SMALLOC_SANITY_CHECK > 0
152    if (sm_bytes > SMALLOC_SANITY_CHECK) {
153       Emsg0(M_ABORT, 0, _("Too much memory used."));
154    }
155 #endif
156    return (void *)buf;
157 }
158
159 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
160                     This is to accomodate mem_pool. */
161
162 void sm_new_owner(const char *fname, int lineno, char *buf)
163 {
164    buf -= HEAD_SIZE;  /* Decrement to header */
165    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
166    ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
167    ((struct abufhead *)buf)->abin_use = true;
168    return;
169 }
170
171 /*  SM_FREE  --  Update free pool availability.  FREE is never called
172                  except  through  this interface or by actuallyfree().
173                  free(x)  is  defined  to  generate  a  call  to  this
174                  routine.  */
175
176 void sm_free(const char *file, int line, void *fp)
177 {
178    char *cp = (char *) fp;
179    struct b_queue *qp;
180
181    if (cp == NULL) {
182       Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, line);
183    }
184
185    cp -= HEAD_SIZE;
186    qp = (struct b_queue *)cp;
187    struct abufhead *head = (struct abufhead *)cp;
188
189    P(mutex);
190    Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
191          head->ablen, fp,
192          head->abfname, head->ablineno);
193
194    if (!head->abin_use) {
195       V(mutex);
196       Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, line);
197    }
198    head->abin_use = false;
199
200    /* The following assertions will catch virtually every release
201       of an address which isn't an allocated buffer. */
202    if (qp->qnext->qprev != qp) {
203       V(mutex);
204       Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, line);
205    }
206    if (qp->qprev->qnext != qp) {
207       V(mutex);
208       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
209    }
210
211    /* The following assertion detects storing off the  end  of  the
212       allocated  space in the buffer by comparing the end of buffer
213       checksum with the address of the buffer.  */
214
215    if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
216       V(mutex);
217       Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
218    }
219    if (sm_buffers > 0) {
220       sm_buffers--;
221       sm_bytes -= head->ablen;
222    }
223
224    qdchain(qp);
225    V(mutex);
226
227    /* Now we wipe the contents of  the  just-released  buffer  with
228       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
229       bits.  This is intended to ruin the day for any miscreant who
230       attempts to access data through a pointer into storage that's
231       been previously released.
232
233       Modified, kes May, 2007 to not zap the header. This allows us
234       to check the in_use bit and detect doubly freed buffers.
235    */
236
237    memset(cp+HEAD_SIZE, 0xAA, (int)(head->ablen - HEAD_SIZE));
238
239    free(cp);
240 }
241
242 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
243                    was available.  */
244
245 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
246 {
247    void *buf;
248
249    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
250
251       /* To catch sloppy code that assumes  buffers  obtained  from
252          malloc()  are  zeroed,  we  preset  the buffer contents to
253          "designer garbage" consisting of alternating bits.  */
254
255       memset(buf, 0x55, (int) nbytes);
256    } else {
257       Emsg0(M_ABORT, 0, _("Out of memory\n"));
258    }
259    return buf;
260 }
261
262 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
263
264 void *sm_calloc(const char *fname, int lineno,
265                 unsigned int nelem, unsigned int elsize)
266 {
267    void *buf;
268
269    if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
270       memset(buf, 0, (int) (nelem * elsize));
271    } else {
272       Emsg0(M_ABORT, 0, _("Out of memory\n"));
273    }
274    return buf;
275 }
276
277 /*  SM_REALLOC  --  Adjust the size of a  previously  allocated  buffer.
278                     Note  that  the trick of "resurrecting" a previously
279                     freed buffer with realloc() is NOT supported by this
280                     function.   Further, because of the need to maintain
281                     our control storage, SM_REALLOC must always allocate
282                     a  new  block  and  copy  the data in the old block.
283                     This may result in programs which make heavy use  of
284                     realloc() running much slower than normally.  */
285
286 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
287 {
288    unsigned osize;
289    void *buf;
290    char *cp = (char *) ptr;
291
292    Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
293    if (size <= 0) {
294       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
295    }
296
297    /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
298       malloc().  SVID is silent  on  this,  but  many  C  libraries
299       permit this.  */
300    if (ptr == NULL) {
301       return sm_malloc(fname, lineno, size);
302    }
303
304    /* If the old and new sizes are the same, be a nice guy and just
305       return the buffer passed in.  */
306    cp -= HEAD_SIZE;
307    struct abufhead *head = (struct abufhead *)cp;
308    osize = head->ablen - (HEAD_SIZE + 1);
309    if (size == osize) {
310       return ptr;
311    }
312
313    /* Sizes differ.  Allocate a new buffer of the  requested  size.
314       If  we  can't  obtain  such a buffer, act as defined in SVID:
315       return NULL from  realloc()  and  leave  the  buffer  in  PTR
316       intact.  */
317
318 // sm_buffers--;
319 // sm_bytes -= head->ablen;
320
321    if ((buf = smalloc(fname, lineno, size)) != NULL) {
322       memcpy(buf, ptr, (int)sm_min(size, osize));
323       /* If the new buffer is larger than the old, fill the balance
324          of it with "designer garbage". */
325       if (size > osize) {
326          memset(((char *) buf) + osize, 0x55, (int) (size - osize));
327       }
328
329       /* All done.  Free and dechain the original buffer. */
330       sm_free(__FILE__, __LINE__, ptr);
331    }
332    Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
333    return buf;
334 }
335
336 /*  ACTUALLYMALLOC  --  Call the system malloc() function to obtain
337                         storage which will eventually be released
338                         by system or library routines not compiled
339                         using SMARTALLOC.  */
340
341 void *actuallymalloc(unsigned int size)
342 {
343    return malloc(size);
344 }
345
346 /*  ACTUALLYCALLOC  --  Call the system calloc() function to obtain
347                         storage which will eventually be released
348                         by system or library routines not compiled
349                         using SMARTALLOC.  */
350
351 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
352 {
353    return calloc(nelem, elsize);
354 }
355
356 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
357                          storage which will eventually be released
358                          by system or library routines not compiled
359                          using SMARTALLOC.  */
360
361 void *actuallyrealloc(void *ptr, unsigned int size)
362 {
363    Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
364    return realloc(ptr, size);
365 }
366
367 /*  ACTUALLYFREE  --  Interface to system free() function to release
368                       buffers allocated by low-level routines. */
369
370 void actuallyfree(void *cp)
371 {
372    free(cp);
373 }
374
375 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
376  *               True).
377  *  N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
378  *    as they have all been shut down at this point.
379  */
380 void sm_dump(bool bufdump, bool in_use) 
381 {
382    struct abufhead *ap;
383
384    P(mutex);
385
386    ap = (struct abufhead *)abqueue.qnext;
387
388    while (ap != (struct abufhead *) &abqueue) {
389
390       if ((ap == NULL) ||
391           (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
392           (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
393          fprintf(stderr, _(
394             "\nOrphaned buffers exist.  Dump terminated following\n"
395             "  discovery of bad links in chain of orphaned buffers.\n"
396             "  Buffer address with bad links: %p\n"), ap);
397          break;
398       }
399
400       if (ap->abfname != NULL) {
401          unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
402          char errmsg[500];
403          char *cp = ((char *)ap) + HEAD_SIZE;
404
405          bsnprintf(errmsg, sizeof(errmsg),
406            _("%s buffer:  %s %6u bytes buf=%p allocated at %s:%d\n"),
407             in_use?"In use":"Orphaned",
408             my_name, memsize, cp, ap->abfname, ap->ablineno
409          );
410          fprintf(stderr, "%s", errmsg);
411          if (bufdump) {
412             char buf[20];
413             unsigned llen = 0;
414
415             errmsg[0] = EOS;
416             while (memsize) {
417                if (llen >= 16) {
418                   bstrncat(errmsg, "\n", sizeof(errmsg));
419                   llen = 0;
420                   fprintf(stderr, "%s", errmsg);
421                   errmsg[0] = EOS;
422                }
423                bsnprintf(buf, sizeof(buf), " %02X",
424                   (*cp++) & 0xFF);
425                bstrncat(errmsg, buf, sizeof(errmsg));
426                llen++;
427                memsize--;
428             }
429             fprintf(stderr, "%s\n", errmsg);
430          }
431       }
432       ap = (struct abufhead *) ap->abq.qnext;
433    }
434    V(mutex);
435 }
436
437 #undef sm_check
438 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
439 void sm_check(const char *fname, int lineno, bool bufdump)
440 {
441    if (!sm_check_rtn(fname, lineno, bufdump)) {
442       Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
443             fname, lineno);
444    }
445 }
446
447 #undef sm_check_rtn
448 /*  SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
449 int sm_check_rtn(const char *fname, int lineno, bool bufdump)
450 {
451    struct abufhead *ap;
452    int bad, badbuf = 0;
453
454    P(mutex);
455    ap = (struct abufhead *) abqueue.qnext;
456    while (ap != (struct abufhead *)&abqueue) {
457       bad = 0;
458       if (ap != NULL) {
459          if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
460             bad = 0x1;
461          }
462          if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
463             bad |= 0x2;
464          }
465          if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
466               ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
467             bad |= 0x4;
468          }
469       } else {
470          bad = 0x8;
471       }
472       badbuf |= bad;
473       if (bad) {
474          fprintf(stderr,
475             _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
476
477          if (bad & 0x1) {
478             fprintf(stderr, _("  discovery of bad prev link.\n"));
479          }
480          if (bad & 0x2) {
481             fprintf(stderr, _("  discovery of bad next link.\n"));
482          }
483          if (bad & 0x4) {
484             fprintf(stderr, _("  discovery of data overrun.\n"));
485          }
486          if (bad & 0x8) {
487             fprintf(stderr, _("  NULL pointer.\n"));
488          }
489
490          if (!ap) {
491             goto get_out;
492          }
493          fprintf(stderr, _("  Buffer address: %p\n"), ap);
494
495          if (ap->abfname != NULL) {
496             unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
497             char errmsg[80];
498
499             fprintf(stderr,
500               _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
501                memsize, ap->ablineno, my_name, ap->abfname
502             );
503             if (bufdump) {
504                unsigned llen = 0;
505                char *cp = ((char *) ap) + HEAD_SIZE;
506
507                errmsg[0] = EOS;
508                while (memsize) {
509                   if (llen >= 16) {
510                      strcat(errmsg, "\n");
511                      llen = 0;
512                      fprintf(stderr, "%s", errmsg);
513                      errmsg[0] = EOS;
514                   }
515                   if (*cp < 0x20) {
516                      sprintf(errmsg + strlen(errmsg), " %02X",
517                         (*cp++) & 0xFF);
518                   } else {
519                      sprintf(errmsg + strlen(errmsg), " %c ",
520                         (*cp++) & 0xFF);
521                   }
522                   llen++;
523                   memsize--;
524                }
525                fprintf(stderr, "%s\n", errmsg);
526             }
527          }
528       }
529       ap = (struct abufhead *)ap->abq.qnext;
530    }
531 get_out:
532    V(mutex);
533    return badbuf ? 0 : 1;
534 }
535
536
537 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
538                    items  as buffers allocated during initialisation) by
539                    calling   sm_static(1).    Normal   orphaned   buffer
540                    detection  can be re-enabled with sm_static(0).  Note
541                    that all the other safeguards still apply to  buffers
542                    allocated  when  sm_static(1)  mode is in effect.  */
543
544 void sm_static(bool mode)
545 {
546    bufimode = mode;
547 }
548
549 /*
550  * Here we overload C++'s global new and delete operators
551  *  so that the memory is allocated through smartalloc.
552  */
553
554 #ifdef xxx
555 void * operator new(size_t size)
556 {
557 // Dmsg1(000, "new called %d\n", size);
558    return sm_malloc(__FILE__, __LINE__, size);
559 }
560
561 void operator delete(void *buf)
562 {
563 // Dmsg1(000, "free called 0x%x\n", buf);
564    sm_free(__FILE__, __LINE__, buf);
565 }
566 #endif
567
568 #endif