| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 
|  | 2 // | 
|  | 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 // you may not use this file except in compliance with the License. | 
|  | 5 // You may obtain a copy of the License at | 
|  | 6 // | 
|  | 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 // | 
|  | 9 // Unless required by applicable law or agreed to in writing, software | 
|  | 10 // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 // See the License for the specific language governing permissions and | 
|  | 13 // limitations under the License. | 
|  | 14 | 
|  | 15 #include "util/mach/exception_types.h" | 
|  | 16 | 
|  | 17 #include <kern/exc_resource.h> | 
|  | 18 #include <signal.h> | 
|  | 19 #include <sys/types.h> | 
|  | 20 #include <unistd.h> | 
|  | 21 | 
|  | 22 #include "base/basictypes.h" | 
|  | 23 #include "base/strings/stringprintf.h" | 
|  | 24 #include "gtest/gtest.h" | 
|  | 25 #include "util/mac/mac_util.h" | 
|  | 26 #include "util/mach/mach_extensions.h" | 
|  | 27 | 
|  | 28 namespace crashpad { | 
|  | 29 namespace test { | 
|  | 30 namespace { | 
|  | 31 | 
|  | 32 TEST(ExceptionTypes, ExcCrashRecoverOriginalException) { | 
|  | 33   struct TestData { | 
|  | 34     mach_exception_code_t code_0; | 
|  | 35     exception_type_t exception; | 
|  | 36     mach_exception_code_t original_code_0; | 
|  | 37     int signal; | 
|  | 38   }; | 
|  | 39   const TestData kTestData[] = { | 
|  | 40       {0xb100001, EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, SIGSEGV}, | 
|  | 41       {0xb100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGSEGV}, | 
|  | 42       {0xa100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGBUS}, | 
|  | 43       {0x4200001, EXC_BAD_INSTRUCTION, 1, SIGILL}, | 
|  | 44       {0x8300001, EXC_ARITHMETIC, 1, SIGFPE}, | 
|  | 45       {0x5600002, EXC_BREAKPOINT, 2, SIGTRAP}, | 
|  | 46       {0x3000000, 0, 0, SIGQUIT}, | 
|  | 47       {0x6000000, 0, 0, SIGABRT}, | 
|  | 48       {0xc000000, 0, 0, SIGSYS}, | 
|  | 49       {0, 0, 0, 0}, | 
|  | 50   }; | 
|  | 51 | 
|  | 52   for (size_t index = 0; index < arraysize(kTestData); ++index) { | 
|  | 53     const TestData& test_data = kTestData[index]; | 
|  | 54     SCOPED_TRACE(base::StringPrintf( | 
|  | 55         "index %zu, code_0 0x%llx", index, test_data.code_0)); | 
|  | 56 | 
|  | 57     mach_exception_code_t original_code_0; | 
|  | 58     int signal; | 
|  | 59     exception_type_t exception = ExcCrashRecoverOriginalException( | 
|  | 60         test_data.code_0, &original_code_0, &signal); | 
|  | 61 | 
|  | 62     EXPECT_EQ(test_data.exception, exception); | 
|  | 63     EXPECT_EQ(test_data.original_code_0, original_code_0); | 
|  | 64     EXPECT_EQ(test_data.signal, signal); | 
|  | 65   } | 
|  | 66 | 
|  | 67   // Now make sure that ExcCrashRecoverOriginalException() properly ignores | 
|  | 68   // optional arguments. | 
|  | 69   static_assert(arraysize(kTestData) >= 1, "must have something to test"); | 
|  | 70   const TestData& test_data = kTestData[0]; | 
|  | 71   EXPECT_EQ( | 
|  | 72       test_data.exception, | 
|  | 73       ExcCrashRecoverOriginalException(test_data.code_0, nullptr, nullptr)); | 
|  | 74 | 
|  | 75   mach_exception_code_t original_code_0; | 
|  | 76   EXPECT_EQ(test_data.exception, | 
|  | 77             ExcCrashRecoverOriginalException( | 
|  | 78                 test_data.code_0, &original_code_0, nullptr)); | 
|  | 79   EXPECT_EQ(test_data.original_code_0, original_code_0); | 
|  | 80 | 
|  | 81   int signal; | 
|  | 82   EXPECT_EQ( | 
|  | 83       test_data.exception, | 
|  | 84       ExcCrashRecoverOriginalException(test_data.code_0, nullptr, &signal)); | 
|  | 85   EXPECT_EQ(test_data.signal, signal); | 
|  | 86 } | 
|  | 87 | 
|  | 88 // These macros come from the #ifdef KERNEL section of <kern/exc_resource.h>: | 
|  | 89 // 10.10 xnu-2782.1.97/osfmk/kern/exc_resource.h. | 
|  | 90 #define EXC_RESOURCE_ENCODE_TYPE(code, type) \ | 
|  | 91   ((code) |= ((static_cast<uint64_t>(type) & 0x7ull) << 61)) | 
|  | 92 #define EXC_RESOURCE_ENCODE_FLAVOR(code, flavor) \ | 
|  | 93   ((code) |= ((static_cast<uint64_t>(flavor) & 0x7ull) << 58)) | 
|  | 94 | 
|  | 95 TEST(ExceptionTypes, IsExceptionNonfatalResource) { | 
|  | 96   const pid_t pid = getpid(); | 
|  | 97 | 
|  | 98   mach_exception_code_t code = 0; | 
|  | 99   EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_CPU); | 
|  | 100   EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_CPU_MONITOR); | 
|  | 101   EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); | 
|  | 102 | 
|  | 103   if (MacOSXMinorVersion() >= 10) { | 
|  | 104     // FLAVOR_CPU_MONITOR_FATAL was introduced in Mac OS X 10.10. | 
|  | 105     code = 0; | 
|  | 106     EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_CPU); | 
|  | 107     EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_CPU_MONITOR_FATAL); | 
|  | 108     EXPECT_FALSE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); | 
|  | 109   } | 
|  | 110 | 
|  | 111   // This assumes that WAKEMON_MAKE_FATAL is not set for this process. The | 
|  | 112   // default is for WAKEMON_MAKE_FATAL to not be set, there’s no public API to | 
|  | 113   // enable it, and nothing in this process should have enabled it. | 
|  | 114   code = 0; | 
|  | 115   EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_WAKEUPS); | 
|  | 116   EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_WAKEUPS_MONITOR); | 
|  | 117   EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); | 
|  | 118 | 
|  | 119   code = 0; | 
|  | 120   EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_MEMORY); | 
|  | 121   EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_HIGH_WATERMARK); | 
|  | 122   EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); | 
|  | 123 | 
|  | 124   // Non-EXC_RESOURCE exceptions should never be considered nonfatal resource | 
|  | 125   // exceptions, because they aren’t resource exceptions at all. | 
|  | 126   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_CRASH, 0xb100001, pid)); | 
|  | 127   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_CRASH, 0x0b00000, pid)); | 
|  | 128   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_CRASH, 0x6000000, pid)); | 
|  | 129   EXPECT_FALSE( | 
|  | 130       IsExceptionNonfatalResource(EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, pid)); | 
|  | 131   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_BAD_INSTRUCTION, 1, pid)); | 
|  | 132   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_ARITHMETIC, 1, pid)); | 
|  | 133   EXPECT_FALSE(IsExceptionNonfatalResource(EXC_BREAKPOINT, 2, pid)); | 
|  | 134   EXPECT_FALSE(IsExceptionNonfatalResource(0, 0, pid)); | 
|  | 135   EXPECT_FALSE(IsExceptionNonfatalResource(kMachExceptionSimulated, 0, pid)); | 
|  | 136 } | 
|  | 137 | 
|  | 138 }  // namespace | 
|  | 139 }  // namespace test | 
|  | 140 }  // namespace crashpad | 
| OLD | NEW | 
|---|