aboutsummaryrefslogtreecommitdiffstats
path: root/Source/lib/utils/leak_detective.c
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2006-04-28 07:14:48 +0000
committerMartin Willi <martin@strongswan.org>2006-04-28 07:14:48 +0000
commit997358a6c475c8886cce388ab325184a1ff733c9 (patch)
tree27a15790e030fc186d00cd710d2a3540f4defe69 /Source/lib/utils/leak_detective.c
parent52923c9acb349adec3d1cc039e7a74c2e822da6e (diff)
downloadstrongswan-997358a6c475c8886cce388ab325184a1ff733c9.tar.bz2
strongswan-997358a6c475c8886cce388ab325184a1ff733c9.tar.xz
- import of strongswan-2.7.0
- applied patch for charon
Diffstat (limited to 'Source/lib/utils/leak_detective.c')
-rw-r--r--Source/lib/utils/leak_detective.c540
1 files changed, 0 insertions, 540 deletions
diff --git a/Source/lib/utils/leak_detective.c b/Source/lib/utils/leak_detective.c
deleted file mode 100644
index 780ba4c05..000000000
--- a/Source/lib/utils/leak_detective.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/**
- * @file leak_detective.c
- *
- * @brief Allocation hooks to find memory leaks.
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <execinfo.h>
-#include <signal.h>
-#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 "leak_detective.h"
-
-#include <types.h>
-#include <utils/logger_manager.h>
-
-#ifdef LEAK_DETECTIVE
-
-/**
- * Magic value which helps to detect memory corruption
- */
-#define MEMORY_HEADER_MAGIC 0xF1367ADF
-
-static void install_hooks(void);
-static void uninstall_hooks(void);
-static void *malloc_hook(size_t, const void *);
-static void *realloc_hook(void *, size_t, const void *);
-static void free_hook(void*, const void *);
-static void load_excluded_functions();
-
-typedef struct memory_header_t memory_header_t;
-
-/**
- * Header which is prepended to each allocated memory block
- */
-struct memory_header_t {
- /**
- * Magci byte which must(!) hold MEMORY_HEADER_MAGIC
- */
- u_int32_t magic;
-
- /**
- * Number of bytes following after the header
- */
- size_t 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;
-
- /**
- * Pointer to next entry in linked list
- */
- memory_header_t *next;
-};
-
-/**
- * first mem header is just a dummy to chain
- * the others on it...
- */
-static memory_header_t first_header = {
- magic: MEMORY_HEADER_MAGIC,
- bytes: 0,
- stack_frame_count: 0,
- previous: NULL,
- next: NULL
-};
-
-/**
- * logger for the leak detective
- */
-static logger_t *logger;
-
-/**
- * standard hooks, used to temparily remove hooking
- */
-static void *old_malloc_hook, *old_realloc_hook, *old_free_hook;
-
-/**
- * are the hooks currently installed?
- */
-static bool installed = FALSE;
-
-/**
- * Mutex to exclusivly uninstall hooks, access heap list
- */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-/**
- * log stack frames queried by backtrace()
- * TODO: Dump symbols of static functions!!!
- */
-static void log_stack_frames(void **stack_frames, int stack_frame_count)
-{
- char **strings;
- size_t i;
-
- strings = backtrace_symbols (stack_frames, stack_frame_count);
-
- logger->log(logger, ERROR, " dumping %d stack frame addresses.", stack_frame_count);
-
- for (i = 0; i < stack_frame_count; i++)
- {
- logger->log(logger, ERROR, " %s", strings[i]);
- }
- free (strings);
-}
-
-/**
- * Report leaks at library destruction
- */
-void report_leaks()
-{
- memory_header_t *hdr;
- int leaks = 0;
-
- /* reaquire a logger is necessary, this will force ((destructor))
- * order to work correctly */
- logger = logger_manager->get_logger(logger_manager, LEAK_DETECT);
- for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
- {
- logger->log(logger, ERROR, "Leak (%d bytes at %p)", hdr->bytes, hdr + 1);
- log_stack_frames(hdr->stack_frames, hdr->stack_frame_count);
- leaks++;
- }
-
- switch (leaks)
- {
- case 0:
- logger->log(logger, CONTROL, "No leaks detected");
- break;
- case 1:
- logger->log(logger, ERROR, "One leak detected");
- break;
- default:
- logger->log(logger, ERROR, "%d leaks detected", leaks);
- break;
- }
-}
-
-/**
- * Installs the malloc hooks, enables leak detection
- */
-static void install_hooks()
-{
- if (!installed)
- {
- old_malloc_hook = __malloc_hook;
- old_realloc_hook = __realloc_hook;
- old_free_hook = __free_hook;
- __malloc_hook = malloc_hook;
- __realloc_hook = realloc_hook;
- __free_hook = free_hook;
- installed = TRUE;
- }
-}
-
-/**
- * Uninstalls the malloc hooks, disables leak detection
- */
-static void uninstall_hooks()
-{
- if (installed)
- {
- __malloc_hook = old_malloc_hook;
- __free_hook = old_free_hook;
- __realloc_hook = old_realloc_hook;
- installed = FALSE;
- }
-}
-
-/**
- * Hook function for malloc()
- */
-void *malloc_hook(size_t bytes, const void *caller)
-{
- memory_header_t *hdr;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
- hdr = malloc(bytes + sizeof(memory_header_t));
-
- hdr->magic = MEMORY_HEADER_MAGIC;
- hdr->bytes = bytes;
- hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT);
-
- /* insert at the beginning of the list */
- hdr->next = first_header.next;
- if (hdr->next)
- {
- hdr->next->previous = hdr;
- }
- hdr->previous = &first_header;
- first_header.next = hdr;
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return hdr + 1;
-}
-
-/**
- * Hook function for free()
- */
-void free_hook(void *ptr, const void *caller)
-{
- void *stack_frames[STACK_FRAMES_COUNT];
- int stack_frame_count;
- memory_header_t *hdr = ptr - sizeof(memory_header_t);
-
- /* allow freeing of NULL */
- if (ptr == NULL)
- {
- return;
- }
-
- pthread_mutex_lock(&mutex);
- if (hdr->magic != MEMORY_HEADER_MAGIC)
- {
- pthread_mutex_unlock(&mutex);
- /* TODO: since pthread_join cannot be excluded cleanly, we are not whining about bad frees */
- return;
- logger->log(logger, ERROR, "freeing of invalid memory (%p)", ptr);
- stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
- log_stack_frames(stack_frames, stack_frame_count);
- return;
- }
- /* remove magic from hdr */
- hdr->magic = 0;
-
- /* remove item from list */
- if (hdr->next)
- {
- hdr->next->previous = hdr->previous;
- }
- hdr->previous->next = hdr->next;
-
- uninstall_hooks();
- free(hdr);
- install_hooks();
- pthread_mutex_unlock(&mutex);
-}
-
-/**
- * Hook function for realloc()
- */
-void *realloc_hook(void *old, size_t bytes, const void *caller)
-{
- void *new;
- memory_header_t *hdr = old - sizeof(memory_header_t);
- void *stack_frames[STACK_FRAMES_COUNT];
- int stack_frame_count;
-
- /* allow reallocation of NULL */
- if (old == NULL)
- {
- return malloc_hook(bytes, caller);
- }
- if (hdr->magic != MEMORY_HEADER_MAGIC)
- {
- logger->log(logger, ERROR, "reallocation of invalid memory (%p)", old);
- stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
- log_stack_frames(stack_frames, stack_frame_count);
- kill(getpid(), SIGKILL);
- return NULL;
- }
-
- /* malloc and free is done with hooks */
- new = malloc_hook(bytes, caller);
- memcpy(new, old, min(bytes, hdr->bytes));
- free_hook(old, caller);
-
- return new;
-}
-
-
-/**
- * Setup leak detective
- */
-void leak_detective_init()
-{
- logger = logger_manager->get_logger(logger_manager, LEAK_DETECT);
- load_excluded_functions();
- install_hooks();
-}
-
-/**
- * Clean up leak detective
- */
-void leak_detective_cleanup()
-{
- uninstall_hooks();
- report_leaks();
-}
-
-
-/**
- * The following glibc functions are excluded from leak detection, since
- * they use static allocated buffers or other ugly allocation hacks.
- * For this to work, the linker must link libstrongswan preferred to
- * the other (overriden) libs.
- */
-struct excluded_function {
- char *lib_name;
- char *function_name;
- void *handle;
- void *lib_function;
-} excluded_functions[] = {
- {"libc.so.6", "inet_ntoa", NULL, NULL},
- {"libpthread.so.0", "pthread_create", NULL, NULL},
- {"libpthread.so.0", "pthread_cancel", NULL, NULL},
- {"libpthread.so.0", "pthread_join", NULL, NULL},
- {"libpthread.so.0", "_pthread_cleanup_push",NULL, NULL},
- {"libpthread.so.0", "_pthread_cleanup_pop", NULL, NULL},
- {"libc.so.6", "mktime", NULL, NULL},
- {"libc.so.6", "vsyslog", NULL, NULL},
- {"libc.so.6", "strerror", NULL, NULL},
-};
-#define INET_NTOA 0
-#define PTHREAD_CREATE 1
-#define PTHREAD_CANCEL 2
-#define PTHREAD_JOIN 3
-#define PTHREAD_CLEANUP_PUSH 4
-#define PTHREAD_CLEANUP_POP 5
-#define MKTIME 6
-#define VSYSLOG 7
-#define STRERROR 8
-
-
-/**
- * Load libraries and function pointers for excluded functions
- */
-static void load_excluded_functions()
-{
- int i;
-
- for (i = 0; i < sizeof(excluded_functions)/sizeof(struct excluded_function); i++)
- {
- void *handle, *function;
- handle = dlopen(excluded_functions[i].lib_name, RTLD_LAZY);
- if (handle == NULL)
- {
- kill(getpid(), SIGSEGV);
- }
-
- function = dlsym(handle, excluded_functions[i].function_name);
-
- if (function == NULL)
- {
- dlclose(handle);
- kill(getpid(), SIGSEGV);
- }
- excluded_functions[i].handle = handle;
- excluded_functions[i].lib_function = function;
- }
-}
-
-char *inet_ntoa(struct in_addr in)
-{
- char *(*_inet_ntoa)(struct in_addr) = excluded_functions[INET_NTOA].lib_function;
- char *result;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- result = _inet_ntoa(in);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return result;
-}
-
-int pthread_create(pthread_t *__restrict __threadp, __const pthread_attr_t *__restrict __attr,
- void *(*__start_routine) (void *), void *__restrict __arg)
-{
- int (*_pthread_create) (pthread_t *__restrict __threadp,
- __const pthread_attr_t *__restrict __attr,
- void *(*__start_routine) (void *),
- void *__restrict __arg) = excluded_functions[PTHREAD_CREATE].lib_function;
- int result;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- result = _pthread_create(__threadp, __attr, __start_routine, __arg);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return result;
-}
-
-
-int pthread_cancel(pthread_t __th)
-{
- int (*_pthread_cancel) (pthread_t) = excluded_functions[PTHREAD_CANCEL].lib_function;
- int result;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- result = _pthread_cancel(__th);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return result;
-}
-
-// /* TODO: join has probs, since it dellocates memory
-// * allocated (somewhere) with leak_detective :-(.
-// * We should exclude all pthread_ functions to fix it !? */
-// int pthread_join(pthread_t __th, void **__thread_return)
-// {
-// int (*_pthread_join) (pthread_t, void **) = excluded_functions[PTHREAD_JOIN].lib_function;
-// int result;
-//
-// pthread_mutex_lock(&mutex);
-// uninstall_hooks();
-//
-// result = _pthread_join(__th, __thread_return);
-//
-// install_hooks();
-// pthread_mutex_unlock(&mutex);
-// return result;
-// }
-//
-// void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
-// void (*__routine) (void *),
-// void *__arg)
-// {
-// int (*__pthread_cleanup_push) (struct _pthread_cleanup_buffer *__buffer,
-// void (*__routine) (void *),
-// void *__arg) =
-// excluded_functions[PTHREAD_CLEANUP_PUSH].lib_function;
-//
-// pthread_mutex_lock(&mutex);
-// uninstall_hooks();
-//
-// __pthread_cleanup_push(__buffer, __routine, __arg);
-//
-// install_hooks();
-// pthread_mutex_unlock(&mutex);
-// return;
-// }
-//
-// void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, int __execute)
-// {
-// int (*__pthread_cleanup_pop) (struct _pthread_cleanup_buffer *__buffer, int __execute) =
-// excluded_functions[PTHREAD_CLEANUP_POP].lib_function;
-//
-// pthread_mutex_lock(&mutex);
-// uninstall_hooks();
-//
-// __pthread_cleanup_pop(__buffer, __execute);
-//
-// install_hooks();
-// pthread_mutex_unlock(&mutex);
-// return;
-// }
-
-time_t mktime(struct tm *tm)
-{
- time_t (*_mktime)(struct tm *tm) = excluded_functions[MKTIME].lib_function;
- time_t result;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- result = _mktime(tm);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return result;
-}
-
-void vsyslog (int __pri, __const char *__fmt, __gnuc_va_list __ap)
-{
- void (*_vsyslog) (int __pri, __const char *__fmt, __gnuc_va_list __ap) = excluded_functions[VSYSLOG].lib_function;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- _vsyslog(__pri, __fmt, __ap);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return;
-}
-
-
-
-char *strerror(int errnum)
-{
- char* (*_strerror) (int) = excluded_functions[STRERROR].lib_function;
- char *result;
-
- pthread_mutex_lock(&mutex);
- uninstall_hooks();
-
- result = _strerror(errnum);
-
- install_hooks();
- pthread_mutex_unlock(&mutex);
- return result;
-}
-
-#endif /* LEAK_DETECTION */