StackTrace.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include "il2cpp-config.h"
  2. #if IL2CPP_TARGET_WINDOWS
  3. #include "WindowsHeaders.h"
  4. #include "dbghelp.h"
  5. #include "os/Mutex.h"
  6. #include "os/StackTrace.h"
  7. namespace il2cpp
  8. {
  9. namespace os
  10. {
  11. void StackTrace::WalkStackNative(WalkStackCallback callback, void* context, WalkOrder walkOrder)
  12. {
  13. const uint32_t kMaxFrames = 128;
  14. void* stack[kMaxFrames];
  15. size_t frames = CaptureStackBackTrace(0, kMaxFrames, stack, NULL);
  16. // If didn't get any frames on the first try, try again
  17. // Sometimes on Windows 10 on a newly created thread CaptureStackBackTrace doesn't work the first time we call it.
  18. if (frames == 0)
  19. frames = CaptureStackBackTrace(0, kMaxFrames, stack, NULL);
  20. IL2CPP_ASSERT(frames > 0 && "CaptureStackBackTrace returned no frames");
  21. if (walkOrder == kFirstCalledToLastCalled)
  22. {
  23. for (size_t i = frames; i--;)
  24. {
  25. if (!callback(reinterpret_cast<Il2CppMethodPointer>(stack[i]), context))
  26. break;
  27. }
  28. }
  29. else
  30. {
  31. for (size_t i = 0; i < frames; i++)
  32. {
  33. if (!callback(reinterpret_cast<Il2CppMethodPointer>(stack[i]), context))
  34. break;
  35. }
  36. }
  37. }
  38. std::string StackTrace::NativeStackTrace()
  39. {
  40. std::string stackTrace;
  41. #if !IL2CPP_TARGET_WINRT && !IL2CPP_TARGET_XBOXONE && !IL2CPP_TARGET_WINDOWS_GAMES
  42. HANDLE hProcess = GetCurrentProcess();
  43. BOOL result = SymInitialize(hProcess, NULL, TRUE);
  44. if (!result)
  45. return std::string();
  46. const uint32_t kMaxFrames = 128;
  47. void* stack[kMaxFrames];
  48. size_t frames = CaptureStackBackTrace(0, kMaxFrames, stack, NULL);
  49. for (size_t i = 0; i < frames; i++)
  50. {
  51. DWORD64 dwDisplacement = 0;
  52. char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
  53. PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
  54. pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  55. pSymbol->MaxNameLen = MAX_SYM_NAME;
  56. if (SymFromAddr(hProcess, (DWORD64)stack[i], &dwDisplacement, pSymbol))
  57. {
  58. stackTrace += "at ";
  59. stackTrace += pSymbol->Name;
  60. stackTrace += "\n ";
  61. }
  62. }
  63. #endif // !IL2CPP_TARGET_WINRT && !IL2CPP_TARGET_XBOXONE && !IL2CPP_TARGET_WINDOWS_GAMES
  64. return stackTrace;
  65. }
  66. const void* StackTrace::GetStackPointer()
  67. {
  68. // TODO implement to avoid extra WalkStack calls
  69. return nullptr;
  70. }
  71. }
  72. }
  73. #endif