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(§ion1); 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(§ion); 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(§ion); 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(§ion); 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(§ion1); 281 EXPECT_FALSE(list.Empty()); 282 Section section2(dump); 283 section2.Append("section two contents"); 284 list.Add(§ion2); 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(§ion); 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 }