diff options
author | Bernard Normier <bernard@zeroc.com> | 2012-08-14 18:30:22 -0400 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2012-08-14 18:30:22 -0400 |
commit | 4435f311d2a711797e8801d77abf24294a1d5c40 (patch) | |
tree | f843ca1479e4fdb6894a9f6ec92111947b423918 /cpp/src/IceUtil/Exception.cpp | |
parent | MinGW minor fixes (diff) | |
download | ice-4435f311d2a711797e8801d77abf24294a1d5c40.tar.bz2 ice-4435f311d2a711797e8801d77abf24294a1d5c40.tar.xz ice-4435f311d2a711797e8801d77abf24294a1d5c40.zip |
Fixed ICE-4818
Added print stack trace support for exceptions on Windows
Diffstat (limited to 'cpp/src/IceUtil/Exception.cpp')
-rw-r--r-- | cpp/src/IceUtil/Exception.cpp | 105 |
1 files changed, 100 insertions, 5 deletions
diff --git a/cpp/src/IceUtil/Exception.cpp b/cpp/src/IceUtil/Exception.cpp index c310b2fcb03..bda16adeff0 100644 --- a/cpp/src/IceUtil/Exception.cpp +++ b/cpp/src/IceUtil/Exception.cpp @@ -17,8 +17,18 @@ #if defined(__GNUC__) && !defined(__sun) && !defined(__FreeBSD__) && !defined(__MINGW32__) # include <execinfo.h> # include <cxxabi.h> +# define ICE_STACK_TRACES +# define ICE_GCC_STACK_TRACES #endif +#if defined(_WIN32) && !defined(__MINGW32__) && !defined(ICE_OS_WINRT) +# include <DbgHelp.h> +# include <iomanip> +# define ICE_STACK_TRACES +# define ICE_WIN32_STACK_TRACES +#endif + + using namespace std; namespace IceUtilInternal @@ -34,6 +44,10 @@ namespace IceUtil::Mutex* globalMutex = 0; +#ifdef ICE_WIN32_STACK_TRACES +HANDLE process = 0; +#endif + class Init { public: @@ -47,21 +61,101 @@ public: { delete globalMutex; globalMutex = 0; +#ifdef ICE_WIN32_STACK_TRACES + if(process != 0) + { + SymCleanup(process); + process = 0; + } +#endif } }; Init init; -#if defined(__GNUC__) && !defined(__sun) && !defined(__FreeBSD__) && !defined(__MINGW32__) +#ifdef ICE_STACK_TRACES string getStackTrace() { + if(!IceUtilInternal::printStackTraces) + { + return ""; + } + string stackTrace; - if(!IceUtilInternal::printStackTraces) +# ifdef ICE_WIN32_STACK_TRACES + // + // Note: the Sym functions are not thread-safe + // + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex); + if(process == 0) { - return stackTrace; + process = GetCurrentProcess(); + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + BOOL ok = SymInitialize(process, 0, TRUE); + if(!ok) + { + process = 0; + return "No stack trace: SymInitialize failed with " + IceUtilInternal::errorToString(GetLastError()); + } } + lock.release(); + + const int stackSize = 61; + void* stack[stackSize]; + + // + // 1: skip the first frame (the call to getStackTrace) + // 1 + stackSize < 63 on XP according to the documentation for CaptureStackBackTrace + // + USHORT frames = CaptureStackBackTrace(1, stackSize, stack, 0); + + if(frames > 0) + { + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buffer); + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + IMAGEHLP_LINE64 line = {}; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + DWORD displacement = 0; + + lock.acquire(); + for(int i = 0; i < frames; i++) + { + if(!stackTrace.empty()) + { + stackTrace += "\n"; + } + + stringstream s; + s << setw(3) << i << " "; + + DWORD64 address = reinterpret_cast<DWORD64>(stack[i]); + + BOOL ok = SymFromAddr(process, address, 0, symbol); + if(ok) + { + s << symbol->Name; + + ok = SymGetLineFromAddr64(process, address, &displacement, &line); + if(ok) + { + s << " at line " << line.LineNumber << " in " << line.FileName; + } + } + else + { + s << hex << "0x" << address; + } + stackTrace += s.str(); + } + lock.release(); + } + +# elif defined(ICE_GCC_STACK_TRACES) const size_t maxDepth = 100; void *stackAddrs[maxDepth]; @@ -174,6 +268,7 @@ getStackTrace() } free(stackStrings); +# endif return stackTrace; } #endif @@ -183,7 +278,7 @@ getStackTrace() IceUtil::Exception::Exception() : _file(0), _line(0) -#if defined(__GNUC__) && !defined(__sun) && !defined(__FreeBSD__) && !defined(__MINGW32__) +#ifdef ICE_STACK_TRACES , _stackTrace(getStackTrace()) #endif { @@ -192,7 +287,7 @@ IceUtil::Exception::Exception() : IceUtil::Exception::Exception(const char* file, int line) : _file(file), _line(line) -#if defined(__GNUC__) && !defined(__sun) && !defined(__FreeBSD__) && !defined(__MINGW32__) +#ifdef ICE_STACK_TRACES , _stackTrace(getStackTrace()) #endif { |