1
// Copyright (c) 2010, Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
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
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.
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.
30
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
32
// synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump
38
#include "breakpad_googletest_includes.h"
39
#include "google_breakpad/common/minidump_format.h"
40
#include "processor/synth_minidump.h"
41
#include "processor/synth_minidump_unittest_data.h"
43
using google_breakpad::SynthMinidump::Context;
44
using google_breakpad::SynthMinidump::Dump;
45
using google_breakpad::SynthMinidump::Exception;
46
using google_breakpad::SynthMinidump::List;
47
using google_breakpad::SynthMinidump::Memory;
48
using google_breakpad::SynthMinidump::Module;
49
using google_breakpad::SynthMinidump::Section;
50
using google_breakpad::SynthMinidump::Stream;
51
using google_breakpad::SynthMinidump::String;
52
using google_breakpad::SynthMinidump::SystemInfo;
53
using google_breakpad::SynthMinidump::Thread;
54
using google_breakpad::test_assembler::kBigEndian;
55
using google_breakpad::test_assembler::kLittleEndian;
56
using google_breakpad::test_assembler::Label;
59
TEST(Section, Simple) {
61
Section section(dump);
62
section.L32(0x12345678);
65
ASSERT_TRUE(section.GetContents(&contents));
66
EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents);
69
TEST(Section, CiteLocationIn) {
70
Dump dump(0, kBigEndian);
71
Section section1(dump), section2(dump);
72
section1.Append("order");
73
section2.Append("mayhem");
74
section2.Finish(0x32287ec2);
75
section2.CiteLocationIn(§ion1);
77
ASSERT_TRUE(section1.GetContents(&contents));
78
string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13);
79
EXPECT_EQ(expected, contents);
82
TEST(Stream, CiteStreamIn) {
83
Dump dump(0, kLittleEndian);
84
Stream stream(dump, 0x40cae2b3);
85
Section section(dump);
86
stream.Append("stream contents");
87
section.Append("section contents");
88
stream.Finish(0x41424344);
89
stream.CiteStreamIn(§ion);
91
ASSERT_TRUE(section.GetContents(&contents));
92
string expected("section contents"
97
EXPECT_EQ(expected, contents);
100
TEST(Memory, CiteMemoryIn) {
101
Dump dump(0, kBigEndian);
102
Memory memory(dump, 0x76d010874ab019f9ULL);
103
Section section(dump);
104
memory.Append("memory contents");
105
section.Append("section contents");
106
memory.Finish(0x51525354);
107
memory.CiteMemoryIn(§ion);
109
ASSERT_TRUE(section.GetContents(&contents));
110
string expected("section contents"
111
"\x76\xd0\x10\x87\x4a\xb0\x19\xf9"
115
EXPECT_EQ(contents, expected);
119
Dump dump(0, kBigEndian);
120
Memory memory(dump, 0x89979731eb060ed4ULL);
121
memory.Append(1729, 42);
122
Label l = memory.Here();
123
ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value());
127
Dump dump(0, kLittleEndian);
128
assert(x86_raw_context.context_flags & MD_CONTEXT_X86);
129
Context context(dump, x86_raw_context);
131
ASSERT_TRUE(context.GetContents(&contents));
132
EXPECT_EQ(sizeof(x86_expected_contents), contents.size());
133
EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size())
138
Dump dump(0, kLittleEndian);
139
assert(arm_raw_context.context_flags & MD_CONTEXT_ARM);
140
Context context(dump, arm_raw_context);
142
ASSERT_TRUE(context.GetContents(&contents));
143
EXPECT_EQ(sizeof(arm_expected_contents), contents.size());
144
EXPECT_TRUE(memcmp(contents.data(), arm_expected_contents, contents.size())
148
TEST(ContextDeathTest, X86BadFlags) {
149
Dump dump(0, kLittleEndian);
151
raw.context_flags = 0;
152
ASSERT_DEATH(Context context(dump, raw);,
153
"context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)");
156
TEST(ContextDeathTest, X86BadEndianness) {
157
Dump dump(0, kBigEndian);
159
raw.context_flags = MD_CONTEXT_X86;
160
ASSERT_DEATH(Context context(dump, raw);,
161
"dump\\.endianness\\(\\) == kLittleEndian");
164
TEST(Thread, Simple) {
165
Dump dump(0, kLittleEndian);
166
Context context(dump, x86_raw_context);
167
context.Finish(0x8665da0c);
168
Memory stack(dump, 0xaad55a93cc3c0efcULL);
169
stack.Append("stack contents");
170
stack.Finish(0xe08cdbd1);
171
Thread thread(dump, 0x3d7ec360, stack, context,
172
0x3593f44d, // suspend count
173
0xab352b82, // priority class
174
0x2753d838, // priority
175
0xeb2de4be3f29e3e9ULL); // thread environment block
177
ASSERT_TRUE(thread.GetContents(&contents));
178
static const u_int8_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
190
EXPECT_EQ(sizeof(expected_bytes), contents.size());
191
EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
194
TEST(Exception, Simple) {
195
Dump dump(0, kLittleEndian);
196
Context context(dump, x86_raw_context);
197
context.Finish(0x8665da0c);
199
Exception exception(dump, context,
200
0x1234abcd, // thread id
201
0xdcba4321, // exception code
202
0xf0e0d0c0, // exception flags
203
0x0919a9b9c9d9e9f9ULL); // exception address
205
ASSERT_TRUE(exception.GetContents(&contents));
206
static const u_int8_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
233
EXPECT_EQ(sizeof(expected_bytes), contents.size());
234
EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
237
TEST(String, Simple) {
238
Dump dump(0, kBigEndian);
239
String s(dump, "All mimsy were the borogoves");
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);
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);
257
ASSERT_TRUE(section.GetContents(&contents));
258
EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents);
262
Dump dump(0, kBigEndian);
263
List<Section> list(dump, 0x2442779c);
264
EXPECT_TRUE(list.Empty());
265
list.Finish(0x84e09808);
267
ASSERT_TRUE(list.GetContents(&contents));
268
EXPECT_EQ(string("\0\0\0\0", 4), contents);
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());
278
EXPECT_FALSE(list.Empty());
279
Section section2(dump);
280
section2.Append("section two contents");
282
list.Finish(0x1e5bb60e);
284
ASSERT_TRUE(list.GetContents(&contents));
285
EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44),
290
Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a);
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
305
TEST(Dump, HeaderBigEndian) {
306
Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744);
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
321
TEST(Dump, OneSection) {
322
Dump dump(0, kLittleEndian);
323
Section section(dump);
324
section.Append("section contents");
327
string dump_contents;
328
// Just check for undefined labels; don't worry about the contents.
329
ASSERT_TRUE(dump.GetContents(&dump_contents));
331
Section referencing_section(dump);
332
section.CiteLocationIn(&referencing_section);
334
ASSERT_TRUE(referencing_section.GetContents(&contents));
335
ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents);