1 // Copyright (c) 2010 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 #include <atlbase.h> 6 #include "chrome_frame/crash_reporting/veh_test.h" 7 #include "testing/gmock/include/gmock/gmock.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 #include "chrome_frame/crash_reporting/vectored_handler-impl.h" 10 11 #pragma code_seg(push, ".m$_0") 12 static void ModuleStart() {} 13 #pragma code_seg(pop) 14 15 #pragma code_seg(push, ".m$_2") 16 DECLSPEC_NOINLINE static void Undetectable(DWORD code) { 17 __try { 18 ::RaiseException(code, 0, 0, NULL); 19 } __except(EXCEPTION_EXECUTE_HANDLER) { 20 21 } 22 }; 23 #pragma code_seg(pop) 24 25 #pragma code_seg(push, ".m$_3") 26 static void UndetectableEnd() {} 27 #pragma code_seg(pop) 28 29 #pragma code_seg(push, ".m$_4") 30 DECLSPEC_NOINLINE static void CatchThis() { 31 __try { 32 ::RaiseException(STATUS_ACCESS_VIOLATION, 0, 0, NULL); 33 } __except(EXCEPTION_EXECUTE_HANDLER) { 34 35 } 36 37 // this will be detected since we are on the stack! 38 Undetectable(STATUS_ILLEGAL_INSTRUCTION); 39 } 40 #pragma code_seg(pop) 41 42 #pragma code_seg(push, ".m$_9") 43 static void ModuleEnd() {} 44 #pragma code_seg(pop) 45 46 using testing::_; 47 namespace { 48 MATCHER_P(ExceptionCodeIs, code, "") { 49 return (arg->ExceptionRecord->ExceptionCode == code); 50 } 51 52 class MockApi : public Win32VEHTraits, 53 public ModuleOfInterestWithExcludedRegion { 54 public: 55 MockApi() { 56 ModuleOfInterestWithExcludedRegion::SetModule(&ModuleStart, &ModuleEnd); 57 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&Undetectable, 58 &UndetectableEnd); 59 } 60 61 MOCK_METHOD1(WriteDump, void(const EXCEPTION_POINTERS*)); 62 MOCK_METHOD0(RtlpGetExceptionList, const EXCEPTION_REGISTRATION_RECORD*()); 63 }; 64 }; // namespace 65 66 typedef VectoredHandlerT<MockApi> VectoredHandlerMock; 67 68 #pragma optimize("y", off) 69 static VectoredHandlerMock* g_mock_veh = NULL; 70 static LONG WINAPI VEH(EXCEPTION_POINTERS* exptrs) { 71 return g_mock_veh->Handler(exptrs); 72 } 73 #pragma optimize("y", on) 74 75 TEST(ChromeFrame, ExceptionExcludedCode) { 76 MockApi api; 77 VectoredHandlerMock veh(&api); 78 79 g_mock_veh = &veh; 80 void* id = ::AddVectoredExceptionHandler(FALSE, VEH); 81 82 EXPECT_CALL(api, RtlpGetExceptionList()) 83 .WillRepeatedly(testing::Return(EXCEPTION_CHAIN_END)); 84 85 testing::Sequence s; 86 87 EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ACCESS_VIOLATION))) 88 .Times(1); 89 90 EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ILLEGAL_INSTRUCTION))) 91 .Times(1); 92 93 CatchThis(); 94 EXPECT_EQ(2, veh.get_exceptions_seen()); 95 96 // Not detected since we are not on the stack. 97 Undetectable(STATUS_INTEGER_DIVIDE_BY_ZERO); 98 EXPECT_EQ(3, veh.get_exceptions_seen()); 99 100 ::RemoveVectoredExceptionHandler(id); 101 g_mock_veh = NULL; 102 } 103