From 10cd7694a4948e613d308448646b73da9a848cc7 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 4 Feb 2009 10:51:09 -0800 Subject: [PATCH] leak-checker: Break backtracing code into new module "backtrace". This allows other code to use the backtracer too. --- lib/automake.mk | 2 + lib/backtrace.c | 123 +++++++++++++++++++++++++++++++++++++++++++ lib/backtrace.h | 48 +++++++++++++++++ lib/leak-checker.c | 73 +++---------------------- lib/vlog-modules.def | 1 + 5 files changed, 180 insertions(+), 67 deletions(-) create mode 100644 lib/backtrace.c create mode 100644 lib/backtrace.h diff --git a/lib/automake.mk b/lib/automake.mk index bb9751a1..d1cccd9e 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -1,6 +1,8 @@ noinst_LIBRARIES += lib/libopenflow.a lib_libopenflow_a_SOURCES = \ + lib/backtrace.c \ + lib/backtrace.h \ lib/bitmap.c \ lib/bitmap.h \ lib/command-line.c \ diff --git a/lib/backtrace.c b/lib/backtrace.c new file mode 100644 index 00000000..067b1968 --- /dev/null +++ b/lib/backtrace.c @@ -0,0 +1,123 @@ +/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#include +#include "backtrace.h" +#include +#include +#include +#include +#include "compiler.h" + +#define THIS_MODULE VLM_backtrace +#include "vlog.h" + +static uintptr_t UNUSED +get_max_stack(void) +{ + static const char file_name[] = "/proc/self/maps"; + char line[1024]; + int line_number; + FILE *f; + + f = fopen(file_name, "r"); + if (f == NULL) { + VLOG_WARN("opening %s failed: %s", file_name, strerror(errno)); + return -1; + } + + for (line_number = 1; fgets(line, sizeof line, f); line_number++) { + if (strstr(line, "[stack]")) { + uintptr_t end; + if (sscanf(line, "%*"SCNxPTR"-%"SCNxPTR, &end) != 1) { + VLOG_WARN("%s:%d: parse error", file_name, line_number); + continue; + } + fclose(f); + return end; + } + } + fclose(f); + + VLOG_WARN("%s: no stack found", file_name); + return -1; +} + +static uintptr_t +stack_high(void) +{ + static uintptr_t high; + if (!high) { + high = get_max_stack(); + } + return high; +} + +static uintptr_t +stack_low(void) +{ +#ifdef __i386__ + uintptr_t low; + asm("movl %%esp,%0" : "=g" (low)); + return low; +#else + /* This causes a warning in GCC that cannot be disabled, so use it only on + * non-x86. */ + int dummy; + return (uintptr_t) &dummy; +#endif +} + +static bool +in_stack(void *p) +{ + uintptr_t address = (uintptr_t) p; + return address >= stack_low() && address < stack_high(); +} + +void +backtrace_capture(struct backtrace *backtrace) +{ + void **frame; + size_t n; + + n = 0; + for (frame = __builtin_frame_address(1); + frame != NULL && in_stack(frame) && frame[0] != NULL + && n < BACKTRACE_MAX_FRAMES; + frame = frame[0]) + { + backtrace->frames[n++] = (uintptr_t) frame[1]; + } + backtrace->n_frames = n; +} diff --git a/lib/backtrace.h b/lib/backtrace.h new file mode 100644 index 00000000..bd2e0b47 --- /dev/null +++ b/lib/backtrace.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#ifndef BACKTRACE_H +#define BACKTRACE_H 1 + +#include + +#define BACKTRACE_MAX_FRAMES 31 + +struct backtrace { + int n_frames; + uintptr_t frames[BACKTRACE_MAX_FRAMES]; +}; + +void backtrace_capture(struct backtrace *); + +#endif /* backtrace.h */ diff --git a/lib/leak-checker.c b/lib/leak-checker.c index a50d5c88..2a16211d 100644 --- a/lib/leak-checker.c +++ b/lib/leak-checker.c @@ -34,6 +34,7 @@ #include #include "leak-checker.h" #include +#include "backtrace.h" #define THIS_MODULE VLM_leak_checker #include "vlog.h" @@ -143,83 +144,21 @@ leak_checker_usage(void) printf(" --check-leaks=FILE log malloc and free calls to FILE\n"); } -static uintptr_t UNUSED -get_max_stack(void) -{ - static const char file_name[] = "/proc/self/maps"; - char line[1024]; - int line_number; - FILE *f; - - f = fopen(file_name, "r"); - if (f == NULL) { - VLOG_WARN("opening %s failed: %s", file_name, strerror(errno)); - return -1; - } - - for (line_number = 1; fgets(line, sizeof line, f); line_number++) { - if (strstr(line, "[stack]")) { - uintptr_t end; - if (sscanf(line, "%*"SCNxPTR"-%"SCNxPTR, &end) != 1) { - VLOG_WARN("%s:%d: parse error", file_name, line_number); - continue; - } - fclose(f); - return end; - } - } - fclose(f); - - VLOG_WARN("%s: no stack found", file_name); - return -1; -} - -static void -get_stack_limits(uintptr_t *lowp, uintptr_t *highp) -{ -#ifndef __i386__ - static bool warned = false; - if (!warned) { - warned = true; - VLOG_WARN("stack limit detection not implemented on " - "this architecture, possible segfaults from leak checker"); - } - *lowp = 0; - *highp = (uintptr_t) -1; -#else - static uintptr_t high; - if (!high) { - high = get_max_stack(); - } - asm("movl %%esp,%0" : "=g" (*lowp)); - *highp = high; -#endif -} - -static bool -in_stack(void *p) -{ - uintptr_t address = (uintptr_t) p; - uintptr_t low, high; - get_stack_limits(&low, &high); - return address >= low && address < high; -} - static void PRINTF_FORMAT(1, 2) log_callers(const char *format, ...) { + struct backtrace backtrace; va_list args; - void **frame; + int i; va_start(args, format); vfprintf(file, format, args); va_end(args); putc(':', file); - for (frame = __builtin_frame_address(0); - frame != NULL && in_stack(frame) && frame[0] != NULL; - frame = frame[0]) { - fprintf(file, " %p", frame[1]); + backtrace_capture(&backtrace); + for (i = 0; i < backtrace.n_frames; i++) { + fprintf(file, " 0x%x", backtrace.frames[i]); } putc('\n', file); } diff --git a/lib/vlog-modules.def b/lib/vlog-modules.def index 14d97e6b..7ff4004e 100644 --- a/lib/vlog-modules.def +++ b/lib/vlog-modules.def @@ -1,4 +1,5 @@ /* Modules that can emit log messages. */ +VLOG_MODULE(backtrace) VLOG_MODULE(brcompat) VLOG_MODULE(bridge) VLOG_MODULE(chain) -- 2.30.2