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