sanitizer_unwind_win.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //===-- sanitizer_unwind_win.cpp ------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. /// Sanitizer unwind Windows specific functions.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_platform.h"
  13. #if SANITIZER_WINDOWS
  14. #define WIN32_LEAN_AND_MEAN
  15. #define NOGDI
  16. #include <windows.h>
  17. #include "sanitizer_dbghelp.h" // for StackWalk64
  18. #include "sanitizer_stacktrace.h"
  19. #include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded
  20. using namespace __sanitizer;
  21. #if !SANITIZER_GO
  22. void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
  23. CHECK_GE(max_depth, 2);
  24. // FIXME: CaptureStackBackTrace might be too slow for us.
  25. // FIXME: Compare with StackWalk64.
  26. // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
  27. size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax),
  28. (void **)&trace_buffer[0], 0);
  29. if (size == 0)
  30. return;
  31. // Skip the RTL frames by searching for the PC in the stacktrace.
  32. uptr pc_location = LocatePcInTrace(pc);
  33. PopStackFrames(pc_location);
  34. // Replace the first frame with the PC because the frame in the
  35. // stacktrace might be incorrect.
  36. trace_buffer[0] = pc;
  37. }
  38. #ifdef __clang__
  39. #pragma clang diagnostic push
  40. #pragma clang diagnostic ignored "-Wframe-larger-than="
  41. #endif
  42. void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
  43. CHECK(context);
  44. CHECK_GE(max_depth, 2);
  45. CONTEXT ctx = *(CONTEXT *)context;
  46. STACKFRAME64 stack_frame;
  47. memset(&stack_frame, 0, sizeof(stack_frame));
  48. InitializeDbgHelpIfNeeded();
  49. size = 0;
  50. # if SANITIZER_WINDOWS64
  51. # if SANITIZER_ARM64
  52. int machine_type = IMAGE_FILE_MACHINE_ARM64;
  53. stack_frame.AddrPC.Offset = ctx.Pc;
  54. stack_frame.AddrFrame.Offset = ctx.Fp;
  55. stack_frame.AddrStack.Offset = ctx.Sp;
  56. # else
  57. int machine_type = IMAGE_FILE_MACHINE_AMD64;
  58. stack_frame.AddrPC.Offset = ctx.Rip;
  59. stack_frame.AddrFrame.Offset = ctx.Rbp;
  60. stack_frame.AddrStack.Offset = ctx.Rsp;
  61. # endif
  62. # else
  63. int machine_type = IMAGE_FILE_MACHINE_I386;
  64. stack_frame.AddrPC.Offset = ctx.Eip;
  65. stack_frame.AddrFrame.Offset = ctx.Ebp;
  66. stack_frame.AddrStack.Offset = ctx.Esp;
  67. # endif
  68. stack_frame.AddrPC.Mode = AddrModeFlat;
  69. stack_frame.AddrFrame.Mode = AddrModeFlat;
  70. stack_frame.AddrStack.Mode = AddrModeFlat;
  71. while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
  72. &stack_frame, &ctx, NULL, SymFunctionTableAccess64,
  73. SymGetModuleBase64, NULL) &&
  74. size < Min(max_depth, kStackTraceMax)) {
  75. trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
  76. }
  77. }
  78. # ifdef __clang__
  79. # pragma clang diagnostic pop
  80. # endif
  81. # endif // #if !SANITIZER_GO
  82. #endif // SANITIZER_WINDOWS