1 // Copyright 2015 The Chromium Authors. All rights reserved. 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/macros.h" 14 #include "base/win/scoped_handle.h" 15 16 namespace base { 17 18 #if !defined(_WIN64) 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(_WIN64) 27 28 // Traits class to adapt GenericScopedHandle for HMODULES. 29 class ModuleHandleTraits : public win::HandleTraits { 30 public: 31 using Handle = HMODULE; 32 33 static bool BASE_EXPORT CloseHandle(HMODULE handle); 34 static bool BASE_EXPORT IsHandleValid(HMODULE handle); 35 static HMODULE BASE_EXPORT NullHandle(); 36 37 BASE_EXPORT static const HMODULE kNonNullModuleForTesting; 38 39 private: 40 DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleHandleTraits); 41 }; 42 43 // HMODULE is not really a handle, and has reference count semantics, so the 44 // standard VerifierTraits does not apply. 45 using ScopedModuleHandle = 46 win::GenericScopedHandle<ModuleHandleTraits, win::DummyVerifierTraits>; 47 48 // Instances of this class are expected to be created and destroyed for each 49 // stack unwinding. This class is not used while the target thread is suspended, 50 // so may allocate from the default heap. 51 class BASE_EXPORT Win32StackFrameUnwinder { 52 public: 53 // Interface for Win32 unwind-related functionality this class depends 54 // on. Provides a seam for testing. 55 class BASE_EXPORT UnwindFunctions { 56 public: 57 virtual ~UnwindFunctions(); 58 59 virtual PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter, 60 PDWORD64 image_base) = 0; 61 virtual void VirtualUnwind(DWORD64 image_base, 62 DWORD64 program_counter, 63 PRUNTIME_FUNCTION runtime_function, 64 CONTEXT* context) = 0; 65 66 // Returns the module containing |program_counter|. Can return null if the 67 // module has been unloaded. 68 virtual ScopedModuleHandle GetModuleForProgramCounter( 69 DWORD64 program_counter) = 0; 70 71 protected: 72 UnwindFunctions(); 73 74 private: 75 DISALLOW_COPY_AND_ASSIGN(UnwindFunctions); 76 }; 77 78 Win32StackFrameUnwinder(); 79 ~Win32StackFrameUnwinder(); 80 81 // Attempts to unwind the frame represented by the stack and instruction 82 // pointers in |context|. If successful, updates |context| and provides the 83 // module associated with the frame in |module|. 84 bool TryUnwind(CONTEXT* context, ScopedModuleHandle* module); 85 86 private: 87 // This function is for internal and test purposes only. 88 Win32StackFrameUnwinder(std::unique_ptr<UnwindFunctions> unwind_functions); 89 friend class Win32StackFrameUnwinderTest; 90 91 // State associated with each stack unwinding. 92 bool at_top_frame_; 93 bool unwind_info_present_for_all_frames_; 94 95 std::unique_ptr<UnwindFunctions> unwind_functions_; 96 97 DISALLOW_COPY_AND_ASSIGN(Win32StackFrameUnwinder); 98 }; 99 100 } // namespace base 101 102 #endif // BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_ 103