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 (at) mozilla.com> <jimb (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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