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