diff options
Diffstat (limited to 'src/libstrongswan/utils/leak_detective.c')
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 155 |
1 files changed, 33 insertions, 122 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index bc7f56ebd..73409158d 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -12,13 +12,8 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: leak_detective.c 4311 2008-08-28 16:27:48Z martin $ + * $Id: leak_detective.c 4609 2008-11-10 16:44:27Z martin $ */ - -#ifdef HAVE_DLADDR -# define _GNU_SOURCE -# include <dlfcn.h> -#endif /* HAVE_DLADDR */ #include <stddef.h> #include <string.h> @@ -28,21 +23,18 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -#include <dlfcn.h> #include <unistd.h> #include <syslog.h> #include <pthread.h> #include <netdb.h> #include <printf.h> #include <locale.h> -#ifdef HAVE_BACKTRACE -# include <execinfo.h> -#endif /* HAVE_BACKTRACE */ #include "leak_detective.h" #include <library.h> #include <debug.h> +#include <utils/backtrace.h> typedef struct private_leak_detective_t private_leak_detective_t; @@ -106,16 +98,6 @@ struct memory_header_t { u_int bytes; /** - * Stack frames at the time of allocation - */ - void *stack_frames[STACK_FRAMES_COUNT]; - - /** - * Number of stacks frames obtained in stack_frames - */ - int stack_frame_count; - - /** * Pointer to previous entry in linked list */ memory_header_t *previous; @@ -126,6 +108,11 @@ struct memory_header_t { memory_header_t *next; /** + * backtrace taken during (re-)allocation + */ + backtrace_t *backtrace; + + /** * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC */ u_int32_t magic; @@ -151,7 +138,7 @@ struct memory_tail_t { static memory_header_t first_header = { magic: MEMORY_HEADER_MAGIC, bytes: 0, - stack_frame_count: 0, + backtrace: NULL, previous: NULL, next: NULL }; @@ -162,88 +149,21 @@ static memory_header_t first_header = { static bool installed = FALSE; /** - * log stack frames queried by backtrace() - * TODO: Dump symbols of static functions. This could be done with - * the addr2line utility or the GNU BFD Library... - */ -static void log_stack_frames(void **stack_frames, int stack_frame_count) -{ -#ifdef HAVE_BACKTRACE - size_t i; - char **strings; - - strings = backtrace_symbols(stack_frames, stack_frame_count); - - fprintf(stderr, " dumping %d stack frame addresses:\n", stack_frame_count); - for (i = 0; i < stack_frame_count; i++) - { -#ifdef HAVE_DLADDR - Dl_info info; - - if (dladdr(stack_frames[i], &info)) - { - char cmd[1024]; - FILE *output; - char c; - void *ptr = stack_frames[i]; - - if (strstr(info.dli_fname, ".so")) - { - ptr = (void*)(stack_frames[i] - info.dli_fbase); - } - snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); - if (info.dli_sname) - { - fprintf(stderr, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", - info.dli_fname, info.dli_fbase, info.dli_sname, - stack_frames[i] - info.dli_saddr, stack_frames[i]); - } - else - { - fprintf(stderr, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, - info.dli_fbase, stack_frames[i]); - } - fprintf(stderr, " -> \e[32m"); - output = popen(cmd, "r"); - if (output) - { - while (TRUE) - { - c = getc(output); - if (c == '\n' || c == EOF) - { - break; - } - fputc(c, stderr); - } - } - else - { -#endif /* HAVE_DLADDR */ - fprintf(stderr, " %s\n", strings[i]); -#ifdef HAVE_DLADDR - } - fprintf(stderr, "\n\e[0m"); - } -#endif /* HAVE_DLADDR */ - } - free (strings); -#endif /* HAVE_BACKTRACE */ -} - -/** * Leak report white list * * List of functions using static allocation buffers or should be suppressed * otherwise on leak report. */ char *whitelist[] = { + /* backtraces, including own */ + "backtrace_create", /* pthread stuff */ "pthread_create", "pthread_setspecific", /* glibc functions */ "mktime", "__gmtime_r", + "localtime_r", "tzset", "inet_ntoa", "strerror", @@ -284,27 +204,16 @@ char *whitelist[] = { /** * check if a stack frame contains functions listed above */ -static bool is_whitelisted(void **stack_frames, int stack_frame_count) +static bool is_whitelisted(backtrace_t *backtrace) { - int i, j; - -#ifdef HAVE_DLADDR - for (i=0; i< stack_frame_count; i++) + int i; + for (i = 0; i < sizeof(whitelist)/sizeof(char*); i++) { - Dl_info info; - - if (dladdr(stack_frames[i], &info) && info.dli_sname) - { - for (j = 0; j < sizeof(whitelist)/sizeof(char*); j++) - { - if (streq(info.dli_sname, whitelist[j])) - { - return TRUE; - } - } + if (backtrace->contains_function(backtrace, whitelist[i])) + { + return TRUE; } } -#endif /* HAVE_DLADDR */ return FALSE; } @@ -318,7 +227,7 @@ void report_leaks() for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - if (is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) + if (is_whitelisted(hdr->backtrace)) { whitelisted++; } @@ -326,7 +235,7 @@ void report_leaks() { fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); /* skip the first frame, contains leak detective logic */ - log_stack_frames(hdr->stack_frames + 1, hdr->stack_frame_count - 1); + hdr->backtrace->log(hdr->backtrace, stderr); leaks++; } } @@ -403,7 +312,7 @@ void *malloc_hook(size_t bytes, const void *caller) hdr->magic = MEMORY_HEADER_MAGIC; hdr->bytes = bytes; - hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + hdr->backtrace = backtrace_create(3); tail->magic = MEMORY_TAIL_MAGIC; install_hooks(); @@ -426,10 +335,9 @@ void *malloc_hook(size_t bytes, const void *caller) */ void free_hook(void *ptr, const void *caller) { - void *stack_frames[STACK_FRAMES_COUNT]; - int stack_frame_count; memory_header_t *hdr; memory_tail_t *tail; + backtrace_t *backtrace; pthread_t thread_id = pthread_self(); int oldpolicy; struct sched_param oldparams, params; @@ -455,8 +363,9 @@ void free_hook(void *ptr, const void *caller) fprintf(stderr, "freeing invalid memory (%p): " "header magic 0x%x, tail magic 0x%x:\n", ptr, hdr->magic, tail->magic); - stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); - log_stack_frames(stack_frames, stack_frame_count); + backtrace = backtrace_create(3); + backtrace->log(backtrace, stderr); + backtrace->destroy(backtrace); } else { @@ -466,10 +375,11 @@ void free_hook(void *ptr, const void *caller) hdr->next->previous = hdr->previous; } hdr->previous->next = hdr->next; - + hdr->backtrace->destroy(hdr->backtrace); + /* clear MAGIC, set mem to something remarkable */ memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); - + free(hdr); } @@ -483,9 +393,8 @@ void free_hook(void *ptr, const void *caller) void *realloc_hook(void *old, size_t bytes, const void *caller) { memory_header_t *hdr; - void *stack_frames[STACK_FRAMES_COUNT]; - int stack_frame_count; memory_tail_t *tail; + backtrace_t *backtrace; pthread_t thread_id = pthread_self(); int oldpolicy; struct sched_param oldparams, params; @@ -512,8 +421,9 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) fprintf(stderr, "reallocating invalid memory (%p): " "header magic 0x%x, tail magic 0x%x:\n", old, hdr->magic, tail->magic); - stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); - log_stack_frames(stack_frames, stack_frame_count); + backtrace = backtrace_create(3); + backtrace->log(backtrace, stderr); + backtrace->destroy(backtrace); } /* clear tail magic, allocate, set tail magic */ memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); @@ -523,7 +433,8 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) /* update statistics */ hdr->bytes = bytes; - hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + hdr->backtrace->destroy(hdr->backtrace); + hdr->backtrace = backtrace_create(3); /* update header of linked list neighbours */ if (hdr->next) |