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 |