00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #pragma once
00038
00039 #include <windows.h>
00040
00041
00042 #if _MSC_VER < 1300
00043 typedef unsigned __int64 DWORD64, *PDWORD64;
00044 #if defined(_WIN64)
00045 typedef unsigned __int64 SIZE_T, *PSIZE_T;
00046 #else
00047 typedef unsigned long SIZE_T, *PSIZE_T;
00048 #endif
00049 #endif // _MSC_VER < 1300
00050
00051 class StackWalkerInternal;
00052 class StackWalker
00053 {
00054 public:
00055 typedef enum StackWalkOptions
00056 {
00057
00058
00059 RetrieveNone = 0,
00060
00061
00062 RetrieveSymbol = 1,
00063
00064
00065 RetrieveLine = 2,
00066
00067
00068 RetrieveModuleInfo = 4,
00069
00070
00071 RetrieveFileVersion = 8,
00072
00073
00074 RetrieveVerbose = 0xF,
00075
00076
00077 SymBuildPath = 0x10,
00078
00079
00080 SymUseSymSrv = 0x20,
00081
00082
00083 SymAll = 0x30,
00084
00085
00086 OptionsAll = 0x3F
00087 } StackWalkOptions;
00088
00089 StackWalker(
00090 int options = OptionsAll,
00091 LPCSTR szSymPath = NULL,
00092 DWORD dwProcessId = GetCurrentProcessId(),
00093 HANDLE hProcess = GetCurrentProcess()
00094 );
00095 StackWalker(DWORD dwProcessId, HANDLE hProcess);
00096 virtual ~StackWalker();
00097
00098 typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(
00099 HANDLE hProcess,
00100 DWORD64 qwBaseAddress,
00101 PVOID lpBuffer,
00102 DWORD nSize,
00103 LPDWORD lpNumberOfBytesRead,
00104 LPVOID pUserData
00105 );
00106
00107 BOOL LoadModules();
00108
00109 BOOL ShowCallstack(
00110 HANDLE hThread = GetCurrentThread(),
00111 const CONTEXT *context = NULL,
00112 PReadProcessMemoryRoutine readMemoryFunction = NULL,
00113 LPVOID pUserData = NULL
00114 );
00115
00116 #if _MSC_VER >= 1300
00117
00118
00119 protected:
00120 #endif
00121 enum { STACKWALK_MAX_NAMELEN = 1024 };
00122
00123 protected:
00124
00125 typedef struct CallstackEntry
00126 {
00127 DWORD64 offset;
00128 CHAR name[STACKWALK_MAX_NAMELEN];
00129 CHAR undName[STACKWALK_MAX_NAMELEN];
00130 CHAR undFullName[STACKWALK_MAX_NAMELEN];
00131 DWORD64 offsetFromSmybol;
00132 DWORD offsetFromLine;
00133 DWORD lineNumber;
00134 CHAR lineFileName[STACKWALK_MAX_NAMELEN];
00135 DWORD symType;
00136 LPCSTR symTypeString;
00137 CHAR moduleName[STACKWALK_MAX_NAMELEN];
00138 DWORD64 baseOfImage;
00139 CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
00140 } CallstackEntry;
00141
00142 typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
00143
00144 virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
00145 virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
00146 virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
00147 virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
00148 virtual void OnOutput(LPCSTR szText);
00149
00150 StackWalkerInternal *m_sw;
00151 HANDLE m_hProcess;
00152 DWORD m_dwProcessId;
00153 BOOL m_modulesLoaded;
00154 LPSTR m_szSymPath;
00155
00156 int m_options;
00157 int m_MaxRecursionCount;
00158
00159 static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
00160
00161 friend StackWalkerInternal;
00162 };
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 #if defined(_M_IX86)
00177 #ifdef CURRENT_THREAD_VIA_EXCEPTION
00178
00179
00180 #define GET_CURRENT_CONTEXT(c, contextFlags) \
00181 do { \
00182 memset(&c, 0, sizeof(CONTEXT)); \
00183 EXCEPTION_POINTERS *pExp = NULL; \
00184 __try { \
00185 throw 0; \
00186 } __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \
00187 if (pExp != NULL) \
00188 memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
00189 c.ContextFlags = contextFlags; \
00190 } while(0);
00191 #else
00192
00193 #define GET_CURRENT_CONTEXT(c, contextFlags) \
00194 do { \
00195 memset(&c, 0, sizeof(CONTEXT)); \
00196 c.ContextFlags = contextFlags; \
00197 __asm call x \
00198 __asm x: pop eax \
00199 __asm mov c.Eip, eax \
00200 __asm mov c.Ebp, ebp \
00201 __asm mov c.Esp, esp \
00202 } while(0);
00203 #endif
00204
00205 #else
00206
00207
00208 #define GET_CURRENT_CONTEXT(c, contextFlags) \
00209 do { \
00210 memset(&c, 0, sizeof(CONTEXT)); \
00211 c.ContextFlags = contextFlags; \
00212 RtlCaptureContext(&c); \
00213 } while(0);
00214 #endif