诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

189 lines
6.0 KiB

  1. /**********************************************************************
  2. *
  3. * StackWalker.h
  4. *
  5. *
  6. * History:
  7. * 2005-07-27 v1 - First public release on http://www.codeproject.com/
  8. * (for additional changes see History in 'StackWalker.cpp'!
  9. *
  10. **********************************************************************/
  11. // #pragma once is supported starting with _MCS_VER 1000,
  12. // so we need not to check the version (because we only support _MSC_VER >= 1100)!
  13. #pragma once
  14. #include <windows.h>
  15. // special defines for VC5/6 (if no actual PSDK is installed):
  16. #if _MSC_VER < 1300
  17. typedef unsigned __int64 DWORD64, *PDWORD64;
  18. #if defined(_WIN64)
  19. typedef unsigned __int64 SIZE_T, *PSIZE_T;
  20. #else
  21. typedef unsigned long SIZE_T, *PSIZE_T;
  22. #endif
  23. #endif // _MSC_VER < 1300
  24. class StackWalkerInternal; // forward
  25. class StackWalker
  26. {
  27. public:
  28. typedef enum StackWalkOptions
  29. {
  30. // No addition info will be retrived
  31. // (only the address is available)
  32. RetrieveNone = 0,
  33. // Try to get the symbol-name
  34. RetrieveSymbol = 1,
  35. // Try to get the line for this symbol
  36. RetrieveLine = 2,
  37. // Try to retrieve the module-infos
  38. RetrieveModuleInfo = 4,
  39. // Also retrieve the version for the DLL/EXE
  40. RetrieveFileVersion = 8,
  41. // Contains all the abouve
  42. RetrieveVerbose = 0xF,
  43. // Generate a "good" symbol-search-path
  44. SymBuildPath = 0x10,
  45. // Also use the public Microsoft-Symbol-Server
  46. SymUseSymSrv = 0x20,
  47. // Contains all the abouve "Sym"-options
  48. SymAll = 0x30,
  49. // Contains all options (default)
  50. OptionsAll = 0x3F
  51. } StackWalkOptions;
  52. StackWalker(
  53. int options = OptionsAll, // 'int' is by design, to combine the enum-flags
  54. LPCSTR szSymPath = NULL,
  55. DWORD dwProcessId = GetCurrentProcessId(),
  56. HANDLE hProcess = GetCurrentProcess()
  57. );
  58. StackWalker(DWORD dwProcessId, HANDLE hProcess);
  59. virtual ~StackWalker();
  60. typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(
  61. HANDLE hProcess,
  62. DWORD64 qwBaseAddress,
  63. PVOID lpBuffer,
  64. DWORD nSize,
  65. LPDWORD lpNumberOfBytesRead,
  66. LPVOID pUserData // optional data, which was passed in "ShowCallstack"
  67. );
  68. BOOL LoadModules();
  69. BOOL ShowCallstack(
  70. HANDLE hThread = GetCurrentThread(),
  71. const CONTEXT *context = NULL,
  72. PReadProcessMemoryRoutine readMemoryFunction = NULL,
  73. LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
  74. );
  75. #if _MSC_VER >= 1300
  76. // due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
  77. // in older compilers in order to use it... starting with VC7 we can declare it as "protected"
  78. protected:
  79. #endif
  80. enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols
  81. protected:
  82. // Entry for each Callstack-Entry
  83. typedef struct CallstackEntry
  84. {
  85. DWORD64 offset; // if 0, we have no valid entry
  86. CHAR name[STACKWALK_MAX_NAMELEN];
  87. CHAR undName[STACKWALK_MAX_NAMELEN];
  88. CHAR undFullName[STACKWALK_MAX_NAMELEN];
  89. DWORD64 offsetFromSmybol;
  90. DWORD offsetFromLine;
  91. DWORD lineNumber;
  92. CHAR lineFileName[STACKWALK_MAX_NAMELEN];
  93. DWORD symType;
  94. LPCSTR symTypeString;
  95. CHAR moduleName[STACKWALK_MAX_NAMELEN];
  96. DWORD64 baseOfImage;
  97. CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
  98. } CallstackEntry;
  99. typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
  100. virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
  101. virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
  102. virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
  103. virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
  104. virtual void OnOutput(LPCSTR szText);
  105. StackWalkerInternal *m_sw;
  106. HANDLE m_hProcess;
  107. DWORD m_dwProcessId;
  108. BOOL m_modulesLoaded;
  109. LPSTR m_szSymPath;
  110. int m_options;
  111. static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
  112. friend StackWalkerInternal;
  113. };
  114. // The "ugly" assembler-implementation is needed for systems before XP
  115. // If you have a new PSDK and you only compile for XP and later, then you can use
  116. // the "RtlCaptureContext"
  117. // Currently there is no define which determines the PSDK-Version...
  118. // So we just use the compiler-version (and assumes that the PSDK is
  119. // the one which was installed by the VS-IDE)
  120. // INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
  121. // But I currently use it in x64/IA64 environments...
  122. //#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
  123. #if defined(_M_IX86)
  124. #ifdef CURRENT_THREAD_VIA_EXCEPTION
  125. // TODO: The following is not a "good" implementation,
  126. // because the callstack is only valid in the "__except" block...
  127. #define GET_CURRENT_CONTEXT(c, contextFlags) \
  128. do { \
  129. memset(&c, 0, sizeof(CONTEXT)); \
  130. EXCEPTION_POINTERS *pExp = NULL; \
  131. __try { \
  132. throw 0; \
  133. } __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \
  134. if (pExp != NULL) \
  135. memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
  136. c.ContextFlags = contextFlags; \
  137. } while(0);
  138. #else
  139. // The following should be enough for walking the callstack...
  140. #define GET_CURRENT_CONTEXT(c, contextFlags) \
  141. do { \
  142. memset(&c, 0, sizeof(CONTEXT)); \
  143. c.ContextFlags = contextFlags; \
  144. __asm call x \
  145. __asm x: pop eax \
  146. __asm mov c.Eip, eax \
  147. __asm mov c.Ebp, ebp \
  148. __asm mov c.Esp, esp \
  149. } while(0);
  150. #endif
  151. #else
  152. // The following is defined for x86 (XP and higher), x64 and IA64:
  153. #define GET_CURRENT_CONTEXT(c, contextFlags) \
  154. do { \
  155. memset(&c, 0, sizeof(CONTEXT)); \
  156. c.ContextFlags = contextFlags; \
  157. RtlCaptureContext(&c); \
  158. } while(0);
  159. #endif