From 20a8d15a4494ba52c0200eb04d95351ae1a8c928 Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Wed, 2 Apr 2008 09:16:16 +0000 Subject: [PATCH] Utils: Add backtrace to exception message in SENF_DEBUG builds --- Utils/Exception.cc | 36 ++++++++++++++++++++++++++++++++++++ Utils/Exception.cci | 6 +++++- Utils/Exception.hh | 8 ++++++++ Utils/Exception.test.cc | 6 +++++- config.hh | 4 ++++ senfscons/SENFSCons.py | 2 +- 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Utils/Exception.cc b/Utils/Exception.cc index f94be754b..c86dade4d 100644 --- a/Utils/Exception.cc +++ b/Utils/Exception.cc @@ -27,6 +27,10 @@ //#include "Exception.ih" // Custom includes +#include <execinfo.h> +#include <sstream> +#include "../config.hh" +#include "impl/demangle.h" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// @@ -44,6 +48,38 @@ prefix_ char const * senf::Exception::what() return message_.c_str(); } +#ifdef SENF_DEBUG +prefix_ void senf::Exception::addBacktrace() +{ + void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS]; + unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) ); + char ** symbols = ::backtrace_symbols(entries, nEntries); + + std::stringstream ss; + ss << "\nException at\n"; + for (unsigned i=0; i<nEntries; ++i) { + std::string sym (symbols[i]); + std::string::size_type fnStart (sym.find("(")); + if (fnStart != std::string::npos) { + std::string::size_type fnEnd (sym.find(")",fnStart+1)); + if (fnEnd != std::string::npos) { + std::string fn (sym,fnStart+1, fnEnd-fnStart-1); + char * demangled ( ::cplus_demangle(fn.c_str(), + DMGL_TYPES|DMGL_AUTO) ); + if (demangled) { + ss << " " << demangled << "( ... )" << std::string(sym,fnEnd+1) << "\n"; + continue; + } + } + } + ss << " " << sym << "\n"; + } + ss << "-- \n" << message_; + message_ = ss.str(); + free(symbols); +} +#endif + /////////////////////////////////////////////////////////////////////////// // senf::SystemException diff --git a/Utils/Exception.cci b/Utils/Exception.cci index b745f8056..1b611a2c1 100644 --- a/Utils/Exception.cci +++ b/Utils/Exception.cci @@ -32,7 +32,11 @@ prefix_ senf::Exception::Exception(std::string const & description) : message_(description) -{} +{ +#ifdef SENF_DEBUG + addBacktrace(); +#endif +} prefix_ std::string const & senf::Exception::message() const diff --git a/Utils/Exception.hh b/Utils/Exception.hh index 5f00926f4..fefe136f8 100644 --- a/Utils/Exception.hh +++ b/Utils/Exception.hh @@ -79,6 +79,11 @@ struct FooException : public senf::Exception { FooException() : senf::Exception("Foo hit the fan") {} }; \endcode + + If SENF is compiled in debug mode (SENF_DEBUG is defined), the exception message will + automatically include a stack backtrace. For this to work, you need to add the + <tt>-rdynamic</tt> option to all link commands. This feature depends on <tt>gcc</tt> and + the GNU-libc. */ namespace senf { @@ -117,6 +122,9 @@ namespace senf { exceptions. */ private: +#ifdef SENF_DEBUG + void addBacktrace(); +#endif std::string message_; }; diff --git a/Utils/Exception.test.cc b/Utils/Exception.test.cc index d3900627f..9a29f7130 100644 --- a/Utils/Exception.test.cc +++ b/Utils/Exception.test.cc @@ -51,7 +51,11 @@ BOOST_AUTO_UNIT_TEST(errnoException) catch (senf::SystemException & e) { BOOST_CHECK_EQUAL( e.errorNumber(), ENOENT ); BOOST_CHECK_EQUAL( e.errorString(), "No such file or directory" ); - BOOST_CHECK_EQUAL( e.what(), "[No such file or directory] ::open()\nmore\nx=1\ny=2" ); + std::string what (e.what()); + std::string::size_type pos (what.find("-- \n")); + if (pos != std::string::npos) + what = std::string(what, pos+4); + BOOST_CHECK_EQUAL( what, "[No such file or directory] ::open()\nmore\nx=1\ny=2" ); } } diff --git a/config.hh b/config.hh index 44dddeb1d..c4459cd4d 100644 --- a/config.hh +++ b/config.hh @@ -76,6 +76,10 @@ # define SENF_SENFLOG_LIMIT senf::log::NOTICE # endif # endif +# +# ifndef SENF_DEBUG_BACKTRACE_NUMCALLERS +# define SENF_DEBUG_BACKTRACE_NUMCALLERS 64 +# endif # # ///////////////////////////////hh.e//////////////////////////////////////// # endif diff --git a/senfscons/SENFSCons.py b/senfscons/SENFSCons.py index 7956bc3d8..d31c844aa 100644 --- a/senfscons/SENFSCons.py +++ b/senfscons/SENFSCons.py @@ -253,7 +253,7 @@ def MakeEnvironment(): # CPPDEFINES = [ '_GLIBCXX_DEBUG' ], env.Append(CXXFLAGS = [ '-O0', '-g', '-fno-inline' ], CPPDEFINES = [ 'SENF_DEBUG' ], - LINKFLAGS = [ '-g' ]) + LINKFLAGS = [ '-g', '-rdynamic' ]) env.Append(CPPDEFINES = [ '$EXTRA_DEFINES' ], LIBS = [ '$EXTRA_LIBS' ], -- GitLab