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 |