diff options
author | Bernard Normier <bernard@zeroc.com> | 2012-11-17 16:57:09 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2012-11-17 16:57:09 -0500 |
commit | f3f23873161bcf6155659e47fc15d4839bf94f7c (patch) | |
tree | 6bd1da81d6561694c9e0c186fb5206b5ab814304 /cpp/src/IceUtil/Exception.cpp | |
parent | Android testsuite minor fixes (diff) | |
download | ice-f3f23873161bcf6155659e47fc15d4839bf94f7c.tar.bz2 ice-f3f23873161bcf6155659e47fc15d4839bf94f7c.tar.xz ice-f3f23873161bcf6155659e47fc15d4839bf94f7c.zip |
Fixed bug ICE-4940: on Windows, the stack trace is now correct even when
the .pdbs are not where they were built.
Diffstat (limited to 'cpp/src/IceUtil/Exception.cpp')
-rw-r--r-- | cpp/src/IceUtil/Exception.cpp | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/cpp/src/IceUtil/Exception.cpp b/cpp/src/IceUtil/Exception.cpp index c90b6bb9879..e17088973d7 100644 --- a/cpp/src/IceUtil/Exception.cpp +++ b/cpp/src/IceUtil/Exception.cpp @@ -15,6 +15,9 @@ # ifndef UNICODE # define UNICODE # endif +# ifndef _UNICODE +# define _UNICODE +# endif #endif #include <IceUtil/Exception.h> @@ -33,14 +36,14 @@ # define ICE_GCC_STACK_TRACES #endif -#if defined(_WIN32) && !defined(__MINGW32__) && !defined(ICE_OS_WINRT) +#ifdef ICE_WIN32_STACK_TRACES # if defined(_MSC_VER) && _MSC_VER >= 1700 # define DBGHELP_TRANSLATE_TCHAR # include <IceUtil/Unicode.h> # endif # include <DbgHelp.h> +# include <tchar.h> # define ICE_STACK_TRACES -# define ICE_WIN32_STACK_TRACES #endif using namespace std; @@ -105,10 +108,65 @@ getStackTrace() IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex); if(process == 0) { + + // + // Compute Search path (best effort) + // consists of the current working directory, this DLL (or exe) directory and %_NT_SYMBOL_PATH% + // + basic_string<TCHAR> searchPath; + const TCHAR pathSeparator = _T('\\'); + const TCHAR searchPathSeparator = _T(';'); + + TCHAR cwd[MAX_PATH]; + if(GetCurrentDirectory(MAX_PATH, cwd) != 0) + { + searchPath = cwd; + } + + HMODULE myModule = 0; + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + "startHook", + &myModule); + // + // If GetModuleHandleEx fails, myModule is NULL, i.e. we'll locate the current exe's directory. + // + + TCHAR myFilename[MAX_PATH]; + DWORD len = GetModuleFileName(myModule, myFilename, MAX_PATH); + if(len != 0 && len < MAX_PATH) + { + assert(myFilename[len] == 0); + + basic_string<TCHAR> myPath = myFilename; + size_t pos = myPath.find_last_of(pathSeparator); + if(pos != basic_string<TCHAR>::npos) + { + myPath = myPath.substr(0, pos); + + if(!searchPath.empty()) + { + searchPath += searchPathSeparator; + } + searchPath += myPath; + } + } + + const DWORD size = 1024; + TCHAR symbolPath[size]; + len = GetEnvironmentVariable(_T("_NT_SYMBOL_PATH"), symbolPath, size); + if(len > 0 && len < size) + { + if(!searchPath.empty()) + { + searchPath += searchPathSeparator; + } + searchPath += symbolPath; + } + process = GetCurrentProcess(); - SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); - BOOL ok = SymInitialize(process, 0, TRUE); - if(!ok) + + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS | SYMOPT_UNDNAME); + if(SymInitialize(process, searchPath.c_str(), TRUE) == 0) { process = 0; return "No stack trace: SymInitialize failed with " + IceUtilInternal::errorToString(GetLastError()); @@ -146,6 +204,9 @@ getStackTrace() DWORD displacement = 0; lock.acquire(); + + // TODO: call SymRefreshModuleList here? (not available on XP) + for(int i = 0; i < frames; i++) { if(!stackTrace.empty()) @@ -295,6 +356,7 @@ getStackTrace() free(stackStrings); # endif + return stackTrace; } #endif |