mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-25 00:00:20 -04:00
Option to skip slow addr2line resolution in leak-detective
This commit is contained in:
parent
36c1650b19
commit
091d178060
@ -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");
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
fprintf(file, "\n\e[0m");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* HAVE_DLADDR */
|
||||
fprintf(file, " %s\n", strings[i]);
|
||||
#ifdef HAVE_DLADDR
|
||||
}
|
||||
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;
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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))
|
||||
{
|
||||
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);
|
||||
leaks++;
|
||||
}
|
||||
}
|
||||
memory_header_t *hdr;
|
||||
int leaks = 0, whitelisted = 0;
|
||||
|
||||
switch (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;
|
||||
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
}
|
||||
switch (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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
|
||||
@ -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.
|
||||
*
|
||||
@ -33,6 +35,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.
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user