stacktrace_windows.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) 2012-2014 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 <windows.h>
  8. #include <dbghelp.h>
  9. #include <stdio.h>
  10. namespace crown
  11. {
  12. void stacktrace()
  13. {
  14. SymInitialize(GetCurrentProcess(), NULL, TRUE);
  15. SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
  16. DWORD mtype;
  17. CONTEXT ctx;
  18. ZeroMemory(&ctx, sizeof(CONTEXT));
  19. ctx.ContextFlags = CONTEXT_CONTROL;
  20. RtlCaptureContext(&ctx);
  21. STACKFRAME64 stack;
  22. ZeroMemory(&stack, sizeof(STACKFRAME64));
  23. #ifdef _M_IX86
  24. mtype = IMAGE_FILE_MACHINE_I386;
  25. stack.AddrPC.Offset = ctx.Eip;
  26. stack.AddrPC.Mode = AddrModeFlat;
  27. stack.AddrFrame.Offset = ctx.Ebp;
  28. stack.AddrFrame.Mode = AddrModeFlat;
  29. stack.AddrStack.Offset = ctx.Esp;
  30. stack.AddrStack.Mode = AddrModeFlat;
  31. #elif _M_X64
  32. mtype = IMAGE_FILE_MACHINE_AMD64;
  33. stack.AddrPC.Offset = ctx.Rip;
  34. stack.AddrPC.Mode = AddrModeFlat;
  35. stack.AddrFrame.Offset = ctx.Rsp;
  36. stack.AddrFrame.Mode = AddrModeFlat;
  37. stack.AddrStack.Offset = ctx.Rsp;
  38. stack.AddrStack.Mode = AddrModeFlat;
  39. #endif
  40. DWORD ldsp = 0;
  41. IMAGEHLP_LINE64 line;
  42. ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
  43. line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
  44. char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
  45. PSYMBOL_INFO sym = (PSYMBOL_INFO)buf;
  46. sym->SizeOfStruct = sizeof(SYMBOL_INFO);
  47. sym->MaxNameLen = MAX_SYM_NAME;
  48. UINT num = 0;
  49. while (StackWalk64(mtype,
  50. GetCurrentProcess(),
  51. GetCurrentThread(),
  52. &stack,
  53. &ctx,
  54. NULL,
  55. SymFunctionTableAccess64,
  56. SymGetModuleBase64,
  57. NULL))
  58. {
  59. if (stack.AddrPC.Offset == 0)
  60. break;
  61. ++num;
  62. BOOL res = SymGetLineFromAddr64(GetCurrentProcess(), stack.AddrPC.Offset, &ldsp, &line) &&
  63. SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
  64. if (res == TRUE)
  65. printf("\t[%i] %s (%s:%d)\n", num, sym->Name, line.FileName, line.LineNumber);
  66. else
  67. printf("\t[%i] 0x%p\n", num, stack.AddrPC.Offset);
  68. }
  69. SymCleanup(GetCurrentProcess());
  70. }
  71. } // namespace crown
  72. #endif // CROWN_PLATFORM_WINDOWS