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