2 * Copyright (C) 2013-2014 Tobias Brunner
3 * Copyright (C) 2006-2013 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32 #include <malloc/malloc.h>
33 /* overload some of our types clashing with mach */
34 #define host_t strongswan_host_t
35 #define processor_t strongswan_processor_t
36 #define thread_t strongswan_thread_t
37 #endif /* __APPLE__ */
39 #include "leak_detective.h"
42 #include <utils/utils.h>
43 #include <utils/debug.h>
44 #include <utils/backtrace.h>
45 #include <collections/hashtable.h>
46 #include <threading/thread_value.h>
47 #include <threading/spinlock.h>
49 typedef struct private_leak_detective_t private_leak_detective_t
;
52 * private data of leak_detective
54 struct private_leak_detective_t
{
59 leak_detective_t
public;
62 * Registered report() function
64 leak_detective_report_cb_t report_cb
;
67 * Registered report() summary function
69 leak_detective_summary_cb_t report_scb
;
72 * Registered user data for callbacks
78 * Magic value which helps to detect memory corruption. Yummy!
80 #define MEMORY_HEADER_MAGIC 0x7ac0be11
83 * Magic written to tail of allocation
85 #define MEMORY_TAIL_MAGIC 0xcafebabe
88 * Pattern which is filled in memory before freeing it
90 #define MEMORY_FREE_PATTERN 0xFF
93 * Pattern which is filled in newly allocated memory
95 #define MEMORY_ALLOC_PATTERN 0xEE
97 typedef struct memory_header_t memory_header_t
;
98 typedef struct memory_tail_t memory_tail_t
;
101 * Header which is prepended to each allocated memory block
103 struct memory_header_t
{
106 * Pointer to previous entry in linked list
108 memory_header_t
*previous
;
111 * Pointer to next entry in linked list
113 memory_header_t
*next
;
116 * backtrace taken during (re-)allocation
118 backtrace_t
*backtrace
;
121 * Padding to make sizeof(memory_header_t) == 32
123 u_int32_t padding
[sizeof(void*) == sizeof(u_int32_t
) ? 3 : 0];
126 * Number of bytes following after the header
131 * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC
135 }__attribute__((__packed__
));
138 * tail appended to each allocated memory block
140 struct memory_tail_t
{
143 * Magic bytes to detect heap overflow, MEMORY_TAIL_MAGIC
147 }__attribute__((__packed__
));
150 * first mem header is just a dummy to chain
151 * the others on it...
153 static memory_header_t first_header
= {
154 .magic
= MEMORY_HEADER_MAGIC
,
158 * Spinlock to access header linked list
160 static spinlock_t
*lock
;
163 * Is leak detection currently enabled?
165 static bool enabled
= FALSE
;
168 * Is leak detection disabled for the current thread?
170 static thread_value_t
*thread_disabled
;
173 * Installs the malloc hooks, enables leak detection
175 static void enable_leak_detective()
181 * Uninstalls the malloc hooks, disables leak detection
183 static void disable_leak_detective()
189 * Enable/Disable leak detective for the current thread
191 * @return Previous value
193 static bool enable_thread(bool enable
)
197 before
= thread_disabled
->get(thread_disabled
) == NULL
;
198 thread_disabled
->set(thread_disabled
, enable
? NULL
: (void*)TRUE
);
203 * Add a header to the beginning of the list
205 static void add_hdr(memory_header_t
*hdr
)
208 hdr
->next
= first_header
.next
;
211 hdr
->next
->previous
= hdr
;
213 hdr
->previous
= &first_header
;
214 first_header
.next
= hdr
;
219 * Remove a header from the list
221 static void remove_hdr(memory_header_t
*hdr
)
226 hdr
->next
->previous
= hdr
->previous
;
228 hdr
->previous
->next
= hdr
->next
;
233 * Check if a header is in the list
235 static bool has_hdr(memory_header_t
*hdr
)
237 memory_header_t
*current
;
241 for (current
= &first_header
; current
!= NULL
; current
= current
->next
)
257 * Copy of original default zone, with functions we call in hooks
259 static malloc_zone_t original
;
262 * Call original malloc()
264 static void* real_malloc(size_t size
)
266 return original
.malloc(malloc_default_zone(), size
);
270 * Call original free()
272 static void real_free(void *ptr
)
274 original
.free(malloc_default_zone(), ptr
);
278 * Call original realloc()
280 static void* real_realloc(void *ptr
, size_t size
)
282 return original
.realloc(malloc_default_zone(), ptr
, size
);
286 * Hook definition: static function with _hook suffix, takes additional zone
288 #define HOOK(ret, name, ...) \
289 static ret name ## _hook(malloc_zone_t *_z, __VA_ARGS__)
292 * forward declaration of hooks
294 HOOK(void*, malloc
, size_t bytes
);
295 HOOK(void*, calloc
, size_t nmemb
, size_t size
);
296 HOOK(void*, valloc
, size_t size
);
297 HOOK(void, free
, void *ptr
);
298 HOOK(void*, realloc
, void *old
, size_t bytes
);
301 * malloc zone size(), must consider the memory header prepended
303 HOOK(size_t, size
, const void *ptr
)
310 before
= enable_thread(FALSE
);
313 ptr
-= sizeof(memory_header_t
);
316 size
= original
.size(malloc_default_zone(), ptr
);
319 enable_thread(before
);
325 * Version of malloc zones we currently support
327 #define MALLOC_ZONE_VERSION 8 /* Snow Leopard */
330 * Hook-in our malloc functions into the default zone
332 static bool register_hooks()
334 static bool once
= FALSE
;
344 zone
= malloc_default_zone();
345 if (zone
->version
!= MALLOC_ZONE_VERSION
)
347 DBG1(DBG_CFG
, "malloc zone version %d unsupported (requiring %d)",
348 zone
->version
, MALLOC_ZONE_VERSION
);
354 page
= (void*)((uintptr_t)zone
/ getpagesize() * getpagesize());
355 if (mprotect(page
, getpagesize(), PROT_WRITE
| PROT_READ
) != 0)
357 DBG1(DBG_CFG
, "malloc zone unprotection failed: %s", strerror(errno
));
361 zone
->size
= size_hook
;
362 zone
->malloc
= malloc_hook
;
363 zone
->calloc
= calloc_hook
;
364 zone
->valloc
= valloc_hook
;
365 zone
->free
= free_hook
;
366 zone
->realloc
= realloc_hook
;
368 /* those other functions can be NULLed out to not use them */
369 zone
->batch_malloc
= NULL
;
370 zone
->batch_free
= NULL
;
371 zone
->memalign
= NULL
;
372 zone
->free_definite_size
= NULL
;
377 #else /* !__APPLE__ */
380 * dlsym() might do a malloc(), but we can't do one before we get the malloc()
381 * function pointer. Use this minimalistic malloc implementation instead.
383 static void* malloc_for_dlsym(size_t size
)
385 static char buf
[1024] = {};
386 static size_t used
= 0;
389 /* roundup to a multiple of 32 */
390 size
= (size
- 1) / 32 * 32 + 32;
392 if (used
+ size
> sizeof(buf
))
402 * Lookup a malloc function, while disabling wrappers
404 static void* get_malloc_fn(char *name
)
411 before
= enable_thread(FALSE
);
413 fn
= dlsym(RTLD_NEXT
, name
);
416 enable_thread(before
);
422 * Call original malloc()
424 static void* real_malloc(size_t size
)
426 static void* (*fn
)(size_t size
);
427 static int recursive
= 0;
431 /* checking recursiveness should actually be thread-specific. But as
432 * it is very likely that the first allocation is done before we go
433 * multi-threaded, we keep it simple. */
436 return malloc_for_dlsym(size
);
439 fn
= get_malloc_fn("malloc");
446 * Call original free()
448 static void real_free(void *ptr
)
450 static void (*fn
)(void *ptr
);
454 fn
= get_malloc_fn("free");
460 * Call original realloc()
462 static void* real_realloc(void *ptr
, size_t size
)
464 static void* (*fn
)(void *ptr
, size_t size
);
468 fn
= get_malloc_fn("realloc");
470 return fn(ptr
, size
);
474 * Hook definition: plain function overloading existing malloc calls
476 #define HOOK(ret, name, ...) ret name(__VA_ARGS__)
479 * Hook initialization when not using hooks, resolve functions.
481 static bool register_hooks()
483 void *buf
= real_malloc(8);
484 buf
= real_realloc(buf
, 16);
489 #endif /* !__APPLE__ */
492 * Leak report white list
494 * List of functions using static allocation buffers or should be suppressed
495 * otherwise on leak report.
497 char *whitelist
[] = {
498 /* backtraces, including own */
503 "pthread_setspecific",
504 "__pthread_setspecific",
505 /* glibc functions */
519 "register_printf_function",
520 "register_printf_specifier",
535 /* ignore dlopen, as we do not dlclose to get proper leak reports */
540 /* mysql functions */
541 "mysql_init_character_set",
544 /* fastcgi library */
547 "xmlInitCharEncodingHandlers",
556 "gcry_check_version",
559 /* OpenSSL: These are needed for unit-tests only, the openssl plugin
560 * does properly clean up any memory during destroy(). */
565 "SSL_COMP_get_compression_methods",
569 "apr_pool_create_ex",
571 "g_type_init_with_debug_flags",
572 "g_type_register_static",
574 "g_type_create_instance",
575 "g_type_add_interface_static",
576 "g_type_interface_add_prerequisite",
577 "g_socket_connection_factory_lookup_type",
581 "gnutls_global_init",
585 * Some functions are hard to whitelist, as they don't use a symbol directly.
586 * Use some static initialization to suppress them on leak reports
588 static void init_static_allocations()
595 localtime_r(&t
, &tm
);
599 * Hashtable hash function
601 static u_int
hash(backtrace_t
*key
)
603 enumerator_t
*enumerator
;
607 enumerator
= key
->create_frame_enumerator(key
);
608 while (enumerator
->enumerate(enumerator
, &addr
))
610 hash
= chunk_hash_inc(chunk_from_thing(addr
), hash
);
612 enumerator
->destroy(enumerator
);
618 * Hashtable equals function
620 static bool equals(backtrace_t
*a
, backtrace_t
*b
)
622 return a
->equals(a
, b
);
626 * Summarize and print backtraces
628 static int print_traces(private_leak_detective_t
*this,
629 leak_detective_report_cb_t cb
, void *user
,
630 int thresh
, int thresh_count
,
631 bool detailed
, int *whitelisted
, size_t *sum
)
634 memory_header_t
*hdr
;
635 enumerator_t
*enumerator
;
636 hashtable_t
*entries
;
638 /** associated backtrace */
639 backtrace_t
*backtrace
;
640 /** total size of all allocations */
642 /** number of allocations */
647 before
= enable_thread(FALSE
);
649 entries
= hashtable_create((hashtable_hash_t
)hash
,
650 (hashtable_equals_t
)equals
, 1024);
652 for (hdr
= first_header
.next
; hdr
!= NULL
; hdr
= hdr
->next
)
655 hdr
->backtrace
->contains_function(hdr
->backtrace
,
656 whitelist
, countof(whitelist
)))
661 entry
= entries
->get(entries
, hdr
->backtrace
);
664 entry
->bytes
+= hdr
->bytes
;
670 .backtrace
= hdr
->backtrace
->clone(hdr
->backtrace
),
674 entries
->put(entries
, entry
->backtrace
, entry
);
684 enumerator
= entries
->create_enumerator(entries
);
685 while (enumerator
->enumerate(enumerator
, NULL
, &entry
))
689 if (!thresh
|| entry
->bytes
>= thresh
)
691 if (!thresh_count
|| entry
->count
>= thresh_count
)
693 this->report_cb(this->report_data
, entry
->count
,
694 entry
->bytes
, entry
->backtrace
, detailed
);
698 entry
->backtrace
->destroy(entry
->backtrace
);
701 enumerator
->destroy(enumerator
);
702 entries
->destroy(entries
);
704 enable_thread(before
);
708 METHOD(leak_detective_t
, report
, void,
709 private_leak_detective_t
*this, bool detailed
)
711 if (lib
->leak_detective
)
713 int leaks
, whitelisted
= 0;
716 leaks
= print_traces(this, this->report_cb
, this->report_data
,
717 0, 0, detailed
, &whitelisted
, &sum
);
718 if (this->report_scb
)
720 this->report_scb(this->report_data
, leaks
, sum
, whitelisted
);
725 METHOD(leak_detective_t
, set_report_cb
, void,
726 private_leak_detective_t
*this, leak_detective_report_cb_t cb
,
727 leak_detective_summary_cb_t scb
, void *user
)
729 this->report_cb
= cb
;
730 this->report_scb
= scb
;
731 this->report_data
= user
;
734 METHOD(leak_detective_t
, leaks
, int,
735 private_leak_detective_t
*this)
739 return print_traces(this, NULL
, NULL
, 0, 0, FALSE
, &whitelisted
, NULL
);
742 METHOD(leak_detective_t
, set_state
, bool,
743 private_leak_detective_t
*this, bool enable
)
745 return enable_thread(enable
);
748 METHOD(leak_detective_t
, usage
, void,
749 private_leak_detective_t
*this, leak_detective_report_cb_t cb
,
750 leak_detective_summary_cb_t scb
, void *user
)
753 int thresh
, thresh_count
, leaks
, whitelisted
= 0;
756 thresh
= lib
->settings
->get_int(lib
->settings
,
757 "%s.leak_detective.usage_threshold", 10240, lib
->ns
);
758 thresh_count
= lib
->settings
->get_int(lib
->settings
,
759 "%s.leak_detective.usage_threshold_count", 0, lib
->ns
);
760 detailed
= lib
->settings
->get_bool(lib
->settings
,
761 "%s.leak_detective.detailed", TRUE
, lib
->ns
);
763 leaks
= print_traces(this, cb
, user
, thresh
, thresh_count
,
764 detailed
, &whitelisted
, &sum
);
767 scb(user
, leaks
, sum
, whitelisted
);
772 * Wrapped malloc() function
774 HOOK(void*, malloc
, size_t bytes
)
776 memory_header_t
*hdr
;
780 if (!enabled
|| thread_disabled
->get(thread_disabled
))
782 return real_malloc(bytes
);
785 hdr
= real_malloc(sizeof(memory_header_t
) + bytes
+ sizeof(memory_tail_t
));
786 tail
= ((void*)hdr
) + bytes
+ sizeof(memory_header_t
);
787 /* set to something which causes crashes */
788 memset(hdr
, MEMORY_ALLOC_PATTERN
,
789 sizeof(memory_header_t
) + bytes
+ sizeof(memory_tail_t
));
791 before
= enable_thread(FALSE
);
792 hdr
->backtrace
= backtrace_create(2);
793 enable_thread(before
);
795 hdr
->magic
= MEMORY_HEADER_MAGIC
;
797 tail
->magic
= MEMORY_TAIL_MAGIC
;
805 * Wrapped calloc() function
807 HOOK(void*, calloc
, size_t nmemb
, size_t size
)
813 memset(ptr
, 0, size
);
819 * Wrapped valloc(), TODO: currently not supported
821 HOOK(void*, valloc
, size_t size
)
823 DBG1(DBG_LIB
, "valloc() used, but leak-detective hook missing");
828 * Wrapped free() function
830 HOOK(void, free
, void *ptr
)
832 memory_header_t
*hdr
;
834 backtrace_t
*backtrace
;
837 if (!enabled
|| thread_disabled
->get(thread_disabled
))
842 /* allow freeing of NULL */
847 hdr
= ptr
- sizeof(memory_header_t
);
848 tail
= ptr
+ hdr
->bytes
;
850 before
= enable_thread(FALSE
);
851 if (hdr
->magic
!= MEMORY_HEADER_MAGIC
||
852 tail
->magic
!= MEMORY_TAIL_MAGIC
)
856 /* memory was allocated by our hooks but is corrupted */
857 fprintf(stderr
, "freeing corrupted memory (%p): "
858 "header magic 0x%x, tail magic 0x%x:\n",
859 ptr
, hdr
->magic
, tail
->magic
);
863 /* memory was not allocated by our hooks */
864 fprintf(stderr
, "freeing invalid memory (%p)\n", ptr
);
866 backtrace
= backtrace_create(2);
867 backtrace
->log(backtrace
, stderr
, TRUE
);
868 backtrace
->destroy(backtrace
);
874 hdr
->backtrace
->destroy(hdr
->backtrace
);
876 /* clear MAGIC, set mem to something remarkable */
877 memset(hdr
, MEMORY_FREE_PATTERN
,
878 sizeof(memory_header_t
) + hdr
->bytes
+ sizeof(memory_tail_t
));
882 enable_thread(before
);
886 * Wrapped realloc() function
888 HOOK(void*, realloc
, void *old
, size_t bytes
)
890 memory_header_t
*hdr
;
892 backtrace_t
*backtrace
;
895 if (!enabled
|| thread_disabled
->get(thread_disabled
))
897 return real_realloc(old
, bytes
);
899 /* allow reallocation of NULL */
902 return malloc(bytes
);
904 /* handle zero size as a free() */
911 hdr
= old
- sizeof(memory_header_t
);
912 tail
= old
+ hdr
->bytes
;
916 if (hdr
->magic
!= MEMORY_HEADER_MAGIC
||
917 tail
->magic
!= MEMORY_TAIL_MAGIC
)
919 fprintf(stderr
, "reallocating invalid memory (%p):\n"
920 "header magic 0x%x:\n", old
, hdr
->magic
);
921 backtrace
= backtrace_create(2);
922 backtrace
->log(backtrace
, stderr
, TRUE
);
923 backtrace
->destroy(backtrace
);
927 /* clear tail magic, allocate, set tail magic */
928 memset(&tail
->magic
, MEMORY_ALLOC_PATTERN
, sizeof(tail
->magic
));
930 hdr
= real_realloc(hdr
,
931 sizeof(memory_header_t
) + bytes
+ sizeof(memory_tail_t
));
932 tail
= ((void*)hdr
) + bytes
+ sizeof(memory_header_t
);
933 tail
->magic
= MEMORY_TAIL_MAGIC
;
935 /* update statistics */
938 before
= enable_thread(FALSE
);
939 hdr
->backtrace
->destroy(hdr
->backtrace
);
940 hdr
->backtrace
= backtrace_create(2);
941 enable_thread(before
);
948 METHOD(leak_detective_t
, destroy
, void,
949 private_leak_detective_t
*this)
951 disable_leak_detective();
953 thread_disabled
->destroy(thread_disabled
);
955 first_header
.next
= NULL
;
961 leak_detective_t
*leak_detective_create()
963 private_leak_detective_t
*this;
968 .set_report_cb
= _set_report_cb
,
971 .set_state
= _set_state
,
976 if (getenv("LEAK_DETECTIVE_DISABLE") != NULL
)
982 lock
= spinlock_create();
983 thread_disabled
= thread_value_create(NULL
);
985 init_static_allocations();
987 if (register_hooks())
989 enable_leak_detective();
991 return &this->public;