OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #if (( defined( __linux__ ) && defined( __GNUC__ )) && !defined( __ANDROID__) || defined ( __APPLE__ )) 00026 #define BACKTRACE_SUPPORTED 00027 #endif 00028 00029 #ifdef BACKTRACE_SUPPORTED 00030 // This is highly platform dependent. Used for backtrace functionality. 00031 #include <execinfo.h> 00032 #include <cxxabi.h> 00033 #endif 00034 00035 #include <iostream> 00036 #include <list> 00037 #include <sstream> 00038 #include <stdexcept> 00039 #include <string> 00040 00041 #include <boost/algorithm/string.hpp> 00042 00043 #include "WException.h" 00044 00045 /** 00046 * initialize static member. 00047 */ 00048 bool WException::noBacktrace = false; 00049 00050 WException::WException( const std::string& msg ): 00051 exception(), 00052 m_labelColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGRed ) ), 00053 m_functionColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGBlue ) ), 00054 m_symbolColor( WTerminalColor() ), 00055 m_headlineColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGYellow ) ) 00056 { 00057 // initialize members 00058 m_msg = msg; 00059 00060 // print stacktrace and message 00061 // no backtrace? 00062 if( !noBacktrace ) 00063 { 00064 std::cerr << m_headlineColor( std::string( "Exception thrown! Callstack's backtrace:" ) ) << std::endl << getBacktrace() << std::endl; 00065 } 00066 } 00067 00068 WException::WException( const std::exception& e ): 00069 exception( e ), 00070 m_labelColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGRed ) ), 00071 m_functionColor( WTerminalColor( WTerminalColor::Off, WTerminalColor::FGBlue ) ), 00072 m_symbolColor( WTerminalColor() ), 00073 m_headlineColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGYellow ) ) 00074 { 00075 m_msg = e.what(); 00076 00077 // print stacktrace and message 00078 // no backtrace? 00079 if( !noBacktrace ) 00080 { 00081 std::cerr << m_headlineColor( std::string( "Exception thrown! Callstack's backtrace:" ) ) << std::endl << getBacktrace() << std::endl; 00082 } 00083 } 00084 00085 WException::~WException() throw() 00086 { 00087 // cleanup 00088 } 00089 00090 const char* WException::what() const throw() 00091 { 00092 // return it 00093 return m_msg.c_str(); 00094 } 00095 00096 std::string WException::getTrace() const 00097 { 00098 std::string result( what() ); 00099 result += "\n\n"; 00100 std::list< std::string >::const_iterator citer; 00101 for( citer = m_trace.begin(); citer != m_trace.end(); ++citer ) 00102 result += "trace: " + *citer + "\n"; 00103 boost::trim( result ); 00104 return result; 00105 } 00106 00107 std::string WException::getBacktrace() const 00108 { 00109 // print trace here 00110 std::ostringstream o; 00111 00112 #ifdef BACKTRACE_SUPPORTED 00113 // This is highly platform dependent. It MIGHT also work on BSD and other unix. 00114 00115 // Automatic callstack backtrace 00116 const size_t maxDepth = 100; 00117 size_t stackDepth; 00118 void* stackAddrs[maxDepth]; 00119 char** stackSymbols; 00120 00121 // acquire stacktrace 00122 stackDepth = backtrace( stackAddrs, maxDepth ); 00123 stackSymbols = backtrace_symbols( stackAddrs, stackDepth ); 00124 00125 // for each stack element -> demangle and print 00126 for( size_t i = 1; i < stackDepth; ++i ) 00127 { 00128 // need some space for function name 00129 // just a guess, especially template names might be even longer 00130 size_t functionLength = 512; 00131 char* function = new char[functionLength]; 00132 00133 // find mangled function name in stackSymbols[i] 00134 char* begin = 0; 00135 char* end = 0; 00136 00137 // find the parentheses and address offset surrounding the mangled name 00138 for( char* j = stackSymbols[i]; *j; ++j ) 00139 { 00140 if( *j == '(' ) 00141 { 00142 begin = j; 00143 } 00144 else if( *j == '+' ) 00145 { 00146 end = j; 00147 } 00148 } 00149 00150 // found? 00151 if( begin && end ) 00152 { 00153 *begin++ = '('; 00154 *end = '\0'; // temporarily end string there (since \0 is string delimiter) 00155 00156 // found our mangled name, now in [begin, end) 00157 int status; 00158 char* ret = abi::__cxa_demangle( begin, function, &functionLength, &status ); 00159 00160 if( ret ) 00161 { 00162 // return value may be a realloc() of the input 00163 function = ret; 00164 } 00165 else 00166 { 00167 // demangling failed, just pretend it's a C function with no args 00168 std::strncpy( function, begin, functionLength ); 00169 std::strncat( function, "()", functionLength ); 00170 function[functionLength-1] = '\0'; 00171 } 00172 *end = '+'; 00173 o << m_labelColor( std::string( "trace: " ) ) 00174 << m_functionColor( function ) 00175 << "\t->\t" 00176 << m_symbolColor( stackSymbols[i] ) << std::endl; 00177 } 00178 else 00179 { 00180 // didn't find the mangled name, just print the whole line 00181 o << m_labelColor( std::string( "trace: " ) ) 00182 << m_functionColor( std::string( "??? " ) ) 00183 << "\t->\t" 00184 << m_symbolColor( stackSymbols[i] ) << std::endl; 00185 } 00186 00187 delete[] function; 00188 } 00189 00190 // backtrace_symbols malloc()ed some mem -> we NEED to use free() 00191 free( stackSymbols ); 00192 #else 00193 o << "Backtrace not supported on your platform. Currently just works on Linux and MacOS with GCC. Sorry!" << std::endl 00194 << "Message was: " << what(); 00195 #endif 00196 00197 return o.str(); 00198 } 00199 00200 void WException::disableBacktrace() 00201 { 00202 noBacktrace = true; 00203 } 00204