1 // Copyright (c) 2010, 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 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump
33 // classes.
34
35 #include <sstream>
36 #include <string>
37
38 #include "breakpad_googletest_includes.h"
39 #include "common/using_std_string.h"
40 #include "google_breakpad/common/minidump_format.h"
41 #include "processor/synth_minidump.h"
42 #include "processor/synth_minidump_unittest_data.h"
43
44 using google_breakpad::SynthMinidump::Context;
45 using google_breakpad::SynthMinidump::Dump;
46 using google_breakpad::SynthMinidump::Exception;
47 using google_breakpad::SynthMinidump::List;
48 using google_breakpad::SynthMinidump::Memory;
49 using google_breakpad::SynthMinidump::Module;
50 using google_breakpad::SynthMinidump::Section;
51 using google_breakpad::SynthMinidump::Stream;
52 using google_breakpad::SynthMinidump::String;
53 using google_breakpad::SynthMinidump::SystemInfo;
54 using google_breakpad::test_assembler::kBigEndian;
55 using google_breakpad::test_assembler::kLittleEndian;
56 using google_breakpad::test_assembler::Label;
57
TEST(Section,Simple)58 TEST(Section, Simple) {
59 Dump dump(0);
60 Section section(dump);
61 section.L32(0x12345678);
62 section.Finish(0);
63 string contents;
64 ASSERT_TRUE(section.GetContents(&contents));
65 EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents);
66 }
67
TEST(Section,CiteLocationIn)68 TEST(Section, CiteLocationIn) {
69 Dump dump(0, kBigEndian);
70 Section section1(dump), section2(dump);
71 section1.Append("order");
72 section2.Append("mayhem");
73 section2.Finish(0x32287ec2);
74 section2.CiteLocationIn(§ion1);
75 string contents;
76 ASSERT_TRUE(section1.GetContents(&contents));
77 string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13);
78 EXPECT_EQ(expected, contents);
79 }
80
TEST(Stream,CiteStreamIn)81 TEST(Stream, CiteStreamIn) {
82 Dump dump(0, kLittleEndian);
83 Stream stream(dump, 0x40cae2b3);
84 Section section(dump);
85 stream.Append("stream contents");
86 section.Append("section contents");
87 stream.Finish(0x41424344);
88 stream.CiteStreamIn(§ion);
89 string contents;
90 ASSERT_TRUE(section.GetContents(&contents));
91 string expected("section contents"
92 "\xb3\xe2\xca\x40"
93 "\x0f\0\0\0"
94 "\x44\x43\x42\x41",
95 16 + 4 + 4 + 4);
96 EXPECT_EQ(expected, contents);
97 }
98
TEST(Memory,CiteMemoryIn)99 TEST(Memory, CiteMemoryIn) {
100 Dump dump(0, kBigEndian);
101 Memory memory(dump, 0x76d010874ab019f9ULL);
102 Section section(dump);
103 memory.Append("memory contents");
104 section.Append("section contents");
105 memory.Finish(0x51525354);
106 memory.CiteMemoryIn(§ion);
107 string contents;
108 ASSERT_TRUE(section.GetContents(&contents));
109 string expected("section contents"
110 "\x76\xd0\x10\x87\x4a\xb0\x19\xf9"
111 "\0\0\0\x0f"
112 "\x51\x52\x53\x54",
113 16 + 8 + 4 + 4);
114 EXPECT_EQ(contents, expected);
115 }
116
TEST(Memory,Here)117 TEST(Memory, Here) {
118 Dump dump(0, kBigEndian);
119 Memory memory(dump, 0x89979731eb060ed4ULL);
120 memory.Append(1729, 42);
121 Label l = memory.Here();
122 ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value());
123 }
124
TEST(Context,X86)125 TEST(Context, X86) {
126 Dump dump(0, kLittleEndian);
127 assert(x86_raw_context.context_flags & MD_CONTEXT_X86);
128 Context context(dump, x86_raw_context);
129 string contents;
130 ASSERT_TRUE(context.GetContents(&contents));
131 EXPECT_EQ(sizeof(x86_expected_contents), contents.size());
132 EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size())
133 == 0);
134 }
135
TEST(Context,ARM)136 TEST(Context, ARM) {
137 Dump dump(0, kLittleEndian);
138 assert(arm_raw_context.context_flags & MD_CONTEXT_ARM);
139 Context context(dump, arm_raw_context);
140 string contents;
141 ASSERT_TRUE(context.GetContents(&contents));
142 EXPECT_EQ(sizeof(arm_expected_contents), contents.size());
143 EXPECT_TRUE(memcmp(contents.data(), arm_expected_contents, contents.size())
144 == 0);
145 }
146
TEST(ContextDeathTest,X86BadFlags)147 TEST(ContextDeathTest, X86BadFlags) {
148 Dump dump(0, kLittleEndian);
149 MDRawContextX86 raw;
150 raw.context_flags = MD_CONTEXT_AMD64;
151 ASSERT_DEATH(Context context(dump, raw);,
152 "context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)");
153 }
154
TEST(ContextDeathTest,X86BadEndianness)155 TEST(ContextDeathTest, X86BadEndianness) {
156 Dump dump(0, kBigEndian);
157 MDRawContextX86 raw;
158 raw.context_flags = MD_CONTEXT_X86;
159 ASSERT_DEATH(Context context(dump, raw);,
160 "dump\\.endianness\\(\\) == kLittleEndian");
161 }
162
TEST(Thread,Simple)163 TEST(Thread, Simple) {
164 Dump dump(0, kLittleEndian);
165 Context context(dump, x86_raw_context);
166 context.Finish(0x8665da0c);
167 Memory stack(dump, 0xaad55a93cc3c0efcULL);
168 stack.Append("stack contents");
169 stack.Finish(0xe08cdbd1);
170 google_breakpad::SynthMinidump::Thread thread(
171 dump, 0x3d7ec360, stack, context,
172 0x3593f44d, // suspend count
173 0xab352b82, // priority class
174 0x2753d838, // priority
175 0xeb2de4be3f29e3e9ULL); // thread environment block
176 string contents;
177 ASSERT_TRUE(thread.GetContents(&contents));
178 static const uint8_t expected_bytes[] = {
179 0x60, 0xc3, 0x7e, 0x3d, // thread id
180 0x4d, 0xf4, 0x93, 0x35, // suspend count
181 0x82, 0x2b, 0x35, 0xab, // priority class
182 0x38, 0xd8, 0x53, 0x27, // priority
183 0xe9, 0xe3, 0x29, 0x3f, 0xbe, 0xe4, 0x2d, 0xeb, // thread environment block
184 0xfc, 0x0e, 0x3c, 0xcc, 0x93, 0x5a, 0xd5, 0xaa, // stack address
185 0x0e, 0x00, 0x00, 0x00, // stack size
186 0xd1, 0xdb, 0x8c, 0xe0, // stack MDRVA
187 0xcc, 0x02, 0x00, 0x00, // context size
188 0x0c, 0xda, 0x65, 0x86 // context MDRVA
189 };
190 EXPECT_EQ(sizeof(expected_bytes), contents.size());
191 EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
192 }
193
TEST(Exception,Simple)194 TEST(Exception, Simple) {
195 Dump dump(0, kLittleEndian);
196 Context context(dump, x86_raw_context);
197 context.Finish(0x8665da0c);
198
199 Exception exception(dump, context,
200 0x1234abcd, // thread id
201 0xdcba4321, // exception code
202 0xf0e0d0c0, // exception flags
203 0x0919a9b9c9d9e9f9ULL); // exception address
204 string contents;
205 ASSERT_TRUE(exception.GetContents(&contents));
206 static const uint8_t expected_bytes[] = {
207 0xcd, 0xab, 0x34, 0x12, // thread id
208 0x00, 0x00, 0x00, 0x00, // __align
209 0x21, 0x43, 0xba, 0xdc, // exception code
210 0xc0, 0xd0, 0xe0, 0xf0, // exception flags
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception record
212 0xf9, 0xe9, 0xd9, 0xc9, 0xb9, 0xa9, 0x19, 0x09, // exception address
213 0x00, 0x00, 0x00, 0x00, // number parameters
214 0x00, 0x00, 0x00, 0x00, // __align
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
230 0xcc, 0x02, 0x00, 0x00, // context size
231 0x0c, 0xda, 0x65, 0x86 // context MDRVA
232 };
233 EXPECT_EQ(sizeof(expected_bytes), contents.size());
234 EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
235 }
236
TEST(String,Simple)237 TEST(String, Simple) {
238 Dump dump(0, kBigEndian);
239 String s(dump, "All mimsy were the borogoves");
240 string contents;
241 ASSERT_TRUE(s.GetContents(&contents));
242 static const char expected[] =
243 "\x00\x00\x00\x38\0A\0l\0l\0 \0m\0i\0m\0s\0y\0 \0w\0e\0r\0e"
244 "\0 \0t\0h\0e\0 \0b\0o\0r\0o\0g\0o\0v\0e\0s";
245 string expected_string(expected, sizeof(expected) - 1);
246 EXPECT_EQ(expected_string, contents);
247 }
248
TEST(String,CiteStringIn)249 TEST(String, CiteStringIn) {
250 Dump dump(0, kLittleEndian);
251 String s(dump, "and the mome wraths outgrabe");
252 Section section(dump);
253 section.Append("initial");
254 s.CiteStringIn(§ion);
255 s.Finish(0xdc2bb469);
256 string contents;
257 ASSERT_TRUE(section.GetContents(&contents));
258 EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents);
259 }
260
TEST(List,Empty)261 TEST(List, Empty) {
262 Dump dump(0, kBigEndian);
263 List<Section> list(dump, 0x2442779c);
264 EXPECT_TRUE(list.Empty());
265 list.Finish(0x84e09808);
266 string contents;
267 ASSERT_TRUE(list.GetContents(&contents));
268 EXPECT_EQ(string("\0\0\0\0", 4), contents);
269 }
270
TEST(List,Two)271 TEST(List, Two) {
272 Dump dump(0, kBigEndian);
273 List<Section> list(dump, 0x26c9f498);
274 Section section1(dump);
275 section1.Append("section one contents");
276 EXPECT_TRUE(list.Empty());
277 list.Add(§ion1);
278 EXPECT_FALSE(list.Empty());
279 Section section2(dump);
280 section2.Append("section two contents");
281 list.Add(§ion2);
282 list.Finish(0x1e5bb60e);
283 string contents;
284 ASSERT_TRUE(list.GetContents(&contents));
285 EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44),
286 contents);
287 }
288
TEST(Dump,Header)289 TEST(Dump, Header) {
290 Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a);
291 dump.Finish();
292 string contents;
293 ASSERT_TRUE(dump.GetContents(&contents));
294 ASSERT_EQ(string("\x4d\x44\x4d\x50" // signature
295 "\xaf\x7f\x81\xb3" // version
296 "\0\0\0\0" // stream count
297 "\x20\0\0\0" // directory RVA (could be anything)
298 "\0\0\0\0" // checksum
299 "\x0a\x1c\x74\x2c" // time_date_stamp
300 "\x4c\xc8\x5c\x68\x33\x8b\x73\x9f", // flags
301 32),
302 contents);
303 }
304
TEST(Dump,HeaderBigEndian)305 TEST(Dump, HeaderBigEndian) {
306 Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744);
307 dump.Finish();
308 string contents;
309 ASSERT_TRUE(dump.GetContents(&contents));
310 ASSERT_EQ(string("\x50\x4d\x44\x4d" // signature
311 "\x16\x16\x93\xe2" // version
312 "\0\0\0\0" // stream count
313 "\0\0\0\x20" // directory RVA (could be anything)
314 "\0\0\0\0" // checksum
315 "\x35\x66\x77\x44" // time_date_stamp
316 "\x20\x6c\xe3\xcc\x6f\xb8\xe0\xf0", // flags
317 32),
318 contents);
319 }
320
TEST(Dump,OneSection)321 TEST(Dump, OneSection) {
322 Dump dump(0, kLittleEndian);
323 Section section(dump);
324 section.Append("section contents");
325 dump.Add(§ion);
326 dump.Finish();
327 string dump_contents;
328 // Just check for undefined labels; don't worry about the contents.
329 ASSERT_TRUE(dump.GetContents(&dump_contents));
330
331 Section referencing_section(dump);
332 section.CiteLocationIn(&referencing_section);
333 string contents;
334 ASSERT_TRUE(referencing_section.GetContents(&contents));
335 ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents);
336 }
337