summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/Exception.cpp
diff options
context:
space:
mode:
authorDwayne Boone <dwayne@zeroc.com>2009-05-07 09:44:25 -0230
committerDwayne Boone <dwayne@zeroc.com>2009-05-07 09:44:25 -0230
commit2d0d9ef78501a0d3c9b6ab77bd31afa845db7cd3 (patch)
treeda8bb8159c737559c48989869a23e280e7cb38bd /cpp/src/IceUtil/Exception.cpp
parentBug 3624 - desupport HP (diff)
downloadice-2d0d9ef78501a0d3c9b6ab77bd31afa845db7cd3.tar.bz2
ice-2d0d9ef78501a0d3c9b6ab77bd31afa845db7cd3.tar.xz
ice-2d0d9ef78501a0d3c9b6ab77bd31afa845db7cd3.zip
Bug 2664 - show stack traces with C++
Diffstat (limited to 'cpp/src/IceUtil/Exception.cpp')
-rw-r--r--cpp/src/IceUtil/Exception.cpp143
1 files changed, 143 insertions, 0 deletions
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 <ostream>
#include <cstdlib>
+#ifdef __GNUC__
+# include <execinfo.h>
+# include <cxxabi.h>
+#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)
{