Fennel: /home/pub/open/dev/fennel/common/Backtrace.cpp Source File (original) (raw)

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 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