Index: components/browser_watcher/stability_debugging.cc |
diff --git a/components/browser_watcher/stability_debugging.cc b/components/browser_watcher/stability_debugging.cc |
index 3c8cc6492928043dbe0de2306bef4581e992e044..aee484c8506d9497e4819ba2da20f05f5199914a 100644 |
--- a/components/browser_watcher/stability_debugging.cc |
+++ b/components/browser_watcher/stability_debugging.cc |
@@ -4,10 +4,48 @@ |
#include "components/browser_watcher/stability_debugging.h" |
+#include <windows.h> |
+ |
+#include <memory> |
+ |
#include "base/debug/activity_tracker.h" |
+#include "build/build_config.h" |
namespace browser_watcher { |
+namespace { |
+ |
+struct VehUnregisterer { |
+ void operator()(void* handle) const { |
+ ::RemoveVectoredExceptionHandler(handle); |
+ } |
+}; |
+ |
+using VehHandle = std::unique_ptr<void, VehUnregisterer>; |
+ |
+uintptr_t GetProgramCounter(const CONTEXT& context) { |
+#if defined(ARCH_CPU_X86) |
+ return context.Eip; |
+#elif defined(ARCH_CPU_X86_64) |
+ return context.Rip; |
+#endif |
+} |
+ |
+LONG CALLBACK VectoredExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { |
+ base::debug::GlobalActivityTracker* tracker = |
+ base::debug::GlobalActivityTracker::Get(); |
+ if (tracker) { |
+ EXCEPTION_RECORD* record = exception_pointers->ExceptionRecord; |
+ uintptr_t pc = GetProgramCounter(*exception_pointers->ContextRecord); |
+ tracker->RecordException(reinterpret_cast<void*>(pc), |
+ record->ExceptionAddress, record->ExceptionCode); |
+ } |
+ |
+ return EXCEPTION_CONTINUE_SEARCH; // Continue to the next handler. |
+} |
+ |
+} // namespace |
+ |
void SetStabilityDataBool(base::StringPiece name, bool value) { |
base::debug::GlobalActivityTracker* global_tracker = |
base::debug::GlobalActivityTracker::Get(); |
@@ -26,4 +64,16 @@ void SetStabilityDataInt(base::StringPiece name, int64_t value) { |
global_tracker->process_data().SetInt(name, value); |
} |
+void RegisterStabilityVEH() { |
+ // Register a vectored exception handler and request it be first. Note that |
+ // subsequent registrations may also request to be first, in which case this |
+ // one will be bumped. |
+ // TODO(manzagop): Depending on observations, it may be necessary to |
+ // consider refreshing the registration, either periodically or at opportune |
+ // (e.g. risky) times. |
+ static VehHandle veh_handler( |
+ ::AddVectoredExceptionHandler(1, &VectoredExceptionHandler)); |
+ DCHECK(veh_handler); |
+} |
+ |
} // namespace browser_watcher |