[ovs-dev] [poll-logging 1/2] backtrace: Make backtrace_capture() work on more systems.

Ben Pfaff blp at nicira.com
Fri May 13 20:07:04 UTC 2011


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      |    1 +
 lib/backtrace.c   |   30 +++++++++++++++++++++++++-----
 m4/openvswitch.m4 |    5 +++++
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5b5f47e..fe91242 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/lib/backtrace.c b/lib/backtrace.c
index 91549db..1c0dfd6 100644
--- a/lib/backtrace.c
+++ b/lib/backtrace.c
@@ -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.
@@ -15,17 +15,34 @@
  */
 
 #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
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index e6d03a6..73db4bb 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -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(
-- 
1.7.4.4




More information about the dev mailing list