summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/Exception.cpp
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2012-11-17 16:57:09 -0500
committerBernard Normier <bernard@zeroc.com>2012-11-17 16:57:09 -0500
commitf3f23873161bcf6155659e47fc15d4839bf94f7c (patch)
tree6bd1da81d6561694c9e0c186fb5206b5ab814304 /cpp/src/IceUtil/Exception.cpp
parentAndroid testsuite minor fixes (diff)
downloadice-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.cpp72
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