#include <cstring>
#include <cstdlib>
+#include <cstdio>
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
-#include <execinfo.h>
-#include <cxxabi.h>
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
+#ifdef HAVE_GCC_ABI_DEMANGLE
+# include <cxxabi.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#ifdef HAVE_GCC_ABI_DEMANGLE
+# define USE_DEMANGLE 1
+#else
+# define USE_DEMANGLE 0
+#endif
+
+const int MAX_DEPTH= 50;
void custom_backtrace(void)
{
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
- void *array[50];
+#ifdef HAVE_EXECINFO_H
+ void *array[MAX_DEPTH];
- size_t size= backtrace(array, 50);
- char **strings= backtrace_symbols(array, size);
+ int backtrace_size= backtrace(array, MAX_DEPTH);
+ fprintf(stderr, "Number of stack frames obtained: %d\n", backtrace_size);
- fprintf(stderr, "Number of stack frames obtained: %lu\n", (unsigned long)size);
+#ifdef HAVE_DLFCN_H
+ Dl_info dlinfo;
+#endif
- for (size_t x= 1; x < size; x++)
- {
- size_t sz= 200;
- char *function= (char *)malloc(sz);
- char *begin= 0;
- char *end= 0;
-
- for (char *j = strings[x]; *j; ++j)
+ for (int x= 0; x < backtrace_size; ++x)
+ {
+#ifdef HAVE_DLFCN_H
+ if (dladdr(array[x], &dlinfo) == 0)
{
- if (*j == '(') {
- begin = j;
- }
- else if (*j == '+') {
- end = j;
- }
+ continue;
}
- if (begin && end)
- {
- begin++;
- *end= '\0';
+#endif
- 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);
- }
- else
+ const char* symname= dlinfo.dli_sname;
+
+ int status;
+ char* demangled= abi::__cxa_demangle(symname, NULL, 0, &status);
+ if (status == 0 and demangled)
{
- fprintf(stderr, "%s\n", strings[x]);
+ symname= demangled;
}
- free(function);
- }
+ printf("object: %s, function: %s\n", dlinfo.dli_fname, symname);
- free (strings);
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+ if (demangled)
+ {
+ free(demangled);
+ }
+ }
+#endif // HAVE_EXECINFO_H
}