/* 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 %p 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 %p 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