Cleanup around linking.
[m6w6/libmemcached] / libmemcached / backtrace.cc
index bc8846bae820703799945342223cb968547f30f0..782ea6a91f80d87e3cbca63cb8d62e269d2e85ba 100644 (file)
@@ -1,8 +1,8 @@
 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  * 
- *  libmcachedd client library.
+ *  Libmemcached client library.
  *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
  *
  */
 
-#include <libmemcached/common.h>
+#include "mem_config.h"
 
-#include <cstring>
+#include "libmemcached/backtrace.hpp"
+
+#include <cstdio>
 #include <cstdlib>
+#include <cstring>
 
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
+#if defined(HAVE_SHARED_ENABLED) && HAVE_SHARED_ENABLED
+
+#ifdef HAVE_EXECINFO_H
 #include <execinfo.h>
-#include <cxxabi.h>
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+#endif
+
+#ifdef HAVE_GCC_ABI_DEMANGLE
+# include <cxxabi.h>
+# define USE_DEMANGLE 1
+#else
+# define USE_DEMANGLE 0
+#endif
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif   
 
+const int MAX_DEPTH= 50;
 
 void custom_backtrace(void)
 {
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
-  void *array[50];
+#ifdef HAVE_EXECINFO_H
+  void *backtrace_buffer[MAX_DEPTH +1];
 
-  size_t size= backtrace(array, 50);
-  char **strings= backtrace_symbols(array, size);
+  int stack_frames= backtrace(backtrace_buffer, MAX_DEPTH);
+  if (stack_frames)
+  {
+    char **symbollist= backtrace_symbols(backtrace_buffer, stack_frames);
+    if (symbollist)
+    {
+      for (int x= 0; x < stack_frames; x++) 
+      {
+        bool was_demangled= false;
 
-  fprintf(stderr, "Number of stack frames obtained: %lu\n", (unsigned long)size);
+        if (USE_DEMANGLE)
+        {
+#ifdef HAVE_DLFCN_H
+          Dl_info dlinfo;
+          if (dladdr(backtrace_buffer[x], &dlinfo))
+          {
+            char demangled_buffer[1024];
+            const char *called_in= "<unresolved>";
+            if (dlinfo.dli_sname)
+            {
+              size_t demangled_size= sizeof(demangled_buffer);
+              int status;
+              char* demangled;
+              if ((demangled= abi::__cxa_demangle(dlinfo.dli_sname, demangled_buffer, &demangled_size, &status)))
+              {
+                called_in= demangled;
+                fprintf(stderr, "---> demangled: %s -> %s\n", demangled_buffer, demangled);
+              }
+              else
+              {
+                called_in= dlinfo.dli_sname;
+              }
 
-  for (size_t x= 1; x < size; x++) 
-  {
-    size_t sz= 200;
-    char *function= (char *)malloc(sz);
-    char *begin= 0;
-    char *end= 0;
+              was_demangled= true;
+              fprintf(stderr, "#%d  %lp in %s at %s\n",
+                      x, backtrace_buffer[x],
+                      called_in,
+                      dlinfo.dli_fname);
+            }
+          }
+#endif
+        }
 
-    for (char *j = strings[x]; *j; ++j)
-    {
-      if (*j == '(') {
-        begin = j;
-      }
-      else if (*j == '+') {
-        end = j;
+        if (was_demangled == false)
+        {
+          fprintf(stderr, "?%d  %lp in %s\n", x, backtrace_buffer[x], symbollist[x]);
+        }
       }
-    }
-    if (begin && end)
-    {
-      begin++;
-      *end= '\0';
 
-      int status;
-      char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
-      if (ret) 
-      {
-        function= ret;
-      }
-      else
-      {
-        strncpy(function, begin, sz);
-        strncat(function, "()", sz);
-        function[sz-1] = '\0';
-      }
-      fprintf(stderr, "%s\n", function);
+      ::free(symbollist);
     }
-    else
-    {
-      fprintf(stderr, "%s\n", strings[x]);
-    }
-    free(function);
   }
+#endif // HAVE_EXECINFO_H
+}
 
+#else // HAVE_SHARED_ENABLED
 
-  free (strings);
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+void custom_backtrace(void)
+{
+  fprintf(stderr, "Backtrace null function called\n");
 }
+#endif // AX_ENABLE_BACKTRACE