From 2d0d9ef78501a0d3c9b6ab77bd31afa845db7cd3 Mon Sep 17 00:00:00 2001 From: Dwayne Boone Date: Thu, 7 May 2009 09:44:25 -0230 Subject: Bug 2664 - show stack traces with C++ --- cpp/src/IceUtil/Exception.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) (limited to 'cpp/src/IceUtil/Exception.cpp') diff --git a/cpp/src/IceUtil/Exception.cpp b/cpp/src/IceUtil/Exception.cpp index 55a32df57c2..6c4cb6624ce 100644 --- a/cpp/src/IceUtil/Exception.cpp +++ b/cpp/src/IceUtil/Exception.cpp @@ -13,6 +13,11 @@ #include #include +#ifdef __GNUC__ +# include +# include +#endif + using namespace std; namespace IceUtil @@ -22,15 +27,147 @@ bool ICE_DECLSPEC_EXPORT nullHandleAbort = false; }; +#ifdef __GNUC__ +namespace +{ + +string +getStackTrace() +{ + string stackTrace; + + const size_t maxDepth = 100; + void *stackAddrs[maxDepth]; + + size_t stackDepth = backtrace(stackAddrs, maxDepth); + char **stackStrings = backtrace_symbols(stackAddrs, stackDepth); + + bool checkException = true; + for (size_t i = 1; i < stackDepth; i++) + { + string line(stackStrings[i]); + + // + // Don't add the traces for the Exception constructors. + // + if(checkException) + { + if(line.find("ExceptionC") != string::npos) + { + continue; + } + else + { + checkException = false; + } + } + else + { + stackTrace += "\n"; + } + + stackTrace += " "; + + // + // For each line attempt to parse the mangled function name as well + // as the source library/executable. + // + string mangled; + string::size_type openParen = line.find_first_of('('); + if(openParen != string::npos) + { + // + // Format: "/opt/Ice/lib/libIceUtil.so.33(_ZN7IceUtil9ExceptionC2EPKci+0x51) [0x73b267]" + // + string::size_type closeParen = line.find_first_of(')', openParen); + if(closeParen != string::npos) + { + string tmp = line.substr(openParen + 1, closeParen - openParen - 1); + string::size_type plus = tmp.find_last_of('+'); + if(plus != string::npos) + { + mangled = tmp.substr(0 , plus); + + stackTrace += line.substr(0, openParen); + } + } + } + else + { + // + // Format: "1 libIce.3.3.1.dylib 0x000933a1 _ZN7IceUtil9ExceptionC2EPKci + 71" + // + string::size_type plus = line.find_last_of('+'); + if(plus != string::npos) + { + string tmp = line.substr(0, plus - 1); + string::size_type space = tmp.find_last_of(" \t"); + if(space != string::npos) + { + tmp = tmp.substr(space + 1, tmp.size() - space); + + string::size_type start = line.find_first_not_of(" \t", 3); + if(start != string::npos) + { + string::size_type finish = line.find_first_of(" \t", start); + if(finish != string::npos) + { + mangled = tmp; + + stackTrace += line.substr(start, finish - start); + } + } + } + } + } + if(mangled.size() != 0) + { + stackTrace += ": "; + + // + // Unmangle the function name + // + int status; + char* unmangled = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status); + if(unmangled) + { + stackTrace += unmangled; + free(unmangled); + } + else + { + stackTrace += mangled; + stackTrace += "()"; + } + } + else + { + stackTrace += line; + } + } + free(stackStrings); + + return stackTrace; +} + +}; +#endif + IceUtil::Exception::Exception() : _file(0), _line(0) +#ifdef __GNUC__ + , _stackTrace(getStackTrace()) +#endif { } IceUtil::Exception::Exception(const char* file, int line) : _file(file), _line(line) +#ifdef __GNUC__ + , _stackTrace(getStackTrace()) +#endif { } @@ -102,6 +239,12 @@ IceUtil::Exception::ice_line() const return _line; } +const string& +IceUtil::Exception::ice_stackTrace() const +{ + return _stackTrace; +} + ostream& IceUtil::operator<<(ostream& out, const IceUtil::Exception& ex) { -- cgit v1.2.3