LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/libdm/mm - dbg_malloc.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 78 104 75.0 %
Date: 2010-04-13 Functions: 6 7 85.7 %
Branches: 42 78 53.8 %

           Branch data     Line data    Source code
       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                 :         16 : char *dm_strdup_aux(const char *str, const char *file, int line)
      22                 :            : {
      23                 :            :         char *ret;
      24                 :            : 
      25         [ -  + ]:         16 :         if (!str) {
      26         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "dm_strdup called with NULL pointer");
      27                 :          0 :                 return NULL;
      28                 :            :         }
      29                 :            : 
      30         [ +  - ]:         16 :         if ((ret = dm_malloc_aux_debug(strlen(str) + 1, file, line)))
      31                 :         16 :                 strcpy(ret, str);
      32                 :            : 
      33                 :         16 :         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                 :       2468 : void *dm_malloc_aux_debug(size_t s, const char *file, int line)
      58                 :            : {
      59                 :            :         struct memblock *nb;
      60                 :       2468 :         size_t tsize = s + sizeof(*nb) + sizeof(unsigned long);
      61                 :            : 
      62         [ -  + ]:       2468 :         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         [ -  + ]:       2468 :         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                 :       2468 :         nb->file = file;
      76                 :       2468 :         nb->line = line;
      77                 :            : 
      78                 :       2468 :         dm_bounds_check();
      79                 :            : 
      80                 :            :         /* setup fields */
      81                 :       2468 :         nb->magic = nb + 1;
      82                 :       2468 :         nb->length = s;
      83                 :       2468 :         nb->id = ++_mem_stats.block_serialno;
      84                 :       2468 :         nb->next = 0;
      85                 :            : 
      86                 :            :         /* stomp a pretty pattern across the new memory
      87                 :            :            and fill in the boundary bytes */
      88                 :            :         {
      89                 :       2468 :                 char *ptr = (char *) (nb + 1);
      90                 :            :                 size_t i;
      91         [ +  + ]:   25528247 :                 for (i = 0; i < s; i++)
      92         [ +  + ]:   25525779 :                         *ptr++ = i & 0x1 ? (char) 0xba : (char) 0xbe;
      93                 :            : 
      94         [ +  + ]:      12340 :                 for (i = 0; i < sizeof(unsigned long); i++)
      95                 :       9872 :                         *ptr++ = (char) nb->id;
      96                 :            :         }
      97                 :            : 
      98                 :       2468 :         nb->prev = _tail;
      99                 :            : 
     100                 :            :         /* link to tail of the list */
     101         [ +  + ]:       2468 :         if (!_head)
     102                 :          1 :                 _head = _tail = nb;
     103                 :            :         else {
     104                 :       2467 :                 _tail->next = nb;
     105                 :       2467 :                 _tail = nb;
     106                 :            :         }
     107                 :            : 
     108                 :       2468 :         _mem_stats.blocks_allocated++;
     109         [ +  + ]:       2468 :         if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
     110                 :       1599 :                 _mem_stats.blocks_max = _mem_stats.blocks_allocated;
     111                 :            : 
     112                 :       2468 :         _mem_stats.bytes += s;
     113         [ +  + ]:       2468 :         if (_mem_stats.bytes > _mem_stats.mbytes)
     114                 :       1547 :                 _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                 :       2468 :         return nb + 1;
     120                 :            : }
     121                 :            : 
     122                 :       2497 : void dm_free_aux(void *p)
     123                 :            : {
     124                 :            :         char *ptr;
     125                 :            :         size_t i;
     126                 :       2497 :         struct memblock *mb = ((struct memblock *) p) - 1;
     127         [ +  + ]:       2497 :         if (!p)
     128                 :         29 :                 return;
     129                 :            : 
     130                 :       2468 :         dm_bounds_check();
     131                 :            : 
     132                 :            :         /* sanity check */
     133         [ -  + ]:       2468 :         assert(mb->magic == p);
     134                 :            : 
     135                 :            :         /* check data at the far boundary */
     136                 :       2468 :         ptr = ((char *) mb) + sizeof(struct memblock) + mb->length;
     137         [ +  + ]:      12340 :         for (i = 0; i < sizeof(unsigned long); i++)
     138         [ -  + ]:       9872 :                 if (*ptr++ != (char) mb->id)
     139                 :          0 :                         assert(!"Damage at far end of block");
     140                 :            : 
     141                 :            :         /* have we freed this before ? */
     142         [ -  + ]:       2468 :         assert(mb->id != 0);
     143                 :            : 
     144                 :            :         /* unlink */
     145         [ +  + ]:       2468 :         if (mb->prev)
     146                 :       2467 :                 mb->prev->next = mb->next;
     147                 :            :         else
     148                 :          1 :                 _head = mb->next;
     149                 :            : 
     150         [ +  + ]:       2468 :         if (mb->next)
     151                 :       2170 :                 mb->next->prev = mb->prev;
     152                 :            :         else
     153                 :        298 :                 _tail = mb->prev;
     154                 :            : 
     155                 :       2468 :         mb->id = 0;
     156                 :            : 
     157                 :            :         /* stomp a different pattern across the memory */
     158                 :       2468 :         ptr = ((char *) mb) + sizeof(struct memblock);
     159         [ +  + ]:   25528247 :         for (i = 0; i < mb->length; i++)
     160         [ +  + ]:   25525779 :                 *ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
     161                 :            : 
     162         [ -  + ]:       2468 :         assert(_mem_stats.blocks_allocated);
     163                 :       2468 :         _mem_stats.blocks_allocated--;
     164                 :       2468 :         _mem_stats.bytes -= mb->length;
     165                 :            : 
     166                 :            :         /* free the memory */
     167                 :       2497 :         free(mb);
     168                 :            : }
     169                 :            : 
     170                 :          2 : void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line)
     171                 :            : {
     172                 :            :         void *r;
     173                 :          2 :         struct memblock *mb = ((struct memblock *) p) - 1;
     174                 :            : 
     175                 :          2 :         r = dm_malloc_aux_debug(s, file, line);
     176                 :            : 
     177         [ +  + ]:          2 :         if (p) {
     178                 :          1 :                 memcpy(r, p, mb->length);
     179                 :          1 :                 dm_free_aux(p);
     180                 :            :         }
     181                 :            : 
     182                 :          2 :         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                 :       4936 : void dm_bounds_check_debug(void)
     221                 :            : {
     222                 :       4936 :         struct memblock *mb = _head;
     223         [ +  + ]:    2941760 :         while (mb) {
     224                 :            :                 size_t i;
     225                 :    2936824 :                 char *ptr = ((char *) (mb + 1)) + mb->length;
     226         [ +  + ]:   14684120 :                 for (i = 0; i < sizeof(unsigned long); i++)
     227         [ -  + ]:   11747296 :                         if (*ptr++ != (char) mb->id)
     228                 :          0 :                                 assert(!"Memory smash");
     229                 :            : 
     230                 :    2936824 :                 mb = mb->next;
     231                 :            :         }
     232                 :       4936 : }
     233                 :            : 
     234                 :          0 : void *dm_malloc_aux(size_t s, const char *file __attribute((unused)),
     235                 :            :                     int line __attribute((unused)))
     236                 :            : {
     237         [ #  # ]:          0 :         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                 :          0 :         return malloc(s);
     244                 :            : }

Generated by: LCOV version 1.8