00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <lestes/std/vector.hh>
00029 #include <cstdlib>
00030 #include <cstring>
00031 #include <sstream>
00032
00033 #if __linux__ && __GXX_ABI_VERSION >= 100
00034 #define HAVE_BACKTRACE_SUPPORT 0
00035 #define HAVE_CXXABI_H 0
00036 #endif
00037
00038 #ifdef HAVE_BACKTRACE_SUPPORT
00039 #include <execinfo.h>
00040 #ifdef HAVE_CXXABI_H
00041 #include <cxxabi.h>
00042 #endif
00043 #endif
00044
00045
00046 package(lestes);
00047 package(std);
00048
00049 lstring assemble_backtrace()
00050 {
00051 const char * lestes_backtrace = ::std::getenv("LESTES_BACKTRACE");
00052 if (lestes_backtrace) {
00053 lstring value(lestes_backtrace);
00054 if (value == "nil" || value == "0") {
00055 return " Backtrace printing disabled.";
00056 }
00057 }
00058 #ifdef HAVE_BACKTRACE_SUPPORT
00059 enum {
00060 INITIAL_ITEMS = 32,
00061 MAX_ITEMS = 512
00062 };
00063 int items = INITIAL_ITEMS;
00064 void ** array = NULL;
00065 int size;
00066 do {
00067 if (array) {
00068 items *= 2;
00069 delete [] array;
00070 }
00071 array = new void *[items];
00072 size = ::backtrace (array, items);
00073 } while (items < MAX_ITEMS && size == items);
00074
00075 char **strings = ::backtrace_symbols (array, size);
00076
00077 ::std::vector < lstring > stringv(strings, strings+size);
00078
00079 ::std::ostringstream oss;
00080 oss << "Obtained " << size << " stack frames:\n";
00081
00082 ::std::vector < lstring >::iterator it = stringv.begin();
00083 ::std::vector < lstring >::iterator jt = stringv.end();
00084 for ( ; it != jt ; ++it ) {
00085 #ifdef HAVE_CXXABI_H
00086 lstring::size_type s1 = it->find('(');
00087 lstring::size_type lastslash = it->rfind('/', s1);
00088 lstring::size_type s2 = it->find('+', s1);
00089
00090 if(s1 == lstring::npos || s2 == lstring::npos ) {
00091 oss << "(?) " << *it << '\n';
00092 } else {
00093 lstring lib;
00094
00095 if(lastslash != lstring::npos)
00096 lib = it->substr(lastslash + 1, s1 - lastslash - 1);
00097 else
00098 lib = it->substr(0, s1+1);
00099
00100 int status=-1;
00101 lstring mangled(*it, s1+1, s2-s1-1);
00102
00103 lstring demangled;
00104
00105
00106 if(!mangled.size() || mangled[0] == '_') {
00107 char * raw = ::__cxxabiv1::__cxa_demangle(mangled.c_str(), NULL, 0, &status);
00108 if (raw) {
00109 demangled = raw;
00110 ::std::free(raw);
00111 } else
00112 demangled = mangled;
00113 } else {
00114 status = 666;
00115 demangled = "XXX";
00116 }
00117
00118
00119 if (status) {
00120 oss << mangled << " in " << lib << " (DEMANGLE FAILED)\n";
00121 } else {
00122 oss << demangled << " in " << lib << '\n';
00123 }
00124
00125
00126
00127 }
00128 #else
00129 oss << *it << '\n';
00130 #endif
00131 }
00132 if(size == items) {
00133 oss << " (... more stack frames ...)\n";
00134 }
00135 free (strings);
00136 if (array)
00137 delete [] array;
00138 return oss.str();
00139 #else
00140 return "(no backtrace support enabled)";
00141 #endif
00142 }
00143
00144 end_package(std);
00145 end_package(lestes);
00146
00147