Index: snapshot/mac/mach_o_image_annotations_reader_test.cc |
diff --git a/snapshot/mac/mach_o_image_annotations_reader_test.cc b/snapshot/mac/mach_o_image_annotations_reader_test.cc |
index 12dc6e510a8ecc3a88d444feccca05c2ce159ad9..6609b059672b908a1220b98edf13fcff9b76b2f5 100644 |
--- a/snapshot/mac/mach_o_image_annotations_reader_test.cc |
+++ b/snapshot/mac/mach_o_image_annotations_reader_test.cc |
@@ -47,6 +47,11 @@ namespace crashpad { |
namespace test { |
namespace { |
+// \return The path to crashpad_snapshot_test_module_crashy_initializer.so |
+std::string ModuleWithCrashyInitializer() { |
+ return Paths::Executable().value() + "_module_crashy_initializer.so"; |
+} |
+ |
//! \return The path to the crashpad_snapshot_test_no_op executable. |
base::FilePath NoOpExecutable() { |
return base::FilePath(Paths::Executable().value() + "_no_op"); |
@@ -62,8 +67,24 @@ class TestMachOImageAnnotationsReader final |
// The child process should crash by calling abort(). The parent verifies |
// that the system libraries set the expected annotations. |
+ // |
+ // This test verifies that the message field in crashreporter_annotations_t |
+ // can be recovered. Either 10.10.2 Libc-1044.1.2/stdlib/FreeBSD/abort.c |
+ // abort() or 10.10.2 Libc-1044.10.1/sys/_libc_fork_child.c |
+ // _libc_fork_child() calls CRSetCrashLogMessage() to set the message field. |
kCrashAbort, |
+ // The child process should crash at module initialization time, when dyld |
+ // will have set an annotation matching the path of the module being |
+ // initialized. |
+ // |
+ // This test exists to verify that the message2 field in |
+ // crashreporter_annotations_t can be recovered. 10.10.2 |
+ // dyld-353.2.1/src/ImageLoaderMachO.cpp |
+ // ImageLoaderMachO::doInitialization() calls CRSetCrashLogMessage2() to set |
+ // the message2 field. |
+ kCrashModuleInitialization, |
+ |
// The child process should crash by setting DYLD_INSERT_LIBRARIES to |
// contain a nonexistent library. The parent verifies that dyld sets the |
// expected annotations. |
@@ -126,7 +147,7 @@ class TestMachOImageAnnotationsReader final |
if (mac_os_x_minor_version > 7) { |
EXPECT_GE(all_annotations_vector.size(), 1u); |
- const char* expected_annotation = nullptr; |
+ std::string expected_annotation; |
switch (test_type_) { |
case kCrashAbort: |
// The child process calls abort(), so the expected annotation |
@@ -145,6 +166,12 @@ class TestMachOImageAnnotationsReader final |
: "crashed on child side of fork pre-exec"; |
break; |
+ case kCrashModuleInitialization: |
+ // This message is set by dyld-353.2.1/src/ImageLoaderMachO.cpp |
+ // ImageLoaderMachO::doInitialization(). |
+ expected_annotation = ModuleWithCrashyInitializer(); |
+ break; |
+ |
case kCrashDyld: |
// This is independent of dyld’s error_string, which is tested |
// below. |
@@ -156,20 +183,19 @@ class TestMachOImageAnnotationsReader final |
break; |
} |
- size_t expected_annotation_length = strlen(expected_annotation); |
bool found = false; |
for (const std::string& annotation : all_annotations_vector) { |
// Look for the expectation as a leading susbtring, because the actual |
// string that dyld uses will have the contents of the |
// DYLD_INSERT_LIBRARIES environment variable appended to it on Mac |
// OS X 10.10. |
- if (annotation.substr(0, expected_annotation_length) == |
+ if (annotation.substr(0, expected_annotation.length()) == |
expected_annotation) { |
found = true; |
break; |
} |
} |
- EXPECT_TRUE(found); |
+ EXPECT_TRUE(found) << expected_annotation; |
} |
// dyld exposes its error_string at least as far back as Mac OS X 10.4. |
@@ -188,7 +214,7 @@ class TestMachOImageAnnotationsReader final |
} |
} |
- EXPECT_TRUE(found); |
+ EXPECT_TRUE(found) << kExpectedAnnotation; |
} |
} |
@@ -250,6 +276,12 @@ class TestMachOImageAnnotationsReader final |
SetExpectedChildTermination(kTerminationSignal, SIGABRT); |
break; |
+ case kCrashModuleInitialization: |
+ // This crash is triggered by __builtin_trap(), which shows up as |
+ // SIGILL. |
+ SetExpectedChildTermination(kTerminationSignal, SIGILL); |
+ break; |
+ |
case kCrashDyld: |
// dyld fatal errors result in the execution of an int3 instruction on |
// x86 and a trap instruction on ARM, both of which raise SIGTRAP. |
@@ -293,12 +325,27 @@ class TestMachOImageAnnotationsReader final |
EXC_MASK_CRASH, RemotePort(), EXCEPTION_DEFAULT, THREAD_STATE_NONE)); |
switch (test_type_) { |
- case kDontCrash: |
+ case kDontCrash: { |
break; |
+ } |
- case kCrashAbort: |
+ case kCrashAbort: { |
abort(); |
break; |
+ } |
+ |
+ case kCrashModuleInitialization: { |
+ // Load a module that crashes while executing a module initializer. |
+ void* dl_handle = dlopen(ModuleWithCrashyInitializer().c_str(), |
+ RTLD_LAZY | RTLD_LOCAL); |
+ |
+ // This should have crashed in the dlopen(). If dlopen() failed, the |
+ // ASSERT_NE() will show the message. If it succeeded without crashing, |
+ // the FAIL() will fail the test. |
+ ASSERT_NE(nullptr, dl_handle) << dlerror(); |
+ FAIL(); |
+ break; |
+ } |
case kCrashDyld: { |
// Set DYLD_INSERT_LIBRARIES to contain a library that does not exist. |
@@ -345,6 +392,12 @@ TEST(MachOImageAnnotationsReader, CrashAbort) { |
test_mach_o_image_annotations_reader.Run(); |
} |
+TEST(MachOImageAnnotationsReader, CrashModuleInitialization) { |
+ TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( |
+ TestMachOImageAnnotationsReader::kCrashModuleInitialization); |
+ test_mach_o_image_annotations_reader.Run(); |
+} |
+ |
TEST(MachOImageAnnotationsReader, CrashDyld) { |
TestMachOImageAnnotationsReader test_mach_o_image_annotations_reader( |
TestMachOImageAnnotationsReader::kCrashDyld); |