leak-checker: Break backtracing code into new module "backtrace".
authorBen Pfaff <blp@nicira.com>
Wed, 4 Feb 2009 18:51:09 +0000 (10:51 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 6 Feb 2009 23:07:50 +0000 (15:07 -0800)
This allows other code to use the backtracer too.

lib/automake.mk
lib/backtrace.c [new file with mode: 0644]
lib/backtrace.h [new file with mode: 0644]
lib/leak-checker.c
lib/vlog-modules.def

index bb9751a177044e0385360d74ff87ca63e3cf4083..d1cccd9eada7752ad9c5605937b650ca9a067d97 100644 (file)
@@ -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 (file)
index 0000000..067b196
--- /dev/null
@@ -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 <config.h>
+#include "backtrace.h"
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#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 (file)
index 0000000..bd2e0b4
--- /dev/null
@@ -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 <stdint.h>
+
+#define BACKTRACE_MAX_FRAMES 31
+
+struct backtrace {
+    int n_frames;
+    uintptr_t frames[BACKTRACE_MAX_FRAMES];
+};
+
+void backtrace_capture(struct backtrace *);
+
+#endif /* backtrace.h */
index a50d5c8801a0dbe60b365670cd98c6a84f66d691..2a16211d523ecc306d5f652bec2cc9b926330278 100644 (file)
@@ -34,6 +34,7 @@
 #include <config.h>
 #include "leak-checker.h"
 #include <inttypes.h>
+#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);
 }
index 14d97e6bbcd44529aa81b4b18c709210ace396a6..7ff4004e9d8f5c9c182699bf774e7b9966634a42 100644 (file)
@@ -1,4 +1,5 @@
 /* Modules that can emit log messages. */
+VLOG_MODULE(backtrace)
 VLOG_MODULE(brcompat)
 VLOG_MODULE(bridge)
 VLOG_MODULE(chain)