Kannel: Open Source WAP and SMS gateway  svn-r5335
gwmem-check.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * gwmem-check.c - memory management wrapper functions, check flavor
59  *
60  * This implementation of the gwmem.h interface checks for writes to
61  * non-allocated areas, and fills freshly allocated and freshly freed
62  * areas with garbage to prevent their use. It also reports memory
63  * leaks.
64  *
65  * Design: Memory is allocated with markers before and after the
66  * area to be used. These markers can be checked to see if anything
67  * has written to them. There is a table of all allocated areas,
68  * which is used to detect memory leaks and which contains context
69  * information about each area.
70  *
71  * The start marker contains the index into this table, so that it
72  * can be looked up quickly -- but if the start marker has been damaged,
73  * the index can still be found by searching the table.
74  *
75  * Enlarging an area with realloc is handled by allocating new area,
76  * copying the old data, and freeing the old area. This is an expensive
77  * operation which is avoided by reserving extra space (up to the nearest
78  * power of two), and only enlarging the area if the requested space is
79  * larger than this extra space. The markers are still placed at exactly
80  * the size requested, so every realloc does mean moving the end marker.
81  *
82  * When data is freed, it is overwritten with 0xdeadbeef, so that code
83  * that tries to use it after freeing will likely crash. The freed area
84  * is kept around for a while, to see if anything tries to write to it
85  * after it's been freed.
86  *
87  * Richard Braakman
88  * Alexander Malysh (added backtrace support)
89  */
90 
91 #include "gw-config.h"
92 
93 #include <stdlib.h>
94 #include <errno.h>
95 #include <string.h>
96 #if HAVE_BACKTRACE
97 #include <execinfo.h>
98 #endif
99 
100 #include "gwlib.h"
101 
102 /* In this module, we must use the real versions so let's undefine the
103  * accident protectors. */
104 #undef malloc
105 #undef realloc
106 #undef calloc
107 #undef free
108 
109 /* Freshly malloced space is filled with NEW_AREA_PATTERN, to break
110  * code that assumes it is filled with zeroes. */
111 #define NEW_AREA_PATTERN 0xcafebabe
112 
113 /* Freed space is filled with FREE_AREA_PATTERN, to break code that
114  * tries to read from it after freeing. */
115 #define FREE_AREA_PATTERN 0xdeadbeef
116 
117 /* The marker before an area is filled with START_MARK_PATTERN
118  * (except for some bookkeeping bytes at the start of the marker). */
119 #define START_MARK_PATTERN 0xdadaface
120 
121 /* The marker beyond an area is filled with END_MARK_PATTERN. */
122 #define END_MARK_PATTERN 0xadadafec
123 
124 /* How many bytes to dump when listing unfreed areas. */
125 #define MAX_DUMP 16
126 
127 static int initialized = 0;
128 
129 /* Use slower, more reliable method of detecting memory corruption. */
130 static int slow = 0;
131 
132 /* We have to use a static mutex here, because otherwise the mutex_create
133  * call would try to allocate memory with gw_malloc before we're
134  * initialized. */
136 
137 struct location
138 {
139  const char *filename;
140  long lineno;
141  const char *function;
142 };
143 
144 /* Duplicating the often-identical location information in every table
145  * entry uses a lot of memory, but saves the effort of maintaining a
146  * data structure for it, and keeps access to it fast. */
147 struct area
148 {
149  void *area; /* The allocated memory area, as seen by caller */
150  size_t area_size; /* Size requested by caller */
151  size_t max_size; /* Size we can expand area to when reallocing */
152  struct location allocator; /* Caller that alloced area */
153  struct location reallocator; /* Caller that last realloced area */
154  struct location claimer; /* Owner of area, set by caller */
155 #if HAVE_BACKTRACE
156  void *frames[10]; /* 10 callers should be sufficient */
157  size_t frame_size;
158 #endif
159 };
160 
161 /* Number of bytes to reserve on either side of each allocated area,
162  * to detect writes just outside the area. It must be at least large
163  * enough to hold a long. */
164 #define MARKER_SIZE 16
165 
166 /* 100 MB */
167 #define MAX_TAB_SIZE (100*1024*1024L)
168 #define MAX_ALLOCATIONS ((long) (MAX_TAB_SIZE/sizeof(struct area)))
169 
170 /* Freed areas are thrown into the free ring. They are not released
171  * back to the system until FREE_RING_SIZE other allocations have been
172  * made. This is more effective at finding bugs than releasing them
173  * immediately, because when we eventually release them we can check
174  * that they have not been tampered with in that time. */
175 #define FREE_RING_SIZE 1024
176 
179 
180 /* Current number of allocations in the "allocated" table. They are
181  * always consecutive and start at the beginning of the table. */
182 static long num_allocations;
183 
184 /* The free ring can wrap around the edges of its array. */
185 static long free_ring_start;
186 static long free_ring_len;
187 
188 /* The next three are used for informational messages at shutdown */
189 /* Largest number of allocations we've had at one time */
191 /* Largest value of the sum of allocated areas we've had at one time */
192 static long highest_total_size;
193 /* Current sum of allocated areas */
194 static long total_size;
195 
196 /* Static functions */
197 
198 static inline void lock(void)
199 {
201 }
202 
203 static inline void unlock(void)
204 {
206 }
207 
208 static unsigned long round_pow2(unsigned long num)
209 {
210  unsigned long i;
211 
212  if (num <= 16)
213  return 16;
214 
215  for (i = 32; i < 0x80000000L; i <<= 1) {
216  if (num <= i)
217  return i;
218  }
219 
220  /* We have to handle this case separately; the loop cannot go that
221  * far because i would overflow. */
222  if (num <= 0x80000000L)
223  return 0x80000000L;
224 
225  return 0xffffffffL;
226 }
227 
228 /* Fill a memory area with a bit pattern */
229 static void fill(unsigned char *p, size_t bytes, long pattern)
230 {
231  while (bytes > sizeof(pattern)) {
232  memcpy(p, &pattern, sizeof(pattern));
233  p += sizeof(pattern);
234  bytes -= sizeof(pattern);
235  }
236  if (bytes > 0)
237  memcpy(p, &pattern, bytes);
238 }
239 
240 /* Check that a filled memory area has not changed */
241 static int untouched(unsigned char *p, size_t bytes, long pattern)
242 {
243  while (bytes > sizeof(pattern)) {
244  if (memcmp(p, &pattern, sizeof(pattern)) != 0)
245  return 0;
246  p += sizeof(pattern);
247  bytes -= sizeof(pattern);
248  }
249  if (bytes > 0 && memcmp(p, &pattern, bytes) != 0)
250  return 0;
251  return 1;
252 }
253 
254 /* Fill the end marker for this area */
255 static inline void endmark(unsigned char *p, size_t size)
256 {
258 }
259 
260 /* Fill the start marker for this area, and assign an number to the
261  * area which can be used for quick lookups later. The number must
262  * not be negative. */
263 static void startmark(unsigned char *p, long number)
264 {
265  gw_assert(MARKER_SIZE >= sizeof(long));
266  gw_assert(number >= 0);
267 
268  fill(p - MARKER_SIZE, sizeof(long), number);
269  fill(p - MARKER_SIZE + sizeof(long),
270  MARKER_SIZE - sizeof(long), START_MARK_PATTERN);
271 }
272 
273 /* Check that the start marker for this area are intact, and return the
274  * marker number if it seems intact. Return a negative number if
275  * it does not seem intact. */
276 static long check_startmark(unsigned char *p)
277 {
278  long number;
279  if (!untouched(p - MARKER_SIZE + sizeof(long),
280  MARKER_SIZE - sizeof(long), START_MARK_PATTERN))
281  return -1;
282  memcpy(&number, p - MARKER_SIZE, sizeof(number));
283  return number;
284 }
285 
286 static int check_endmark(unsigned char *p, size_t size)
287 {
289  return -1;
290  return 0;
291 }
292 
293 static int check_marks(struct area *area, long index)
294 {
295  int result = 0;
296 
297  if (check_startmark(area->area) != index) {
298  error(0, "Start marker was damaged for area %ld", index);
299  result = -1;
300  }
301  if (check_endmark(area->area, area->area_size) < 0) {
302  error(0, "End marker was damaged for area %ld", index);
303  result = -1;
304  }
305 
306  return result;
307 }
308 
309 static void dump_area(struct area *area)
310 {
311  debug("gwlib.gwmem", 0, "Area %p, size %ld, max_size %ld",
312  area->area, (long) area->area_size, (long) area->max_size);
313  debug("gwlib.gwmem", 0, "Allocated by %s() at %s:%ld",
317  if (area->reallocator.function) {
318  debug("gwlib.gwmem", 0, "Re-allocated by %s() at %s:%ld",
322  }
323  if (area->claimer.function) {
324  debug("gwlib.gwmem", 0, "Claimed by %s() at %s:%ld",
327  area->claimer.lineno);
328  }
329  if (area->area_size > 0) {
330  size_t i;
331  unsigned char *p;
332  char buf[MAX_DUMP * 3 + 1];
333 
334  p = area->area;
335  buf[0] = '\0';
336  for (i = 0; i < area->area_size && i < MAX_DUMP; ++i)
337  sprintf(strchr(buf, '\0'), "%02x ", p[i]);
338 
339  debug("gwlib.gwmem", 0, "Contents of area (first %d bytes):", MAX_DUMP);
340  debug("gwlib.gwmem", 0, " %s", buf);
341  }
342 #if HAVE_BACKTRACE
343  {
344  size_t i;
345  char **strings = backtrace_symbols(area->frames, area->frame_size);
346  debug("gwlib.gwmem", 0, "Backtrace of last malloc/realloc:");
347  for (i = 0; i < area->frame_size; i++) {
348  if (strings != NULL)
349  debug("gwlib.gwmem", 0, "%s", strings[i]);
350  else
351  debug("gwlib.gwmem", 0, "%p", area->frames[i]);
352  }
353  free(strings);
354  }
355 #endif
356 }
357 
358 static struct area *find_area(unsigned char *p)
359 {
360  long index;
361  struct area *area;
362  long suspicious_pointer;
363  unsigned long p_ul;
364 
365  gw_assert(p != NULL);
366 
367  p_ul = (unsigned long) p;
368  suspicious_pointer =
369  (sizeof(p) == sizeof(long) &&
370  (p_ul == NEW_AREA_PATTERN || p_ul == FREE_AREA_PATTERN ||
371  p_ul == START_MARK_PATTERN || p_ul == END_MARK_PATTERN));
372 
373  if (slow || suspicious_pointer) {
374  /* Extra check, which does not touch the (perhaps not allocated)
375  * memory area. It's slow, but may help pinpoint problems that
376  * would otherwise cause segfaults. */
377  for (index = 0; index < num_allocations; index++) {
378  if (allocated[index].area == p)
379  break;
380  }
381  if (index == num_allocations) {
382  error(0, "Area %p not found in allocation table.", p);
383  return NULL;
384  }
385  }
386 
387  index = check_startmark(p);
388  if (index >= 0 && index < num_allocations &&
389  allocated[index].area == p) {
390  area = &allocated[index];
391  if (check_endmark(p, area->area_size) < 0) {
392  error(0, "End marker was damaged for area %p", p);
393  dump_area(area);
394  }
395  return area;
396  }
397 
398  error(0, "Start marker was damaged for area %p", p);
399  for (index = 0; index < num_allocations; index++) {
400  if (allocated[index].area == p) {
401  area = &allocated[index];
402  dump_area(area);
403  return area;
404  }
405  }
406 
407  error(0, "Could not find area information.");
408  return NULL;
409 }
410 
411 static void change_total_size(long change)
412 {
413  total_size += change;
416 }
417 
418 static struct area *record_allocation(unsigned char *p, size_t size,
419  const char *filename, long lineno, const char *function)
420 {
421  struct area *area;
422  static struct area empty_area;
423 
425  panic(0, "Too many concurrent allocations.");
426  }
427 
429  *area = empty_area;
430  area->area = p;
431  area->area_size = size;
432  area->max_size = size;
434  area->allocator.lineno = lineno;
435  area->allocator.function = function;
436 #if HAVE_BACKTRACE
437  area->frame_size = backtrace(area->frames, sizeof(area->frames) / sizeof(void*));
438 #endif
439 
442 
443  num_allocations++;
447 
448  return area;
449 }
450 
451 static void remove_allocation(struct area *area)
452 {
454  num_allocations--;
455  if (area == &allocated[num_allocations])
456  return;
460 }
461 
462 static void drop_from_free_ring(long index)
463 {
464  struct area *area;
465 
466  area = &free_ring[index];
467  if (check_marks(area, index) < 0 ||
469  error(0, "Freed area %p has been tampered with.", area->area);
470  dump_area(area);
471  }
472  free((unsigned char *)area->area - MARKER_SIZE);
473 }
474 
475 static void put_on_free_ring(struct area *area)
476 {
477  /* Simple case: We're still filling the free ring. */
481  free_ring_len++;
482  return;
483  }
484 
485  /* Normal case: We need to check and release a free ring entry,
486  * then put this one in its place. */
487 
492 }
493 
494 static void free_area(struct area *area)
495 {
499 }
500 
501 void gw_check_init_mem(int slow_flag)
502 {
504  slow = slow_flag;
505  initialized = 1;
506 }
507 
509 {
511  initialized = 0;
512 }
513 
514 void *gw_check_malloc(size_t size, const char *filename, long lineno,
515  const char *function)
516 {
517  unsigned char *p;
518 
520 
521  /* ANSI C89 says malloc(0) is implementation-defined. Avoid it. */
522  gw_assert(size > 0);
523 
524  p = malloc(size + 2 * MARKER_SIZE);
525  if (p == NULL)
526  panic(errno, "Memory allocation of %ld bytes failed.", (long)size);
527  p += MARKER_SIZE;
528 
529  lock();
531  record_allocation(p, size, filename, lineno, function);
532  unlock();
533 
534  return p;
535 }
536 
537 void *gw_check_calloc(int nmemb, size_t size, const char *filename, long lineno,
538  const char *function)
539 {
540  unsigned char *p;
541 
543 
544  /* ANSI C89 says malloc(0) is implementation-defined. Avoid it. */
545  gw_assert(size > 0);
546  gw_assert(nmemb > 0);
547 
548  p = calloc(1, (nmemb*size) + 2 * MARKER_SIZE);
549  if (p == NULL)
550  panic(errno, "Memory allocation of %ld bytes failed.", (long)size);
551 
552  p += MARKER_SIZE;
553 
554  lock();
555  record_allocation(p, size, filename, lineno, function);
556  unlock();
557 
558  return p;
559 }
560 
561 void *gw_check_realloc(void *p, size_t size, const char *filename,
562  long lineno, const char *function)
563 {
564  struct area *area;
565 
566  if (p == NULL)
567  return gw_check_malloc(size, filename, lineno, function);
568 
570  gw_assert(size > 0);
571 
572  lock();
573  area = find_area(p);
574  if (!area) {
575  unlock();
576  panic(0, "Realloc called on non-allocated area");
577  }
578 
579  if (size == area->area_size) {
580  /* No changes */
581  } else if (size <= area->max_size) {
583  area->area_size = size;
584  endmark(p, size);
585  } else if (size > area->max_size) {
586  /* The current block is not large enough for the reallocation.
587  * We will allocate a new block, copy the data over, and free
588  * the old block. We round the size up to a power of two,
589  * to prevent frequent reallocations. */
590  struct area *new_area;
591  size_t new_size;
592  unsigned char *new_p;
593 
594  new_size = round_pow2(size + 2 * MARKER_SIZE);
595  new_p = malloc(new_size);
596  new_size -= 2 * MARKER_SIZE;
597  new_p += MARKER_SIZE;
598  memcpy(new_p, p, area->area_size);
599  fill(new_p + area->area_size, size - area->area_size,
601  new_area = record_allocation(new_p, size,
605  new_area->max_size = new_size;
606  free_area(area);
607 
608  p = new_p;
609  area = new_area;
610  }
611 
613  area->reallocator.lineno = lineno;
614  area->reallocator.function = function;
615  unlock();
616  return p;
617 }
618 
619 void gw_check_free(void *p, const char *filename, long lineno,
620  const char *function)
621 {
622  struct area *area;
624 
625  if (p == NULL)
626  return;
627 
628  lock();
629  area = find_area(p);
630  if (!area) {
631  unlock();
632  panic(0, "Free called on non-allocated area");
633  }
634 
635  free_area(area);
636  unlock();
637 }
638 
639 char *gw_check_strdup(const char *str, const char *filename, long lineno,
640  const char *function)
641 {
642  char *copy;
643  int size;
644 
646  gw_assert(str != NULL);
647 
648  size = strlen(str) + 1;
649  copy = gw_check_malloc(size, filename, lineno, function);
650  memcpy(copy, str, size);
651  return copy;
652 }
653 
654 void *gw_check_claim_area(void *p, const char *filename, long lineno,
655  const char *function)
656 {
657  struct area *area;
658 
659  /* Allow this for the convenience of wrapper macros. */
660  if (p == NULL)
661  return NULL;
662 
663  lock();
664  area = find_area(p);
665  if (!area) {
666  unlock();
667  panic(0, "Claim_area called on non-allocated area");
668  }
669 
671  area->claimer.lineno = lineno;
672  area->claimer.function = function;
673  unlock();
674 
675  /* For convenience of calling macros */
676  return p;
677 }
678 
680 {
681  long calculated_size;
682  long index;
683 
685  lock();
686 
687  for (index = 0; index < free_ring_len; index++) {
688  drop_from_free_ring(index);
689  }
690  free_ring_len = 0;
691 
692  calculated_size = 0;
693  for (index = 0; index < num_allocations; index++) {
694  calculated_size += allocated[index].area_size;
695  }
696  gw_assert(calculated_size == total_size);
697 
698  debug("gwlib.gwmem", 0, "----------------------------------------");
699  debug("gwlib.gwmem", 0, "Current allocations: %ld areas, %ld bytes",
701  debug("gwlib.gwmem", 0, "Highest number of allocations: %ld areas",
703  debug("gwlib.gwmem", 0, "Highest memory usage: %ld bytes",
705  for (index = 0; index < num_allocations; index++) {
706  check_marks(&allocated[index], index);
707  dump_area(&allocated[index]);
708  }
709 
710  unlock();
711 }
712 
714 {
715  struct area *area;
716 
717  lock();
718  area = find_area(p);
719  unlock();
720  return area != NULL;
721 }
722 
723 long gw_check_area_size(void *p)
724 {
725  struct area *area;
726  size_t size;
727 
728  lock();
729  area = find_area(p);
730  if (!area) {
731  unlock();
732  warning(0, "Area_size called on non-allocated area %p", p);
733  return -1;
734  }
735  size = area->area_size;
736  unlock();
737  return size;
738 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static void lock(void)
Definition: gwmem-check.c:198
int number
Definition: smsc_cimd2.c:213
int size
Definition: wsasm.c:84
static void unlock(void)
Definition: gwmem-check.c:203
static struct area * find_area(unsigned char *p)
Definition: gwmem-check.c:358
static void drop_from_free_ring(long index)
Definition: gwmem-check.c:462
void * gw_check_calloc(int nmemb, size_t size, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:537
static void fill(unsigned char *p, size_t bytes, long pattern)
Definition: gwmem-check.c:229
gw_assert(wtls_machine->packet_to_send !=NULL)
static void startmark(unsigned char *p, long number)
Definition: gwmem-check.c:263
#define mutex_unlock(m)
Definition: thread.h:136
char * gw_check_strdup(const char *str, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:639
const char * function
Definition: gwmem-check.c:141
static int check_endmark(unsigned char *p, size_t size)
Definition: gwmem-check.c:286
static void endmark(unsigned char *p, size_t size)
Definition: gwmem-check.c:255
static void dump_area(struct area *area)
Definition: gwmem-check.c:309
#define FREE_AREA_PATTERN
Definition: gwmem-check.c:115
void * malloc(YYSIZE_T)
#define calloc(a, b)
Definition: gwmem.h:192
static void change_total_size(long change)
Definition: gwmem-check.c:411
const char * filename
Definition: gwmem-check.c:139
static struct area * record_allocation(unsigned char *p, size_t size, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:418
static int slow
Definition: gwmem-check.c:130
static long check_startmark(unsigned char *p)
Definition: gwmem-check.c:276
int gw_check_is_allocated(void *p)
Definition: gwmem-check.c:713
static struct area free_ring[FREE_RING_SIZE]
Definition: gwmem-check.c:178
size_t area_size
Definition: gwmem-check.c:150
void free(void *)
long lineno
Definition: gwmem-check.c:140
#define NEW_AREA_PATTERN
Definition: gwmem-check.c:111
#define START_MARK_PATTERN
Definition: gwmem-check.c:119
static long free_ring_len
Definition: gwmem-check.c:186
void gw_check_check_leaks(void)
Definition: gwmem-check.c:679
#define MAX_ALLOCATIONS
Definition: gwmem-check.c:168
#define mutex_init_static(mutex)
Definition: thread.h:115
#define END_MARK_PATTERN
Definition: gwmem-check.c:122
void * gw_check_claim_area(void *p, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:654
void warning(int err, const char *fmt,...)
Definition: log.c:660
struct location claimer
Definition: gwmem-check.c:154
static int check_marks(struct area *area, long index)
Definition: gwmem-check.c:293
static long num_allocations
Definition: gwmem-check.c:182
char filename[FILENAME_MAX+1]
Definition: log.c:171
void * gw_check_malloc(size_t size, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:514
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
static unsigned long round_pow2(unsigned long num)
Definition: gwmem-check.c:208
void gw_check_init_mem(int slow_flag)
Definition: gwmem-check.c:501
#define MARKER_SIZE
Definition: gwmem-check.c:164
static long total_size
Definition: gwmem-check.c:194
static void free_area(struct area *area)
Definition: gwmem-check.c:494
struct location reallocator
Definition: gwmem-check.c:153
static int untouched(unsigned char *p, size_t bytes, long pattern)
Definition: gwmem-check.c:241
static long free_ring_start
Definition: gwmem-check.c:185
static int initialized
Definition: gwmem-check.c:127
static long highest_num_allocations
Definition: gwmem-check.c:190
static Mutex gwmem_lock
Definition: gwmem-check.c:135
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define panic
Definition: log.h:87
static struct area allocated[MAX_ALLOCATIONS]
Definition: gwmem-check.c:177
void gw_check_shutdown(void)
Definition: gwmem-check.c:508
#define FREE_RING_SIZE
Definition: gwmem-check.c:175
static void put_on_free_ring(struct area *area)
Definition: gwmem-check.c:475
Definition: thread.h:76
struct location allocator
Definition: gwmem-check.c:152
void * gw_check_realloc(void *p, size_t size, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:561
#define MAX_DUMP
Definition: gwmem-check.c:125
#define mutex_lock(m)
Definition: thread.h:130
static long highest_total_size
Definition: gwmem-check.c:192
size_t max_size
Definition: gwmem-check.c:151
long gw_check_area_size(void *p)
Definition: gwmem-check.c:723
void gw_check_free(void *p, const char *filename, long lineno, const char *function)
Definition: gwmem-check.c:619
void * area
Definition: gwmem-check.c:149
static void remove_allocation(struct area *area)
Definition: gwmem-check.c:451
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.