callstack_windows.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #if CROWN_PLATFORM_WINDOWS
  7. #include "log.h"
  8. #include "win_headers.h"
  9. #include <dbghelp.h>
  10. namespace crown
  11. {
  12. namespace error
  13. {
  14. void print_callstack()
  15. {
  16. SymInitialize(GetCurrentProcess(), NULL, TRUE);
  17. SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
  18. DWORD mtype;
  19. CONTEXT ctx;
  20. ZeroMemory(&ctx, sizeof(CONTEXT));
  21. ctx.ContextFlags = CONTEXT_CONTROL;
  22. RtlCaptureContext(&ctx);
  23. STACKFRAME64 stack;
  24. ZeroMemory(&stack, sizeof(STACKFRAME64));
  25. #ifdef _M_IX86
  26. mtype = IMAGE_FILE_MACHINE_I386;
  27. stack.AddrPC.Offset = ctx.Eip;
  28. stack.AddrPC.Mode = AddrModeFlat;
  29. stack.AddrFrame.Offset = ctx.Ebp;
  30. stack.AddrFrame.Mode = AddrModeFlat;
  31. stack.AddrStack.Offset = ctx.Esp;
  32. stack.AddrStack.Mode = AddrModeFlat;
  33. #elif _M_X64
  34. mtype = IMAGE_FILE_MACHINE_AMD64;
  35. stack.AddrPC.Offset = ctx.Rip;
  36. stack.AddrPC.Mode = AddrModeFlat;
  37. stack.AddrFrame.Offset = ctx.Rsp;
  38. stack.AddrFrame.Mode = AddrModeFlat;
  39. stack.AddrStack.Offset = ctx.Rsp;
  40. stack.AddrStack.Mode = AddrModeFlat;
  41. #endif
  42. DWORD ldsp = 0;
  43. IMAGEHLP_LINE64 line;
  44. ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
  45. line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
  46. char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
  47. PSYMBOL_INFO sym = (PSYMBOL_INFO)buf;
  48. sym->SizeOfStruct = sizeof(SYMBOL_INFO);
  49. sym->MaxNameLen = MAX_SYM_NAME;
  50. UINT num = 0;
  51. while (StackWalk64(mtype
  52. , GetCurrentProcess()
  53. , GetCurrentThread()
  54. , &stack
  55. , &ctx
  56. , NULL
  57. , SymFunctionTableAccess64
  58. , SymGetModuleBase64
  59. , NULL
  60. ))
  61. {
  62. if (stack.AddrPC.Offset == 0)
  63. break;
  64. ++num;
  65. BOOL res = SymGetLineFromAddr64(GetCurrentProcess()
  66. , stack.AddrPC.Offset
  67. , &ldsp
  68. , &line
  69. );
  70. res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
  71. if (res == TRUE)
  72. loge("\t[%2i] %s in %s:%d", num, sym->Name, line.FileName, line.LineNumber);
  73. else
  74. loge("\t[%2i] 0x%p", num, stack.AddrPC.Offset);
  75. }
  76. SymCleanup(GetCurrentProcess());
  77. }
  78. } // namespace error
  79. } // namespace crown
  80. #endif // CROWN_PLATFORM_WINDOWS