OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "util/mach/exc_server_variants.h" | 15 #include "util/mach/exc_server_variants.h" |
16 | 16 |
17 #include <mach/mach.h> | 17 #include <mach/mach.h> |
| 18 #include <signal.h> |
18 #include <string.h> | 19 #include <string.h> |
19 | 20 |
20 #include "base/basictypes.h" | 21 #include "base/basictypes.h" |
21 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
22 #include "gmock/gmock.h" | 23 #include "gmock/gmock.h" |
23 #include "gtest/gtest.h" | 24 #include "gtest/gtest.h" |
24 #include "util/mach/exception_behaviors.h" | 25 #include "util/mach/exception_behaviors.h" |
25 #include "util/mach/mach_extensions.h" | 26 #include "util/mach/mach_extensions.h" |
26 #include "util/test/mac/mach_errors.h" | 27 #include "util/test/mac/mach_errors.h" |
27 #include "util/test/mac/mach_multiprocess.h" | 28 #include "util/test/mac/mach_multiprocess.h" |
(...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 EXPECT_NE(kMachPortNull, thread); | 898 EXPECT_NE(kMachPortNull, thread); |
898 EXPECT_EQ(ChildTask(), task); | 899 EXPECT_EQ(ChildTask(), task); |
899 } else { | 900 } else { |
900 EXPECT_EQ(kMachPortNull, thread); | 901 EXPECT_EQ(kMachPortNull, thread); |
901 EXPECT_EQ(kMachPortNull, task); | 902 EXPECT_EQ(kMachPortNull, task); |
902 } | 903 } |
903 | 904 |
904 EXPECT_EQ(EXC_CRASH, exception); | 905 EXPECT_EQ(EXC_CRASH, exception); |
905 EXPECT_EQ(2u, code_count); | 906 EXPECT_EQ(2u, code_count); |
906 | 907 |
907 // The code_count check above would ideally use ASSERT_EQ so that the next | 908 // The exception and code_count checks above would ideally use ASSERT_EQ so |
908 // conditional would not be necessary, but ASSERT_* requires a function | 909 // that the next conditional would not be necessary, but ASSERT_* requires a |
909 // returning type void, and the interface dictates otherwise here. | 910 // function returning type void, and the interface dictates otherwise here. |
910 if (code_count >= 1) { | 911 if (exception == EXC_CRASH && code_count >= 1) { |
911 // The signal that terminated the process is stored in code[0] along with | 912 int signal; |
912 // some other data. See 10.9.4 xnu-2422.110.17/bsd/kern/kern_exit.c | 913 ExcCrashRecoverOriginalException(code[0], NULL, &signal); |
913 // proc_prepareexit(). | 914 SetExpectedChildTermination(kTerminationSignal, signal); |
914 int sig = (code[0] >> 24) & 0xff; | |
915 SetExpectedChildTermination(kTerminationSignal, sig); | |
916 } | 915 } |
917 | 916 |
918 const bool has_state = ExceptionBehaviorHasState(behavior); | 917 const bool has_state = ExceptionBehaviorHasState(behavior); |
919 if (has_state) { | 918 if (has_state) { |
920 EXPECT_EQ(flavor_, *flavor); | 919 EXPECT_EQ(flavor_, *flavor); |
921 EXPECT_EQ(state_count_, old_state_count); | 920 EXPECT_EQ(state_count_, old_state_count); |
922 EXPECT_NE(static_cast<const natural_t*>(NULL), old_state); | 921 EXPECT_NE(static_cast<const natural_t*>(NULL), old_state); |
923 EXPECT_EQ(static_cast<mach_msg_type_number_t>(THREAD_STATE_MAX), | 922 EXPECT_EQ(static_cast<mach_msg_type_number_t>(THREAD_STATE_MAX), |
924 *new_state_count); | 923 *new_state_count); |
925 EXPECT_NE(static_cast<natural_t*>(NULL), new_state); | 924 EXPECT_NE(static_cast<natural_t*>(NULL), new_state); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 base::StringPrintf("index %zu, flavor %d", index, test.flavor)); | 1067 base::StringPrintf("index %zu, flavor %d", index, test.flavor)); |
1069 | 1068 |
1070 TestExcServerVariants test_exc_server_variants( | 1069 TestExcServerVariants test_exc_server_variants( |
1071 MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY, | 1070 MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY, |
1072 test.flavor, | 1071 test.flavor, |
1073 test.count); | 1072 test.count); |
1074 test_exc_server_variants.Run(); | 1073 test_exc_server_variants.Run(); |
1075 } | 1074 } |
1076 } | 1075 } |
1077 | 1076 |
| 1077 TEST(ExcServerVariants, ExcCrashRecoverOriginalException) { |
| 1078 struct TestData { |
| 1079 mach_exception_data_type_t code_0; |
| 1080 exception_type_t exception; |
| 1081 mach_exception_data_type_t original_code_0; |
| 1082 int signal; |
| 1083 }; |
| 1084 const TestData kTestData[] = { |
| 1085 {0xb100001, EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, SIGSEGV}, |
| 1086 {0xb100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGSEGV}, |
| 1087 {0xa100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGBUS}, |
| 1088 {0x4200001, EXC_BAD_INSTRUCTION, 1, SIGILL}, |
| 1089 {0x8300001, EXC_ARITHMETIC, 1, SIGFPE}, |
| 1090 {0x5600002, EXC_BREAKPOINT, 2, SIGTRAP}, |
| 1091 {0x6000000, 0, 0, SIGABRT}, |
| 1092 {0, 0, 0, 0}, |
| 1093 }; |
| 1094 |
| 1095 for (size_t index = 0; index < arraysize(kTestData); ++index) { |
| 1096 const TestData& test_data = kTestData[index]; |
| 1097 SCOPED_TRACE(base::StringPrintf("index %zu, code_0 0x%llx", |
| 1098 index, |
| 1099 test_data.code_0)); |
| 1100 |
| 1101 mach_exception_data_type_t original_code_0; |
| 1102 int signal; |
| 1103 exception_type_t exception = |
| 1104 ExcCrashRecoverOriginalException(test_data.code_0, |
| 1105 &original_code_0, |
| 1106 &signal); |
| 1107 |
| 1108 EXPECT_EQ(test_data.exception, exception); |
| 1109 EXPECT_EQ(test_data.original_code_0, original_code_0); |
| 1110 EXPECT_EQ(test_data.signal, signal); |
| 1111 } |
| 1112 |
| 1113 // Now make sure that ExcCrashRecoverOriginalException() properly ignores |
| 1114 // optional arguments. |
| 1115 COMPILE_ASSERT(arraysize(kTestData) >= 1, must_have_something_to_test); |
| 1116 const TestData& test_data = kTestData[0]; |
| 1117 EXPECT_EQ(test_data.exception, |
| 1118 ExcCrashRecoverOriginalException(test_data.code_0, NULL, NULL)); |
| 1119 |
| 1120 mach_exception_data_type_t original_code_0; |
| 1121 EXPECT_EQ(test_data.exception, |
| 1122 ExcCrashRecoverOriginalException( |
| 1123 test_data.code_0, &original_code_0, NULL)); |
| 1124 EXPECT_EQ(test_data.original_code_0, original_code_0); |
| 1125 |
| 1126 int signal; |
| 1127 EXPECT_EQ(test_data.exception, |
| 1128 ExcCrashRecoverOriginalException(test_data.code_0, NULL, &signal)); |
| 1129 EXPECT_EQ(test_data.signal, signal); |
| 1130 } |
| 1131 |
1078 TEST(ExcServerVariants, ExcServerSuccessfulReturnValue) { | 1132 TEST(ExcServerVariants, ExcServerSuccessfulReturnValue) { |
1079 struct TestData { | 1133 struct TestData { |
1080 exception_behavior_t behavior; | 1134 exception_behavior_t behavior; |
1081 bool set_thread_state; | 1135 bool set_thread_state; |
1082 kern_return_t kr; | 1136 kern_return_t kr; |
1083 }; | 1137 }; |
1084 const TestData kTestData[] = { | 1138 const TestData kTestData[] = { |
1085 {EXCEPTION_DEFAULT, false, KERN_SUCCESS}, | 1139 {EXCEPTION_DEFAULT, false, KERN_SUCCESS}, |
1086 {EXCEPTION_STATE, false, MACH_RCV_PORT_DIED}, | 1140 {EXCEPTION_STATE, false, MACH_RCV_PORT_DIED}, |
1087 {EXCEPTION_STATE_IDENTITY, false, MACH_RCV_PORT_DIED}, | 1141 {EXCEPTION_STATE_IDENTITY, false, MACH_RCV_PORT_DIED}, |
(...skipping 18 matching lines...) Expand all Loading... |
1106 test_data.behavior, | 1160 test_data.behavior, |
1107 test_data.set_thread_state ? "true" : "false")); | 1161 test_data.set_thread_state ? "true" : "false")); |
1108 | 1162 |
1109 EXPECT_EQ(test_data.kr, | 1163 EXPECT_EQ(test_data.kr, |
1110 ExcServerSuccessfulReturnValue(test_data.behavior, | 1164 ExcServerSuccessfulReturnValue(test_data.behavior, |
1111 test_data.set_thread_state)); | 1165 test_data.set_thread_state)); |
1112 } | 1166 } |
1113 } | 1167 } |
1114 | 1168 |
1115 } // namespace | 1169 } // namespace |
OLD | NEW |