[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