Path: blob/main_old/util/windows/third_party/StackWalker/src/StackWalker.h
1695 views
#ifndef __STACKWALKER_H__1#define __STACKWALKER_H__23#if defined(_MSC_VER)45/**********************************************************************6*7* StackWalker.h8*9*10*11* LICENSE (http://www.opensource.org/licenses/bsd-license.php)12*13* Copyright (c) 2005-2009, Jochen Kalmbach14* All rights reserved.15*16* Redistribution and use in source and binary forms, with or without modification,17* are permitted provided that the following conditions are met:18*19* Redistributions of source code must retain the above copyright notice,20* this list of conditions and the following disclaimer.21* Redistributions in binary form must reproduce the above copyright notice,22* this list of conditions and the following disclaimer in the documentation23* and/or other materials provided with the distribution.24* Neither the name of Jochen Kalmbach nor the names of its contributors may be25* used to endorse or promote products derived from this software without26* specific prior written permission.27* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"28* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,29* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE30* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE31* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES32* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;33* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND34* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT35* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS36* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.37*38* **********************************************************************/39// #pragma once is supported starting with _MSC_VER 1000,40// so we need not to check the version (because we only support _MSC_VER >= 1100)!41#pragma once4243#include <windows.h>4445#if _MSC_VER >= 190046#pragma warning(disable : 4091)47#endif4849// special defines for VC5/6 (if no actual PSDK is installed):50#if _MSC_VER < 130051typedef unsigned __int64 DWORD64, *PDWORD64;52#if defined(_WIN64)53typedef unsigned __int64 SIZE_T, *PSIZE_T;54#else55typedef unsigned long SIZE_T, *PSIZE_T;56#endif57#endif // _MSC_VER < 13005859class StackWalkerInternal; // forward60class StackWalker61{62public:63typedef enum StackWalkOptions64{65// No addition info will be retrieved66// (only the address is available)67RetrieveNone = 0,6869// Try to get the symbol-name70RetrieveSymbol = 1,7172// Try to get the line for this symbol73RetrieveLine = 2,7475// Try to retrieve the module-infos76RetrieveModuleInfo = 4,7778// Also retrieve the version for the DLL/EXE79RetrieveFileVersion = 8,8081// Contains all the above82RetrieveVerbose = 0xF,8384// Generate a "good" symbol-search-path85SymBuildPath = 0x10,8687// Also use the public Microsoft-Symbol-Server88SymUseSymSrv = 0x20,8990// Contains all the above "Sym"-options91SymAll = 0x30,9293// Contains all options (default)94OptionsAll = 0x3F95} StackWalkOptions;9697StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags98LPCSTR szSymPath = NULL,99DWORD dwProcessId = GetCurrentProcessId(),100HANDLE hProcess = GetCurrentProcess());101StackWalker(DWORD dwProcessId, HANDLE hProcess);102virtual ~StackWalker();103104typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(105HANDLE hProcess,106DWORD64 qwBaseAddress,107PVOID lpBuffer,108DWORD nSize,109LPDWORD lpNumberOfBytesRead,110LPVOID pUserData // optional data, which was passed in "ShowCallstack"111);112113BOOL LoadModules();114115BOOL ShowCallstack(116HANDLE hThread = GetCurrentThread(),117const CONTEXT* context = NULL,118PReadProcessMemoryRoutine readMemoryFunction = NULL,119LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback120);121122BOOL ShowObject(LPVOID pObject);123124#if _MSC_VER >= 1300125// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"126// in older compilers in order to use it... starting with VC7 we can declare it as "protected"127protected:128#endif129enum130{131STACKWALK_MAX_NAMELEN = 1024132}; // max name length for found symbols133134protected:135// Entry for each Callstack-Entry136typedef struct CallstackEntry137{138DWORD64 offset; // if 0, we have no valid entry139CHAR name[STACKWALK_MAX_NAMELEN];140CHAR undName[STACKWALK_MAX_NAMELEN];141CHAR undFullName[STACKWALK_MAX_NAMELEN];142DWORD64 offsetFromSmybol;143DWORD offsetFromLine;144DWORD lineNumber;145CHAR lineFileName[STACKWALK_MAX_NAMELEN];146DWORD symType;147LPCSTR symTypeString;148CHAR moduleName[STACKWALK_MAX_NAMELEN];149DWORD64 baseOfImage;150CHAR loadedImageName[STACKWALK_MAX_NAMELEN];151} CallstackEntry;152153typedef enum CallstackEntryType154{155firstEntry,156nextEntry,157lastEntry158} CallstackEntryType;159160virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);161virtual void OnLoadModule(LPCSTR img,162LPCSTR mod,163DWORD64 baseAddr,164DWORD size,165DWORD result,166LPCSTR symType,167LPCSTR pdbName,168ULONGLONG fileVersion);169virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);170virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);171virtual void OnOutput(LPCSTR szText);172173StackWalkerInternal* m_sw;174HANDLE m_hProcess;175DWORD m_dwProcessId;176BOOL m_modulesLoaded;177LPSTR m_szSymPath;178179int m_options;180int m_MaxRecursionCount;181182static BOOL __stdcall myReadProcMem(HANDLE hProcess,183DWORD64 qwBaseAddress,184PVOID lpBuffer,185DWORD nSize,186LPDWORD lpNumberOfBytesRead);187188friend StackWalkerInternal;189}; // class StackWalker190191// The "ugly" assembler-implementation is needed for systems before XP192// If you have a new PSDK and you only compile for XP and later, then you can use193// the "RtlCaptureContext"194// Currently there is no define which determines the PSDK-Version...195// So we just use the compiler-version (and assumes that the PSDK is196// the one which was installed by the VS-IDE)197198// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...199// But I currently use it in x64/IA64 environments...200//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)201202#if defined(_M_IX86)203#ifdef CURRENT_THREAD_VIA_EXCEPTION204// TODO: The following is not a "good" implementation,205// because the callstack is only valid in the "__except" block...206#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \207do \208{ \209memset(&c, 0, sizeof(CONTEXT)); \210EXCEPTION_POINTERS* pExp = NULL; \211__try \212{ \213throw 0; \214} \215__except (((pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER \216: EXCEPTION_EXECUTE_HANDLER)) \217{ \218} \219if (pExp != NULL) \220memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \221c.ContextFlags = contextFlags; \222} while (0);223#else224// clang-format off225// The following should be enough for walking the callstack...226#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \227do \228{ \229memset(&c, 0, sizeof(CONTEXT)); \230c.ContextFlags = contextFlags; \231__asm call x \232__asm x: pop eax \233__asm mov c.Eip, eax \234__asm mov c.Ebp, ebp \235__asm mov c.Esp, esp \236} while (0)237// clang-format on238#endif239240#else241242// The following is defined for x86 (XP and higher), x64 and IA64:243#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \244do \245{ \246memset(&c, 0, sizeof(CONTEXT)); \247c.ContextFlags = contextFlags; \248RtlCaptureContext(&c); \249} while (0)250#endif251252#endif //defined(_MSC_VER)253254#endif // __STACKWALKER_H__255256257