//====================================================================================================================== // // This file is part of waLBerla. waLBerla is free software: you can // redistribute it and/or modify it under the terms of the GNU General Public // License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // waLBerla is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // //! \file PrintStacktrace.cpp //! \ingroup core //! \author Martin Bauer <martin.bauer@fau.de> // //====================================================================================================================== #include "PrintStacktrace.h" #include "core/DataTypes.h" #include <iostream> namespace walberla { namespace debug { void printStacktrace() { printStacktrace( std::cerr ); } } // namespace debug } // namespace walberla #if defined(WALBERLA_CXX_COMPILER_IS_GNU) || defined(WALBERLA_CXX_COMPILER_IS_INTEL) || defined( WALBERLA_CXX_COMPILER_IS_CLANG) #include <execinfo.h> #include <stdlib.h> #include <string> namespace walberla { namespace debug { void printStacktrace( std::ostream & os ) { using std::string; using std::cerr; using std::endl; const int BACKTRACE_LENGTH = 20; void * array[BACKTRACE_LENGTH]; size_t size; char **strings; size_t i; size = numeric_cast< size_t >( backtrace (array, BACKTRACE_LENGTH) ); strings = backtrace_symbols (array, int_c(size) ); os << "Backtrace: " << std::endl; for (i = 0; i < size; i++) { std::string line ( strings[i] ); // one line might look like this: //./PrintStacktraceTest(_ZN8walberla4core15printStacktraceEv+0x4b) [0x408c6b] // extract the portion in the brackets () and demangle it size_t leftBracket = line.find_first_of( '(' ); size_t rightBracket = line.find_first_of( ')', leftBracket ); string appName = line.substr( 0, leftBracket ); string bracketPart = line.substr( leftBracket+1, rightBracket - leftBracket -1 ); string rest = line.substr( rightBracket +1 ); // split the bracketPart on plus sign size_t plusPos = bracketPart.find_first_of('+'); string functionName = bracketPart.substr(0, plusPos ); string offset = bracketPart.substr( plusPos+1 ); // try to demangle -> no return code if successfull // but the returned string starts with "demangle" if demangling failed // really hacky :( string demangled = demangle( functionName ); if ( demangled.substr(0, 8) == "demangle") demangled = functionName; os << "\t" << appName << " \t " << demangled << endl; } free (strings); } } // namespace debug } // namespace walberla #elif defined(WALBERLA_CXX_COMPILER_IS_MSVC) #pragma warning( push ) #pragma warning( disable : 4091 ) #include "extern/StackWalker.h" namespace walberla { namespace debug { class WalberlaStackWalker : public stack_walker::StackWalker { public: WalberlaStackWalker( std::ostream & os ) : StackWalker(), os_( os ) { } protected: virtual void OnOutput( LPCSTR szText ) { os_ << szText; } virtual void OnSymInit ( LPCSTR /*szSearchPath*/, DWORD /*symOptions*/, LPCSTR /*szUserName*/ ) { } virtual void OnLoadModule ( LPCSTR /*img*/, LPCSTR /*mod*/, DWORD64 /*baseAddr*/, DWORD /*size*/, DWORD /*result*/, LPCSTR /*symType*/, LPCSTR /*pdbName*/, ULONGLONG /*fileVersion*/ ) { } virtual void OnDbgHelpErr ( LPCSTR /*szFuncName*/, DWORD /*gle*/, DWORD64 /*addr*/ ) { } std::ostream & os_; }; void printStacktrace( std::ostream & os ) { WalberlaStackWalker sw( os ); sw.ShowCallstack(); } } // namespace debug } // namespace walberla #pragma warning( pop ) #else namespace walberla { namespace debug { void printStacktrace( std::ostream & ) {} } // namespace debug } // namespace walberla #endif