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
00029
00030
00031
00032
00033
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/StackTrace.hpp"
00040
00041 #ifdef BLOCXX_WIN32
00042 #include <iostream>
00043 namespace BLOCXX_NAMESPACE
00044 {
00045 using std::cerr;
00046 using std::endl;
00047 void StackTrace::printStackTrace(EDoStackTraceFlag)
00048 {
00049 cerr << "StackTrace::printStackTrace not implemented yet" << endl;
00050 }
00051 }
00052 #else
00053
00054 #include "blocxx/Exec.hpp"
00055 #include "blocxx/UnnamedPipe.hpp"
00056 #include "blocxx/Format.hpp"
00057 #include "blocxx/Array.hpp"
00058 #include "blocxx/StringBuffer.hpp"
00059
00060 #include <fstream>
00061 #include <iostream>
00062
00063 #if defined(BLOCXX_HAVE_BACKTRACE)
00064 #include <execinfo.h>
00065 #endif
00066
00067 #if defined(BLOCXX_HAVE_CXXABI_H)
00068 #include <cxxabi.h>
00069 #endif
00070
00071 #ifdef BLOCXX_HAVE_UNISTD_H
00072 extern "C"
00073 {
00074 #include <unistd.h>
00075 }
00076 #endif
00077
00078 namespace BLOCXX_NAMESPACE
00079 {
00080
00081 using std::ifstream;
00082 using std::ofstream;
00083 using std::flush;
00084
00085 #ifndef BLOCXX_DEFAULT_GDB_PATH
00086 #define BLOCXX_DEFAULT_GDB_PATH "/usr/bin/gdb"
00087 #endif
00088
00089
00090 void StackTrace::printStackTrace(EDoStackTraceFlag doStackTrace)
00091 {
00092 std::cerr << getStackTrace(doStackTrace);
00093 }
00094
00095 String StackTrace::getStackTrace(EDoStackTraceFlag doStackTrace)
00096 {
00097
00098 if (doStackTrace == E_NO_CHECK_ENV_VAR || (doStackTrace == E_CHECK_ENV_VAR && getenv("BLOCXX_STACKTRACE")))
00099 {
00100
00101
00102
00103 #ifdef BLOCXX_HAVE_BACKTRACE
00104 void *array[200];
00105
00106 size_t size = backtrace (array, 200);
00107 char **strings = backtrace_symbols (array, size);
00108
00109 StringBuffer bt;
00110
00111 size_t i;
00112 for (i = 0; i < size; i++)
00113 {
00114 #if defined(BLOCXX_HAVE_CXXABI_H)
00115 bt += strings[i];
00116 int status;
00117
00118 char* firstparen = ::strchr(strings[i], '(');
00119 char* lastparen = ::strchr(strings[i], '+');
00120 if (firstparen != 0 && lastparen != 0 && firstparen < lastparen)
00121 {
00122 bt += ": ";
00123 *lastparen = '\0';
00124 char* realname = abi::__cxa_demangle(firstparen+1, 0, 0, &status);
00125 bt += realname;
00126 free(realname);
00127 }
00128 #else
00129 bt += strings[i];
00130 #endif
00131 bt += "\n";
00132 }
00133
00134 free (strings);
00135
00136 return bt.releaseString();
00137 #else
00138 ifstream file(BLOCXX_DEFAULT_GDB_PATH);
00139 if (file)
00140 {
00141 file.close();
00142 String scriptName("/tmp/owgdb-");
00143 String outputName("/tmp/owgdbout-");
00144
00145 outputName += String(UInt32(::getpid()));
00146 scriptName += String(UInt32(::getpid())) + ".sh";
00147 String exeName("/proc/");
00148 exeName += String(UInt32(::getpid())) + "/exe";
00149
00150 ofstream scriptFile(scriptName.c_str(), std::ios::out);
00151 scriptFile << "#!/bin/sh\n"
00152 << "gdb " << exeName << " " << ::getpid() << " << EOS > " << outputName << " 2>&1\n"
00153
00154 << "bt\n"
00155 << "detach\n"
00156 << "q\n"
00157 << "EOS\n" << flush;
00158 scriptFile.close();
00159 Array<String> command;
00160 command.push_back( "/bin/sh" );
00161 command.push_back( scriptName );
00162 Exec::system(command);
00163 ifstream outputFile(outputName.c_str(), std::ios::in);
00164 StringBuffer output;
00165 while (outputFile)
00166 {
00167 output += String::getLine(outputFile);
00168 output += "\n";
00169 }
00170 outputFile.close();
00171 unlink(outputName.c_str());
00172 unlink(scriptName.c_str());
00173 return output.releaseString();
00174 }
00175 #endif
00176 }
00177 return String();
00178 }
00179
00180 }
00181
00182 #endif // ifdef BLOCXX_WIN32