2 * Copyright (c) 2008, 2009 Nicira Networks.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include "leak-checker.h"
20 #include "backtrace.h"
22 #define THIS_MODULE VLM_leak_checker
25 #ifndef HAVE_MALLOC_HOOKS
27 leak_checker_start(const char *file_name UNUSED)
29 VLOG_WARN("not enabling leak checker because the libc in use does not "
30 "have the required hooks");
34 leak_checker_set_limit(off_t max_size UNUSED)
39 leak_checker_claim(const void *p UNUSED)
44 leak_checker_usage(void)
46 printf(" --check-leaks=FILE (accepted but ignored in this build)\n");
48 #else /* HAVE_MALLOC_HOOKS */
54 typedef void *malloc_hook_type(size_t, const void *);
55 typedef void *realloc_hook_type(void *, size_t, const void *);
56 typedef void free_hook_type(void *, const void *);
59 malloc_hook_type *malloc_hook_func;
60 realloc_hook_type *realloc_hook_func;
61 free_hook_type *free_hook_func;
64 static malloc_hook_type hook_malloc;
65 static realloc_hook_type hook_realloc;
66 static free_hook_type hook_free;
68 static struct hooks libc_hooks;
69 static const struct hooks our_hooks = { hook_malloc, hook_realloc, hook_free };
72 static off_t limit = 10 * 1000 * 1000;
75 get_hooks(struct hooks *hooks)
77 hooks->malloc_hook_func = __malloc_hook;
78 hooks->realloc_hook_func = __realloc_hook;
79 hooks->free_hook_func = __free_hook;
83 set_hooks(const struct hooks *hooks)
85 __malloc_hook = hooks->malloc_hook_func;
86 __realloc_hook = hooks->realloc_hook_func;
87 __free_hook = hooks->free_hook_func;
91 leak_checker_start(const char *file_name)
94 file = fopen(file_name, "w");
96 VLOG_WARN("failed to create \"%s\": %s",
97 file_name, strerror(errno));
100 setvbuf(file, NULL, _IOLBF, 0);
101 VLOG_WARN("enabled memory leak logging to \"%s\"", file_name);
102 get_hooks(&libc_hooks);
103 set_hooks(&our_hooks);
108 leak_checker_stop(void)
113 set_hooks(&libc_hooks);
114 VLOG_WARN("disabled memory leak logging");
119 leak_checker_set_limit(off_t limit_)
125 leak_checker_usage(void)
127 printf(" --check-leaks=FILE log malloc and free calls to FILE\n");
130 static void PRINTF_FORMAT(1, 2)
131 log_callers(const char *format, ...)
133 struct backtrace backtrace;
137 va_start(args, format);
138 vfprintf(file, format, args);
142 backtrace_capture(&backtrace);
143 for (i = 0; i < backtrace.n_frames; i++) {
144 fprintf(file, " 0x%x", backtrace.frames[i]);
156 VLOG_WARN("error writing leak checker log file");
161 if (count++ >= 100 && limit) {
164 if (fstat(fileno(file), &s) < 0) {
165 VLOG_WARN("cannot fstat leak checker log file: %s",
170 if (s.st_size > limit) {
171 VLOG_WARN("leak checker log file size exceeded limit");
178 set_hooks(&our_hooks);
183 hook_malloc(size_t size, const void *caller UNUSED)
187 set_hooks(&libc_hooks);
189 get_hooks(&libc_hooks);
191 log_callers("malloc(%zu) -> %p", size, p);
198 leak_checker_claim(const void *p)
205 set_hooks(&libc_hooks);
206 log_callers("claim(%p)", p);
212 hook_free(void *p, const void *caller UNUSED)
218 set_hooks(&libc_hooks);
220 get_hooks(&libc_hooks);
222 log_callers("free(%p)", p);
228 hook_realloc(void *p, size_t size, const void *caller UNUSED)
232 set_hooks(&libc_hooks);
233 q = realloc(p, size);
234 get_hooks(&libc_hooks);
237 log_callers("realloc(%p, %zu) -> %p", p, size, q);
244 #endif /* HAVE_MALLOC_HOOKS */