Chromium Code Reviews| Index: base/profiler/win32_stack_frame_unwinder.cc |
| diff --git a/base/profiler/win32_stack_frame_unwinder.cc b/base/profiler/win32_stack_frame_unwinder.cc |
| index 2f09e8e88750e15340c9445e3d00c499f2c8276c..dcde0511cb83b5445f4c4b76917eb9dc46c0fcce 100644 |
| --- a/base/profiler/win32_stack_frame_unwinder.cc |
| +++ b/base/profiler/win32_stack_frame_unwinder.cc |
| @@ -4,6 +4,8 @@ |
| #include "base/profiler/win32_stack_frame_unwinder.h" |
| +#include <windows.h> |
| + |
| #include "base/containers/hash_tables.h" |
| #include "base/memory/singleton.h" |
| #include "base/stl_util.h" |
| @@ -12,6 +14,27 @@ namespace base { |
| // Win32UnwindFunctions ------------------------------------------------------- |
| +const HMODULE ModuleHandleTraits::kNonNullModuleForTesting = |
| + reinterpret_cast<HMODULE>(static_cast<uintptr_t>(-1)); |
| + |
| +// static |
| +bool ModuleHandleTraits::CloseHandle(HMODULE handle) { |
| + if (handle == kNonNullModuleForTesting) |
| + return true; |
| + |
| + return ::FreeLibrary(handle) != 0; |
| +} |
| + |
| +// static |
| +bool ModuleHandleTraits::IsHandleValid(HMODULE handle) { |
| + return handle != nullptr; |
| +} |
| + |
| +// static |
| +HMODULE ModuleHandleTraits::NullHandle() { |
| + return nullptr; |
| +} |
| + |
| namespace { |
| // Implements the UnwindFunctions interface for the corresponding Win32 |
| @@ -29,6 +52,9 @@ public: |
| PRUNTIME_FUNCTION runtime_function, |
| CONTEXT* context) override; |
| + ScopedModuleHandle GetModuleForProgramCounter( |
| + DWORD64 program_counter) override; |
| + |
| private: |
| DISALLOW_COPY_AND_ASSIGN(Win32UnwindFunctions); |
| }; |
| @@ -63,6 +89,18 @@ void Win32UnwindFunctions::VirtualUnwind(DWORD64 image_base, |
| #endif |
| } |
| +ScopedModuleHandle Win32UnwindFunctions::GetModuleForProgramCounter( |
| + DWORD64 program_counter) { |
| + HMODULE module_handle = nullptr; |
| + if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, |
| + reinterpret_cast<LPCTSTR>(program_counter), |
| + &module_handle)) { |
| + const DWORD error = ::GetLastError(); |
| + DCHECK_EQ(ERROR_MOD_NOT_FOUND, static_cast<int>(error)); |
| + } |
| + return ScopedModuleHandle(module_handle); |
| +} |
| + |
| // LeafUnwindBlacklist -------------------------------------------------------- |
| // Records modules that are known to have functions that violate the Microsoft |
| @@ -140,10 +178,17 @@ Win32StackFrameUnwinder::Win32StackFrameUnwinder() |
| Win32StackFrameUnwinder::~Win32StackFrameUnwinder() {} |
| -bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context) { |
| +bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context, |
| + ScopedModuleHandle* module) { |
| #ifdef _WIN64 |
| CHECK(!at_top_frame_ || unwind_info_present_for_all_frames_); |
| + ScopedModuleHandle frame_module = |
| + unwind_functions_->GetModuleForProgramCounter(context->Rip); |
| + // The module may have been unloaded since we recorded the stack. |
| + if (!frame_module.IsValid()) |
| + return false; |
|
cpu_(ooo_6.6-7.5)
2015/10/29 21:22:19
we should note that the module at that address cou
Mike Wittman
2015/10/29 23:23:28
Done.
|
| + |
| ULONG64 image_base; |
| // Try to look up unwind metadata for the current function. |
| PRUNTIME_FUNCTION runtime_function = |
| @@ -229,6 +274,7 @@ bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context) { |
| } |
| } |
| + module->Set(frame_module.Take()); |
| return true; |
| #else |
| NOTREACHED(); |