LCOV - code coverage report
Current view: directory - libdm/mm - dbg_malloc.c (source / functions) Found Hit Coverage
Test: unnamed Lines: 104 74 71.2 %
Date: 2010-04-13 Functions: 7 6 85.7 %

       1                 : /*
       2                 :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
       3                 :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :  *
       5                 :  * This file is part of the device-mapper userspace tools.
       6                 :  *
       7                 :  * This copyrighted material is made available to anyone wishing to use,
       8                 :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :  * of the GNU Lesser General Public License v.2.1.
      10                 :  *
      11                 :  * You should have received a copy of the GNU Lesser General Public License
      12                 :  * along with this program; if not, write to the Free Software Foundation,
      13                 :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :  */
      15                 : 
      16                 : #include "dmlib.h"
      17                 : 
      18                 : #include <assert.h>
      19                 : #include <stdarg.h>
      20                 : 
      21            2108 : char *dm_strdup_aux(const char *str, const char *file, int line)
      22                 : {
      23                 :         char *ret;
      24                 : 
      25            2108 :         if (!str) {
      26               0 :                 log_error(INTERNAL_ERROR "dm_strdup called with NULL pointer");
      27               0 :                 return NULL;
      28                 :         }
      29                 : 
      30            2108 :         if ((ret = dm_malloc_aux_debug(strlen(str) + 1, file, line)))
      31            2108 :                 strcpy(ret, str);
      32                 : 
      33            2108 :         return ret;
      34                 : }
      35                 : 
      36                 : struct memblock {
      37                 :         struct memblock *prev, *next;   /* All allocated blocks are linked */
      38                 :         size_t length;          /* Size of the requested block */
      39                 :         int id;                 /* Index of the block */
      40                 :         const char *file;       /* File that allocated */
      41                 :         int line;               /* Line that allocated */
      42                 :         void *magic;            /* Address of this block */
      43                 : } __attribute__((aligned(8)));
      44                 : 
      45                 : static struct {
      46                 :         unsigned block_serialno;/* Non-decreasing serialno of block */
      47                 :         unsigned blocks_allocated; /* Current number of blocks allocated */
      48                 :         unsigned blocks_max;    /* Max no of concurrently-allocated blocks */
      49                 :         unsigned int bytes, mbytes;
      50                 : 
      51                 : } _mem_stats = {
      52                 : 0, 0, 0, 0, 0};
      53                 : 
      54                 : static struct memblock *_head = 0;
      55                 : static struct memblock *_tail = 0;
      56                 : 
      57           10414 : void *dm_malloc_aux_debug(size_t s, const char *file, int line)
      58                 : {
      59                 :         struct memblock *nb;
      60           10414 :         size_t tsize = s + sizeof(*nb) + sizeof(unsigned long);
      61                 : 
      62           10414 :         if (s > 50000000) {
      63               0 :                 log_error("Huge memory allocation (size %" PRIsize_t
      64                 :                           ") rejected - metadata corruption?", s);
      65               0 :                 return 0;
      66                 :         }
      67                 : 
      68           10414 :         if (!(nb = malloc(tsize))) {
      69               0 :                 log_error("couldn't allocate any memory, size = %" PRIsize_t,
      70                 :                           s);
      71               0 :                 return 0;
      72                 :         }
      73                 : 
      74                 :         /* set up the file and line info */
      75           10414 :         nb->file = file;
      76           10414 :         nb->line = line;
      77                 : 
      78           10414 :         dm_bounds_check();
      79                 : 
      80                 :         /* setup fields */
      81           10414 :         nb->magic = nb + 1;
      82           10414 :         nb->length = s;
      83           10414 :         nb->id = ++_mem_stats.block_serialno;
      84           10414 :         nb->next = 0;
      85                 : 
      86                 :         /* stomp a pretty pattern across the new memory
      87                 :            and fill in the boundary bytes */
      88                 :         {
      89           10414 :                 char *ptr = (char *) (nb + 1);
      90                 :                 size_t i;
      91        62914670 :                 for (i = 0; i < s; i++)
      92        62904256 :                         *ptr++ = i & 0x1 ? (char) 0xba : (char) 0xbe;
      93                 : 
      94           93726 :                 for (i = 0; i < sizeof(unsigned long); i++)
      95           83312 :                         *ptr++ = (char) nb->id;
      96                 :         }
      97                 : 
      98           10414 :         nb->prev = _tail;
      99                 : 
     100                 :         /* link to tail of the list */
     101           10414 :         if (!_head)
     102             605 :                 _head = _tail = nb;
     103                 :         else {
     104            9809 :                 _tail->next = nb;
     105            9809 :                 _tail = nb;
     106                 :         }
     107                 : 
     108           10414 :         _mem_stats.blocks_allocated++;
     109           10414 :         if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
     110            5601 :                 _mem_stats.blocks_max = _mem_stats.blocks_allocated;
     111                 : 
     112           10414 :         _mem_stats.bytes += s;
     113           10414 :         if (_mem_stats.bytes > _mem_stats.mbytes)
     114            5008 :                 _mem_stats.mbytes = _mem_stats.bytes;
     115                 : 
     116                 :         /* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
     117                 :                   _mem_stats.bytes); */
     118                 : 
     119           10414 :         return nb + 1;
     120                 : }
     121                 : 
     122           10141 : void dm_free_aux(void *p)
     123                 : {
     124                 :         char *ptr;
     125                 :         size_t i;
     126           10141 :         struct memblock *mb = ((struct memblock *) p) - 1;
     127           10141 :         if (!p)
     128             329 :                 return;
     129                 : 
     130            9812 :         dm_bounds_check();
     131                 : 
     132                 :         /* sanity check */
     133            9812 :         assert(mb->magic == p);
     134                 : 
     135                 :         /* check data at the far boundary */
     136            9812 :         ptr = ((char *) mb) + sizeof(struct memblock) + mb->length;
     137           88308 :         for (i = 0; i < sizeof(unsigned long); i++)
     138           78496 :                 if (*ptr++ != (char) mb->id)
     139               0 :                         assert(!"Damage at far end of block");
     140                 : 
     141                 :         /* have we freed this before ? */
     142            9812 :         assert(mb->id != 0);
     143                 : 
     144                 :         /* unlink */
     145            9812 :         if (mb->prev)
     146            9207 :                 mb->prev->next = mb->next;
     147                 :         else
     148             605 :                 _head = mb->next;
     149                 : 
     150            9812 :         if (mb->next)
     151            7044 :                 mb->next->prev = mb->prev;
     152                 :         else
     153            2768 :                 _tail = mb->prev;
     154                 : 
     155            9812 :         mb->id = 0;
     156                 : 
     157                 :         /* stomp a different pattern across the memory */
     158            9812 :         ptr = ((char *) mb) + sizeof(struct memblock);
     159        62858684 :         for (i = 0; i < mb->length; i++)
     160        62848872 :                 *ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
     161                 : 
     162            9812 :         assert(_mem_stats.blocks_allocated);
     163            9812 :         _mem_stats.blocks_allocated--;
     164            9812 :         _mem_stats.bytes -= mb->length;
     165                 : 
     166                 :         /* free the memory */
     167            9812 :         free(mb);
     168                 : }
     169                 : 
     170               0 : void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line)
     171                 : {
     172                 :         void *r;
     173               0 :         struct memblock *mb = ((struct memblock *) p) - 1;
     174                 : 
     175               0 :         r = dm_malloc_aux_debug(s, file, line);
     176                 : 
     177               0 :         if (p) {
     178               0 :                 memcpy(r, p, mb->length);
     179               0 :                 dm_free_aux(p);
     180                 :         }
     181                 : 
     182               0 :         return r;
     183                 : }
     184                 : 
     185               1 : int dm_dump_memory_debug(void)
     186                 : {
     187               1 :         unsigned long tot = 0;
     188                 :         struct memblock *mb;
     189                 :         char str[32];
     190                 :         size_t c;
     191                 : 
     192               1 :         if (_head)
     193               0 :                 log_very_verbose("You have a memory leak:");
     194                 : 
     195               1 :         for (mb = _head; mb; mb = mb->next) {
     196               0 :                 for (c = 0; c < sizeof(str) - 1; c++) {
     197               0 :                         if (c >= mb->length)
     198               0 :                                 str[c] = ' ';
     199               0 :                         else if (*(char *)(mb->magic + c) == '\0')
     200               0 :                                 str[c] = '\0';
     201               0 :                         else if (*(char *)(mb->magic + c) < ' ')
     202               0 :                                 str[c] = '?';
     203                 :                         else
     204               0 :                                 str[c] = *(char *)(mb->magic + c);
     205                 :                 }
     206               0 :                 str[sizeof(str) - 1] = '\0';
     207                 : 
     208               0 :                 LOG_MESG(_LOG_INFO, mb->file, mb->line, 0,
     209                 :                          "block %d at %p, size %" PRIsize_t "\t [%s]",
     210                 :                          mb->id, mb->magic, mb->length, str);
     211               0 :                 tot += mb->length;
     212                 :         }
     213                 : 
     214               1 :         if (_head)
     215               0 :                 log_very_verbose("%ld bytes leaked in total", tot);
     216                 : 
     217               1 :         return 1;
     218                 : }
     219                 : 
     220           20226 : void dm_bounds_check_debug(void)
     221                 : {
     222           20226 :         struct memblock *mb = _head;
     223         5048640 :         while (mb) {
     224                 :                 size_t i;
     225         5008188 :                 char *ptr = ((char *) (mb + 1)) + mb->length;
     226        45073692 :                 for (i = 0; i < sizeof(unsigned long); i++)
     227        40065504 :                         if (*ptr++ != (char) mb->id)
     228               0 :                                 assert(!"Memory smash");
     229                 : 
     230         5008188 :                 mb = mb->next;
     231                 :         }
     232           20226 : }
     233                 : 
     234            1949 : void *dm_malloc_aux(size_t s, const char *file __attribute((unused)),
     235                 :                     int line __attribute((unused)))
     236                 : {
     237            1949 :         if (s > 50000000) {
     238               0 :                 log_error("Huge memory allocation (size %" PRIsize_t
     239                 :                           ") rejected - metadata corruption?", s);
     240               0 :                 return 0;
     241                 :         }
     242                 : 
     243            1949 :         return malloc(s);
     244                 : }

Generated by: LCOV version 1.7