diff options
author | Martin Willi <martin@revosec.ch> | 2010-05-19 15:22:12 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-05-20 17:37:18 +0200 |
commit | 091d178060faaa25b16e89e4e9ec9ee7c374210c (patch) | |
tree | 4ffabf7631ec6ce0f1abdf2a50a838dd3947ce39 /src | |
parent | 36c1650b19577a23cee2b75c4db85dcae65608fe (diff) | |
download | strongswan-091d178060faaa25b16e89e4e9ec9ee7c374210c.tar.bz2 strongswan-091d178060faaa25b16e89e4e9ec9ee7c374210c.tar.xz |
Option to skip slow addr2line resolution in leak-detective
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/charon.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/library.c | 5 | ||||
-rw-r--r-- | src/libstrongswan/threading/lock_profiler.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/backtrace.c | 42 | ||||
-rw-r--r-- | src/libstrongswan/utils/backtrace.h | 5 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 60 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.h | 9 |
7 files changed, 76 insertions, 49 deletions
diff --git a/src/charon/charon.c b/src/charon/charon.c index 35be63064..33866881f 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -190,7 +190,7 @@ static void segv_handler(int signal) DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal); backtrace = backtrace_create(2); - backtrace->log(backtrace, stderr); + backtrace->log(backtrace, stderr, TRUE); backtrace->destroy(backtrace); DBG1(DBG_DMN, "killing ourself, received critical signal"); diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c index 108ac2ca0..8166d2457 100644 --- a/src/libstrongswan/library.c +++ b/src/libstrongswan/library.c @@ -59,6 +59,10 @@ library_t *lib; void library_deinit() { private_library_t *this = (private_library_t*)lib; + bool detailed; + + detailed = lib->settings->get_bool(lib->settings, + "libstrongswan.leak_detective.detailed", TRUE); this->public.plugins->destroy(this->public.plugins); this->public.settings->destroy(this->public.settings); @@ -76,6 +80,7 @@ void library_deinit() #ifdef LEAK_DETECTIVE if (this->detective) { + this->detective->report(this->detective, detailed); this->detective->destroy(this->detective); } #endif /* LEAK_DETECTIVE */ diff --git a/src/libstrongswan/threading/lock_profiler.h b/src/libstrongswan/threading/lock_profiler.h index b64453ba1..1ae496455 100644 --- a/src/libstrongswan/threading/lock_profiler.h +++ b/src/libstrongswan/threading/lock_profiler.h @@ -63,7 +63,7 @@ static inline void profiler_cleanup(lock_profile_t *profile) { fprintf(stderr, "%d.%03ds / %d times in lock created at:", profile->waited.tv_sec, profile->waited.tv_usec, profile->locked); - profile->backtrace->log(profile->backtrace, stderr); + profile->backtrace->log(profile->backtrace, stderr, TRUE); } profile->backtrace->destroy(profile->backtrace); } diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c index 5bba8ec21..a67245194 100644 --- a/src/libstrongswan/utils/backtrace.c +++ b/src/libstrongswan/utils/backtrace.c @@ -53,7 +53,7 @@ struct private_backtrace_t { /** * Implementation of backtrace_t.log */ -static void log_(private_backtrace_t *this, FILE *file) +static void log_(private_backtrace_t *this, FILE *file, bool detailed) { #ifdef HAVE_BACKTRACE size_t i; @@ -78,7 +78,6 @@ static void log_(private_backtrace_t *this, FILE *file) { ptr = (void*)(this->frames[i] - info.dli_fbase); } - snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); if (info.dli_sname) { fprintf(file, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", @@ -90,28 +89,33 @@ static void log_(private_backtrace_t *this, FILE *file) fprintf(file, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, info.dli_fbase, this->frames[i]); } - fprintf(file, " -> \e[32m"); - output = popen(cmd, "r"); - if (output) + if (detailed) { - while (TRUE) + fprintf(file, " -> \e[32m"); + snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", + info.dli_fname, ptr); + output = popen(cmd, "r"); + if (output) { - c = getc(output); - if (c == '\n' || c == EOF) + while (TRUE) { - break; + c = getc(output); + if (c == '\n' || c == EOF) + { + break; + } + fputc(c, file); } - fputc(c, file); + pclose(output); } - pclose(output); - } - else - { -#endif /* HAVE_DLADDR */ - fprintf(file, " %s\n", strings[i]); -#ifdef HAVE_DLADDR + else + { + #endif /* HAVE_DLADDR */ + fprintf(file, " %s\n", strings[i]); + #ifdef HAVE_DLADDR + } + fprintf(file, "\n\e[0m"); } - fprintf(file, "\n\e[0m"); } else { @@ -174,7 +178,7 @@ backtrace_t *backtrace_create(int skip) memcpy(this->frames, frames + skip, frame_count * sizeof(void*)); this->frame_count = frame_count; - this->public.log = (void(*)(backtrace_t*,FILE*))log_; + this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_; this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function; this->public.destroy = (void(*)(backtrace_t*))destroy; diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h index c4d4284d1..c6b0ec78f 100644 --- a/src/libstrongswan/utils/backtrace.h +++ b/src/libstrongswan/utils/backtrace.h @@ -34,8 +34,11 @@ struct backtrace_t { /** * Log the backtrace to a FILE stream. + * + * @param file FILE to log backtrace to + * @param detailed TRUE to resolve line/file using addr2line (slow) */ - void (*log)(backtrace_t *this, FILE *file); + void (*log)(backtrace_t *this, FILE *file, bool detailed); /** * Check if the backtrace contains a frame in a specific function. diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 2f8a7187c..74bcdc43f 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -233,39 +233,45 @@ static bool is_whitelisted(backtrace_t *backtrace) /** * Report leaks at library destruction */ -void report_leaks() +static void report(private_leak_detective_t *this, bool detailed) { - memory_header_t *hdr; - int leaks = 0, whitelisted = 0; - - for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) + if (lib->leak_detective) { - if (is_whitelisted(hdr->backtrace)) + memory_header_t *hdr; + int leaks = 0, whitelisted = 0; + + for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - whitelisted++; + if (is_whitelisted(hdr->backtrace)) + { + whitelisted++; + } + else + { + fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); + /* skip the first frame, contains leak detective logic */ + hdr->backtrace->log(hdr->backtrace, stderr, detailed); + leaks++; + } } - else + switch (leaks) { - fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); - /* skip the first frame, contains leak detective logic */ - hdr->backtrace->log(hdr->backtrace, stderr); - leaks++; + case 0: + fprintf(stderr, "No leaks detected"); + break; + case 1: + fprintf(stderr, "One leak detected"); + break; + default: + fprintf(stderr, "%d leaks detected", leaks); + break; } + fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted); } - - switch (leaks) + else { - case 0: - fprintf(stderr, "No leaks detected"); - break; - case 1: - fprintf(stderr, "One leak detected"); - break; - default: - fprintf(stderr, "%d leaks detected", leaks); - break; + fprintf(stderr, "Leak detective disabled\n"); } - fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted); } /** @@ -395,7 +401,7 @@ void free_hook(void *ptr, const void *caller) fprintf(stderr, "freeing invalid memory (%p)", ptr); } backtrace = backtrace_create(3); - backtrace->log(backtrace, stderr); + backtrace->log(backtrace, stderr, TRUE); backtrace->destroy(backtrace); } else @@ -454,7 +460,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) "header magic 0x%x, tail magic 0x%x:\n", old, hdr->magic, tail->magic); backtrace = backtrace_create(3); - backtrace->log(backtrace, stderr); + backtrace->log(backtrace, stderr, TRUE); backtrace->destroy(backtrace); } /* clear tail magic, allocate, set tail magic */ @@ -487,7 +493,6 @@ static void destroy(private_leak_detective_t *this) if (installed) { uninstall_hooks(); - report_leaks(); } free(this); } @@ -499,6 +504,7 @@ leak_detective_t *leak_detective_create() { private_leak_detective_t *this = malloc_thing(private_leak_detective_t); + this->public.report = (void(*)(leak_detective_t*,bool))report; this->public.destroy = (void(*)(leak_detective_t*))destroy; if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h index 181f8f3db..fa45a6076 100644 --- a/src/libstrongswan/utils/leak_detective.h +++ b/src/libstrongswan/utils/leak_detective.h @@ -23,6 +23,8 @@ typedef struct leak_detective_t leak_detective_t; +#include <library.h> + /** * Leak detective finds leaks and bad frees using malloc hooks. * @@ -34,6 +36,13 @@ typedef struct leak_detective_t leak_detective_t; struct leak_detective_t { /** + * Report leaks to stderr. + * + * @param detailed TRUE to resolve line/filename of leak (slow) + */ + void (*report)(leak_detective_t *this, bool detailed); + + /** * Destroy a leak_detective instance. */ void (*destroy)(leak_detective_t *this); |