Signed-off-by: Steven Noonan <steven@uplinklabs.net>
O3O2MFGRNWKNTZ43AAWUALJWGCGI4E442PGR2ZFKYOSU4XSDYDGQC
#ifdef OSX
#include <dlfcn.h>
typedef int (*backtrace_t)(void * *, int);
typedef char **(*backtrace_symbols_t)(void * const *, int);
// used to convert from void* to function pointer (without a
// compiler warning).
template <typename TO, typename FROM> TO nasty_cast(FROM f) {
union {
FROM f; TO t;
} u; u.f = f; return u.t;
}
#ifdef __GLIBC__
// NOTE: This should work on OS X, according to
// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/ManPages/man3/backtrace_symbols.3.html
#if (defined(UNIX) || defined(OSX))
int num_frames = backtrace(frames, ARRAYSZ(frames));
#if defined (OSX)
backtrace_t backtrace;
backtrace_symbols_t backtrace_symbols;
backtrace = nasty_cast<backtrace_t, void*>(dlsym(RTLD_DEFAULT, "backtrace"));
backtrace_symbols = nasty_cast<backtrace_symbols_t, void*>(dlsym(RTLD_DEFAULT, "backtrace_symbols"));
if (!backtrace || !backtrace_symbols)
{
fprintf(stderr, "Couldn't get a stack trace." EOL);
fprintf(file, "Couldn't get a stack trace." EOL);
return;
}
#endif
for (int i = ignore_count; i < num_frames; i++)
{
fprintf(file, "%s" EOL, symbols[i]);
}
// Now we prettify the printout to even show demangled C++ function names.
std::string bt = "";
for (int i = 0; i < num_frames; i++) {
#if defined (OSX)
char *addr = ::strstr(symbols[i], "0x");
char *mangled = ::strchr(addr, ' ') + 1;
char *offset = ::strchr(addr, '+');
char *postmangle = ::strchr(mangled, ' ');
if (mangled) *(mangled - 1) = 0;
bt += addr;
int status;
bt += ": ";
if (addr && mangled) {
if (postmangle)
*postmangle = '\0';
char *realname = abi::__cxa_demangle(mangled, 0, 0, &status);
if (realname) {
bt += realname;
} else {
bt += mangled;
}
bt += " ";
bt += offset;
free(realname);
}
#else // OSX
bt += symbols[i];
int status;
/* extract the identifier from symbols[i]. It's inside of parens. */
char * firstparen = ::strchr(symbols[i], '(');
char * lastparen = ::strchr(symbols[i], '+');
if (firstparen != 0 && lastparen != 0 && firstparen < lastparen) {
bt += ": ";
*lastparen = '\0';
char * realname = abi::__cxa_demangle(firstparen + 1, 0, 0, &status);
if (realname != NULL) {
bt += realname;
}
free(realname);
}
#endif
bt += EOL;
}