1 // Copyright (c) 2014 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include <sys/syscall.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include <string>
35
36 #include "breakpad_googletest_includes.h"
37 #include "client/linux/handler/exception_handler.h"
38 #include "client/linux/microdump_writer/microdump_writer.h"
39 #include "common/linux/eintr_wrapper.h"
40 #include "common/linux/ignore_ret.h"
41 #include "common/scoped_ptr.h"
42 #include "common/tests/auto_tempdir.h"
43 #include "common/using_std_string.h"
44
45 using namespace google_breakpad;
46
47 namespace {
48
49 typedef testing::Test MicrodumpWriterTest;
50
TEST(MicrodumpWriterTest,Setup)51 TEST(MicrodumpWriterTest, Setup) {
52 int fds[2];
53 ASSERT_NE(-1, pipe(fds));
54
55 AutoTempDir temp_dir;
56 string stderr_file = temp_dir.path() + "/stderr.log";
57 int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
58 ASSERT_NE(-1, err_fd);
59
60 const pid_t child = fork();
61 if (child == 0) {
62 close(fds[1]);
63 char b;
64 IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
65 close(fds[0]);
66 syscall(__NR_exit);
67 }
68 close(fds[0]);
69
70 ExceptionHandler::CrashContext context;
71 memset(&context, 0, sizeof(context));
72
73 // Set a non-zero tid to avoid tripping asserts.
74 context.tid = child;
75
76 // Push some extra mapping to check the MappingList logic.
77 const uint32_t memory_size = sysconf(_SC_PAGESIZE);
78 const char* kMemoryName = "libfoo.so";
79 const uint8_t kModuleGUID[sizeof(MDGUID)] = {
80 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
81 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
82 };
83
84 MappingInfo info;
85 info.start_addr = memory_size;
86 info.size = memory_size;
87 info.offset = 42;
88 strcpy(info.name, kMemoryName);
89
90 MappingList mappings;
91 MappingEntry mapping;
92 mapping.first = info;
93 memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
94 mappings.push_back(mapping);
95
96 // Redirect temporarily stderr to the stderr.log file.
97 int save_err = dup(STDERR_FILENO);
98 ASSERT_NE(-1, save_err);
99 ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
100
101 ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings));
102
103 // Revert stderr back to the console.
104 dup2(save_err, STDERR_FILENO);
105 close(save_err);
106
107 // Read back the stderr file and check for the microdump marker.
108 fsync(err_fd);
109 lseek(err_fd, 0, SEEK_SET);
110 const size_t kBufSize = 64 * 1024;
111 scoped_array<char> buf(new char[kBufSize]);
112 ASSERT_GT(read(err_fd, buf.get(), kBufSize), 0);
113
114 ASSERT_NE(static_cast<char*>(0), strstr(
115 buf.get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
116 ASSERT_NE(static_cast<char*>(0), strstr(
117 buf.get(), "-----END BREAKPAD MICRODUMP-----"));
118
119 #ifdef __LP64__
120 ASSERT_NE(static_cast<char*>(0), strstr(
121 buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 "
122 "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
123 #else
124 ASSERT_NE(static_cast<char*>(0), strstr(
125 buf.get(), "M 00001000 0000002A 00001000 "
126 "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
127 #endif
128
129 close(err_fd);
130 close(fds[1]);
131 }
132
133 } // namespace
134