00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/common/Backtrace.h"
00026 #include "fennel/common/TraceTarget.h"
00027
00028 #include <sstream>
00029
00030 #ifndef __MSVC__
00031 #include <cxxabi.h>
00032 #endif
00033
00034 using std::endl;
00035 using std::ostream;
00036
00037 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/common/Backtrace.cpp#12 $");
00038
00039 Backtrace::~Backtrace()
00040 {
00041 if (ownbuf) {
00042 delete[] addrbuf;
00043 }
00044 }
00045
00046 Backtrace::Backtrace(size_t maxdepth)
00047 : ownbuf(true), bufsize(maxdepth + 1)
00048 {
00049 #ifndef __MSVC__
00050 addrbuf = new void * [bufsize];
00051 depth = backtrace(addrbuf, bufsize);
00052 #endif
00053 }
00054
00055 Backtrace::Backtrace(size_t bufsize, void** buffer)
00056 : ownbuf(false), bufsize(bufsize)
00057 {
00058 #ifndef __MSVC__
00059 addrbuf = buffer;
00060 depth = backtrace(addrbuf, bufsize);
00061 #endif
00062 }
00063
00064
00065
00066
00067 void Backtrace::print(int fd) const
00068 {
00069 #ifndef __MSVC__
00070
00071 if (depth > 1) {
00072 backtrace_symbols_fd(addrbuf + 1, depth - 1, fd);
00073 }
00074 #endif
00075 }
00076
00077 #ifndef __MSVC__
00078 int Backtrace::lookupLibraryBase(
00079 struct dl_phdr_info *pInfo, size_t size, void *pData)
00080 {
00081 LibraryInfo *pLibInfo = reinterpret_cast<LibraryInfo *>(pData);
00082 if (strcmp(pLibInfo->pImageName, pInfo->dlpi_name) == 0) {
00083 pLibInfo->baseAddress = pInfo->dlpi_addr;
00084 return 1;
00085 }
00086 return 0;
00087 }
00088 #endif
00089
00090
00091
00092
00093
00094
00095 ostream& Backtrace::print(ostream& os) const
00096 {
00097 #ifndef __MSVC__
00098 char **syms = backtrace_symbols(addrbuf, depth);
00099 if (syms) {
00100
00101 for (int i = 1; i < depth; i++) {
00102
00103
00104
00105 char *pSymbol = syms[i];
00106 char *pLeftParen = strchr(pSymbol, '(');
00107 char *pPlus = strchr(pSymbol, '+');
00108 char *pLeftBracket = strchr(pSymbol, '[');
00109 char *pRightBracket = strchr(pSymbol, ']');
00110
00111
00112
00113
00114 if (pLeftParen && (pLeftParen[1] != '_')) {
00115 pLeftParen = NULL;
00116 }
00117
00118 if (!pLeftParen || !pPlus || (pLeftParen > pPlus)
00119 || !pLeftBracket || !pRightBracket
00120 || (pLeftBracket > pRightBracket)
00121 || (pPlus > pLeftBracket))
00122 {
00123
00124 os << pSymbol << endl;
00125 continue;
00126 }
00127
00128
00129
00130
00131 *pLeftParen = 0;
00132 LibraryInfo libInfo;
00133 libInfo.baseAddress = 0;
00134 libInfo.pImageName = pSymbol;
00135 dl_iterate_phdr(lookupLibraryBase, &libInfo);
00136
00137
00138 os << pSymbol << '(';
00139
00140
00141 *pLeftParen = '(';
00142
00143 *pPlus = 0;
00144 writeDemangled(os, pLeftParen + 1);
00145
00146 *pPlus = '+';
00147 *pLeftBracket = 0;
00148 os << pPlus;
00149 *pLeftBracket = '[';
00150 os << '[';
00151
00152
00153 *pRightBracket = 0;
00154 unsigned long addr = strtoul(
00155 pLeftBracket + 1, NULL, 16);
00156 *pRightBracket = ']';
00157 if (libInfo.baseAddress) {
00158 addr -= libInfo.baseAddress;
00159 }
00160 os << "0x";
00161 os << std::hex;
00162 os << addr;
00163 os << std::dec;
00164 os << ']';
00165 os << endl;
00166 }
00167 free(syms);
00168 }
00169 #endif
00170 return os;
00171 }
00172
00173 void Backtrace::writeDemangled(std::ostream &out, char const *pMangled)
00174 {
00175 int status = -3;
00176 char *pDemangled = NULL;
00177 #ifndef __MSVC__
00178 pDemangled =
00179 abi::__cxa_demangle(pMangled, NULL, NULL, &status);
00180 #endif
00181 if (status || !pDemangled) {
00182
00183
00184 out << pMangled;
00185 } else {
00186 out << pDemangled;
00187 free(pDemangled);
00188 }
00189 }
00190
00191 std::ostream* AutoBacktrace::pstream = &std::cerr;
00192 SharedTraceTarget AutoBacktrace::ptrace;
00193
00194 #ifndef __MSVC__
00195 struct sigaction AutoBacktrace::nextAction[BACKTRACE_SIG_MAX];
00196 #endif
00197
00198 void AutoBacktrace::signal_handler(int signum)
00199 {
00200 #ifndef __MSVC__
00201 Backtrace bt;
00202 if (ptrace) {
00203 std::ostringstream oss;
00204 oss <<
00205 "*** CAUGHT SIGNAL " << signum << "; BACKTRACE:" << std::endl;
00206 oss << bt;
00207 std::string msg = oss.str();
00208 if (pstream) {
00209 *pstream << msg;
00210 }
00211 ptrace->notifyTrace("backtrace", TRACE_SEVERE, msg);
00212 } else if (pstream) {
00213 *pstream <<
00214 "*** CAUGHT SIGNAL " << signum << "; BACKTRACE:" << std::endl;
00215 *pstream << bt;
00216 }
00217
00218
00219 sigaction(signum, &(nextAction[signum]), NULL);
00220 raise(signum);
00221 #endif
00222 }
00223
00224 void AutoBacktrace::setOutputStream()
00225 {
00226 pstream = 0;
00227 }
00228
00229 void AutoBacktrace::setOutputStream(ostream& os)
00230 {
00231 pstream = &os;
00232 }
00233
00234 void AutoBacktrace::setTraceTarget(SharedTraceTarget p)
00235 {
00236 ptrace = p;
00237 }
00238
00239 void AutoBacktrace::install(bool includeSegFault)
00240 {
00241
00242
00243
00244 #ifndef __MSVC__
00245 installSignal(SIGILL);
00246 installSignal(SIGABRT);
00247
00248 if (includeSegFault) {
00249 installSignal(SIGSEGV);
00250 }
00251
00252 installSignal(SIGBUS);
00253 #endif
00254 }
00255
00256 void AutoBacktrace::installSignal(int signum)
00257 {
00258 #ifndef __MSVC__
00259 permAssert(signum < BACKTRACE_SIG_MAX);
00260 struct sigaction act;
00261 struct sigaction old_act;
00262 act.sa_handler = signal_handler;
00263 sigemptyset (&act.sa_mask);
00264 act.sa_flags = 0;
00265 int rc = sigaction(signum, &act, &old_act);
00266 if (rc) {
00267 return;
00268 }
00269 if (old_act.sa_handler != signal_handler) {
00270
00271 nextAction[signum] = old_act;
00272 }
00273 #endif
00274 }
00275
00276 FENNEL_END_CPPFILE("$Id");
00277
00278