Skip to content

Commit

Permalink
Merge pull request #42 from remittor-pr/fix_cpp_exp
Browse files Browse the repository at this point in the history
Fix stack trace info for C++ exceptions
  • Loading branch information
JochenKalmbach authored Apr 5, 2021
2 parents 4161d09 + f10743f commit 5332051
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 70 deletions.
147 changes: 108 additions & 39 deletions Main/StackWalker/StackWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,14 @@
#include <stdlib.h>
#include <tchar.h>
#include <windows.h>
#include <new>

#pragma comment(lib, "version.lib") // for "VerQueryValue"

#pragma warning(disable : 4826)
#if _MSC_VER >= 1900
#pragma warning(disable : 4091) // For fix unnamed enums from DbgHelp.h
#endif


// If VC7 and later, then use the shipped 'dbghelp.h'-file
Expand Down Expand Up @@ -249,13 +255,12 @@ static void MyStrCpy(char* szDest, size_t nMaxDestSize, const char* szSrc)
class StackWalkerInternal
{
public:
StackWalkerInternal(StackWalker* parent, HANDLE hProcess)
StackWalkerInternal(StackWalker* parent, HANDLE hProcess, PCONTEXT ctx)
{
m_parent = parent;
m_hDbhHelp = NULL;
pSC = NULL;
m_hProcess = hProcess;
m_szSymPath = NULL;
pSFTA = NULL;
pSGLFA = NULL;
pSGMB = NULL;
Expand All @@ -268,7 +273,11 @@ class StackWalkerInternal
pSW = NULL;
pUDSN = NULL;
pSGSP = NULL;
m_ctx.ContextFlags = 0;
if (ctx != NULL)
m_ctx = *ctx;
}

~StackWalkerInternal()
{
if (pSC != NULL)
Expand All @@ -277,10 +286,8 @@ class StackWalkerInternal
FreeLibrary(m_hDbhHelp);
m_hDbhHelp = NULL;
m_parent = NULL;
if (m_szSymPath != NULL)
free(m_szSymPath);
m_szSymPath = NULL;
}

BOOL Init(LPCSTR szSymPath)
{
if (m_parent == NULL)
Expand Down Expand Up @@ -381,9 +388,7 @@ class StackWalkerInternal
}

// SymInitialize
if (szSymPath != NULL)
m_szSymPath = _strdup(szSymPath);
if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
if (this->pSI(m_hProcess, szSymPath, FALSE) == FALSE)
this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);

DWORD symOptions = this->pSGO(); // SymGetOptions
Expand All @@ -409,12 +414,12 @@ class StackWalkerInternal

StackWalker* m_parent;

CONTEXT m_ctx;
HMODULE m_hDbhHelp;
HANDLE m_hProcess;
LPSTR m_szSymPath;

#pragma pack(push, 8)
typedef struct IMAGEHLP_MODULE64_V3
typedef struct _IMAGEHLP_MODULE64_V3
{
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
DWORD64 BaseOfImage; // base load address of module
Expand All @@ -441,9 +446,9 @@ class StackWalkerInternal
// new elements: 17-Dec-2003
BOOL SourceIndexed; // pdb supports source server
BOOL Publics; // contains public symbols
};
} IMAGEHLP_MODULE64_V3, *PIMAGEHLP_MODULE64_V3;

typedef struct IMAGEHLP_MODULE64_V2
typedef struct _IMAGEHLP_MODULE64_V2
{
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
DWORD64 BaseOfImage; // base load address of module
Expand All @@ -455,7 +460,7 @@ class StackWalkerInternal
CHAR ModuleName[32]; // module name
CHAR ImageName[256]; // image name
CHAR LoadedImageName[256]; // symbol file name
};
} IMAGEHLP_MODULE64_V2, *PIMAGEHLP_MODULE64_V2;
#pragma pack(pop)

// SymCleanup()
Expand Down Expand Up @@ -495,14 +500,14 @@ class StackWalkerInternal
tSGSFA pSGSFA;

// SymInitialize()
typedef BOOL(__stdcall* tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
typedef BOOL(__stdcall* tSI)(IN HANDLE hProcess, IN LPCSTR UserSearchPath, IN BOOL fInvadeProcess);
tSI pSI;

// SymLoadModule64()
typedef DWORD64(__stdcall* tSLM)(IN HANDLE hProcess,
IN HANDLE hFile,
IN PSTR ImageName,
IN PSTR ModuleName,
IN LPCSTR ImageName,
IN LPCSTR ModuleName,
IN DWORD64 BaseOfDll,
IN DWORD SizeOfDll);
tSLM pSLM;
Expand Down Expand Up @@ -870,41 +875,102 @@ class StackWalkerInternal
};

// #############################################################
StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess)

#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
extern "C" void* __cdecl _getptd();
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1900
extern "C" void** __cdecl __current_exception_context();
#endif

static PCONTEXT get_current_exception_context()
{
this->m_options = OptionsAll;
PCONTEXT * pctx = NULL;
#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
LPSTR ptd = (LPSTR)_getptd();
if (ptd)
pctx = (PCONTEXT *)(ptd + (sizeof(void*) == 4 ? 0x8C : 0xF8));
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1900
pctx = (PCONTEXT *)__current_exception_context();
#endif
return pctx ? *pctx : NULL;
}

bool StackWalker::Init(ExceptType extype, int options, LPCSTR szSymPath, DWORD dwProcessId,
HANDLE hProcess, PEXCEPTION_POINTERS exp)
{
PCONTEXT ctx = NULL;
if (extype == AfterCatch)
ctx = get_current_exception_context();
if (extype == AfterExcept && exp)
ctx = exp->ContextRecord;
this->m_options = options;
this->m_modulesLoaded = FALSE;
this->m_hProcess = hProcess;
this->m_sw = new StackWalkerInternal(this, this->m_hProcess);
this->m_dwProcessId = dwProcessId;
this->m_szSymPath = NULL;
this->m_MaxRecursionCount = 1000;
this->m_sw = NULL;
SetTargetProcess(dwProcessId, hProcess);
SetSymPath(szSymPath);
/* MSVC ignore std::nothrow specifier for `new` operator */
LPVOID buf = malloc(sizeof(StackWalkerInternal));
if (!buf)
return false;
memset(buf, 0, sizeof(StackWalkerInternal));
this->m_sw = new(buf) StackWalkerInternal(this, this->m_hProcess, ctx); // placement new
return true;
}

StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess)
{
Init(NonExcept, OptionsAll, NULL, dwProcessId, hProcess);
}

StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
{
this->m_options = options;
this->m_modulesLoaded = FALSE;
this->m_hProcess = hProcess;
this->m_sw = new StackWalkerInternal(this, this->m_hProcess);
this->m_dwProcessId = dwProcessId;
if (szSymPath != NULL)
{
this->m_szSymPath = _strdup(szSymPath);
this->m_options |= SymBuildPath;
}
else
this->m_szSymPath = NULL;
this->m_MaxRecursionCount = 1000;
Init(NonExcept, options, szSymPath, dwProcessId, hProcess);
}

StackWalker::StackWalker(ExceptType extype, int options, PEXCEPTION_POINTERS exp)
{
Init(extype, options, NULL, GetCurrentProcessId(), GetCurrentProcess(), exp);
}

StackWalker::~StackWalker()
{
if (m_szSymPath != NULL)
SetSymPath(NULL);
if (m_sw != NULL) {
m_sw->~StackWalkerInternal(); // call the object's destructor
free(m_sw);
}
m_sw = NULL;
}

bool StackWalker::SetSymPath(LPCSTR szSymPath)
{
if (m_szSymPath)
free(m_szSymPath);
m_szSymPath = NULL;
if (this->m_sw != NULL)
delete this->m_sw;
this->m_sw = NULL;
if (szSymPath == NULL)
return true;
m_szSymPath = _strdup(szSymPath);
if (m_szSymPath)
m_options |= SymBuildPath;
return true;
}

bool StackWalker::SetTargetProcess(DWORD dwProcessId, HANDLE hProcess)
{
m_dwProcessId = dwProcessId;
m_hProcess = hProcess;
if (m_sw)
m_sw->m_hProcess = hProcess;
return true;
}

PCONTEXT StackWalker::GetCurrentExceptionContext()
{
return get_current_exception_context();
}

BOOL StackWalker::LoadModules()
Expand Down Expand Up @@ -1068,7 +1134,10 @@ BOOL StackWalker::ShowCallstack(HANDLE hThread,
if (GetThreadId(hThread) == GetCurrentThreadId())
#endif
{
GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, USED_CONTEXT_FLAGS);
if (m_sw->m_ctx.ContextFlags != 0)
c = m_sw->m_ctx; // context taken at Init
else
GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, USED_CONTEXT_FLAGS);
}
else
{
Expand Down
26 changes: 22 additions & 4 deletions Main/StackWalker/StackWalker.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@

#include <windows.h>

#if _MSC_VER >= 1900
#pragma warning(disable : 4091)
#endif

// special defines for VC5/6 (if no actual PSDK is installed):
#if _MSC_VER < 1300
typedef unsigned __int64 DWORD64, *PDWORD64;
Expand All @@ -61,6 +57,13 @@ class StackWalkerInternal; // forward
class StackWalker
{
public:
typedef enum ExceptType
{
NonExcept = 0, // RtlCaptureContext
AfterExcept = 1,
AfterCatch = 2, // get_current_exception_context
} ExceptType;

typedef enum StackWalkOptions
{
// No addition info will be retrieved
Expand Down Expand Up @@ -95,13 +98,28 @@ class StackWalker
OptionsAll = 0x3F
} StackWalkOptions;

StackWalker(ExceptType extype, int options = OptionsAll, PEXCEPTION_POINTERS exp = NULL);

StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
LPCSTR szSymPath = NULL,
DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess());

StackWalker(DWORD dwProcessId, HANDLE hProcess);

virtual ~StackWalker();

bool SetSymPath(LPCSTR szSymPath);

bool SetTargetProcess(DWORD dwProcessId, HANDLE hProcess);

PCONTEXT GetCurrentExceptionContext();

private:
bool Init(ExceptType extype, int options, LPCSTR szSymPath, DWORD dwProcessId,
HANDLE hProcess, PEXCEPTION_POINTERS exp = NULL);

public:
typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
HANDLE hProcess,
DWORD64 qwBaseAddress,
Expand Down
24 changes: 12 additions & 12 deletions Main/StackWalker/StackWalker_VC2015.sln
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@ Global
Release_VC2015-UNICODE|x64 = Release_VC2015-UNICODE|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Itanium.ActiveCfg = Debug_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Itanium.Build.0 = Debug_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Win32.ActiveCfg = Debug_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Win32.Build.0 = Debug_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|x64.ActiveCfg = Debug_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|x64.Build.0 = Debug_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Itanium.ActiveCfg = Debug_VC2015|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Itanium.Build.0 = Debug_VC2015|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Win32.ActiveCfg = Debug_VC2015|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|Win32.Build.0 = Debug_VC2015|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|x64.ActiveCfg = Debug_VC2015|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015|x64.Build.0 = Debug_VC2015|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|Itanium.ActiveCfg = Debug_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|Itanium.Build.0 = Debug_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|Win32.ActiveCfg = Debug_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|Win32.Build.0 = Debug_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|x64.ActiveCfg = Debug_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2015-UNICODE|x64.Build.0 = Debug_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Itanium.ActiveCfg = Release_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Itanium.Build.0 = Release_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Win32.ActiveCfg = Release_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Win32.Build.0 = Release_VC2015-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|x64.ActiveCfg = Release_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|x64.Build.0 = Release_VC2015-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Itanium.ActiveCfg = Release_VC2015|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Itanium.Build.0 = Release_VC2015|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Win32.ActiveCfg = Release_VC2015|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|Win32.Build.0 = Release_VC2015|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|x64.ActiveCfg = Release_VC2015|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015|x64.Build.0 = Release_VC2015|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015-UNICODE|Itanium.ActiveCfg = Release_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015-UNICODE|Itanium.Build.0 = Release_VC2015-UNICODE|Itanium
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2015-UNICODE|Win32.ActiveCfg = Release_VC2015-UNICODE|Win32
Expand Down
19 changes: 8 additions & 11 deletions Main/StackWalker/StackWalker_VC2017.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ Global
Release_VC2017-UNICODE|x64 = Release_VC2017-UNICODE|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|Win32.ActiveCfg = Debug_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|Win32.Build.0 = Debug_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|x64.ActiveCfg = Debug_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|x64.Build.0 = Debug_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|Win32.ActiveCfg = Debug_VC2017|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|Win32.Build.0 = Debug_VC2017|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|x64.ActiveCfg = Debug_VC2017|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017|x64.Build.0 = Debug_VC2017|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017-UNICODE|Win32.ActiveCfg = Debug_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017-UNICODE|Win32.Build.0 = Debug_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017-UNICODE|x64.ActiveCfg = Debug_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Debug_VC2017-UNICODE|x64.Build.0 = Debug_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|Win32.ActiveCfg = Release_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|Win32.Build.0 = Release_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|x64.ActiveCfg = Release_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|x64.Build.0 = Release_VC2017-UNICODE|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|Win32.ActiveCfg = Release_VC2017|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|Win32.Build.0 = Release_VC2017|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|x64.ActiveCfg = Release_VC2017|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017|x64.Build.0 = Release_VC2017|x64
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017-UNICODE|Win32.ActiveCfg = Release_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017-UNICODE|Win32.Build.0 = Release_VC2017-UNICODE|Win32
{89B2BD42-B130-4811-9043-71A8EBC40DE5}.Release_VC2017-UNICODE|x64.ActiveCfg = Release_VC2017-UNICODE|x64
Expand All @@ -36,7 +36,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {66CC86C2-413E-467D-AC75-7B4BD9AE3ECD}
EndGlobalSection
EndGlobal
Loading

0 comments on commit 5332051

Please sign in to comment.