1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_ 6 #define BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_ 7 8 #include <windows.h> 9 10 #include <memory> 11 12 #include "base/base_export.h" 13 #include "base/profiler/module_cache.h" 14 #include "build/build_config.h" 15 16 namespace base { 17 18 #if !defined(ARCH_CPU_64_BITS) 19 // Allows code to compile for x86. Actual support for x86 will require either 20 // refactoring these interfaces or separate architecture-specific interfaces. 21 struct RUNTIME_FUNCTION { 22 DWORD BeginAddress; 23 DWORD EndAddress; 24 }; 25 using PRUNTIME_FUNCTION = RUNTIME_FUNCTION*; 26 #endif // !defined(ARCH_CPU_64_BITS) 27 ContextPC(CONTEXT * context)28inline ULONG64 ContextPC(CONTEXT* context) { 29 #if defined(ARCH_CPU_X86_64) 30 return context->Rip; 31 #elif defined(ARCH_CPU_X86) 32 return context->Eip; 33 #elif defined(ARCH_CPU_ARM64) 34 return context->Pc; 35 #else 36 #error Unsupported Windows Arch 37 #endif 38 } 39 40 // This class is not used while the target thread is suspended, so may allocate 41 // from the default heap. 42 class BASE_EXPORT Win32StackFrameUnwinder { 43 public: 44 // Interface for Win32 unwind-related functionality this class depends 45 // on. Provides a seam for testing. 46 class BASE_EXPORT UnwindFunctions { 47 public: 48 UnwindFunctions(const UnwindFunctions&) = delete; 49 UnwindFunctions& operator=(const UnwindFunctions&) = delete; 50 51 virtual ~UnwindFunctions(); 52 53 virtual PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter, 54 PDWORD64 image_base) = 0; 55 virtual void VirtualUnwind(DWORD64 image_base, 56 DWORD64 program_counter, 57 PRUNTIME_FUNCTION runtime_function, 58 CONTEXT* context) = 0; 59 60 protected: 61 UnwindFunctions(); 62 }; 63 64 explicit Win32StackFrameUnwinder(); 65 66 Win32StackFrameUnwinder(const Win32StackFrameUnwinder&) = delete; 67 Win32StackFrameUnwinder& operator=(const Win32StackFrameUnwinder&) = delete; 68 69 ~Win32StackFrameUnwinder(); 70 71 // Attempts to unwind the frame represented by |context|, where the 72 // instruction pointer is known to be in |module|. Updates |context| if 73 // successful. 74 bool TryUnwind(bool at_top_frame, 75 CONTEXT* context, 76 const ModuleCache::Module* module); 77 78 private: 79 // This function is for internal and test purposes only. 80 Win32StackFrameUnwinder(std::unique_ptr<UnwindFunctions> unwind_functions); 81 friend class Win32StackFrameUnwinderTest; 82 83 std::unique_ptr<UnwindFunctions> unwind_functions_; 84 }; 85 86 } // namespace base 87 88 #endif // BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_ 89