/ src / processor / synth_minidump_unittest.cc
synth_minidump_unittest.cc
  1  // Copyright 2010 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 30  
 31  // synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump
 32  // classes.
 33  
 34  #ifdef HAVE_CONFIG_H
 35  #include <config.h>  // Must come first
 36  #endif
 37  
 38  #include <sstream>
 39  #include <string>
 40  
 41  #include "breakpad_googletest_includes.h"
 42  #include "common/using_std_string.h"
 43  #include "google_breakpad/common/minidump_format.h"
 44  #include "processor/synth_minidump.h"
 45  #include "processor/synth_minidump_unittest_data.h"
 46  
 47  using google_breakpad::SynthMinidump::Context;
 48  using google_breakpad::SynthMinidump::Dump;
 49  using google_breakpad::SynthMinidump::Exception;
 50  using google_breakpad::SynthMinidump::List;
 51  using google_breakpad::SynthMinidump::Memory;
 52  using google_breakpad::SynthMinidump::Module;
 53  using google_breakpad::SynthMinidump::Section;
 54  using google_breakpad::SynthMinidump::Stream;
 55  using google_breakpad::SynthMinidump::String;
 56  using google_breakpad::SynthMinidump::SystemInfo;
 57  using google_breakpad::test_assembler::kBigEndian;
 58  using google_breakpad::test_assembler::kLittleEndian;
 59  using google_breakpad::test_assembler::Label;
 60  
 61  TEST(Section, Simple) {
 62    Dump dump(0);
 63    Section section(dump);
 64    section.L32(0x12345678);
 65    section.Finish(0);
 66    string contents;
 67    ASSERT_TRUE(section.GetContents(&contents));
 68    EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents);
 69  }
 70  
 71  TEST(Section, CiteLocationIn) {
 72    Dump dump(0, kBigEndian);
 73    Section section1(dump), section2(dump);
 74    section1.Append("order");
 75    section2.Append("mayhem");
 76    section2.Finish(0x32287ec2);
 77    section2.CiteLocationIn(&section1);
 78    string contents;
 79    ASSERT_TRUE(section1.GetContents(&contents));
 80    string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13);
 81    EXPECT_EQ(expected, contents);
 82  }
 83  
 84  TEST(Stream, CiteStreamIn) {
 85    Dump dump(0, kLittleEndian);
 86    Stream stream(dump, 0x40cae2b3);
 87    Section section(dump);
 88    stream.Append("stream contents");
 89    section.Append("section contents");
 90    stream.Finish(0x41424344);
 91    stream.CiteStreamIn(&section);
 92    string contents;
 93    ASSERT_TRUE(section.GetContents(&contents));
 94    string expected("section contents"
 95                    "\xb3\xe2\xca\x40"
 96                    "\x0f\0\0\0"
 97                    "\x44\x43\x42\x41",
 98                    16 + 4 + 4 + 4);
 99    EXPECT_EQ(expected, contents);
100  }
101  
102  TEST(Memory, CiteMemoryIn) {
103    Dump dump(0, kBigEndian);
104    Memory memory(dump, 0x76d010874ab019f9ULL);
105    Section section(dump);
106    memory.Append("memory contents");
107    section.Append("section contents");
108    memory.Finish(0x51525354);
109    memory.CiteMemoryIn(&section);
110    string contents;
111    ASSERT_TRUE(section.GetContents(&contents));
112    string expected("section contents"
113                    "\x76\xd0\x10\x87\x4a\xb0\x19\xf9"
114                    "\0\0\0\x0f"
115                    "\x51\x52\x53\x54",
116                    16 + 8 + 4 + 4);
117    EXPECT_EQ(contents, expected);
118  }
119  
120  TEST(Memory, Here) {
121    Dump dump(0, kBigEndian);
122    Memory memory(dump, 0x89979731eb060ed4ULL);
123    memory.Append(1729, 42);
124    Label l = memory.Here();
125    ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value());
126  }
127  
128  TEST(Context, X86) {
129    Dump dump(0, kLittleEndian);
130    assert(x86_raw_context.context_flags & MD_CONTEXT_X86);
131    Context context(dump, x86_raw_context);
132    string contents;
133    ASSERT_TRUE(context.GetContents(&contents));
134    EXPECT_EQ(sizeof(x86_expected_contents), contents.size());
135    EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size())
136                == 0);
137  }
138  
139  TEST(Context, ARM) {
140    Dump dump(0, kLittleEndian);
141    assert(arm_raw_context.context_flags & MD_CONTEXT_ARM);
142    Context context(dump, arm_raw_context);
143    string contents;
144    ASSERT_TRUE(context.GetContents(&contents));
145    EXPECT_EQ(sizeof(arm_expected_contents), contents.size());
146    EXPECT_TRUE(memcmp(contents.data(), arm_expected_contents, contents.size())
147                == 0);
148  }
149  
150  TEST(ContextDeathTest, X86BadFlags) {
151    Dump dump(0, kLittleEndian);
152    MDRawContextX86 raw;
153    raw.context_flags = MD_CONTEXT_AMD64;
154    ASSERT_DEATH(Context context(dump, raw);,
155                 "context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)");
156  }
157  
158  TEST(ContextDeathTest, X86BadEndianness) {
159    Dump dump(0, kBigEndian);
160    MDRawContextX86 raw;
161    raw.context_flags = MD_CONTEXT_X86;
162    ASSERT_DEATH(Context context(dump, raw);,
163                 "dump\\.endianness\\(\\) == kLittleEndian");
164  }
165  
166  TEST(Thread, Simple) {
167    Dump dump(0, kLittleEndian);
168    Context context(dump, x86_raw_context);
169    context.Finish(0x8665da0c);
170    Memory stack(dump, 0xaad55a93cc3c0efcULL);
171    stack.Append("stack contents");
172    stack.Finish(0xe08cdbd1);
173    google_breakpad::SynthMinidump::Thread thread(
174        dump, 0x3d7ec360, stack, context,
175        0x3593f44d, // suspend count
176        0xab352b82, // priority class
177        0x2753d838, // priority
178        0xeb2de4be3f29e3e9ULL); // thread environment block
179    string contents;
180    ASSERT_TRUE(thread.GetContents(&contents));
181    static const uint8_t expected_bytes[] = {
182      0x60, 0xc3, 0x7e, 0x3d, // thread id
183      0x4d, 0xf4, 0x93, 0x35, // suspend count
184      0x82, 0x2b, 0x35, 0xab, // priority class
185      0x38, 0xd8, 0x53, 0x27, // priority
186      0xe9, 0xe3, 0x29, 0x3f, 0xbe, 0xe4, 0x2d, 0xeb, // thread environment block
187      0xfc, 0x0e, 0x3c, 0xcc, 0x93, 0x5a, 0xd5, 0xaa, // stack address
188      0x0e, 0x00, 0x00, 0x00, // stack size
189      0xd1, 0xdb, 0x8c, 0xe0, // stack MDRVA
190      0xcc, 0x02, 0x00, 0x00, // context size
191      0x0c, 0xda, 0x65, 0x86  // context MDRVA
192    };
193    EXPECT_EQ(sizeof(expected_bytes), contents.size());
194    EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
195  }
196  
197  TEST(Exception, Simple) {
198    Dump dump(0, kLittleEndian);
199    Context context(dump, x86_raw_context);
200    context.Finish(0x8665da0c);
201    
202    Exception exception(dump, context,
203                        0x1234abcd, // thread id
204                        0xdcba4321, // exception code
205                        0xf0e0d0c0, // exception flags
206                        0x0919a9b9c9d9e9f9ULL); // exception address
207    string contents;
208    ASSERT_TRUE(exception.GetContents(&contents));
209    static const uint8_t expected_bytes[] = {
210      0xcd, 0xab, 0x34, 0x12, // thread id
211      0x00, 0x00, 0x00, 0x00, // __align
212      0x21, 0x43, 0xba, 0xdc, // exception code
213      0xc0, 0xd0, 0xe0, 0xf0, // exception flags
214      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception record
215      0xf9, 0xe9, 0xd9, 0xc9, 0xb9, 0xa9, 0x19, 0x09, // exception address
216      0x00, 0x00, 0x00, 0x00, // number parameters
217      0x00, 0x00, 0x00, 0x00, // __align
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      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
231      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
232      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
233      0xcc, 0x02, 0x00, 0x00, // context size
234      0x0c, 0xda, 0x65, 0x86  // context MDRVA
235    };
236    EXPECT_EQ(sizeof(expected_bytes), contents.size());
237    EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
238  }
239  
240  TEST(String, Simple) {
241    Dump dump(0, kBigEndian);
242    String s(dump, "All mimsy were the borogoves");
243    string contents;
244    ASSERT_TRUE(s.GetContents(&contents));
245    static const char expected[] = 
246      "\x00\x00\x00\x38\0A\0l\0l\0 \0m\0i\0m\0s\0y\0 \0w\0e\0r\0e"
247      "\0 \0t\0h\0e\0 \0b\0o\0r\0o\0g\0o\0v\0e\0s";
248    string expected_string(expected, sizeof(expected) - 1);
249    EXPECT_EQ(expected_string, contents);
250  }
251  
252  TEST(String, CiteStringIn) {
253    Dump dump(0, kLittleEndian);
254    String s(dump, "and the mome wraths outgrabe");
255    Section section(dump);
256    section.Append("initial");
257    s.CiteStringIn(&section);
258    s.Finish(0xdc2bb469);
259    string contents;
260    ASSERT_TRUE(section.GetContents(&contents));
261    EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents);
262  }
263  
264  TEST(List, Empty) {
265    Dump dump(0, kBigEndian);
266    List<Section> list(dump, 0x2442779c);
267    EXPECT_TRUE(list.Empty());
268    list.Finish(0x84e09808);
269    string contents;
270    ASSERT_TRUE(list.GetContents(&contents));
271    EXPECT_EQ(string("\0\0\0\0", 4), contents);
272  }
273  
274  TEST(List, Two) {
275    Dump dump(0, kBigEndian);
276    List<Section> list(dump, 0x26c9f498);
277    Section section1(dump);
278    section1.Append("section one contents");
279    EXPECT_TRUE(list.Empty());
280    list.Add(&section1);
281    EXPECT_FALSE(list.Empty());
282    Section section2(dump);
283    section2.Append("section two contents");
284    list.Add(&section2);
285    list.Finish(0x1e5bb60e);
286    string contents;
287    ASSERT_TRUE(list.GetContents(&contents));
288    EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44),
289              contents);
290  }
291  
292  TEST(Dump, Header) {
293    Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a);
294    dump.Finish();
295    string contents;
296    ASSERT_TRUE(dump.GetContents(&contents));
297    ASSERT_EQ(string("\x4d\x44\x4d\x50"   // signature
298                     "\xaf\x7f\x81\xb3"   // version
299                     "\0\0\0\0"           // stream count
300                     "\x20\0\0\0"         // directory RVA (could be anything)
301                     "\0\0\0\0"           // checksum
302                     "\x0a\x1c\x74\x2c"   // time_date_stamp
303                     "\x4c\xc8\x5c\x68\x33\x8b\x73\x9f", // flags
304                     32),
305              contents);
306  }
307  
308  TEST(Dump, HeaderBigEndian) {
309    Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744);
310    dump.Finish();
311    string contents;
312    ASSERT_TRUE(dump.GetContents(&contents));
313    ASSERT_EQ(string("\x50\x4d\x44\x4d"   // signature
314                     "\x16\x16\x93\xe2"   // version
315                     "\0\0\0\0"           // stream count
316                     "\0\0\0\x20"         // directory RVA (could be anything)
317                     "\0\0\0\0"           // checksum
318                     "\x35\x66\x77\x44"   // time_date_stamp
319                     "\x20\x6c\xe3\xcc\x6f\xb8\xe0\xf0", // flags
320                     32),
321              contents);
322  }
323  
324  TEST(Dump, OneSection) {
325    Dump dump(0, kLittleEndian);
326    Section section(dump);
327    section.Append("section contents");
328    dump.Add(&section);
329    dump.Finish();
330    string dump_contents;
331    // Just check for undefined labels; don't worry about the contents.
332    ASSERT_TRUE(dump.GetContents(&dump_contents));
333  
334    Section referencing_section(dump);
335    section.CiteLocationIn(&referencing_section);
336    string contents;
337    ASSERT_TRUE(referencing_section.GetContents(&contents));
338    ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents);
339  }