backtrace: Make backtrace_capture() work on more systems.
authorBen Pfaff <blp@nicira.com>
Fri, 13 May 2011 18:55:22 +0000 (11:55 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 13 May 2011 21:37:14 +0000 (14:37 -0700)
The backtrace_capture() implementation only worked properly with GNU C on
systems that have a simple stack frame with a frame pointer.  Notably,
the x86-64 ABI by default has no frame pointer, so this failed on x86-64.

However, glibc has a function named backtrace() that does what we want.
This commit tests for this function and uses it when it is present, fixing
x86-64 backtraces.

configure.ac
lib/backtrace.c
m4/openvswitch.m4

index 5b5f47e..fe91242 100644 (file)
@@ -61,6 +61,7 @@ AC_CHECK_HEADERS([mntent.h sys/statvfs.h])
 
 OVS_CHECK_PKIDIR
 OVS_CHECK_RUNDIR
+OVS_CHECK_BACKTRACE
 OVS_CHECK_MALLOC_HOOKS
 OVS_CHECK_VALGRIND
 OVS_CHECK_SOCKET_LIBS
index 91549db..1c0dfd6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include <config.h>
+
 #include "backtrace.h"
+
 #include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stdio.h>
+
 #include "compiler.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(backtrace);
 
-static uintptr_t OVS_UNUSED
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+void
+backtrace_capture(struct backtrace *b)
+{
+    void *frames[BACKTRACE_MAX_FRAMES];
+    int i;
+
+    b->n_frames = backtrace(frames, BACKTRACE_MAX_FRAMES);
+    for (i = 0; i < b->n_frames; i++) {
+        b->frames[i] = (uintptr_t) frames[i];
+    }
+}
+#elif __GNUC__
+static uintptr_t
 get_max_stack(void)
 {
     static const char file_name[] = "/proc/self/maps";
@@ -83,7 +100,6 @@ in_stack(void *p)
 void
 backtrace_capture(struct backtrace *backtrace)
 {
-#ifdef __GNUC__
     void **frame;
     size_t n;
 
@@ -96,7 +112,11 @@ backtrace_capture(struct backtrace *backtrace)
         backtrace->frames[n++] = (uintptr_t) frame[1];
     }
     backtrace->n_frames = n;
-#else
+}
+#else  /* !HAVE_BACKTRACE && !__GNUC__ */
+void
+backtrace_capture(struct backtrace *backtrace)
+{
     backtrace->n_frames = 0;
-#endif
 }
+#endif
index e6d03a6..73db4bb 100644 (file)
@@ -152,6 +152,11 @@ AC_DEFUN([OVS_CHECK_LOGDIR],
      [LOGDIR='${localstatedir}/log/${PACKAGE}'])
    AC_SUBST([LOGDIR])])
 
+dnl Defines HAVE_BACKTRACE if backtrace() is declared in <execinfo.h>
+dnl and exists in libc.
+AC_DEFUN([OVS_CHECK_BACKTRACE],
+  [AC_CHECK_HEADER([execinfo.h], [AC_CHECK_FUNCS([backtrace])])])
+
 dnl Checks for __malloc_hook, etc., supported by glibc.
 AC_DEFUN([OVS_CHECK_MALLOC_HOOKS],
   [AC_CACHE_CHECK(