fork(5) download
  1. //#pragma warning( disable: 4786 )
  2. #include <windows.h>
  3. #include <winnt.h>
  4.  
  5. #include <string>
  6. #include <vector>
  7. #include <Psapi.h>
  8. #include <algorithm>
  9. #include <iomanip>
  10. #include <iostream>
  11. #include <stdexcept>
  12. #include <iterator>
  13.  
  14. #pragma comment(lib, "psapi.lib")
  15. #pragma comment(lib, "dbghelp.lib")
  16.  
  17. #pragma pack( push, before_imagehlp, 8 )
  18. #include <imagehlp.h>
  19. #pragma pack( pop, before_imagehlp )
  20.  
  21. struct module_data {
  22. std::string image_name;
  23. std::string module_name;
  24. void *base_address;
  25. DWORD load_size;
  26. };
  27. typedef std::vector<module_data> ModuleList;
  28.  
  29. extern void __declspec(dllimport) ThreadFunc1(void (*f)());
  30.  
  31. HANDLE thread_done;
  32. HANDLE thread_ready;
  33.  
  34. bool show_stack(std::ostream &, HANDLE hThread, CONTEXT& c);
  35. DWORD __stdcall TargetThread( void *arg );
  36. void ThreadFunc1();
  37. void ThreadFunc2();
  38. DWORD Filter( EXCEPTION_POINTERS *ep );
  39. void *load_modules_symbols( HANDLE hProcess, DWORD pid );
  40.  
  41. class thread_suspender {
  42. HANDLE thread;
  43. public:
  44. thread_suspender(HANDLE t) :thread(t) { SuspendThread(thread); }
  45. ~thread_suspender() { ResumeThread(thread); }
  46. };
  47.  
  48. int main() {
  49. HANDLE thread;
  50. DWORD thread_id;
  51.  
  52. try {
  53. thread_ready = CreateEvent( NULL, false, false, NULL );
  54. thread_done = CreateEvent(NULL, false, false,NULL);
  55.  
  56. thread = CreateThread( NULL, 0, TargetThread, NULL, 0, &thread_id );
  57.  
  58. WaitForSingleObject( thread_ready, INFINITE );
  59. CloseHandle(thread_ready);
  60.  
  61. {
  62. thread_suspender t(thread);
  63.  
  64. CONTEXT c = {0};
  65. c.ContextFlags = CONTEXT_FULL;
  66. GetThreadContext(thread, &c);
  67. show_stack(std::cout, thread, c);
  68. }
  69. SetEvent(thread_done);
  70. WaitForSingleObject(thread, INFINITE);
  71. }
  72. catch (std::exception const &e) {
  73. std::cout << "Caught Exception: " << e.what() << "\n";
  74. }
  75. return 0;
  76. }
  77.  
  78. // if you use C++ exception handling: install a translator function
  79. // with set_se_translator(). In the context of that function (but *not*
  80. // afterwards), you can either do your stack dump, or save the CONTEXT
  81. // record as a local copy. Note that you must do the stack dump at the
  82. // earliest opportunity, to avoid the interesting stack-frames being gone
  83. // by the time you do the dump.
  84. DWORD Filter(EXCEPTION_POINTERS *ep) {
  85. HANDLE thread;
  86.  
  87. DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
  88. GetCurrentProcess(), &thread, 0, false, DUPLICATE_SAME_ACCESS);
  89. std::cout << "Walking stack from exception.";
  90. show_stack(std::cout, thread, *(ep->ContextRecord));
  91. std::cout << "\nEnd of exception stack walk.\n";
  92. CloseHandle(thread);
  93.  
  94. return EXCEPTION_EXECUTE_HANDLER;
  95. }
  96.  
  97. void ThreadFunc2() {
  98. // First, cause an exception. The filter above forces a stack dump.
  99. __try { DebugBreak(); }
  100. __except (Filter(GetExceptionInformation())) { }
  101.  
  102. // Then signal that the thread is ready for a normal stack dump
  103. SetEvent(thread_ready);
  104. // and wait until the main thread finishes dumping the stack.
  105. WaitForSingleObject(thread_done, INFINITE);
  106. }
  107.  
  108. DWORD __stdcall TargetThread( void *arg ) {
  109. (void) arg;
  110. ThreadFunc1(ThreadFunc2);
  111. return 0;
  112. }
  113.  
  114. class SymHandler {
  115. HANDLE p;
  116. public:
  117. SymHandler(HANDLE process, char const *path=NULL, bool intrude = false) : p(process) {
  118. if (!SymInitialize(p, path, intrude))
  119. throw(std::logic_error("Unable to initialize symbol handler"));
  120. }
  121. ~SymHandler() { SymCleanup(p); }
  122. };
  123.  
  124. #ifdef _M_X64
  125. STACKFRAME64 init_stack_frame(CONTEXT c) {
  126. STACKFRAME64 s;
  127. s.AddrPC.Offset = c.Rip;
  128. s.AddrPC.Mode = AddrModeFlat;
  129. s.AddrStack.Offset = c.Rsp;
  130. s.AddrStack.Mode = AddrModeFlat;
  131. s.AddrFrame.Offset = c.Rbp;
  132. s.AddrFrame.Mode = AddrModeFlat;
  133. return s;
  134. }
  135. #else
  136. STACKFRAME64 init_stack_frame(CONTEXT c) {
  137. STACKFRAME64 s;
  138. s.AddrPC.Offset = c.Eip;
  139. s.AddrPC.Mode = AddrModeFlat;
  140. s.AddrStack.Offset = c.Esp;
  141. s.AddrStack.Mode = AddrModeFlat;
  142. s.AddrFrame.Offset = c.Ebp;
  143. s.AddrFrame.Mode = AddrModeFlat;
  144. return s;
  145. }
  146. #endif
  147.  
  148. void sym_options(DWORD add, DWORD remove=0) {
  149. DWORD symOptions = SymGetOptions();
  150. symOptions |= add;
  151. symOptions &= ~remove;
  152. SymSetOptions(symOptions);
  153. }
  154.  
  155. class symbol {
  156. typedef IMAGEHLP_SYMBOL64 sym_type;
  157. sym_type *sym;
  158. static const int max_name_len = 1024;
  159. public:
  160. symbol(HANDLE process, DWORD64 address) : sym((sym_type *)::operator new(sizeof(*sym) + max_name_len)) {
  161. memset(sym, '\0', sizeof(*sym) + max_name_len);
  162. sym->SizeOfStruct = sizeof(*sym);
  163. sym->MaxNameLength = max_name_len;
  164. DWORD64 displacement;
  165.  
  166. if (!SymGetSymFromAddr64(process, address, &displacement, sym))
  167. throw(std::logic_error("Bad symbol"));
  168. }
  169.  
  170. std::string name() { return std::string(sym->Name); }
  171. std::string undecorated_name() {
  172. std::vector<char> und_name(max_name_len);
  173. UnDecorateSymbolName(sym->Name, &und_name[0], max_name_len, UNDNAME_COMPLETE);
  174. return std::string(&und_name[0], strlen(&und_name[0]));
  175. }
  176. };
  177.  
  178. bool show_stack(std::ostream &os, HANDLE hThread, CONTEXT& c) {
  179. HANDLE process = GetCurrentProcess();
  180. int frame_number=0;
  181. DWORD offset_from_symbol=0;
  182. IMAGEHLP_LINE64 line = {0};
  183.  
  184. SymHandler handler(process);
  185.  
  186. sym_options(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
  187.  
  188. void *base = load_modules_symbols(process, GetCurrentProcessId());
  189.  
  190. STACKFRAME64 s = init_stack_frame(c);
  191.  
  192. line.SizeOfStruct = sizeof line;
  193.  
  194. IMAGE_NT_HEADERS *h = ImageNtHeader(base);
  195. DWORD image_type = h->FileHeader.Machine;
  196.  
  197. do {
  198. if (!StackWalk64(image_type, process, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
  199. return false;
  200.  
  201. os << std::setw(3) << "\n" << frame_number << "\t";
  202. if (s.AddrPC.Offset != 0) {
  203. std::cout << symbol(process, s.AddrPC.Offset).undecorated_name();
  204.  
  205. if (SymGetLineFromAddr64(process, s.AddrPC.Offset, &offset_from_symbol, &line))
  206. os << "\t" << line.FileName << "(" << line.LineNumber << ")";
  207. }
  208. else
  209. os << "(No Symbols: PC == 0)";
  210. ++frame_number;
  211. } while (s.AddrReturn.Offset != 0);
  212. return true;
  213. }
  214.  
  215. class get_mod_info {
  216. HANDLE process;
  217. static const int buffer_length = 4096;
  218. public:
  219. get_mod_info(HANDLE h) : process(h) {}
  220.  
  221. module_data operator()(HMODULE module) {
  222. module_data ret;
  223. char temp[buffer_length];
  224. MODULEINFO mi;
  225.  
  226. GetModuleInformation(process, module, &mi, sizeof(mi));
  227. ret.base_address = mi.lpBaseOfDll;
  228. ret.load_size = mi.SizeOfImage;
  229.  
  230. GetModuleFileNameEx(process, module, temp, sizeof(temp));
  231. ret.image_name = temp;
  232. GetModuleBaseName(process, module, temp, sizeof(temp));
  233. ret.module_name = temp;
  234. std::vector<char> img(ret.image_name.begin(), ret.image_name.end());
  235. std::vector<char> mod(ret.module_name.begin(), ret.module_name.end());
  236. SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size);
  237. return ret;
  238. }
  239. };
  240.  
  241. void *load_modules_symbols(HANDLE process, DWORD pid) {
  242. ModuleList modules;
  243.  
  244. DWORD cbNeeded;
  245. std::vector<HMODULE> module_handles(1);
  246.  
  247. EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
  248. module_handles.resize(cbNeeded/sizeof(HMODULE));
  249. EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
  250.  
  251. std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process));
  252. return modules[0].base_address;
  253. }
  254.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:2:21: error: windows.h: No such file or directory
prog.cpp:3:19: error: winnt.h: No such file or directory
prog.cpp:7:19: error: Psapi.h: No such file or directory
prog.cpp:14: warning: ignoring #pragma comment 
prog.cpp:15: warning: ignoring #pragma comment 
prog.cpp:18:22: error: imagehlp.h: No such file or directory
prog.cpp:25: error: ‘DWORD’ does not name a type
prog.cpp:29: warning: ‘__declspec’ initialized and declared ‘extern’
prog.cpp:29: error: variable or field ‘__declspec’ declared void
prog.cpp:29: error: ‘dllimport’ was not declared in this scope
prog.cpp:31: error: ‘HANDLE’ does not name a type
prog.cpp:32: error: ‘HANDLE’ does not name a type
prog.cpp:34: error: ‘HANDLE’ has not been declared
prog.cpp:34: error: ‘CONTEXT’ has not been declared
prog.cpp:35: error: ‘DWORD’ does not name a type
prog.cpp:38: error: ‘DWORD’ does not name a type
prog.cpp:39: error: ‘HANDLE’ was not declared in this scope
prog.cpp:39: error: ‘DWORD’ was not declared in this scope
prog.cpp:39: error: initializer expression list treated as compound expression
prog.cpp:42: error: ‘HANDLE’ does not name a type
prog.cpp:44: error: expected `)' before ‘t’
prog.cpp: In destructor ‘thread_suspender::~thread_suspender()’:
prog.cpp:45: error: ‘thread’ was not declared in this scope
prog.cpp:45: error: ‘ResumeThread’ was not declared in this scope
prog.cpp: In function ‘int main()’:
prog.cpp:49: error: ‘HANDLE’ was not declared in this scope
prog.cpp:49: error: expected `;' before ‘thread’
prog.cpp:50: error: ‘DWORD’ was not declared in this scope
prog.cpp:50: error: expected `;' before ‘thread_id’
prog.cpp:53: error: ‘thread_ready’ was not declared in this scope
prog.cpp:53: error: ‘CreateEvent’ was not declared in this scope
prog.cpp:54: error: ‘thread_done’ was not declared in this scope
prog.cpp:56: error: ‘thread’ was not declared in this scope
prog.cpp:56: error: ‘TargetThread’ was not declared in this scope
prog.cpp:56: error: ‘thread_id’ was not declared in this scope
prog.cpp:56: error: ‘CreateThread’ was not declared in this scope
prog.cpp:58: error: ‘INFINITE’ was not declared in this scope
prog.cpp:58: error: ‘WaitForSingleObject’ was not declared in this scope
prog.cpp:59: error: ‘CloseHandle’ was not declared in this scope
prog.cpp:64: error: ‘CONTEXT’ was not declared in this scope
prog.cpp:64: error: expected `;' before ‘c’
prog.cpp:65: error: ‘c’ was not declared in this scope
prog.cpp:65: error: ‘CONTEXT_FULL’ was not declared in this scope
prog.cpp:66: error: ‘GetThreadContext’ was not declared in this scope
prog.cpp:69: error: ‘SetEvent’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:84: error: ‘DWORD’ does not name a type
prog.cpp: In function ‘void ThreadFunc2()’:
prog.cpp:99: error: ‘__try’ was not declared in this scope
prog.cpp:99: error: expected `;' before ‘{’ token
prog.cpp:100: error: ‘GetExceptionInformation’ was not declared in this scope
prog.cpp:100: error: ‘Filter’ was not declared in this scope
prog.cpp:100: error: ‘__except’ was not declared in this scope
prog.cpp:100: error: expected `;' before ‘{’ token
prog.cpp:103: error: ‘thread_ready’ was not declared in this scope
prog.cpp:103: error: ‘SetEvent’ was not declared in this scope
prog.cpp:105: error: ‘thread_done’ was not declared in this scope
prog.cpp:105: error: ‘INFINITE’ was not declared in this scope
prog.cpp:105: error: ‘WaitForSingleObject’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:108: error: ‘DWORD’ does not name a type
prog.cpp:115: error: ‘HANDLE’ does not name a type
prog.cpp:117: error: expected `)' before ‘process’
prog.cpp: In destructor ‘SymHandler::~SymHandler()’:
prog.cpp:121: error: ‘p’ was not declared in this scope
prog.cpp:121: error: ‘SymCleanup’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:136: error: ‘STACKFRAME64’ does not name a type
prog.cpp:148: error: variable or field ‘sym_options’ declared void
prog.cpp:148: error: ‘DWORD’ was not declared in this scope
prog.cpp:148: error: ‘DWORD’ was not declared in this scope
prog.cpp:156: error: ‘IMAGEHLP_SYMBOL64’ does not name a type
prog.cpp:157: error: ISO C++ forbids declaration of ‘sym_type’ with no type
prog.cpp:157: error: expected ‘;’ before ‘*’ token
prog.cpp:160: error: expected `)' before ‘process’
prog.cpp: In member function ‘std::string symbol::name()’:
prog.cpp:170: error: ‘sym’ was not declared in this scope
prog.cpp: In member function ‘std::string symbol::undecorated_name()’:
prog.cpp:173: error: ‘sym’ was not declared in this scope
prog.cpp:173: error: ‘UNDNAME_COMPLETE’ was not declared in this scope
prog.cpp:173: error: ‘UnDecorateSymbolName’ was not declared in this scope
prog.cpp:174: error: ‘strlen’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:178: error: ‘HANDLE’ has not been declared
prog.cpp:178: error: ‘CONTEXT’ has not been declared
prog.cpp: In function ‘bool show_stack(std::ostream&, int, int&)’:
prog.cpp:179: error: ‘HANDLE’ was not declared in this scope
prog.cpp:179: error: expected `;' before ‘process’
prog.cpp:181: error: ‘DWORD’ was not declared in this scope
prog.cpp:181: error: expected `;' before ‘offset_from_symbol’
prog.cpp:182: error: ‘IMAGEHLP_LINE64’ was not declared in this scope
prog.cpp:182: error: expected `;' before ‘line’
prog.cpp:184: error: ‘process’ was not declared in this scope
prog.cpp:186: error: ‘SYMOPT_LOAD_LINES’ was not declared in this scope
prog.cpp:186: error: ‘SYMOPT_UNDNAME’ was not declared in this scope
prog.cpp:186: error: ‘sym_options’ was not declared in this scope
prog.cpp:188: error: ‘GetCurrentProcessId’ was not declared in this scope
prog.cpp:188: error: ‘load_modules_symbols’ cannot be used as a function
prog.cpp:190: error: ‘STACKFRAME64’ was not declared in this scope
prog.cpp:190: error: expected `;' before ‘s’
prog.cpp:192: error: ‘line’ was not declared in this scope
prog.cpp:194: error: ‘IMAGE_NT_HEADERS’ was not declared in this scope
prog.cpp:194: error: ‘h’ was not declared in this scope
prog.cpp:194: error: ‘ImageNtHeader’ was not declared in this scope
prog.cpp:195: error: expected `;' before ‘image_type’
prog.cpp:198: error: ‘image_type’ was not declared in this scope
prog.cpp:198: error: ‘s’ was not declared in this scope
prog.cpp:198: error: ‘SymFunctionTableAccess64’ was not declared in this scope
prog.cpp:198: error: ‘SymGetModuleBase64’ was not declared in this scope
prog.cpp:198: error: ‘StackWalk64’ was not declared in this scope
prog.cpp:202: error: ‘s’ was not declared in this scope
prog.cpp:205: error: ‘offset_from_symbol’ was not declared in this scope
prog.cpp:205: error: ‘SymGetLineFromAddr64’ was not declared in this scope
prog.cpp:211: error: ‘s’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:216: error: ‘HANDLE’ does not name a type
prog.cpp:219: error: expected `)' before ‘h’
prog.cpp:221: error: ‘HMODULE’ has not been declared
prog.cpp: In member function ‘module_data get_mod_info::operator()(int)’:
prog.cpp:224: error: ‘MODULEINFO’ was not declared in this scope
prog.cpp:224: error: expected `;' before ‘mi’
prog.cpp:226: error: ‘process’ was not declared in this scope
prog.cpp:226: error: ‘mi’ was not declared in this scope
prog.cpp:226: error: ‘GetModuleInformation’ was not declared in this scope
prog.cpp:228: error: ‘struct module_data’ has no member named ‘load_size’
prog.cpp:230: error: ‘GetModuleFileNameEx’ was not declared in this scope
prog.cpp:232: error: ‘GetModuleBaseName’ was not declared in this scope
prog.cpp:236: error: ‘DWORD64’ was not declared in this scope
prog.cpp:236: error: ‘struct module_data’ has no member named ‘load_size’
prog.cpp:236: error: ‘SymLoadModule64’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:241: error: redefinition of ‘void* load_modules_symbols’
prog.cpp:39: error: ‘void* load_modules_symbols’ previously defined here
prog.cpp:241: error: ‘HANDLE’ was not declared in this scope
prog.cpp:241: error: ‘DWORD’ was not declared in this scope
stdout
Standard output is empty