Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2010, Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | |
michael@0 | 30 | // Unit test for Minidump. Uses a pre-generated minidump and |
michael@0 | 31 | // verifies that certain streams are correct. |
michael@0 | 32 | |
michael@0 | 33 | #include <iostream> |
michael@0 | 34 | #include <fstream> |
michael@0 | 35 | #include <sstream> |
michael@0 | 36 | #include <stdlib.h> |
michael@0 | 37 | #include <string> |
michael@0 | 38 | #include <vector> |
michael@0 | 39 | |
michael@0 | 40 | #include "breakpad_googletest_includes.h" |
michael@0 | 41 | #include "common/using_std_string.h" |
michael@0 | 42 | #include "google_breakpad/common/minidump_format.h" |
michael@0 | 43 | #include "google_breakpad/processor/minidump.h" |
michael@0 | 44 | #include "processor/logging.h" |
michael@0 | 45 | #include "processor/synth_minidump.h" |
michael@0 | 46 | |
michael@0 | 47 | namespace { |
michael@0 | 48 | |
michael@0 | 49 | using google_breakpad::Minidump; |
michael@0 | 50 | using google_breakpad::MinidumpContext; |
michael@0 | 51 | using google_breakpad::MinidumpException; |
michael@0 | 52 | using google_breakpad::MinidumpMemoryInfo; |
michael@0 | 53 | using google_breakpad::MinidumpMemoryInfoList; |
michael@0 | 54 | using google_breakpad::MinidumpMemoryList; |
michael@0 | 55 | using google_breakpad::MinidumpMemoryRegion; |
michael@0 | 56 | using google_breakpad::MinidumpModule; |
michael@0 | 57 | using google_breakpad::MinidumpModuleList; |
michael@0 | 58 | using google_breakpad::MinidumpSystemInfo; |
michael@0 | 59 | using google_breakpad::MinidumpThread; |
michael@0 | 60 | using google_breakpad::MinidumpThreadList; |
michael@0 | 61 | using google_breakpad::SynthMinidump::Context; |
michael@0 | 62 | using google_breakpad::SynthMinidump::Dump; |
michael@0 | 63 | using google_breakpad::SynthMinidump::Exception; |
michael@0 | 64 | using google_breakpad::SynthMinidump::Memory; |
michael@0 | 65 | using google_breakpad::SynthMinidump::Module; |
michael@0 | 66 | using google_breakpad::SynthMinidump::Stream; |
michael@0 | 67 | using google_breakpad::SynthMinidump::String; |
michael@0 | 68 | using google_breakpad::SynthMinidump::SystemInfo; |
michael@0 | 69 | using google_breakpad::SynthMinidump::Thread; |
michael@0 | 70 | using google_breakpad::test_assembler::kBigEndian; |
michael@0 | 71 | using google_breakpad::test_assembler::kLittleEndian; |
michael@0 | 72 | using std::ifstream; |
michael@0 | 73 | using std::istringstream; |
michael@0 | 74 | using std::vector; |
michael@0 | 75 | using ::testing::Return; |
michael@0 | 76 | |
michael@0 | 77 | class MinidumpTest : public ::testing::Test { |
michael@0 | 78 | public: |
michael@0 | 79 | void SetUp() { |
michael@0 | 80 | minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + |
michael@0 | 81 | "/src/processor/testdata/minidump2.dmp"; |
michael@0 | 82 | } |
michael@0 | 83 | string minidump_file_; |
michael@0 | 84 | }; |
michael@0 | 85 | |
michael@0 | 86 | TEST_F(MinidumpTest, TestMinidumpFromFile) { |
michael@0 | 87 | Minidump minidump(minidump_file_); |
michael@0 | 88 | ASSERT_EQ(minidump.path(), minidump_file_); |
michael@0 | 89 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 90 | const MDRawHeader* header = minidump.header(); |
michael@0 | 91 | ASSERT_NE(header, (MDRawHeader*)NULL); |
michael@0 | 92 | ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); |
michael@0 | 93 | //TODO: add more checks here |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | TEST_F(MinidumpTest, TestMinidumpFromStream) { |
michael@0 | 97 | // read minidump contents into memory, construct a stringstream around them |
michael@0 | 98 | ifstream file_stream(minidump_file_.c_str(), std::ios::in); |
michael@0 | 99 | ASSERT_TRUE(file_stream.good()); |
michael@0 | 100 | vector<char> bytes; |
michael@0 | 101 | file_stream.seekg(0, std::ios_base::end); |
michael@0 | 102 | ASSERT_TRUE(file_stream.good()); |
michael@0 | 103 | bytes.resize(file_stream.tellg()); |
michael@0 | 104 | file_stream.seekg(0, std::ios_base::beg); |
michael@0 | 105 | ASSERT_TRUE(file_stream.good()); |
michael@0 | 106 | file_stream.read(&bytes[0], bytes.size()); |
michael@0 | 107 | ASSERT_TRUE(file_stream.good()); |
michael@0 | 108 | string str(&bytes[0], bytes.size()); |
michael@0 | 109 | istringstream stream(str); |
michael@0 | 110 | ASSERT_TRUE(stream.good()); |
michael@0 | 111 | |
michael@0 | 112 | // now read minidump from stringstream |
michael@0 | 113 | Minidump minidump(stream); |
michael@0 | 114 | ASSERT_EQ(minidump.path(), ""); |
michael@0 | 115 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 116 | const MDRawHeader* header = minidump.header(); |
michael@0 | 117 | ASSERT_NE(header, (MDRawHeader*)NULL); |
michael@0 | 118 | ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); |
michael@0 | 119 | //TODO: add more checks here |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | TEST(Dump, ReadBackEmpty) { |
michael@0 | 123 | Dump dump(0); |
michael@0 | 124 | dump.Finish(); |
michael@0 | 125 | string contents; |
michael@0 | 126 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 127 | istringstream stream(contents); |
michael@0 | 128 | Minidump minidump(stream); |
michael@0 | 129 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 130 | ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | TEST(Dump, ReadBackEmptyBigEndian) { |
michael@0 | 134 | Dump big_minidump(0, kBigEndian); |
michael@0 | 135 | big_minidump.Finish(); |
michael@0 | 136 | string contents; |
michael@0 | 137 | ASSERT_TRUE(big_minidump.GetContents(&contents)); |
michael@0 | 138 | istringstream stream(contents); |
michael@0 | 139 | Minidump minidump(stream); |
michael@0 | 140 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 141 | ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | TEST(Dump, OneStream) { |
michael@0 | 145 | Dump dump(0, kBigEndian); |
michael@0 | 146 | Stream stream(dump, 0xfbb7fa2bU); |
michael@0 | 147 | stream.Append("stream contents"); |
michael@0 | 148 | dump.Add(&stream); |
michael@0 | 149 | dump.Finish(); |
michael@0 | 150 | |
michael@0 | 151 | string contents; |
michael@0 | 152 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 153 | istringstream minidump_stream(contents); |
michael@0 | 154 | Minidump minidump(minidump_stream); |
michael@0 | 155 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 156 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 157 | |
michael@0 | 158 | const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); |
michael@0 | 159 | ASSERT_TRUE(dir != NULL); |
michael@0 | 160 | EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); |
michael@0 | 161 | |
michael@0 | 162 | uint32_t stream_length; |
michael@0 | 163 | ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length)); |
michael@0 | 164 | ASSERT_EQ(15U, stream_length); |
michael@0 | 165 | char stream_contents[15]; |
michael@0 | 166 | ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents))); |
michael@0 | 167 | EXPECT_EQ(string("stream contents"), |
michael@0 | 168 | string(stream_contents, sizeof(stream_contents))); |
michael@0 | 169 | |
michael@0 | 170 | EXPECT_FALSE(minidump.GetThreadList()); |
michael@0 | 171 | EXPECT_FALSE(minidump.GetModuleList()); |
michael@0 | 172 | EXPECT_FALSE(minidump.GetMemoryList()); |
michael@0 | 173 | EXPECT_FALSE(minidump.GetException()); |
michael@0 | 174 | EXPECT_FALSE(minidump.GetAssertion()); |
michael@0 | 175 | EXPECT_FALSE(minidump.GetSystemInfo()); |
michael@0 | 176 | EXPECT_FALSE(minidump.GetMiscInfo()); |
michael@0 | 177 | EXPECT_FALSE(minidump.GetBreakpadInfo()); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | TEST(Dump, OneMemory) { |
michael@0 | 181 | Dump dump(0, kBigEndian); |
michael@0 | 182 | Memory memory(dump, 0x309d68010bd21b2cULL); |
michael@0 | 183 | memory.Append("memory contents"); |
michael@0 | 184 | dump.Add(&memory); |
michael@0 | 185 | dump.Finish(); |
michael@0 | 186 | |
michael@0 | 187 | string contents; |
michael@0 | 188 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 189 | istringstream minidump_stream(contents); |
michael@0 | 190 | Minidump minidump(minidump_stream); |
michael@0 | 191 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 192 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 193 | |
michael@0 | 194 | const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); |
michael@0 | 195 | ASSERT_TRUE(dir != NULL); |
michael@0 | 196 | EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); |
michael@0 | 197 | |
michael@0 | 198 | MinidumpMemoryList *memory_list = minidump.GetMemoryList(); |
michael@0 | 199 | ASSERT_TRUE(memory_list != NULL); |
michael@0 | 200 | ASSERT_EQ(1U, memory_list->region_count()); |
michael@0 | 201 | |
michael@0 | 202 | MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0); |
michael@0 | 203 | ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase()); |
michael@0 | 204 | ASSERT_EQ(15U, region1->GetSize()); |
michael@0 | 205 | const uint8_t *region1_bytes = region1->GetMemory(); |
michael@0 | 206 | ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0); |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | // One thread --- and its requisite entourage. |
michael@0 | 210 | TEST(Dump, OneThread) { |
michael@0 | 211 | Dump dump(0, kLittleEndian); |
michael@0 | 212 | Memory stack(dump, 0x2326a0fa); |
michael@0 | 213 | stack.Append("stack for thread"); |
michael@0 | 214 | |
michael@0 | 215 | MDRawContextX86 raw_context; |
michael@0 | 216 | const uint32_t kExpectedEIP = 0x6913f540; |
michael@0 | 217 | raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; |
michael@0 | 218 | raw_context.edi = 0x3ecba80d; |
michael@0 | 219 | raw_context.esi = 0x382583b9; |
michael@0 | 220 | raw_context.ebx = 0x7fccc03f; |
michael@0 | 221 | raw_context.edx = 0xf62f8ec2; |
michael@0 | 222 | raw_context.ecx = 0x46a6a6a8; |
michael@0 | 223 | raw_context.eax = 0x6a5025e2; |
michael@0 | 224 | raw_context.ebp = 0xd9fabb4a; |
michael@0 | 225 | raw_context.eip = kExpectedEIP; |
michael@0 | 226 | raw_context.cs = 0xbffe6eda; |
michael@0 | 227 | raw_context.eflags = 0xb2ce1e2d; |
michael@0 | 228 | raw_context.esp = 0x659caaa4; |
michael@0 | 229 | raw_context.ss = 0x2e951ef7; |
michael@0 | 230 | Context context(dump, raw_context); |
michael@0 | 231 | |
michael@0 | 232 | Thread thread(dump, 0xa898f11b, stack, context, |
michael@0 | 233 | 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); |
michael@0 | 234 | |
michael@0 | 235 | dump.Add(&stack); |
michael@0 | 236 | dump.Add(&context); |
michael@0 | 237 | dump.Add(&thread); |
michael@0 | 238 | dump.Finish(); |
michael@0 | 239 | |
michael@0 | 240 | string contents; |
michael@0 | 241 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 242 | |
michael@0 | 243 | istringstream minidump_stream(contents); |
michael@0 | 244 | Minidump minidump(minidump_stream); |
michael@0 | 245 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 246 | ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
michael@0 | 247 | |
michael@0 | 248 | MinidumpMemoryList *md_memory_list = minidump.GetMemoryList(); |
michael@0 | 249 | ASSERT_TRUE(md_memory_list != NULL); |
michael@0 | 250 | ASSERT_EQ(1U, md_memory_list->region_count()); |
michael@0 | 251 | |
michael@0 | 252 | MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0); |
michael@0 | 253 | ASSERT_EQ(0x2326a0faU, md_region->GetBase()); |
michael@0 | 254 | ASSERT_EQ(16U, md_region->GetSize()); |
michael@0 | 255 | const uint8_t *region_bytes = md_region->GetMemory(); |
michael@0 | 256 | ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); |
michael@0 | 257 | |
michael@0 | 258 | MinidumpThreadList *thread_list = minidump.GetThreadList(); |
michael@0 | 259 | ASSERT_TRUE(thread_list != NULL); |
michael@0 | 260 | ASSERT_EQ(1U, thread_list->thread_count()); |
michael@0 | 261 | |
michael@0 | 262 | MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0); |
michael@0 | 263 | ASSERT_TRUE(md_thread != NULL); |
michael@0 | 264 | uint32_t thread_id; |
michael@0 | 265 | ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); |
michael@0 | 266 | ASSERT_EQ(0xa898f11bU, thread_id); |
michael@0 | 267 | MinidumpMemoryRegion *md_stack = md_thread->GetMemory(); |
michael@0 | 268 | ASSERT_TRUE(md_stack != NULL); |
michael@0 | 269 | ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); |
michael@0 | 270 | ASSERT_EQ(16U, md_stack->GetSize()); |
michael@0 | 271 | const uint8_t *md_stack_bytes = md_stack->GetMemory(); |
michael@0 | 272 | ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); |
michael@0 | 273 | |
michael@0 | 274 | MinidumpContext *md_context = md_thread->GetContext(); |
michael@0 | 275 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 276 | ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); |
michael@0 | 277 | |
michael@0 | 278 | uint64_t eip; |
michael@0 | 279 | ASSERT_TRUE(md_context->GetInstructionPointer(&eip)); |
michael@0 | 280 | EXPECT_EQ(kExpectedEIP, eip); |
michael@0 | 281 | |
michael@0 | 282 | const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); |
michael@0 | 283 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 284 | ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), |
michael@0 | 285 | (md_raw_context->context_flags |
michael@0 | 286 | & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); |
michael@0 | 287 | EXPECT_EQ(0x3ecba80dU, raw_context.edi); |
michael@0 | 288 | EXPECT_EQ(0x382583b9U, raw_context.esi); |
michael@0 | 289 | EXPECT_EQ(0x7fccc03fU, raw_context.ebx); |
michael@0 | 290 | EXPECT_EQ(0xf62f8ec2U, raw_context.edx); |
michael@0 | 291 | EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); |
michael@0 | 292 | EXPECT_EQ(0x6a5025e2U, raw_context.eax); |
michael@0 | 293 | EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); |
michael@0 | 294 | EXPECT_EQ(kExpectedEIP, raw_context.eip); |
michael@0 | 295 | EXPECT_EQ(0xbffe6edaU, raw_context.cs); |
michael@0 | 296 | EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); |
michael@0 | 297 | EXPECT_EQ(0x659caaa4U, raw_context.esp); |
michael@0 | 298 | EXPECT_EQ(0x2e951ef7U, raw_context.ss); |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | TEST(Dump, ThreadMissingMemory) { |
michael@0 | 302 | Dump dump(0, kLittleEndian); |
michael@0 | 303 | Memory stack(dump, 0x2326a0fa); |
michael@0 | 304 | // Stack has no contents. |
michael@0 | 305 | |
michael@0 | 306 | MDRawContextX86 raw_context; |
michael@0 | 307 | memset(&raw_context, 0, sizeof(raw_context)); |
michael@0 | 308 | raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; |
michael@0 | 309 | Context context(dump, raw_context); |
michael@0 | 310 | |
michael@0 | 311 | Thread thread(dump, 0xa898f11b, stack, context, |
michael@0 | 312 | 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); |
michael@0 | 313 | |
michael@0 | 314 | dump.Add(&stack); |
michael@0 | 315 | dump.Add(&context); |
michael@0 | 316 | dump.Add(&thread); |
michael@0 | 317 | dump.Finish(); |
michael@0 | 318 | |
michael@0 | 319 | string contents; |
michael@0 | 320 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 321 | |
michael@0 | 322 | istringstream minidump_stream(contents); |
michael@0 | 323 | Minidump minidump(minidump_stream); |
michael@0 | 324 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 325 | ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
michael@0 | 326 | |
michael@0 | 327 | // This should succeed even though the thread has no stack memory. |
michael@0 | 328 | MinidumpThreadList* thread_list = minidump.GetThreadList(); |
michael@0 | 329 | ASSERT_TRUE(thread_list != NULL); |
michael@0 | 330 | ASSERT_EQ(1U, thread_list->thread_count()); |
michael@0 | 331 | |
michael@0 | 332 | MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); |
michael@0 | 333 | ASSERT_TRUE(md_thread != NULL); |
michael@0 | 334 | |
michael@0 | 335 | uint32_t thread_id; |
michael@0 | 336 | ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); |
michael@0 | 337 | ASSERT_EQ(0xa898f11bU, thread_id); |
michael@0 | 338 | |
michael@0 | 339 | MinidumpContext* md_context = md_thread->GetContext(); |
michael@0 | 340 | ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context); |
michael@0 | 341 | |
michael@0 | 342 | MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); |
michael@0 | 343 | ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | TEST(Dump, ThreadMissingContext) { |
michael@0 | 347 | Dump dump(0, kLittleEndian); |
michael@0 | 348 | Memory stack(dump, 0x2326a0fa); |
michael@0 | 349 | stack.Append("stack for thread"); |
michael@0 | 350 | |
michael@0 | 351 | // Context is empty. |
michael@0 | 352 | Context context(dump); |
michael@0 | 353 | |
michael@0 | 354 | Thread thread(dump, 0xa898f11b, stack, context, |
michael@0 | 355 | 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); |
michael@0 | 356 | |
michael@0 | 357 | dump.Add(&stack); |
michael@0 | 358 | dump.Add(&context); |
michael@0 | 359 | dump.Add(&thread); |
michael@0 | 360 | dump.Finish(); |
michael@0 | 361 | |
michael@0 | 362 | string contents; |
michael@0 | 363 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 364 | |
michael@0 | 365 | istringstream minidump_stream(contents); |
michael@0 | 366 | Minidump minidump(minidump_stream); |
michael@0 | 367 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 368 | ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
michael@0 | 369 | |
michael@0 | 370 | // This should succeed even though the thread has no stack memory. |
michael@0 | 371 | MinidumpThreadList* thread_list = minidump.GetThreadList(); |
michael@0 | 372 | ASSERT_TRUE(thread_list != NULL); |
michael@0 | 373 | ASSERT_EQ(1U, thread_list->thread_count()); |
michael@0 | 374 | |
michael@0 | 375 | MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); |
michael@0 | 376 | ASSERT_TRUE(md_thread != NULL); |
michael@0 | 377 | |
michael@0 | 378 | uint32_t thread_id; |
michael@0 | 379 | ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); |
michael@0 | 380 | ASSERT_EQ(0xa898f11bU, thread_id); |
michael@0 | 381 | MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); |
michael@0 | 382 | ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); |
michael@0 | 383 | |
michael@0 | 384 | MinidumpContext* md_context = md_thread->GetContext(); |
michael@0 | 385 | ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context); |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | TEST(Dump, OneModule) { |
michael@0 | 389 | static const MDVSFixedFileInfo fixed_file_info = { |
michael@0 | 390 | 0xb2fba33a, // signature |
michael@0 | 391 | 0x33d7a728, // struct_version |
michael@0 | 392 | 0x31afcb20, // file_version_hi |
michael@0 | 393 | 0xe51cdab1, // file_version_lo |
michael@0 | 394 | 0xd1ea6907, // product_version_hi |
michael@0 | 395 | 0x03032857, // product_version_lo |
michael@0 | 396 | 0x11bf71d7, // file_flags_mask |
michael@0 | 397 | 0x5fb8cdbf, // file_flags |
michael@0 | 398 | 0xe45d0d5d, // file_os |
michael@0 | 399 | 0x107d9562, // file_type |
michael@0 | 400 | 0x5a8844d4, // file_subtype |
michael@0 | 401 | 0xa8d30b20, // file_date_hi |
michael@0 | 402 | 0x651c3e4e // file_date_lo |
michael@0 | 403 | }; |
michael@0 | 404 | |
michael@0 | 405 | Dump dump(0, kBigEndian); |
michael@0 | 406 | String module_name(dump, "single module"); |
michael@0 | 407 | Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, |
michael@0 | 408 | module_name, |
michael@0 | 409 | 0xb1054d2a, |
michael@0 | 410 | 0x34571371, |
michael@0 | 411 | fixed_file_info, // from synth_minidump_unittest_data.h |
michael@0 | 412 | NULL, NULL); |
michael@0 | 413 | |
michael@0 | 414 | dump.Add(&module); |
michael@0 | 415 | dump.Add(&module_name); |
michael@0 | 416 | dump.Finish(); |
michael@0 | 417 | |
michael@0 | 418 | string contents; |
michael@0 | 419 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 420 | istringstream minidump_stream(contents); |
michael@0 | 421 | Minidump minidump(minidump_stream); |
michael@0 | 422 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 423 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 424 | |
michael@0 | 425 | const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); |
michael@0 | 426 | ASSERT_TRUE(dir != NULL); |
michael@0 | 427 | EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); |
michael@0 | 428 | |
michael@0 | 429 | MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
michael@0 | 430 | ASSERT_TRUE(md_module_list != NULL); |
michael@0 | 431 | ASSERT_EQ(1U, md_module_list->module_count()); |
michael@0 | 432 | |
michael@0 | 433 | const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); |
michael@0 | 434 | ASSERT_TRUE(md_module != NULL); |
michael@0 | 435 | ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); |
michael@0 | 436 | ASSERT_EQ(0xada542bd, md_module->size()); |
michael@0 | 437 | ASSERT_EQ("single module", md_module->code_file()); |
michael@0 | 438 | |
michael@0 | 439 | const MDRawModule *md_raw_module = md_module->module(); |
michael@0 | 440 | ASSERT_TRUE(md_raw_module != NULL); |
michael@0 | 441 | ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); |
michael@0 | 442 | ASSERT_EQ(0x34571371U, md_raw_module->checksum); |
michael@0 | 443 | ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, |
michael@0 | 444 | sizeof(fixed_file_info)) == 0); |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | TEST(Dump, OneSystemInfo) { |
michael@0 | 448 | Dump dump(0, kLittleEndian); |
michael@0 | 449 | String csd_version(dump, "Petulant Pierogi"); |
michael@0 | 450 | SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); |
michael@0 | 451 | |
michael@0 | 452 | dump.Add(&system_info); |
michael@0 | 453 | dump.Add(&csd_version); |
michael@0 | 454 | dump.Finish(); |
michael@0 | 455 | |
michael@0 | 456 | string contents; |
michael@0 | 457 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 458 | istringstream minidump_stream(contents); |
michael@0 | 459 | Minidump minidump(minidump_stream); |
michael@0 | 460 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 461 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 462 | |
michael@0 | 463 | const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); |
michael@0 | 464 | ASSERT_TRUE(dir != NULL); |
michael@0 | 465 | EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); |
michael@0 | 466 | |
michael@0 | 467 | MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo(); |
michael@0 | 468 | ASSERT_TRUE(md_system_info != NULL); |
michael@0 | 469 | ASSERT_EQ("windows", md_system_info->GetOS()); |
michael@0 | 470 | ASSERT_EQ("x86", md_system_info->GetCPU()); |
michael@0 | 471 | ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); |
michael@0 | 472 | ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor()); |
michael@0 | 473 | } |
michael@0 | 474 | |
michael@0 | 475 | TEST(Dump, BigDump) { |
michael@0 | 476 | Dump dump(0, kLittleEndian); |
michael@0 | 477 | |
michael@0 | 478 | // A SystemInfo stream. |
michael@0 | 479 | String csd_version(dump, "Munificent Macaque"); |
michael@0 | 480 | SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); |
michael@0 | 481 | dump.Add(&csd_version); |
michael@0 | 482 | dump.Add(&system_info); |
michael@0 | 483 | |
michael@0 | 484 | // Five threads! |
michael@0 | 485 | Memory stack0(dump, 0x70b9ebfc); |
michael@0 | 486 | stack0.Append("stack for thread zero"); |
michael@0 | 487 | MDRawContextX86 raw_context0; |
michael@0 | 488 | raw_context0.context_flags = MD_CONTEXT_X86_INTEGER; |
michael@0 | 489 | raw_context0.eip = 0xaf0709e4; |
michael@0 | 490 | Context context0(dump, raw_context0); |
michael@0 | 491 | Thread thread0(dump, 0xbbef4432, stack0, context0, |
michael@0 | 492 | 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL); |
michael@0 | 493 | dump.Add(&stack0); |
michael@0 | 494 | dump.Add(&context0); |
michael@0 | 495 | dump.Add(&thread0); |
michael@0 | 496 | |
michael@0 | 497 | Memory stack1(dump, 0xf988cc45); |
michael@0 | 498 | stack1.Append("stack for thread one"); |
michael@0 | 499 | MDRawContextX86 raw_context1; |
michael@0 | 500 | raw_context1.context_flags = MD_CONTEXT_X86_INTEGER; |
michael@0 | 501 | raw_context1.eip = 0xe4f56f81; |
michael@0 | 502 | Context context1(dump, raw_context1); |
michael@0 | 503 | Thread thread1(dump, 0x657c3f58, stack1, context1, |
michael@0 | 504 | 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL); |
michael@0 | 505 | dump.Add(&stack1); |
michael@0 | 506 | dump.Add(&context1); |
michael@0 | 507 | dump.Add(&thread1); |
michael@0 | 508 | |
michael@0 | 509 | Memory stack2(dump, 0xc8a92e7c); |
michael@0 | 510 | stack2.Append("stack for thread two"); |
michael@0 | 511 | MDRawContextX86 raw_context2; |
michael@0 | 512 | raw_context2.context_flags = MD_CONTEXT_X86_INTEGER; |
michael@0 | 513 | raw_context2.eip = 0xb336a438; |
michael@0 | 514 | Context context2(dump, raw_context2); |
michael@0 | 515 | Thread thread2(dump, 0xdf4b8a71, stack2, context2, |
michael@0 | 516 | 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL); |
michael@0 | 517 | dump.Add(&stack2); |
michael@0 | 518 | dump.Add(&context2); |
michael@0 | 519 | dump.Add(&thread2); |
michael@0 | 520 | |
michael@0 | 521 | Memory stack3(dump, 0x36d08e08); |
michael@0 | 522 | stack3.Append("stack for thread three"); |
michael@0 | 523 | MDRawContextX86 raw_context3; |
michael@0 | 524 | raw_context3.context_flags = MD_CONTEXT_X86_INTEGER; |
michael@0 | 525 | raw_context3.eip = 0xdf99a60c; |
michael@0 | 526 | Context context3(dump, raw_context3); |
michael@0 | 527 | Thread thread3(dump, 0x86e6c341, stack3, context3, |
michael@0 | 528 | 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL); |
michael@0 | 529 | dump.Add(&stack3); |
michael@0 | 530 | dump.Add(&context3); |
michael@0 | 531 | dump.Add(&thread3); |
michael@0 | 532 | |
michael@0 | 533 | Memory stack4(dump, 0x1e0ab4fa); |
michael@0 | 534 | stack4.Append("stack for thread four"); |
michael@0 | 535 | MDRawContextX86 raw_context4; |
michael@0 | 536 | raw_context4.context_flags = MD_CONTEXT_X86_INTEGER; |
michael@0 | 537 | raw_context4.eip = 0xaa646267; |
michael@0 | 538 | Context context4(dump, raw_context4); |
michael@0 | 539 | Thread thread4(dump, 0x261a28d4, stack4, context4, |
michael@0 | 540 | 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL); |
michael@0 | 541 | dump.Add(&stack4); |
michael@0 | 542 | dump.Add(&context4); |
michael@0 | 543 | dump.Add(&thread4); |
michael@0 | 544 | |
michael@0 | 545 | // Three modules! |
michael@0 | 546 | String module1_name(dump, "module one"); |
michael@0 | 547 | Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name); |
michael@0 | 548 | dump.Add(&module1_name); |
michael@0 | 549 | dump.Add(&module1); |
michael@0 | 550 | |
michael@0 | 551 | String module2_name(dump, "module two"); |
michael@0 | 552 | Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name); |
michael@0 | 553 | dump.Add(&module2_name); |
michael@0 | 554 | dump.Add(&module2); |
michael@0 | 555 | |
michael@0 | 556 | String module3_name(dump, "module three"); |
michael@0 | 557 | Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name); |
michael@0 | 558 | dump.Add(&module3_name); |
michael@0 | 559 | dump.Add(&module3); |
michael@0 | 560 | |
michael@0 | 561 | // Add one more memory region, on top of the five stacks. |
michael@0 | 562 | Memory memory5(dump, 0x61979e828040e564ULL); |
michael@0 | 563 | memory5.Append("contents of memory 5"); |
michael@0 | 564 | dump.Add(&memory5); |
michael@0 | 565 | |
michael@0 | 566 | dump.Finish(); |
michael@0 | 567 | |
michael@0 | 568 | string contents; |
michael@0 | 569 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 570 | istringstream minidump_stream(contents); |
michael@0 | 571 | Minidump minidump(minidump_stream); |
michael@0 | 572 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 573 | ASSERT_EQ(4U, minidump.GetDirectoryEntryCount()); |
michael@0 | 574 | |
michael@0 | 575 | // Check the threads. |
michael@0 | 576 | MinidumpThreadList *thread_list = minidump.GetThreadList(); |
michael@0 | 577 | ASSERT_TRUE(thread_list != NULL); |
michael@0 | 578 | ASSERT_EQ(5U, thread_list->thread_count()); |
michael@0 | 579 | uint32_t thread_id; |
michael@0 | 580 | ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); |
michael@0 | 581 | ASSERT_EQ(0xbbef4432U, thread_id); |
michael@0 | 582 | ASSERT_EQ(0x70b9ebfcU, |
michael@0 | 583 | thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase()); |
michael@0 | 584 | ASSERT_EQ(0xaf0709e4U, |
michael@0 | 585 | thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86() |
michael@0 | 586 | ->eip); |
michael@0 | 587 | |
michael@0 | 588 | ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id)); |
michael@0 | 589 | ASSERT_EQ(0x657c3f58U, thread_id); |
michael@0 | 590 | ASSERT_EQ(0xf988cc45U, |
michael@0 | 591 | thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase()); |
michael@0 | 592 | ASSERT_EQ(0xe4f56f81U, |
michael@0 | 593 | thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86() |
michael@0 | 594 | ->eip); |
michael@0 | 595 | |
michael@0 | 596 | ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id)); |
michael@0 | 597 | ASSERT_EQ(0xdf4b8a71U, thread_id); |
michael@0 | 598 | ASSERT_EQ(0xc8a92e7cU, |
michael@0 | 599 | thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase()); |
michael@0 | 600 | ASSERT_EQ(0xb336a438U, |
michael@0 | 601 | thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86() |
michael@0 | 602 | ->eip); |
michael@0 | 603 | |
michael@0 | 604 | ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id)); |
michael@0 | 605 | ASSERT_EQ(0x86e6c341U, thread_id); |
michael@0 | 606 | ASSERT_EQ(0x36d08e08U, |
michael@0 | 607 | thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase()); |
michael@0 | 608 | ASSERT_EQ(0xdf99a60cU, |
michael@0 | 609 | thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86() |
michael@0 | 610 | ->eip); |
michael@0 | 611 | |
michael@0 | 612 | ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id)); |
michael@0 | 613 | ASSERT_EQ(0x261a28d4U, thread_id); |
michael@0 | 614 | ASSERT_EQ(0x1e0ab4faU, |
michael@0 | 615 | thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase()); |
michael@0 | 616 | ASSERT_EQ(0xaa646267U, |
michael@0 | 617 | thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86() |
michael@0 | 618 | ->eip); |
michael@0 | 619 | |
michael@0 | 620 | // Check the modules. |
michael@0 | 621 | MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
michael@0 | 622 | ASSERT_TRUE(md_module_list != NULL); |
michael@0 | 623 | ASSERT_EQ(3U, md_module_list->module_count()); |
michael@0 | 624 | EXPECT_EQ(0xeb77da57b5d4cbdaULL, |
michael@0 | 625 | md_module_list->GetModuleAtIndex(0)->base_address()); |
michael@0 | 626 | EXPECT_EQ(0x8675884adfe5ac90ULL, |
michael@0 | 627 | md_module_list->GetModuleAtIndex(1)->base_address()); |
michael@0 | 628 | EXPECT_EQ(0x95fc1544da321b6cULL, |
michael@0 | 629 | md_module_list->GetModuleAtIndex(2)->base_address()); |
michael@0 | 630 | } |
michael@0 | 631 | |
michael@0 | 632 | TEST(Dump, OneMemoryInfo) { |
michael@0 | 633 | Dump dump(0, kBigEndian); |
michael@0 | 634 | Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM); |
michael@0 | 635 | |
michael@0 | 636 | // Add the MDRawMemoryInfoList header. |
michael@0 | 637 | const uint64_t kNumberOfEntries = 1; |
michael@0 | 638 | stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header |
michael@0 | 639 | .D32(sizeof(MDRawMemoryInfo)) // size_of_entry |
michael@0 | 640 | .D64(kNumberOfEntries); // number_of_entries |
michael@0 | 641 | |
michael@0 | 642 | |
michael@0 | 643 | // Now add a MDRawMemoryInfo entry. |
michael@0 | 644 | const uint64_t kBaseAddress = 0x1000; |
michael@0 | 645 | const uint64_t kRegionSize = 0x2000; |
michael@0 | 646 | stream.D64(kBaseAddress) // base_address |
michael@0 | 647 | .D64(kBaseAddress) // allocation_base |
michael@0 | 648 | .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection |
michael@0 | 649 | .D32(0) // __alignment1 |
michael@0 | 650 | .D64(kRegionSize) // region_size |
michael@0 | 651 | .D32(MD_MEMORY_STATE_COMMIT) // state |
michael@0 | 652 | .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection |
michael@0 | 653 | .D32(MD_MEMORY_TYPE_PRIVATE) // type |
michael@0 | 654 | .D32(0); // __alignment2 |
michael@0 | 655 | |
michael@0 | 656 | dump.Add(&stream); |
michael@0 | 657 | dump.Finish(); |
michael@0 | 658 | |
michael@0 | 659 | string contents; |
michael@0 | 660 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 661 | istringstream minidump_stream(contents); |
michael@0 | 662 | Minidump minidump(minidump_stream); |
michael@0 | 663 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 664 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 665 | |
michael@0 | 666 | const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); |
michael@0 | 667 | ASSERT_TRUE(dir != NULL); |
michael@0 | 668 | EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type); |
michael@0 | 669 | |
michael@0 | 670 | MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList(); |
michael@0 | 671 | ASSERT_TRUE(info_list != NULL); |
michael@0 | 672 | ASSERT_EQ(1U, info_list->info_count()); |
michael@0 | 673 | |
michael@0 | 674 | const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0); |
michael@0 | 675 | ASSERT_EQ(kBaseAddress, info1->GetBase()); |
michael@0 | 676 | ASSERT_EQ(kRegionSize, info1->GetSize()); |
michael@0 | 677 | ASSERT_TRUE(info1->IsExecutable()); |
michael@0 | 678 | ASSERT_TRUE(info1->IsWritable()); |
michael@0 | 679 | |
michael@0 | 680 | // Should get back the same memory region here. |
michael@0 | 681 | const MinidumpMemoryInfo *info2 = |
michael@0 | 682 | info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2); |
michael@0 | 683 | ASSERT_EQ(kBaseAddress, info2->GetBase()); |
michael@0 | 684 | ASSERT_EQ(kRegionSize, info2->GetSize()); |
michael@0 | 685 | } |
michael@0 | 686 | |
michael@0 | 687 | TEST(Dump, OneExceptionX86) { |
michael@0 | 688 | Dump dump(0, kLittleEndian); |
michael@0 | 689 | |
michael@0 | 690 | MDRawContextX86 raw_context; |
michael@0 | 691 | raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; |
michael@0 | 692 | raw_context.edi = 0x3ecba80d; |
michael@0 | 693 | raw_context.esi = 0x382583b9; |
michael@0 | 694 | raw_context.ebx = 0x7fccc03f; |
michael@0 | 695 | raw_context.edx = 0xf62f8ec2; |
michael@0 | 696 | raw_context.ecx = 0x46a6a6a8; |
michael@0 | 697 | raw_context.eax = 0x6a5025e2; |
michael@0 | 698 | raw_context.ebp = 0xd9fabb4a; |
michael@0 | 699 | raw_context.eip = 0x6913f540; |
michael@0 | 700 | raw_context.cs = 0xbffe6eda; |
michael@0 | 701 | raw_context.eflags = 0xb2ce1e2d; |
michael@0 | 702 | raw_context.esp = 0x659caaa4; |
michael@0 | 703 | raw_context.ss = 0x2e951ef7; |
michael@0 | 704 | Context context(dump, raw_context); |
michael@0 | 705 | |
michael@0 | 706 | Exception exception(dump, context, |
michael@0 | 707 | 0x1234abcd, // thread id |
michael@0 | 708 | 0xdcba4321, // exception code |
michael@0 | 709 | 0xf0e0d0c0, // exception flags |
michael@0 | 710 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 711 | |
michael@0 | 712 | dump.Add(&context); |
michael@0 | 713 | dump.Add(&exception); |
michael@0 | 714 | dump.Finish(); |
michael@0 | 715 | |
michael@0 | 716 | string contents; |
michael@0 | 717 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 718 | |
michael@0 | 719 | istringstream minidump_stream(contents); |
michael@0 | 720 | Minidump minidump(minidump_stream); |
michael@0 | 721 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 722 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 723 | |
michael@0 | 724 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 725 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 726 | |
michael@0 | 727 | uint32_t thread_id; |
michael@0 | 728 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 729 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 730 | |
michael@0 | 731 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 732 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 733 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 734 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 735 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 736 | raw_exception->exception_record.exception_address); |
michael@0 | 737 | |
michael@0 | 738 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 739 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 740 | ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); |
michael@0 | 741 | const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); |
michael@0 | 742 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 743 | ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), |
michael@0 | 744 | (md_raw_context->context_flags |
michael@0 | 745 | & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); |
michael@0 | 746 | EXPECT_EQ(0x3ecba80dU, raw_context.edi); |
michael@0 | 747 | EXPECT_EQ(0x382583b9U, raw_context.esi); |
michael@0 | 748 | EXPECT_EQ(0x7fccc03fU, raw_context.ebx); |
michael@0 | 749 | EXPECT_EQ(0xf62f8ec2U, raw_context.edx); |
michael@0 | 750 | EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); |
michael@0 | 751 | EXPECT_EQ(0x6a5025e2U, raw_context.eax); |
michael@0 | 752 | EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); |
michael@0 | 753 | EXPECT_EQ(0x6913f540U, raw_context.eip); |
michael@0 | 754 | EXPECT_EQ(0xbffe6edaU, raw_context.cs); |
michael@0 | 755 | EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); |
michael@0 | 756 | EXPECT_EQ(0x659caaa4U, raw_context.esp); |
michael@0 | 757 | EXPECT_EQ(0x2e951ef7U, raw_context.ss); |
michael@0 | 758 | } |
michael@0 | 759 | |
michael@0 | 760 | TEST(Dump, OneExceptionX86XState) { |
michael@0 | 761 | Dump dump(0, kLittleEndian); |
michael@0 | 762 | |
michael@0 | 763 | MDRawContextX86 raw_context; |
michael@0 | 764 | raw_context.context_flags = MD_CONTEXT_X86_INTEGER | |
michael@0 | 765 | MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE; |
michael@0 | 766 | raw_context.edi = 0x3ecba80d; |
michael@0 | 767 | raw_context.esi = 0x382583b9; |
michael@0 | 768 | raw_context.ebx = 0x7fccc03f; |
michael@0 | 769 | raw_context.edx = 0xf62f8ec2; |
michael@0 | 770 | raw_context.ecx = 0x46a6a6a8; |
michael@0 | 771 | raw_context.eax = 0x6a5025e2; |
michael@0 | 772 | raw_context.ebp = 0xd9fabb4a; |
michael@0 | 773 | raw_context.eip = 0x6913f540; |
michael@0 | 774 | raw_context.cs = 0xbffe6eda; |
michael@0 | 775 | raw_context.eflags = 0xb2ce1e2d; |
michael@0 | 776 | raw_context.esp = 0x659caaa4; |
michael@0 | 777 | raw_context.ss = 0x2e951ef7; |
michael@0 | 778 | Context context(dump, raw_context); |
michael@0 | 779 | |
michael@0 | 780 | Exception exception(dump, context, |
michael@0 | 781 | 0x1234abcd, // thread id |
michael@0 | 782 | 0xdcba4321, // exception code |
michael@0 | 783 | 0xf0e0d0c0, // exception flags |
michael@0 | 784 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 785 | |
michael@0 | 786 | dump.Add(&context); |
michael@0 | 787 | dump.Add(&exception); |
michael@0 | 788 | dump.Finish(); |
michael@0 | 789 | |
michael@0 | 790 | string contents; |
michael@0 | 791 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 792 | |
michael@0 | 793 | istringstream minidump_stream(contents); |
michael@0 | 794 | Minidump minidump(minidump_stream); |
michael@0 | 795 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 796 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 797 | |
michael@0 | 798 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 799 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 800 | |
michael@0 | 801 | uint32_t thread_id; |
michael@0 | 802 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 803 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 804 | |
michael@0 | 805 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 806 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 807 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 808 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 809 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 810 | raw_exception->exception_record.exception_address); |
michael@0 | 811 | |
michael@0 | 812 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 813 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 814 | ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); |
michael@0 | 815 | const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); |
michael@0 | 816 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 817 | ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), |
michael@0 | 818 | (md_raw_context->context_flags |
michael@0 | 819 | & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); |
michael@0 | 820 | EXPECT_EQ(0x3ecba80dU, raw_context.edi); |
michael@0 | 821 | EXPECT_EQ(0x382583b9U, raw_context.esi); |
michael@0 | 822 | EXPECT_EQ(0x7fccc03fU, raw_context.ebx); |
michael@0 | 823 | EXPECT_EQ(0xf62f8ec2U, raw_context.edx); |
michael@0 | 824 | EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); |
michael@0 | 825 | EXPECT_EQ(0x6a5025e2U, raw_context.eax); |
michael@0 | 826 | EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); |
michael@0 | 827 | EXPECT_EQ(0x6913f540U, raw_context.eip); |
michael@0 | 828 | EXPECT_EQ(0xbffe6edaU, raw_context.cs); |
michael@0 | 829 | EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); |
michael@0 | 830 | EXPECT_EQ(0x659caaa4U, raw_context.esp); |
michael@0 | 831 | EXPECT_EQ(0x2e951ef7U, raw_context.ss); |
michael@0 | 832 | } |
michael@0 | 833 | |
michael@0 | 834 | // Testing that the CPU type can be loaded from a system info stream when |
michael@0 | 835 | // the CPU flags are missing from the context_flags of an exception record |
michael@0 | 836 | TEST(Dump, OneExceptionX86NoCPUFlags) { |
michael@0 | 837 | Dump dump(0, kLittleEndian); |
michael@0 | 838 | |
michael@0 | 839 | MDRawContextX86 raw_context; |
michael@0 | 840 | // Intentionally not setting CPU type in the context_flags |
michael@0 | 841 | raw_context.context_flags = 0; |
michael@0 | 842 | raw_context.edi = 0x3ecba80d; |
michael@0 | 843 | raw_context.esi = 0x382583b9; |
michael@0 | 844 | raw_context.ebx = 0x7fccc03f; |
michael@0 | 845 | raw_context.edx = 0xf62f8ec2; |
michael@0 | 846 | raw_context.ecx = 0x46a6a6a8; |
michael@0 | 847 | raw_context.eax = 0x6a5025e2; |
michael@0 | 848 | raw_context.ebp = 0xd9fabb4a; |
michael@0 | 849 | raw_context.eip = 0x6913f540; |
michael@0 | 850 | raw_context.cs = 0xbffe6eda; |
michael@0 | 851 | raw_context.eflags = 0xb2ce1e2d; |
michael@0 | 852 | raw_context.esp = 0x659caaa4; |
michael@0 | 853 | raw_context.ss = 0x2e951ef7; |
michael@0 | 854 | Context context(dump, raw_context); |
michael@0 | 855 | |
michael@0 | 856 | Exception exception(dump, context, |
michael@0 | 857 | 0x1234abcd, // thread id |
michael@0 | 858 | 0xdcba4321, // exception code |
michael@0 | 859 | 0xf0e0d0c0, // exception flags |
michael@0 | 860 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 861 | |
michael@0 | 862 | dump.Add(&context); |
michael@0 | 863 | dump.Add(&exception); |
michael@0 | 864 | |
michael@0 | 865 | // Add system info. This is needed as an alternative source for CPU type |
michael@0 | 866 | // information. Note, that the CPU flags were intentionally skipped from |
michael@0 | 867 | // the context_flags and this alternative source is required. |
michael@0 | 868 | String csd_version(dump, "Service Pack 2"); |
michael@0 | 869 | SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); |
michael@0 | 870 | dump.Add(&system_info); |
michael@0 | 871 | dump.Add(&csd_version); |
michael@0 | 872 | |
michael@0 | 873 | dump.Finish(); |
michael@0 | 874 | |
michael@0 | 875 | string contents; |
michael@0 | 876 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 877 | |
michael@0 | 878 | istringstream minidump_stream(contents); |
michael@0 | 879 | Minidump minidump(minidump_stream); |
michael@0 | 880 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 881 | ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
michael@0 | 882 | |
michael@0 | 883 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 884 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 885 | |
michael@0 | 886 | uint32_t thread_id; |
michael@0 | 887 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 888 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 889 | |
michael@0 | 890 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 891 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 892 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 893 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 894 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 895 | raw_exception->exception_record.exception_address); |
michael@0 | 896 | |
michael@0 | 897 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 898 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 899 | |
michael@0 | 900 | ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); |
michael@0 | 901 | const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); |
michael@0 | 902 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 903 | |
michael@0 | 904 | // Even though the CPU flags were missing from the context_flags, the |
michael@0 | 905 | // GetContext call above is expected to load the missing CPU flags from the |
michael@0 | 906 | // system info stream and set the CPU type bits in context_flags. |
michael@0 | 907 | ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags); |
michael@0 | 908 | |
michael@0 | 909 | EXPECT_EQ(0x3ecba80dU, raw_context.edi); |
michael@0 | 910 | EXPECT_EQ(0x382583b9U, raw_context.esi); |
michael@0 | 911 | EXPECT_EQ(0x7fccc03fU, raw_context.ebx); |
michael@0 | 912 | EXPECT_EQ(0xf62f8ec2U, raw_context.edx); |
michael@0 | 913 | EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); |
michael@0 | 914 | EXPECT_EQ(0x6a5025e2U, raw_context.eax); |
michael@0 | 915 | EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); |
michael@0 | 916 | EXPECT_EQ(0x6913f540U, raw_context.eip); |
michael@0 | 917 | EXPECT_EQ(0xbffe6edaU, raw_context.cs); |
michael@0 | 918 | EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); |
michael@0 | 919 | EXPECT_EQ(0x659caaa4U, raw_context.esp); |
michael@0 | 920 | EXPECT_EQ(0x2e951ef7U, raw_context.ss); |
michael@0 | 921 | } |
michael@0 | 922 | |
michael@0 | 923 | // This test covers a scenario where a dump contains an exception but the |
michael@0 | 924 | // context record of the exception is missing the CPU type information in its |
michael@0 | 925 | // context_flags. The dump has no system info stream so it is imposible to |
michael@0 | 926 | // deduce the CPU type, hence the context record is unusable. |
michael@0 | 927 | TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) { |
michael@0 | 928 | Dump dump(0, kLittleEndian); |
michael@0 | 929 | |
michael@0 | 930 | MDRawContextX86 raw_context; |
michael@0 | 931 | // Intentionally not setting CPU type in the context_flags |
michael@0 | 932 | raw_context.context_flags = 0; |
michael@0 | 933 | raw_context.edi = 0x3ecba80d; |
michael@0 | 934 | raw_context.esi = 0x382583b9; |
michael@0 | 935 | raw_context.ebx = 0x7fccc03f; |
michael@0 | 936 | raw_context.edx = 0xf62f8ec2; |
michael@0 | 937 | raw_context.ecx = 0x46a6a6a8; |
michael@0 | 938 | raw_context.eax = 0x6a5025e2; |
michael@0 | 939 | raw_context.ebp = 0xd9fabb4a; |
michael@0 | 940 | raw_context.eip = 0x6913f540; |
michael@0 | 941 | raw_context.cs = 0xbffe6eda; |
michael@0 | 942 | raw_context.eflags = 0xb2ce1e2d; |
michael@0 | 943 | raw_context.esp = 0x659caaa4; |
michael@0 | 944 | raw_context.ss = 0x2e951ef7; |
michael@0 | 945 | Context context(dump, raw_context); |
michael@0 | 946 | |
michael@0 | 947 | Exception exception(dump, context, |
michael@0 | 948 | 0x1234abcd, // thread id |
michael@0 | 949 | 0xdcba4321, // exception code |
michael@0 | 950 | 0xf0e0d0c0, // exception flags |
michael@0 | 951 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 952 | |
michael@0 | 953 | dump.Add(&context); |
michael@0 | 954 | dump.Add(&exception); |
michael@0 | 955 | dump.Finish(); |
michael@0 | 956 | |
michael@0 | 957 | string contents; |
michael@0 | 958 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 959 | |
michael@0 | 960 | istringstream minidump_stream(contents); |
michael@0 | 961 | Minidump minidump(minidump_stream); |
michael@0 | 962 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 963 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 964 | |
michael@0 | 965 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 966 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 967 | |
michael@0 | 968 | uint32_t thread_id; |
michael@0 | 969 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 970 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 971 | |
michael@0 | 972 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 973 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 974 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 975 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 976 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 977 | raw_exception->exception_record.exception_address); |
michael@0 | 978 | |
michael@0 | 979 | // The context record of the exception is unusable because the context_flags |
michael@0 | 980 | // don't have CPU type information and at the same time the minidump lacks |
michael@0 | 981 | // system info stream so it is impossible to deduce the CPU type. |
michael@0 | 982 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 983 | ASSERT_EQ(NULL, md_context); |
michael@0 | 984 | } |
michael@0 | 985 | |
michael@0 | 986 | TEST(Dump, OneExceptionARM) { |
michael@0 | 987 | Dump dump(0, kLittleEndian); |
michael@0 | 988 | |
michael@0 | 989 | MDRawContextARM raw_context; |
michael@0 | 990 | raw_context.context_flags = MD_CONTEXT_ARM_INTEGER; |
michael@0 | 991 | raw_context.iregs[0] = 0x3ecba80d; |
michael@0 | 992 | raw_context.iregs[1] = 0x382583b9; |
michael@0 | 993 | raw_context.iregs[2] = 0x7fccc03f; |
michael@0 | 994 | raw_context.iregs[3] = 0xf62f8ec2; |
michael@0 | 995 | raw_context.iregs[4] = 0x46a6a6a8; |
michael@0 | 996 | raw_context.iregs[5] = 0x6a5025e2; |
michael@0 | 997 | raw_context.iregs[6] = 0xd9fabb4a; |
michael@0 | 998 | raw_context.iregs[7] = 0x6913f540; |
michael@0 | 999 | raw_context.iregs[8] = 0xbffe6eda; |
michael@0 | 1000 | raw_context.iregs[9] = 0xb2ce1e2d; |
michael@0 | 1001 | raw_context.iregs[10] = 0x659caaa4; |
michael@0 | 1002 | raw_context.iregs[11] = 0xf0e0d0c0; |
michael@0 | 1003 | raw_context.iregs[12] = 0xa9b8c7d6; |
michael@0 | 1004 | raw_context.iregs[13] = 0x12345678; |
michael@0 | 1005 | raw_context.iregs[14] = 0xabcd1234; |
michael@0 | 1006 | raw_context.iregs[15] = 0x10203040; |
michael@0 | 1007 | raw_context.cpsr = 0x2e951ef7; |
michael@0 | 1008 | Context context(dump, raw_context); |
michael@0 | 1009 | |
michael@0 | 1010 | Exception exception(dump, context, |
michael@0 | 1011 | 0x1234abcd, // thread id |
michael@0 | 1012 | 0xdcba4321, // exception code |
michael@0 | 1013 | 0xf0e0d0c0, // exception flags |
michael@0 | 1014 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 1015 | |
michael@0 | 1016 | dump.Add(&context); |
michael@0 | 1017 | dump.Add(&exception); |
michael@0 | 1018 | dump.Finish(); |
michael@0 | 1019 | |
michael@0 | 1020 | string contents; |
michael@0 | 1021 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 1022 | |
michael@0 | 1023 | istringstream minidump_stream(contents); |
michael@0 | 1024 | Minidump minidump(minidump_stream); |
michael@0 | 1025 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 1026 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 1027 | |
michael@0 | 1028 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 1029 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 1030 | |
michael@0 | 1031 | uint32_t thread_id; |
michael@0 | 1032 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 1033 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 1034 | |
michael@0 | 1035 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 1036 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 1037 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 1038 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 1039 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 1040 | raw_exception->exception_record.exception_address); |
michael@0 | 1041 | |
michael@0 | 1042 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 1043 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 1044 | ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); |
michael@0 | 1045 | const MDRawContextARM *md_raw_context = md_context->GetContextARM(); |
michael@0 | 1046 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 1047 | ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, |
michael@0 | 1048 | (md_raw_context->context_flags |
michael@0 | 1049 | & MD_CONTEXT_ARM_INTEGER)); |
michael@0 | 1050 | EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); |
michael@0 | 1051 | EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); |
michael@0 | 1052 | EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); |
michael@0 | 1053 | EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); |
michael@0 | 1054 | EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); |
michael@0 | 1055 | EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); |
michael@0 | 1056 | EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); |
michael@0 | 1057 | EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); |
michael@0 | 1058 | EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); |
michael@0 | 1059 | EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); |
michael@0 | 1060 | EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); |
michael@0 | 1061 | EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); |
michael@0 | 1062 | EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); |
michael@0 | 1063 | EXPECT_EQ(0x12345678U, raw_context.iregs[13]); |
michael@0 | 1064 | EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); |
michael@0 | 1065 | EXPECT_EQ(0x10203040U, raw_context.iregs[15]); |
michael@0 | 1066 | EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); |
michael@0 | 1067 | } |
michael@0 | 1068 | |
michael@0 | 1069 | TEST(Dump, OneExceptionARMOldFlags) { |
michael@0 | 1070 | Dump dump(0, kLittleEndian); |
michael@0 | 1071 | |
michael@0 | 1072 | MDRawContextARM raw_context; |
michael@0 | 1073 | // MD_CONTEXT_ARM_INTEGER, but with _OLD |
michael@0 | 1074 | raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002; |
michael@0 | 1075 | raw_context.iregs[0] = 0x3ecba80d; |
michael@0 | 1076 | raw_context.iregs[1] = 0x382583b9; |
michael@0 | 1077 | raw_context.iregs[2] = 0x7fccc03f; |
michael@0 | 1078 | raw_context.iregs[3] = 0xf62f8ec2; |
michael@0 | 1079 | raw_context.iregs[4] = 0x46a6a6a8; |
michael@0 | 1080 | raw_context.iregs[5] = 0x6a5025e2; |
michael@0 | 1081 | raw_context.iregs[6] = 0xd9fabb4a; |
michael@0 | 1082 | raw_context.iregs[7] = 0x6913f540; |
michael@0 | 1083 | raw_context.iregs[8] = 0xbffe6eda; |
michael@0 | 1084 | raw_context.iregs[9] = 0xb2ce1e2d; |
michael@0 | 1085 | raw_context.iregs[10] = 0x659caaa4; |
michael@0 | 1086 | raw_context.iregs[11] = 0xf0e0d0c0; |
michael@0 | 1087 | raw_context.iregs[12] = 0xa9b8c7d6; |
michael@0 | 1088 | raw_context.iregs[13] = 0x12345678; |
michael@0 | 1089 | raw_context.iregs[14] = 0xabcd1234; |
michael@0 | 1090 | raw_context.iregs[15] = 0x10203040; |
michael@0 | 1091 | raw_context.cpsr = 0x2e951ef7; |
michael@0 | 1092 | Context context(dump, raw_context); |
michael@0 | 1093 | |
michael@0 | 1094 | Exception exception(dump, context, |
michael@0 | 1095 | 0x1234abcd, // thread id |
michael@0 | 1096 | 0xdcba4321, // exception code |
michael@0 | 1097 | 0xf0e0d0c0, // exception flags |
michael@0 | 1098 | 0x0919a9b9c9d9e9f9ULL); // exception address |
michael@0 | 1099 | |
michael@0 | 1100 | dump.Add(&context); |
michael@0 | 1101 | dump.Add(&exception); |
michael@0 | 1102 | dump.Finish(); |
michael@0 | 1103 | |
michael@0 | 1104 | string contents; |
michael@0 | 1105 | ASSERT_TRUE(dump.GetContents(&contents)); |
michael@0 | 1106 | |
michael@0 | 1107 | istringstream minidump_stream(contents); |
michael@0 | 1108 | Minidump minidump(minidump_stream); |
michael@0 | 1109 | ASSERT_TRUE(minidump.Read()); |
michael@0 | 1110 | ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); |
michael@0 | 1111 | |
michael@0 | 1112 | MinidumpException *md_exception = minidump.GetException(); |
michael@0 | 1113 | ASSERT_TRUE(md_exception != NULL); |
michael@0 | 1114 | |
michael@0 | 1115 | uint32_t thread_id; |
michael@0 | 1116 | ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); |
michael@0 | 1117 | ASSERT_EQ(0x1234abcdU, thread_id); |
michael@0 | 1118 | |
michael@0 | 1119 | const MDRawExceptionStream* raw_exception = md_exception->exception(); |
michael@0 | 1120 | ASSERT_TRUE(raw_exception != NULL); |
michael@0 | 1121 | EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); |
michael@0 | 1122 | EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); |
michael@0 | 1123 | EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, |
michael@0 | 1124 | raw_exception->exception_record.exception_address); |
michael@0 | 1125 | |
michael@0 | 1126 | MinidumpContext *md_context = md_exception->GetContext(); |
michael@0 | 1127 | ASSERT_TRUE(md_context != NULL); |
michael@0 | 1128 | ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); |
michael@0 | 1129 | const MDRawContextARM *md_raw_context = md_context->GetContextARM(); |
michael@0 | 1130 | ASSERT_TRUE(md_raw_context != NULL); |
michael@0 | 1131 | ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, |
michael@0 | 1132 | (md_raw_context->context_flags |
michael@0 | 1133 | & MD_CONTEXT_ARM_INTEGER)); |
michael@0 | 1134 | EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); |
michael@0 | 1135 | EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); |
michael@0 | 1136 | EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); |
michael@0 | 1137 | EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); |
michael@0 | 1138 | EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); |
michael@0 | 1139 | EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); |
michael@0 | 1140 | EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); |
michael@0 | 1141 | EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); |
michael@0 | 1142 | EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); |
michael@0 | 1143 | EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); |
michael@0 | 1144 | EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); |
michael@0 | 1145 | EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); |
michael@0 | 1146 | EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); |
michael@0 | 1147 | EXPECT_EQ(0x12345678U, raw_context.iregs[13]); |
michael@0 | 1148 | EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); |
michael@0 | 1149 | EXPECT_EQ(0x10203040U, raw_context.iregs[15]); |
michael@0 | 1150 | EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); |
michael@0 | 1151 | } |
michael@0 | 1152 | |
michael@0 | 1153 | } // namespace |