stacktrace.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #pragma once
  2. #include <windows.h>
  3. #include <DbgHelp.h>
  4. #include <iostream>
  5. //#include "Logger.h"
  6. #pragma comment(lib, "dbghelp.lib")
  7. class DiosTempOutputFile
  8. {
  9. HANDLE m_FileHandle;
  10. public:
  11. DiosTempOutputFile()
  12. {
  13. m_FileHandle = INVALID_HANDLE_VALUE;
  14. };
  15. virtual ~DiosTempOutputFile(void)
  16. {
  17. Close();
  18. };
  19. bool Create(const char *pszFile)
  20. {
  21. //new one
  22. m_FileHandle = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  23. if (m_FileHandle == INVALID_HANDLE_VALUE)
  24. {
  25. throw "ERROR AT Create FILE";
  26. return false;
  27. }
  28. return true;
  29. };
  30. bool Open(const char *pszFile)
  31. {
  32. m_FileHandle = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  33. if (m_FileHandle == INVALID_HANDLE_VALUE)
  34. {
  35. throw "ERROR AT Open FILE";
  36. return false;
  37. }
  38. return true;
  39. };
  40. void Close()
  41. {
  42. if (m_FileHandle != INVALID_HANDLE_VALUE)
  43. {
  44. CloseHandle(m_FileHandle);
  45. m_FileHandle = INVALID_HANDLE_VALUE;
  46. }
  47. };
  48. bool is_open()
  49. {
  50. return (m_FileHandle != INVALID_HANDLE_VALUE);
  51. };
  52. DiosTempOutputFile& operator << (DWORD Val)
  53. {
  54. if (m_FileHandle != INVALID_HANDLE_VALUE)
  55. {
  56. if (SetFilePointer(m_FileHandle, 0, 0, FILE_END) != INVALID_SET_FILE_POINTER)
  57. {
  58. DWORD returnedLenth = 0;
  59. char szVal[16];
  60. sprintf_s(szVal, 16, "%u", Val);
  61. if (WriteFile(m_FileHandle, szVal, (DWORD)strlen(szVal), &returnedLenth, 0) == FALSE)
  62. {
  63. printf("\n\nERROR AT WRITE FILE:\n\n");
  64. throw "ERROR AT WRITE FILE";
  65. }
  66. return (*this);
  67. }
  68. }
  69. throw "ERROR AT WRITE FILE ON EMPTY HANDLE";
  70. return (*this);
  71. };
  72. DiosTempOutputFile& operator << (const char* pVal)
  73. {
  74. if (m_FileHandle != INVALID_HANDLE_VALUE)
  75. {
  76. if (SetFilePointer(m_FileHandle, 0, 0, FILE_END) != INVALID_SET_FILE_POINTER)
  77. {
  78. DWORD returnedLenth = 0;
  79. if (WriteFile(m_FileHandle, pVal, (DWORD)strlen(pVal), &returnedLenth, 0) == FALSE)
  80. {
  81. printf("\n\nERROR AT WRITE FILE:\n\n");
  82. throw "ERROR AT WRITE FILE";
  83. }
  84. return (*this);
  85. }
  86. }
  87. throw "ERROR AT WRITE FILE ON EMPTY HANDLE";
  88. return (*this);
  89. };
  90. };
  91. class StackTrace {
  92. private:
  93. static const int m_MaxFrameCount = 62;
  94. int m_FrameCount;
  95. void* m_Frames[m_MaxFrameCount];
  96. HANDLE m_Mutex;
  97. //string GetCurTime()
  98. //{
  99. // SYSTEMTIME st;
  100. // GetLocalTime(&st);
  101. // string Context;
  102. // printf("hit At %4d-%2d-%2d %2d:%2d:%2d.%3d\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  103. //}
  104. public:
  105. StackTrace() {
  106. m_Mutex = CreateMutex(0, 0, 0);
  107. m_FrameCount = CaptureStackBackTrace(1, m_MaxFrameCount, m_Frames, NULL);
  108. Print();
  109. }
  110. ~StackTrace() {
  111. CloseHandle(m_Mutex);
  112. };
  113. void Print()
  114. {
  115. HANDLE process = GetCurrentProcess();
  116. SymSetOptions(SYMOPT_LOAD_LINES); // set symbol option to load the source code lines
  117. SymInitialize(process, NULL, TRUE); // init symbol
  118. char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; // define the PSYMBOL_INFO
  119. PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
  120. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  121. symbol->MaxNameLen = MAX_SYM_NAME;
  122. IMAGEHLP_LINE64 line; // define the IMAGEHLP_LINE64
  123. line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
  124. DiosTempOutputFile Outfile;
  125. WaitForSingleObject(m_Mutex, INFINITE);
  126. Outfile.Open("StackTrace.log");
  127. Outfile << "StackTrace Entry\n";
  128. for (int i = 0; i < m_FrameCount; i++)
  129. {
  130. DWORD64 dw64Displacement;
  131. SymFromAddr(process, (DWORD64)(m_Frames[i]), &dw64Displacement, symbol); // get symbol info
  132. std::cout << symbol->Name;
  133. DWORD dwDisplacement;
  134. if (SymGetLineFromAddr64(process, (DWORD64)(m_Frames[i]), &dwDisplacement, &line)) // get line info
  135. {
  136. std::cout << symbol->Name << ", " << line.FileName << ", line " << line.LineNumber;
  137. {
  138. SYSTEMTIME st;
  139. GetLocalTime(&st);
  140. char szTime[128];
  141. sprintf_s(szTime, 64, "%4d-%2d-%2d %2d:%2d:%2d.%3d PID[%0x08]TID[%0x08]", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, GetCurrentProcessId(), GetCurrentThreadId());
  142. //TPRINTA_ERROR("%s,%s,line:%d", symbol->Name, line.FileName, line.LineNumber);
  143. Outfile << szTime << symbol->Name << ", " << line.FileName << ", line " << line.LineNumber << "\n";
  144. }
  145. }
  146. std::cout << std::endl;
  147. }
  148. Outfile << "StackTrace Exit\n";
  149. SymCleanup(process);
  150. ReleaseMutex(m_Mutex);
  151. }
  152. };