| 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, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 #include "util/mach/exc_server_variants.h" | 40 #include "util/mach/exc_server_variants.h" |
| 41 #include "util/mach/exception_ports.h" | 41 #include "util/mach/exception_ports.h" |
| 42 #include "util/mach/mach_extensions.h" | 42 #include "util/mach/mach_extensions.h" |
| 43 #include "util/mach/mach_message.h" | 43 #include "util/mach/mach_message.h" |
| 44 #include "util/mach/mach_message_server.h" | 44 #include "util/mach/mach_message_server.h" |
| 45 | 45 |
| 46 namespace crashpad { | 46 namespace crashpad { |
| 47 namespace test { | 47 namespace test { |
| 48 namespace { | 48 namespace { |
| 49 | 49 |
| 50 // \return The path to crashpad_snapshot_test_module_crashy_initializer.so |
| 51 std::string ModuleWithCrashyInitializer() { |
| 52 return Paths::Executable().value() + "_module_crashy_initializer.so"; |
| 53 } |
| 54 |
| 50 //! \return The path to the crashpad_snapshot_test_no_op executable. | 55 //! \return The path to the crashpad_snapshot_test_no_op executable. |
| 51 base::FilePath NoOpExecutable() { | 56 base::FilePath NoOpExecutable() { |
| 52 return base::FilePath(Paths::Executable().value() + "_no_op"); | 57 return base::FilePath(Paths::Executable().value() + "_no_op"); |
| 53 } | 58 } |
| 54 | 59 |
| 55 class TestMachOImageAnnotationsReader final | 60 class TestMachOImageAnnotationsReader final |
| 56 : public MachMultiprocess, | 61 : public MachMultiprocess, |
| 57 public UniversalMachExcServer::Interface { | 62 public UniversalMachExcServer::Interface { |
| 58 public: | 63 public: |
| 59 enum TestType { | 64 enum TestType { |
| 60 // Don’t crash, just test the CrashpadInfo interface. | 65 // Don’t crash, just test the CrashpadInfo interface. |
| 61 kDontCrash = 0, | 66 kDontCrash = 0, |
| 62 | 67 |
| 63 // The child process should crash by calling abort(). The parent verifies | 68 // The child process should crash by calling abort(). The parent verifies |
| 64 // that the system libraries set the expected annotations. | 69 // that the system libraries set the expected annotations. |
| 70 // |
| 71 // This test verifies that the message field in crashreporter_annotations_t |
| 72 // can be recovered. Either 10.10.2 Libc-1044.1.2/stdlib/FreeBSD/abort.c |
| 73 // abort() or 10.10.2 Libc-1044.10.1/sys/_libc_fork_child.c |
| 74 // _libc_fork_child() calls CRSetCrashLogMessage() to set the message field. |
| 65 kCrashAbort, | 75 kCrashAbort, |
| 66 | 76 |
| 77 // The child process should crash at module initialization time, when dyld |
| 78 // will have set an annotation matching the path of the module being |
| 79 // initialized. |
| 80 // |
| 81 // This test exists to verify that the message2 field in |
| 82 // crashreporter_annotations_t can be recovered. 10.10.2 |
| 83 // dyld-353.2.1/src/ImageLoaderMachO.cpp |
| 84 // ImageLoaderMachO::doInitialization() calls CRSetCrashLogMessage2() to set |
| 85 // the message2 field. |
| 86 kCrashModuleInitialization, |
| 87 |
| 67 // The child process should crash by setting DYLD_INSERT_LIBRARIES to | 88 // The child process should crash by setting DYLD_INSERT_LIBRARIES to |
| 68 // contain a nonexistent library. The parent verifies that dyld sets the | 89 // contain a nonexistent library. The parent verifies that dyld sets the |
| 69 // expected annotations. | 90 // expected annotations. |
| 70 kCrashDyld, | 91 kCrashDyld, |
| 71 }; | 92 }; |
| 72 | 93 |
| 73 explicit TestMachOImageAnnotationsReader(TestType test_type) | 94 explicit TestMachOImageAnnotationsReader(TestType test_type) |
| 74 : MachMultiprocess(), | 95 : MachMultiprocess(), |
| 75 UniversalMachExcServer::Interface(), | 96 UniversalMachExcServer::Interface(), |
| 76 test_type_(test_type) { | 97 test_type_(test_type) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 } | 140 } |
| 120 } | 141 } |
| 121 | 142 |
| 122 // Mac OS X 10.6 doesn’t have support for CrashReporter annotations | 143 // Mac OS X 10.6 doesn’t have support for CrashReporter annotations |
| 123 // (CrashReporterClient.h), so don’t look for any special annotations in | 144 // (CrashReporterClient.h), so don’t look for any special annotations in |
| 124 // that version. | 145 // that version. |
| 125 int mac_os_x_minor_version = MacOSXMinorVersion(); | 146 int mac_os_x_minor_version = MacOSXMinorVersion(); |
| 126 if (mac_os_x_minor_version > 7) { | 147 if (mac_os_x_minor_version > 7) { |
| 127 EXPECT_GE(all_annotations_vector.size(), 1u); | 148 EXPECT_GE(all_annotations_vector.size(), 1u); |
| 128 | 149 |
| 129 const char* expected_annotation = nullptr; | 150 std::string expected_annotation; |
| 130 switch (test_type_) { | 151 switch (test_type_) { |
| 131 case kCrashAbort: | 152 case kCrashAbort: |
| 132 // The child process calls abort(), so the expected annotation | 153 // The child process calls abort(), so the expected annotation |
| 133 // reflects this, with a string set by 10.7.5 | 154 // reflects this, with a string set by 10.7.5 |
| 134 // Libc-763.13/stdlib/abort-fbsd.c abort(). This string is still | 155 // Libc-763.13/stdlib/abort-fbsd.c abort(). This string is still |
| 135 // present in 10.9.5 Libc-997.90.3/stdlib/FreeBSD/abort.c abort(), | 156 // present in 10.9.5 Libc-997.90.3/stdlib/FreeBSD/abort.c abort(), |
| 136 // but because abort() tests to see if a message is already set and | 157 // but because abort() tests to see if a message is already set and |
| 137 // something else in Libc will have set a message, this string is | 158 // something else in Libc will have set a message, this string is |
| 138 // not the expectation on 10.9 or higher. Instead, after fork(), the | 159 // not the expectation on 10.9 or higher. Instead, after fork(), the |
| 139 // child process has a message indicating that a fork() without | 160 // child process has a message indicating that a fork() without |
| 140 // exec() occurred. See 10.9.5 Libc-997.90.3/sys/_libc_fork_child.c | 161 // exec() occurred. See 10.9.5 Libc-997.90.3/sys/_libc_fork_child.c |
| 141 // _libc_fork_child(). | 162 // _libc_fork_child(). |
| 142 expected_annotation = | 163 expected_annotation = |
| 143 mac_os_x_minor_version <= 8 | 164 mac_os_x_minor_version <= 8 |
| 144 ? "abort() called" | 165 ? "abort() called" |
| 145 : "crashed on child side of fork pre-exec"; | 166 : "crashed on child side of fork pre-exec"; |
| 146 break; | 167 break; |
| 147 | 168 |
| 169 case kCrashModuleInitialization: |
| 170 // This message is set by dyld-353.2.1/src/ImageLoaderMachO.cpp |
| 171 // ImageLoaderMachO::doInitialization(). |
| 172 expected_annotation = ModuleWithCrashyInitializer(); |
| 173 break; |
| 174 |
| 148 case kCrashDyld: | 175 case kCrashDyld: |
| 149 // This is independent of dyld’s error_string, which is tested | 176 // This is independent of dyld’s error_string, which is tested |
| 150 // below. | 177 // below. |
| 151 expected_annotation = "dyld: launch, loading dependent libraries"; | 178 expected_annotation = "dyld: launch, loading dependent libraries"; |
| 152 break; | 179 break; |
| 153 | 180 |
| 154 default: | 181 default: |
| 155 ADD_FAILURE(); | 182 ADD_FAILURE(); |
| 156 break; | 183 break; |
| 157 } | 184 } |
| 158 | 185 |
| 159 size_t expected_annotation_length = strlen(expected_annotation); | |
| 160 bool found = false; | 186 bool found = false; |
| 161 for (const std::string& annotation : all_annotations_vector) { | 187 for (const std::string& annotation : all_annotations_vector) { |
| 162 // Look for the expectation as a leading susbtring, because the actual | 188 // Look for the expectation as a leading susbtring, because the actual |
| 163 // string that dyld uses will have the contents of the | 189 // string that dyld uses will have the contents of the |
| 164 // DYLD_INSERT_LIBRARIES environment variable appended to it on Mac | 190 // DYLD_INSERT_LIBRARIES environment variable appended to it on Mac |
| 165 // OS X 10.10. | 191 // OS X 10.10. |
| 166 if (annotation.substr(0, expected_annotation_length) == | 192 if (annotation.substr(0, expected_annotation.length()) == |
| 167 expected_annotation) { | 193 expected_annotation) { |
| 168 found = true; | 194 found = true; |
| 169 break; | 195 break; |
| 170 } | 196 } |
| 171 } | 197 } |
| 172 EXPECT_TRUE(found); | 198 EXPECT_TRUE(found) << expected_annotation; |
| 173 } | 199 } |
| 174 | 200 |
| 175 // dyld exposes its error_string at least as far back as Mac OS X 10.4. | 201 // dyld exposes its error_string at least as far back as Mac OS X 10.4. |
| 176 if (test_type_ == kCrashDyld) { | 202 if (test_type_ == kCrashDyld) { |
| 177 const char kExpectedAnnotation[] = "could not load inserted library"; | 203 const char kExpectedAnnotation[] = "could not load inserted library"; |
| 178 size_t expected_annotation_length = strlen(kExpectedAnnotation); | 204 size_t expected_annotation_length = strlen(kExpectedAnnotation); |
| 179 bool found = false; | 205 bool found = false; |
| 180 for (const std::string& annotation : all_annotations_vector) { | 206 for (const std::string& annotation : all_annotations_vector) { |
| 181 // Look for the expectation as a leading substring, because the actual | 207 // Look for the expectation as a leading substring, because the actual |
| 182 // string will contain the library’s pathname and, on Mac OS X 10.9 | 208 // string will contain the library’s pathname and, on Mac OS X 10.9 |
| 183 // and later, a reason. | 209 // and later, a reason. |
| 184 if (annotation.substr(0, expected_annotation_length) == | 210 if (annotation.substr(0, expected_annotation_length) == |
| 185 kExpectedAnnotation) { | 211 kExpectedAnnotation) { |
| 186 found = true; | 212 found = true; |
| 187 break; | 213 break; |
| 188 } | 214 } |
| 189 } | 215 } |
| 190 | 216 |
| 191 EXPECT_TRUE(found); | 217 EXPECT_TRUE(found) << kExpectedAnnotation; |
| 192 } | 218 } |
| 193 } | 219 } |
| 194 | 220 |
| 195 return ExcServerSuccessfulReturnValue(behavior, false); | 221 return ExcServerSuccessfulReturnValue(behavior, false); |
| 196 } | 222 } |
| 197 | 223 |
| 198 private: | 224 private: |
| 199 // MachMultiprocess: | 225 // MachMultiprocess: |
| 200 | 226 |
| 201 void MachMultiprocessParent() override { | 227 void MachMultiprocessParent() override { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 MachMessageServer::kReceiveLargeError, | 269 MachMessageServer::kReceiveLargeError, |
| 244 kMachMessageTimeoutWaitIndefinitely); | 270 kMachMessageTimeoutWaitIndefinitely); |
| 245 EXPECT_EQ(MACH_MSG_SUCCESS, mr) | 271 EXPECT_EQ(MACH_MSG_SUCCESS, mr) |
| 246 << MachErrorMessage(mr, "MachMessageServer::Run"); | 272 << MachErrorMessage(mr, "MachMessageServer::Run"); |
| 247 | 273 |
| 248 switch (test_type_) { | 274 switch (test_type_) { |
| 249 case kCrashAbort: | 275 case kCrashAbort: |
| 250 SetExpectedChildTermination(kTerminationSignal, SIGABRT); | 276 SetExpectedChildTermination(kTerminationSignal, SIGABRT); |
| 251 break; | 277 break; |
| 252 | 278 |
| 279 case kCrashModuleInitialization: |
| 280 // This crash is triggered by __builtin_trap(), which shows up as |
| 281 // SIGILL. |
| 282 SetExpectedChildTermination(kTerminationSignal, SIGILL); |
| 283 break; |
| 284 |
| 253 case kCrashDyld: | 285 case kCrashDyld: |
| 254 // dyld fatal errors result in the execution of an int3 instruction on | 286 // dyld fatal errors result in the execution of an int3 instruction on |
| 255 // x86 and a trap instruction on ARM, both of which raise SIGTRAP. | 287 // x86 and a trap instruction on ARM, both of which raise SIGTRAP. |
| 256 // 10.9.5 dyld-239.4/src/dyldStartup.s _dyld_fatal_error. | 288 // 10.9.5 dyld-239.4/src/dyldStartup.s _dyld_fatal_error. |
| 257 SetExpectedChildTermination(kTerminationSignal, SIGTRAP); | 289 SetExpectedChildTermination(kTerminationSignal, SIGTRAP); |
| 258 break; | 290 break; |
| 259 | 291 |
| 260 default: | 292 default: |
| 261 FAIL(); | 293 FAIL(); |
| 262 break; | 294 break; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 286 CheckedReadFile(ReadPipeHandle(), &c, sizeof(c)); | 318 CheckedReadFile(ReadPipeHandle(), &c, sizeof(c)); |
| 287 | 319 |
| 288 // Direct an exception message to the exception server running in the | 320 // Direct an exception message to the exception server running in the |
| 289 // parent. | 321 // parent. |
| 290 ExceptionPorts exception_ports(ExceptionPorts::kTargetTypeTask, | 322 ExceptionPorts exception_ports(ExceptionPorts::kTargetTypeTask, |
| 291 mach_task_self()); | 323 mach_task_self()); |
| 292 ASSERT_TRUE(exception_ports.SetExceptionPort( | 324 ASSERT_TRUE(exception_ports.SetExceptionPort( |
| 293 EXC_MASK_CRASH, RemotePort(), EXCEPTION_DEFAULT, THREAD_STATE_NONE)); | 325 EXC_MASK_CRASH, RemotePort(), EXCEPTION_DEFAULT, THREAD_STATE_NONE)); |
| 294 | 326 |
| 295 switch (test_type_) { | 327 switch (test_type_) { |
| 296 case kDontCrash: | 328 case kDontCrash: { |
| 297 break; | 329 break; |
| 330 } |
| 298 | 331 |
| 299 case kCrashAbort: | 332 case kCrashAbort: { |
| 300 abort(); | 333 abort(); |
| 301 break; | 334 break; |
| 335 } |
| 336 |
| 337 case kCrashModuleInitialization: { |
| 338 // Load a module that crashes while executing a module initializer. |
| 339 void* dl_handle = dlopen(ModuleWithCrashyInitializer().c_str(), |
| 340 RTLD_LAZY | RTLD_LOCAL); |
| 341 |
| 342 // This should have crashed in the dlopen(). If dlopen() failed, the |
| 343 // ASSERT_NE() will show the message. If it succeeded without crashing, |
| 344 // the FAIL() will fail the test. |
| 345 ASSERT_NE(nullptr, dl_handle) << dlerror(); |
| 346 FAIL(); |
| 347 break; |
| 348 } |
| 302 | 349 |
| 303 case kCrashDyld: { | 350 case kCrashDyld: { |
| 304 // Set DYLD_INSERT_LIBRARIES to contain a library that does not exist. | 351 // Set DYLD_INSERT_LIBRARIES to contain a library that does not exist. |
| 305 // Unable to load it, dyld will abort with a fatal error. | 352 // Unable to load it, dyld will abort with a fatal error. |
| 306 ASSERT_EQ( | 353 ASSERT_EQ( |
| 307 0, | 354 0, |
| 308 setenv( | 355 setenv( |
| 309 "DYLD_INSERT_LIBRARIES", "/var/empty/NoDirectory/NoLibrary", 1)) | 356 "DYLD_INSERT_LIBRARIES", "/var/empty/NoDirectory/NoLibrary", 1)) |
| 310 << ErrnoMessage("setenv"); | 357 << ErrnoMessage("setenv"); |
| 311 | 358 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 338 TestMachOImageAnnotationsReader::kDontCrash); | 385 TestMachOImageAnnotationsReader::kDontCrash); |
| 339 test_mach_o_image_annotations_reader.Run(); | 386 test_mach_o_image_annotations_reader.Run(); |
| 340 } | 387 } |
| 341 | 388 |
| 342 TEST(MachOImageAnnotationsReader, CrashAbort) { | 389 TEST(MachOImageAnnotationsReader, CrashAbort) { |
| 343 TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( | 390 TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( |
| 344 TestMachOImageAnnotationsReader::kCrashAbort); | 391 TestMachOImageAnnotationsReader::kCrashAbort); |
| 345 test_mach_o_image_annotations_reader.Run(); | 392 test_mach_o_image_annotations_reader.Run(); |
| 346 } | 393 } |
| 347 | 394 |
| 395 TEST(MachOImageAnnotationsReader, CrashModuleInitialization) { |
| 396 TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( |
| 397 TestMachOImageAnnotationsReader::kCrashModuleInitialization); |
| 398 test_mach_o_image_annotations_reader.Run(); |
| 399 } |
| 400 |
| 348 TEST(MachOImageAnnotationsReader, CrashDyld) { | 401 TEST(MachOImageAnnotationsReader, CrashDyld) { |
| 349 TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( | 402 TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( |
| 350 TestMachOImageAnnotationsReader::kCrashDyld); | 403 TestMachOImageAnnotationsReader::kCrashDyld); |
| 351 test_mach_o_image_annotations_reader.Run(); | 404 test_mach_o_image_annotations_reader.Run(); |
| 352 } | 405 } |
| 353 | 406 |
| 354 } // namespace | 407 } // namespace |
| 355 } // namespace test | 408 } // namespace test |
| 356 } // namespace crashpad | 409 } // namespace crashpad |
| OLD | NEW |