[Mobies-commit] [commit] r3742 - in UDM/trunk: . Projects/Win32/VC9/src/UdmDll Projects/Win32/VC9/src/UdmUtil include lib src/UdmUtil
endre at redhat1.isis.vanderbilt.edu
endre at redhat1.isis.vanderbilt.edu
Mon May 16 04:04:02 CDT 2011
Author: endre
Date: Mon May 16 04:04:02 2011
New Revision: 3742
Log:
New function UdmUtil::stacktrace() to get the call stack and changed udm_exception to save the stack trace.
The call stack is available in debug builds on Windows. It's available
on Linux when building with "-g -fkeep-inline-functions -rdynamic compiler"
flags.
test_staticleaks fails now on Windows, need to investigate if calling
SymCleanup() will fix it.
The implementation is based on a possible future Boost implementation:
[boost] [Backtrace] Any interest in portable stack trace?
http://lists.boost.org/Archives/boost/2010/10/172303.php
Modified:
UDM/trunk/Projects/Win32/VC9/src/UdmDll/UdmDll.vcproj
UDM/trunk/Projects/Win32/VC9/src/UdmUtil/UdmUtil.vcproj
UDM/trunk/configure.ac
UDM/trunk/include/ErrHand.h
UDM/trunk/include/UdmUtil.h
UDM/trunk/lib/Makefile.am
UDM/trunk/src/UdmUtil/UdmUtil.cpp
Modified: UDM/trunk/Projects/Win32/VC9/src/UdmDll/UdmDll.vcproj
==============================================================================
--- UDM/trunk/Projects/Win32/VC9/src/UdmDll/UdmDll.vcproj Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/Projects/Win32/VC9/src/UdmDll/UdmDll.vcproj Mon May 16 04:04:02 2011 (r3742)
@@ -84,7 +84,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="UdmUtil.lib UdmBase.lib UDMPOI.lib UdmOcl.lib Uml.lib UdmDom.lib UdmGme.lib UdmXMI.lib Xalan-C_1.lib xerces-c_2.lib zlib.lib GOCL.lib"
+ AdditionalDependencies="UdmUtil.lib UdmBase.lib UDMPOI.lib UdmOcl.lib Uml.lib UdmDom.lib UdmGme.lib UdmXMI.lib Xalan-C_1.lib xerces-c_2.lib zlib.lib GOCL.lib dbghelp.lib"
OutputFile="$(OutDir)\UdmDll_3_2.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -187,7 +187,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="UdmBaseD.lib UdmOclD.lib UdmPOID.lib UmlD.lib UdmDomD.lib UdmGmeD.lib UdmXMID.lib UdmUtilD.lib Xalan-C_1D.lib xerces-c_2D.lib zlibD.lib GOCLD.lib"
+ AdditionalDependencies="UdmBaseD.lib UdmOclD.lib UdmPOID.lib UmlD.lib UdmDomD.lib UdmGmeD.lib UdmXMID.lib UdmUtilD.lib Xalan-C_1D.lib xerces-c_2D.lib zlibD.lib GOCLD.lib dbghelp.lib"
OutputFile="$(OutDir)\UdmDll_3_2D.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
Modified: UDM/trunk/Projects/Win32/VC9/src/UdmUtil/UdmUtil.vcproj
==============================================================================
--- UDM/trunk/Projects/Win32/VC9/src/UdmUtil/UdmUtil.vcproj Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/Projects/Win32/VC9/src/UdmUtil/UdmUtil.vcproj Mon May 16 04:04:02 2011 (r3742)
@@ -71,6 +71,7 @@
/>
<Tool
Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib"
OutputFile="$(OutDir)\UdmUtilD.lib"
SuppressStartupBanner="true"
/>
@@ -149,6 +150,7 @@
/>
<Tool
Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib"
OutputFile="$(OutDir)\UdmUtil.lib"
SuppressStartupBanner="true"
/>
Modified: UDM/trunk/configure.ac
==============================================================================
--- UDM/trunk/configure.ac Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/configure.ac Mon May 16 04:04:02 2011 (r3742)
@@ -53,6 +53,7 @@
# Checks for libraries.
CPPUNITLIBS="-lcppunit -ldl"
+DLOPENLIBS=""
MINIZIPLIBS="-lz -lminizip"
XALANLIBS="-lxalan-c"
XERCESLIBS="-lxerces-c"
@@ -70,6 +71,13 @@
AC_CHECK_HEADER([boost/mpl/vector.hpp], [],
[AC_MSG_ERROR([boost/mpl/vector.hpp header is needed; please install Boost])])
+# For stack traces
+AC_CHECK_HEADERS([execinfo.h dlfcn.h cxxabi.h])
+
+if test "x$ac_cv_header_dlfcn_h" = "xyes"; then
+ DLOPENLIBS="-ldl"
+fi
+
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -89,6 +97,7 @@
AC_SUBST([antlr])
AC_SUBST([swig])
AC_SUBST([CPPUNITLIBS])
+AC_SUBST([DLOPENLIBS])
AC_SUBST([MINIZIPLIBS])
AC_SUBST([XALANLIBS])
AC_SUBST([XERCESLIBS])
Modified: UDM/trunk/include/ErrHand.h
==============================================================================
--- UDM/trunk/include/ErrHand.h Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/include/ErrHand.h Mon May 16 04:04:02 2011 (r3742)
@@ -67,20 +67,35 @@
#define UDM_RVALUE
#endif
+namespace UdmUtil {
+ UDM_DLL std::string stacktrace();
+}
+
class udm_exception : public std::exception
{
public:
- udm_exception() throw();
- udm_exception(const udm_exception &a) throw() : description(a.description) { }
- udm_exception(const std::string &d) throw() : description(d) { }
- udm_exception(const char *d) throw() : description(d) { }
+ udm_exception() throw() : stacktrace(UdmUtil::stacktrace()) { _init(); }
+ udm_exception(const udm_exception &a) throw() : description(a.description), stacktrace(UdmUtil::stacktrace()) { _init(); }
+ udm_exception(const std::string &d) throw() : description(d), stacktrace(UdmUtil::stacktrace()) { _init(); }
+ udm_exception(const char *d) throw() : description(d), stacktrace(UdmUtil::stacktrace()) { _init(); }
const udm_exception &operator =(const udm_exception &a) throw()
- { description = a.description; return *this; }
+ { description = a.description; stacktrace = UdmUtil::stacktrace(); _init(); return *this; }
virtual ~udm_exception() throw() { }
- virtual const char *what() const throw() { return description.c_str(); }
+ virtual const char *what() const throw() { return descr_wstack.c_str(); }
+ virtual const char *where() const throw() { return stacktrace.c_str(); }
+
protected:
std::string description;
+ std::string descr_wstack;
+ std::string stacktrace;
+
+ void _init() {
+ descr_wstack = description;
+ descr_wstack += "\n";
+ descr_wstack += stacktrace;
+ }
+
};
// int64
Modified: UDM/trunk/include/UdmUtil.h
==============================================================================
--- UDM/trunk/include/UdmUtil.h Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/include/UdmUtil.h Mon May 16 04:04:02 2011 (r3742)
@@ -77,6 +77,7 @@
// Converts a double value to a string, using the least necessary
// precision to represent the original double value.
UDM_DLL string doubleToString(double val, int minimum_precision = 2);
+ UDM_DLL string stacktrace();
};
#endif //MOBIES_UDMUTIL_H
Modified: UDM/trunk/lib/Makefile.am
==============================================================================
--- UDM/trunk/lib/Makefile.am Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/lib/Makefile.am Mon May 16 04:04:02 2011 (r3742)
@@ -12,7 +12,7 @@
../src/UdmXmi/libudmxmi.la \
../src/UdmOcl/libudmocl.la \
../src/UdmOclPat/GOCL/src/libgocl.la \
- $(XERCESLIBS) $(XALANLIBS) $(MINIZIPLIBS)
+ $(XERCESLIBS) $(XALANLIBS) $(MINIZIPLIBS) $(DLOPENLIBS)
libudm_la_LDFLAGS = -version-info 3:1:3
# Force C++ linking
nodist_EXTRA_libudm_la_SOURCES = dummy.cxx
Modified: UDM/trunk/src/UdmUtil/UdmUtil.cpp
==============================================================================
--- UDM/trunk/src/UdmUtil/UdmUtil.cpp Fri May 13 16:20:19 2011 (r3741)
+++ UDM/trunk/src/UdmUtil/UdmUtil.cpp Mon May 16 04:04:02 2011 (r3742)
@@ -3,6 +3,25 @@
#include <UdmStatic.h>
#include <UdmUtil.h>
+#if defined(HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+#if defined(HAVE_DLFCN_H)
+#include <dlfcn.h>
+#endif
+
+#if defined(HAVE_CXXABI_H)
+#include <cxxabi.h>
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <dbghelp.h>
+#endif
+
+#include <sstream>
+
using namespace Uml;
@@ -823,4 +842,187 @@
return result;
}
-};
+
+
+ #if defined(HAVE_EXECINFO_H)
+
+ string demangled_symbol(const char *str)
+ {
+ ostringstream sym;
+
+#if defined(HAVE_CXXABI_H)
+ int status = 0;
+
+ char *demangled = abi::__cxa_demangle(str, 0, 0, &status);
+ if (demangled) {
+ sym << demangled;
+ free(demangled);
+ } else
+ sym << str;
+#else
+ sym << str;
+#endif
+
+ return sym.str();
+ }
+
+#if defined(HAVE_DLFCN_H)
+
+ vector<string> get_symbols(void * const *addresses, int stack_depth)
+ {
+ vector<string> res;
+ res.reserve(stack_depth - 1);
+
+ for (size_t i = 1; i < stack_depth; i++) {
+ ostringstream sym;
+
+ if (addresses[i]) {
+ Dl_info info = { 0 };
+ if (dladdr(addresses[i], &info) == 0)
+ sym << "???";
+ else {
+ if (info.dli_sname)
+ sym << demangled_symbol(info.dli_sname);
+ else
+ sym << "???";
+
+ unsigned offset = (char *)addresses[i] - (char *)info.dli_saddr;
+ sym << hex << " + 0x" << offset;
+
+ sym << " [" << addresses[i] << "]";
+ }
+ }
+
+ res.push_back(sym.str());
+ }
+
+ return res;
+ }
+
+#else // if defined(HAVE_DLFCN_H)
+
+ vector<string> get_symbols(void * const *addresses, int stack_depth)
+ {
+ vector<string> res;
+ res.reserve(stack_depth - 1);
+
+ char **symbols = backtrace_symbols(addresses, stack_depth);
+ if (symbols == NULL)
+ return res;
+
+ for (size_t i = 1; i < stack_depth; i++) {
+ ostringstream sym;
+
+ if (symbols[i]) {
+ char *str;
+ // look for the string starting after the first '(' and ended by the following ')' or '+'
+ if (1 == sscanf(symbols[i], "%*[^(](%a[^)+]", &str)) {
+ sym << demangled_symbol(str);
+ free(str);
+
+ // look for the offset between '+' and ')'
+ if (1 == sscanf(symbols[i], "%*[^(]%*[^+]+%a[^)]", &str)) {
+ sym << " + " << str;
+ free(str);
+ }
+ } else
+ sym << symbols[i];
+
+ sym << " [" << addresses[i] << "]";
+ }
+
+ res.push_back(sym.str());
+ }
+
+ free(symbols);
+
+ return res;
+ }
+
+#endif // if defined(HAVE_DLFCN_H)
+
+ #else // if defined(HAVE_EXECINFO_H)
+
+ vector<string> get_symbols()
+ {
+ vector<string> res;
+
+ static HANDLE hProcess = 0;
+ static bool syms_ready = false;
+
+ // initialization of Symbol Handler
+ if (hProcess == 0) {
+ hProcess = GetCurrentProcess();
+
+ SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
+ if (SymInitialize(hProcess, NULL, TRUE))
+ syms_ready = true;
+ }
+
+ if (!syms_ready)
+ return res;
+
+ void *addresses[62];
+ size_t stack_depth = RtlCaptureStackBackTrace(1, 62, addresses, NULL);
+ res.reserve(stack_depth);
+
+ for (size_t i = 1; i < stack_depth; i++) {
+ ostringstream sym;
+
+ if (addresses[i]) {
+ DWORD64 dwAddress = (DWORD64)addresses[i];
+
+ // get source file info
+ {
+ DWORD dwDisplacement;
+ IMAGEHLP_LINE64 line;
+
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ if (SymGetLineFromAddr64(hProcess, dwAddress, &dwDisplacement, &line))
+ sym << line.FileName << ":" << line.LineNumber << " ";
+ }
+
+ // get symbol info
+ vector<char> buffer(sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)&buffer.front();
+
+ pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ pSymbol->MaxNameLen = MAX_SYM_NAME;
+
+ DWORD64 dwDisplacement = 0;
+ if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
+ sym << pSymbol->Name << hex << " + 0x" << dwDisplacement;
+ else
+ sym << "???";
+ }
+
+ res.push_back(sym.str());
+ }
+
+ return res;
+ }
+
+ #endif // if defined(HAVE_EXECINFO_H)
+
+ UDM_DLL string stacktrace()
+ {
+ string trace = "Call stack:\n";
+
+#if defined(HAVE_EXECINFO_H)
+
+ // limit stack depth to 64 frames
+ void *stack_addrs[64];
+ size_t stack_depth = backtrace(stack_addrs, 64);
+
+ vector<string> v = get_symbols(stack_addrs, stack_depth);
+
+#elif defined(_WIN32)
+ vector<string> v = get_symbols();
+#endif // defined(HAVE_EXECINFO_H)
+
+ for (size_t i = 0; i < v.size(); i++)
+ trace += " " + v[i] + "\n";
+
+ return trace;
+ };
+};
\ No newline at end of file
More information about the Mobies-commit
mailing list