PageRenderTime 131ms CodeModel.GetById 27ms app.highlight 97ms RepoModel.GetById 1ms app.codeStats 1ms

/thirdparty/breakpad/processor/minidump_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 907 lines | 748 code | 114 blank | 45 comment | 39 complexity | 5473437013dd1c92ef8ca3f07270c58d MD5 | raw file
  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// Unit test for Minidump.  Uses a pre-generated minidump and
 31// verifies that certain streams are correct.
 32
 33#include <iostream>
 34#include <fstream>
 35#include <sstream>
 36#include <stdlib.h>
 37#include <string>
 38#include <vector>
 39#include "breakpad_googletest_includes.h"
 40#include "google_breakpad/common/minidump_format.h"
 41#include "google_breakpad/processor/minidump.h"
 42#include "processor/logging.h"
 43#include "processor/synth_minidump.h"
 44
 45namespace {
 46
 47using google_breakpad::Minidump;
 48using google_breakpad::MinidumpContext;
 49using google_breakpad::MinidumpException;
 50using google_breakpad::MinidumpMemoryInfo;
 51using google_breakpad::MinidumpMemoryInfoList;
 52using google_breakpad::MinidumpMemoryList;
 53using google_breakpad::MinidumpMemoryRegion;
 54using google_breakpad::MinidumpModule;
 55using google_breakpad::MinidumpModuleList;
 56using google_breakpad::MinidumpSystemInfo;
 57using google_breakpad::MinidumpThread;
 58using google_breakpad::MinidumpThreadList;
 59using google_breakpad::SynthMinidump::Context;
 60using google_breakpad::SynthMinidump::Dump;
 61using google_breakpad::SynthMinidump::Exception;
 62using google_breakpad::SynthMinidump::Memory;
 63using google_breakpad::SynthMinidump::Module;
 64using google_breakpad::SynthMinidump::Stream;
 65using google_breakpad::SynthMinidump::String;
 66using google_breakpad::SynthMinidump::SystemInfo;
 67using google_breakpad::SynthMinidump::Thread;
 68using google_breakpad::test_assembler::kBigEndian;
 69using google_breakpad::test_assembler::kLittleEndian;
 70using std::ifstream;
 71using std::istringstream;
 72using std::string;
 73using std::vector;
 74using ::testing::Return;
 75
 76class MinidumpTest : public ::testing::Test {
 77public:
 78  void SetUp() {
 79    minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
 80      "/src/processor/testdata/minidump2.dmp";
 81  }
 82  string minidump_file_;
 83};
 84
 85TEST_F(MinidumpTest, TestMinidumpFromFile) {
 86  Minidump minidump(minidump_file_);
 87  ASSERT_EQ(minidump.path(), minidump_file_);
 88  ASSERT_TRUE(minidump.Read());
 89  const MDRawHeader* header = minidump.header();
 90  ASSERT_NE(header, (MDRawHeader*)NULL);
 91  ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
 92  //TODO: add more checks here
 93}
 94
 95TEST_F(MinidumpTest, TestMinidumpFromStream) {
 96  // read minidump contents into memory, construct a stringstream around them
 97  ifstream file_stream(minidump_file_.c_str(), std::ios::in);
 98  ASSERT_TRUE(file_stream.good());
 99  vector<char> bytes;
100  file_stream.seekg(0, std::ios_base::end);
101  ASSERT_TRUE(file_stream.good());
102  bytes.resize(file_stream.tellg());
103  file_stream.seekg(0, std::ios_base::beg);
104  ASSERT_TRUE(file_stream.good());
105  file_stream.read(&bytes[0], bytes.size());
106  ASSERT_TRUE(file_stream.good());
107  string str(&bytes[0], bytes.size());
108  istringstream stream(str);
109  ASSERT_TRUE(stream.good());
110
111  // now read minidump from stringstream
112  Minidump minidump(stream);
113  ASSERT_EQ(minidump.path(), "");
114  ASSERT_TRUE(minidump.Read());
115  const MDRawHeader* header = minidump.header();
116  ASSERT_NE(header, (MDRawHeader*)NULL);
117  ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
118  //TODO: add more checks here
119}
120
121TEST(Dump, ReadBackEmpty) {
122  Dump dump(0);
123  dump.Finish();
124  string contents;
125  ASSERT_TRUE(dump.GetContents(&contents));
126  istringstream stream(contents);
127  Minidump minidump(stream);
128  ASSERT_TRUE(minidump.Read());
129  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
130}
131
132TEST(Dump, ReadBackEmptyBigEndian) {
133  Dump big_minidump(0, kBigEndian);
134  big_minidump.Finish();
135  string contents;
136  ASSERT_TRUE(big_minidump.GetContents(&contents));
137  istringstream stream(contents);
138  Minidump minidump(stream);
139  ASSERT_TRUE(minidump.Read());
140  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
141}
142
143TEST(Dump, OneStream) {
144  Dump dump(0, kBigEndian);
145  Stream stream(dump, 0xfbb7fa2bU);
146  stream.Append("stream contents");
147  dump.Add(&stream);
148  dump.Finish();
149  
150  string contents;
151  ASSERT_TRUE(dump.GetContents(&contents));
152  istringstream minidump_stream(contents);
153  Minidump minidump(minidump_stream);
154  ASSERT_TRUE(minidump.Read());
155  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
156
157  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
158  ASSERT_TRUE(dir != NULL);
159  EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
160
161  u_int32_t stream_length;
162  ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
163  ASSERT_EQ(15U, stream_length);
164  char stream_contents[15];
165  ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
166  EXPECT_EQ(string("stream contents"),
167            string(stream_contents, sizeof(stream_contents)));
168
169  EXPECT_FALSE(minidump.GetThreadList());
170  EXPECT_FALSE(minidump.GetModuleList());
171  EXPECT_FALSE(minidump.GetMemoryList());
172  EXPECT_FALSE(minidump.GetException());
173  EXPECT_FALSE(minidump.GetAssertion());
174  EXPECT_FALSE(minidump.GetSystemInfo());
175  EXPECT_FALSE(minidump.GetMiscInfo());
176  EXPECT_FALSE(minidump.GetBreakpadInfo());
177}
178
179TEST(Dump, OneMemory) {
180  Dump dump(0, kBigEndian);
181  Memory memory(dump, 0x309d68010bd21b2cULL);
182  memory.Append("memory contents");
183  dump.Add(&memory);
184  dump.Finish();
185
186  string contents;
187  ASSERT_TRUE(dump.GetContents(&contents));
188  istringstream minidump_stream(contents);
189  Minidump minidump(minidump_stream);
190  ASSERT_TRUE(minidump.Read());
191  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
192
193  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
194  ASSERT_TRUE(dir != NULL);
195  EXPECT_EQ((u_int32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
196
197  MinidumpMemoryList *memory_list = minidump.GetMemoryList();
198  ASSERT_TRUE(memory_list != NULL);
199  ASSERT_EQ(1U, memory_list->region_count());
200
201  MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
202  ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
203  ASSERT_EQ(15U, region1->GetSize());
204  const u_int8_t *region1_bytes = region1->GetMemory();
205  ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
206}
207
208// One thread --- and its requisite entourage.
209TEST(Dump, OneThread) {
210  Dump dump(0, kLittleEndian);
211  Memory stack(dump, 0x2326a0fa);
212  stack.Append("stack for thread");
213
214  MDRawContextX86 raw_context;
215  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
216  raw_context.edi = 0x3ecba80d;
217  raw_context.esi = 0x382583b9;
218  raw_context.ebx = 0x7fccc03f;
219  raw_context.edx = 0xf62f8ec2;
220  raw_context.ecx = 0x46a6a6a8;
221  raw_context.eax = 0x6a5025e2;
222  raw_context.ebp = 0xd9fabb4a;
223  raw_context.eip = 0x6913f540;
224  raw_context.cs = 0xbffe6eda;
225  raw_context.eflags = 0xb2ce1e2d;
226  raw_context.esp = 0x659caaa4;
227  raw_context.ss = 0x2e951ef7;
228  Context context(dump, raw_context);
229  
230  Thread thread(dump, 0xa898f11b, stack, context,
231                0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
232  
233  dump.Add(&stack);
234  dump.Add(&context);
235  dump.Add(&thread);
236  dump.Finish();
237
238  string contents;
239  ASSERT_TRUE(dump.GetContents(&contents));
240
241  istringstream minidump_stream(contents);
242  Minidump minidump(minidump_stream);
243  ASSERT_TRUE(minidump.Read());
244  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
245
246  MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
247  ASSERT_TRUE(md_memory_list != NULL);
248  ASSERT_EQ(1U, md_memory_list->region_count());
249
250  MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
251  ASSERT_EQ(0x2326a0faU, md_region->GetBase());
252  ASSERT_EQ(16U, md_region->GetSize());
253  const u_int8_t *region_bytes = md_region->GetMemory();
254  ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
255
256  MinidumpThreadList *thread_list = minidump.GetThreadList();
257  ASSERT_TRUE(thread_list != NULL);
258  ASSERT_EQ(1U, thread_list->thread_count());
259
260  MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
261  ASSERT_TRUE(md_thread != NULL);
262  u_int32_t thread_id;
263  ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
264  ASSERT_EQ(0xa898f11bU, thread_id);
265  MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
266  ASSERT_TRUE(md_stack != NULL);
267  ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
268  ASSERT_EQ(16U, md_stack->GetSize());
269  const u_int8_t *md_stack_bytes = md_stack->GetMemory();
270  ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
271
272  MinidumpContext *md_context = md_thread->GetContext();
273  ASSERT_TRUE(md_context != NULL);
274  ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
275  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
276  ASSERT_TRUE(md_raw_context != NULL);
277  ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
278            (md_raw_context->context_flags
279             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
280  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
281  EXPECT_EQ(0x382583b9U, raw_context.esi);
282  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
283  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
284  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
285  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
286  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
287  EXPECT_EQ(0x6913f540U, raw_context.eip);
288  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
289  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
290  EXPECT_EQ(0x659caaa4U, raw_context.esp);
291  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
292}
293
294TEST(Dump, OneModule) {
295  static const MDVSFixedFileInfo fixed_file_info = {
296    0xb2fba33a,                           // signature
297    0x33d7a728,                           // struct_version
298    0x31afcb20,                           // file_version_hi
299    0xe51cdab1,                           // file_version_lo
300    0xd1ea6907,                           // product_version_hi
301    0x03032857,                           // product_version_lo
302    0x11bf71d7,                           // file_flags_mask
303    0x5fb8cdbf,                           // file_flags
304    0xe45d0d5d,                           // file_os
305    0x107d9562,                           // file_type
306    0x5a8844d4,                           // file_subtype
307    0xa8d30b20,                           // file_date_hi
308    0x651c3e4e                            // file_date_lo
309  };
310
311  Dump dump(0, kBigEndian);
312  String module_name(dump, "single module");
313  Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
314                module_name,
315                0xb1054d2a,
316                0x34571371,
317                fixed_file_info, // from synth_minidump_unittest_data.h
318                NULL, NULL);
319
320  dump.Add(&module);
321  dump.Add(&module_name);
322  dump.Finish();
323  
324  string contents;
325  ASSERT_TRUE(dump.GetContents(&contents));
326  istringstream minidump_stream(contents);
327  Minidump minidump(minidump_stream);
328  ASSERT_TRUE(minidump.Read());
329  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
330
331  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
332  ASSERT_TRUE(dir != NULL);
333  EXPECT_EQ((u_int32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
334
335  MinidumpModuleList *md_module_list = minidump.GetModuleList();
336  ASSERT_TRUE(md_module_list != NULL);
337  ASSERT_EQ(1U, md_module_list->module_count());
338
339  const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
340  ASSERT_TRUE(md_module != NULL);
341  ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
342  ASSERT_EQ(0xada542bd, md_module->size());
343  ASSERT_EQ("single module", md_module->code_file());
344
345  const MDRawModule *md_raw_module = md_module->module();
346  ASSERT_TRUE(md_raw_module != NULL);
347  ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
348  ASSERT_EQ(0x34571371U, md_raw_module->checksum);
349  ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
350                     sizeof(fixed_file_info)) == 0);
351}
352
353TEST(Dump, OneSystemInfo) {
354  Dump dump(0, kLittleEndian);
355  String csd_version(dump, "Petulant Pierogi");
356  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
357
358  dump.Add(&system_info);
359  dump.Add(&csd_version);
360  dump.Finish();
361                         
362  string contents;
363  ASSERT_TRUE(dump.GetContents(&contents));
364  istringstream minidump_stream(contents);
365  Minidump minidump(minidump_stream);
366  ASSERT_TRUE(minidump.Read());
367  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
368
369  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
370  ASSERT_TRUE(dir != NULL);
371  EXPECT_EQ((u_int32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
372
373  MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
374  ASSERT_TRUE(md_system_info != NULL);
375  ASSERT_EQ("windows", md_system_info->GetOS());
376  ASSERT_EQ("x86", md_system_info->GetCPU());
377  ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
378  ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
379}
380
381TEST(Dump, BigDump) {
382  Dump dump(0, kLittleEndian);
383
384  // A SystemInfo stream.
385  String csd_version(dump, "Munificent Macaque");
386  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
387  dump.Add(&csd_version);
388  dump.Add(&system_info);
389
390  // Five threads!
391  Memory stack0(dump, 0x70b9ebfc);
392  stack0.Append("stack for thread zero");
393  MDRawContextX86 raw_context0;
394  raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
395  raw_context0.eip = 0xaf0709e4;
396  Context context0(dump, raw_context0);
397  Thread thread0(dump, 0xbbef4432, stack0, context0,
398                 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
399  dump.Add(&stack0);
400  dump.Add(&context0);
401  dump.Add(&thread0);
402
403  Memory stack1(dump, 0xf988cc45);
404  stack1.Append("stack for thread one");
405  MDRawContextX86 raw_context1;
406  raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
407  raw_context1.eip = 0xe4f56f81;
408  Context context1(dump, raw_context1);
409  Thread thread1(dump, 0x657c3f58, stack1, context1,
410                 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
411  dump.Add(&stack1);
412  dump.Add(&context1);
413  dump.Add(&thread1);
414
415  Memory stack2(dump, 0xc8a92e7c);
416  stack2.Append("stack for thread two");
417  MDRawContextX86 raw_context2;
418  raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
419  raw_context2.eip = 0xb336a438;
420  Context context2(dump, raw_context2);
421  Thread thread2(dump, 0xdf4b8a71, stack2, context2,
422                 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
423  dump.Add(&stack2);
424  dump.Add(&context2);
425  dump.Add(&thread2);
426
427  Memory stack3(dump, 0x36d08e08);
428  stack3.Append("stack for thread three");
429  MDRawContextX86 raw_context3;
430  raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
431  raw_context3.eip = 0xdf99a60c;
432  Context context3(dump, raw_context3);
433  Thread thread3(dump, 0x86e6c341, stack3, context3,
434                 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
435  dump.Add(&stack3);
436  dump.Add(&context3);
437  dump.Add(&thread3);
438
439  Memory stack4(dump, 0x1e0ab4fa);
440  stack4.Append("stack for thread four");
441  MDRawContextX86 raw_context4;
442  raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
443  raw_context4.eip = 0xaa646267;
444  Context context4(dump, raw_context4);
445  Thread thread4(dump, 0x261a28d4, stack4, context4,
446                 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
447  dump.Add(&stack4);
448  dump.Add(&context4);
449  dump.Add(&thread4);
450
451  // Three modules!
452  String module1_name(dump, "module one");
453  Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
454  dump.Add(&module1_name);
455  dump.Add(&module1);
456
457  String module2_name(dump, "module two");
458  Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
459  dump.Add(&module2_name);
460  dump.Add(&module2);
461
462  String module3_name(dump, "module three");
463  Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
464  dump.Add(&module3_name);
465  dump.Add(&module3);
466
467  // Add one more memory region, on top of the five stacks.
468  Memory memory5(dump, 0x61979e828040e564ULL);
469  memory5.Append("contents of memory 5");
470  dump.Add(&memory5);
471
472  dump.Finish();
473
474  string contents;
475  ASSERT_TRUE(dump.GetContents(&contents));
476  istringstream minidump_stream(contents);
477  Minidump minidump(minidump_stream);
478  ASSERT_TRUE(minidump.Read());
479  ASSERT_EQ(4U, minidump.GetDirectoryEntryCount());
480
481  // Check the threads.
482  MinidumpThreadList *thread_list = minidump.GetThreadList();
483  ASSERT_TRUE(thread_list != NULL);
484  ASSERT_EQ(5U, thread_list->thread_count());
485  u_int32_t thread_id;
486  ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
487  ASSERT_EQ(0xbbef4432U, thread_id);
488  ASSERT_EQ(0x70b9ebfcU,
489            thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
490  ASSERT_EQ(0xaf0709e4U,
491            thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
492            ->eip);
493
494  ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
495  ASSERT_EQ(0x657c3f58U, thread_id);
496  ASSERT_EQ(0xf988cc45U,
497            thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
498  ASSERT_EQ(0xe4f56f81U,
499            thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
500            ->eip);
501
502  ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
503  ASSERT_EQ(0xdf4b8a71U, thread_id);
504  ASSERT_EQ(0xc8a92e7cU,
505            thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
506  ASSERT_EQ(0xb336a438U,
507            thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
508            ->eip);
509
510  ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
511  ASSERT_EQ(0x86e6c341U, thread_id);
512  ASSERT_EQ(0x36d08e08U,
513            thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
514  ASSERT_EQ(0xdf99a60cU,
515            thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
516            ->eip);
517
518  ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
519  ASSERT_EQ(0x261a28d4U, thread_id);
520  ASSERT_EQ(0x1e0ab4faU,
521            thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
522  ASSERT_EQ(0xaa646267U,
523            thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
524            ->eip);
525
526  // Check the modules.
527  MinidumpModuleList *md_module_list = minidump.GetModuleList();
528  ASSERT_TRUE(md_module_list != NULL);
529  ASSERT_EQ(3U, md_module_list->module_count());
530  EXPECT_EQ(0xeb77da57b5d4cbdaULL,
531            md_module_list->GetModuleAtIndex(0)->base_address());
532  EXPECT_EQ(0x8675884adfe5ac90ULL,
533            md_module_list->GetModuleAtIndex(1)->base_address());
534  EXPECT_EQ(0x95fc1544da321b6cULL,
535            md_module_list->GetModuleAtIndex(2)->base_address());
536}
537
538TEST(Dump, OneMemoryInfo) {
539  Dump dump(0, kBigEndian);
540  Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
541
542  // Add the MDRawMemoryInfoList header.
543  const u_int64_t kNumberOfEntries = 1;
544  stream.D32(sizeof(MDRawMemoryInfoList))  // size_of_header
545        .D32(sizeof(MDRawMemoryInfo))      // size_of_entry
546        .D64(kNumberOfEntries);            // number_of_entries
547
548  
549  // Now add a MDRawMemoryInfo entry.
550  const u_int64_t kBaseAddress = 0x1000;
551  const u_int64_t kRegionSize = 0x2000;
552  stream.D64(kBaseAddress)                         // base_address
553        .D64(kBaseAddress)                         // allocation_base
554        .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE)  // allocation_protection
555        .D32(0)                                    // __alignment1
556        .D64(kRegionSize)                          // region_size
557        .D32(MD_MEMORY_STATE_COMMIT)               // state
558        .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE)  // protection
559        .D32(MD_MEMORY_TYPE_PRIVATE)               // type
560        .D32(0);                                   // __alignment2
561
562  dump.Add(&stream);
563  dump.Finish();
564
565  string contents;
566  ASSERT_TRUE(dump.GetContents(&contents));
567  istringstream minidump_stream(contents);
568  Minidump minidump(minidump_stream);
569  ASSERT_TRUE(minidump.Read());
570  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
571
572  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
573  ASSERT_TRUE(dir != NULL);
574  EXPECT_EQ((u_int32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
575
576  MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
577  ASSERT_TRUE(info_list != NULL);
578  ASSERT_EQ(1U, info_list->info_count());
579
580  const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
581  ASSERT_EQ(kBaseAddress, info1->GetBase());
582  ASSERT_EQ(kRegionSize, info1->GetSize());
583  ASSERT_TRUE(info1->IsExecutable());
584  ASSERT_TRUE(info1->IsWritable());
585
586  // Should get back the same memory region here.
587  const MinidumpMemoryInfo *info2 =
588      info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
589  ASSERT_EQ(kBaseAddress, info2->GetBase());
590  ASSERT_EQ(kRegionSize, info2->GetSize());
591}
592
593TEST(Dump, OneExceptionX86) {
594  Dump dump(0, kLittleEndian);
595
596  MDRawContextX86 raw_context;
597  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
598  raw_context.edi = 0x3ecba80d;
599  raw_context.esi = 0x382583b9;
600  raw_context.ebx = 0x7fccc03f;
601  raw_context.edx = 0xf62f8ec2;
602  raw_context.ecx = 0x46a6a6a8;
603  raw_context.eax = 0x6a5025e2;
604  raw_context.ebp = 0xd9fabb4a;
605  raw_context.eip = 0x6913f540;
606  raw_context.cs = 0xbffe6eda;
607  raw_context.eflags = 0xb2ce1e2d;
608  raw_context.esp = 0x659caaa4;
609  raw_context.ss = 0x2e951ef7;
610  Context context(dump, raw_context);
611
612  Exception exception(dump, context,
613                      0x1234abcd, // thread id
614                      0xdcba4321, // exception code
615                      0xf0e0d0c0, // exception flags
616                      0x0919a9b9c9d9e9f9ULL); // exception address
617  
618  dump.Add(&context);
619  dump.Add(&exception);
620  dump.Finish();
621
622  string contents;
623  ASSERT_TRUE(dump.GetContents(&contents));
624
625  istringstream minidump_stream(contents);
626  Minidump minidump(minidump_stream);
627  ASSERT_TRUE(minidump.Read());
628  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
629
630  MinidumpException *md_exception = minidump.GetException();
631  ASSERT_TRUE(md_exception != NULL);
632
633  u_int32_t thread_id;
634  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
635  ASSERT_EQ(0x1234abcd, thread_id);
636
637  const MDRawExceptionStream* raw_exception = md_exception->exception();
638  ASSERT_TRUE(raw_exception != NULL);
639  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
640  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
641  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
642            raw_exception->exception_record.exception_address);
643
644  MinidumpContext *md_context = md_exception->GetContext();
645  ASSERT_TRUE(md_context != NULL);
646  ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
647  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
648  ASSERT_TRUE(md_raw_context != NULL);
649  ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
650            (md_raw_context->context_flags
651             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
652  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
653  EXPECT_EQ(0x382583b9U, raw_context.esi);
654  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
655  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
656  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
657  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
658  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
659  EXPECT_EQ(0x6913f540U, raw_context.eip);
660  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
661  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
662  EXPECT_EQ(0x659caaa4U, raw_context.esp);
663  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
664}
665
666TEST(Dump, OneExceptionX86XState) {
667  Dump dump(0, kLittleEndian);
668
669  MDRawContextX86 raw_context;
670  raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
671    MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
672  raw_context.edi = 0x3ecba80d;
673  raw_context.esi = 0x382583b9;
674  raw_context.ebx = 0x7fccc03f;
675  raw_context.edx = 0xf62f8ec2;
676  raw_context.ecx = 0x46a6a6a8;
677  raw_context.eax = 0x6a5025e2;
678  raw_context.ebp = 0xd9fabb4a;
679  raw_context.eip = 0x6913f540;
680  raw_context.cs = 0xbffe6eda;
681  raw_context.eflags = 0xb2ce1e2d;
682  raw_context.esp = 0x659caaa4;
683  raw_context.ss = 0x2e951ef7;
684  Context context(dump, raw_context);
685
686  Exception exception(dump, context,
687                      0x1234abcd, // thread id
688                      0xdcba4321, // exception code
689                      0xf0e0d0c0, // exception flags
690                      0x0919a9b9c9d9e9f9ULL); // exception address
691  
692  dump.Add(&context);
693  dump.Add(&exception);
694  dump.Finish();
695
696  string contents;
697  ASSERT_TRUE(dump.GetContents(&contents));
698
699  istringstream minidump_stream(contents);
700  Minidump minidump(minidump_stream);
701  ASSERT_TRUE(minidump.Read());
702  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
703
704  MinidumpException *md_exception = minidump.GetException();
705  ASSERT_TRUE(md_exception != NULL);
706
707  u_int32_t thread_id;
708  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
709  ASSERT_EQ(0x1234abcd, thread_id);
710
711  const MDRawExceptionStream* raw_exception = md_exception->exception();
712  ASSERT_TRUE(raw_exception != NULL);
713  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
714  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
715  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
716            raw_exception->exception_record.exception_address);
717
718  MinidumpContext *md_context = md_exception->GetContext();
719  ASSERT_TRUE(md_context != NULL);
720  ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
721  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
722  ASSERT_TRUE(md_raw_context != NULL);
723  ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
724            (md_raw_context->context_flags
725             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
726  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
727  EXPECT_EQ(0x382583b9U, raw_context.esi);
728  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
729  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
730  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
731  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
732  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
733  EXPECT_EQ(0x6913f540U, raw_context.eip);
734  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
735  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
736  EXPECT_EQ(0x659caaa4U, raw_context.esp);
737  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
738}
739
740TEST(Dump, OneExceptionARM) {
741  Dump dump(0, kLittleEndian);
742
743  MDRawContextARM raw_context;
744  raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
745  raw_context.iregs[0] = 0x3ecba80d;
746  raw_context.iregs[1] = 0x382583b9;
747  raw_context.iregs[2] = 0x7fccc03f;
748  raw_context.iregs[3] = 0xf62f8ec2;
749  raw_context.iregs[4] = 0x46a6a6a8;
750  raw_context.iregs[5] = 0x6a5025e2;
751  raw_context.iregs[6] = 0xd9fabb4a;
752  raw_context.iregs[7] = 0x6913f540;
753  raw_context.iregs[8] = 0xbffe6eda;
754  raw_context.iregs[9] = 0xb2ce1e2d;
755  raw_context.iregs[10] = 0x659caaa4;
756  raw_context.iregs[11] = 0xf0e0d0c0;
757  raw_context.iregs[12] = 0xa9b8c7d6;
758  raw_context.iregs[13] = 0x12345678;
759  raw_context.iregs[14] = 0xabcd1234;
760  raw_context.iregs[15] = 0x10203040;
761  raw_context.cpsr = 0x2e951ef7;
762  Context context(dump, raw_context);
763
764  Exception exception(dump, context,
765                      0x1234abcd, // thread id
766                      0xdcba4321, // exception code
767                      0xf0e0d0c0, // exception flags
768                      0x0919a9b9c9d9e9f9ULL); // exception address
769  
770  dump.Add(&context);
771  dump.Add(&exception);
772  dump.Finish();
773
774  string contents;
775  ASSERT_TRUE(dump.GetContents(&contents));
776
777  istringstream minidump_stream(contents);
778  Minidump minidump(minidump_stream);
779  ASSERT_TRUE(minidump.Read());
780  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
781
782  MinidumpException *md_exception = minidump.GetException();
783  ASSERT_TRUE(md_exception != NULL);
784
785  u_int32_t thread_id;
786  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
787  ASSERT_EQ(0x1234abcd, thread_id);
788
789  const MDRawExceptionStream* raw_exception = md_exception->exception();
790  ASSERT_TRUE(raw_exception != NULL);
791  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
792  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
793  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
794            raw_exception->exception_record.exception_address);
795
796  MinidumpContext *md_context = md_exception->GetContext();
797  ASSERT_TRUE(md_context != NULL);
798  ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
799  const MDRawContextARM *md_raw_context = md_context->GetContextARM();
800  ASSERT_TRUE(md_raw_context != NULL);
801  ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM_INTEGER,
802            (md_raw_context->context_flags
803             & MD_CONTEXT_ARM_INTEGER));
804  EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
805  EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
806  EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
807  EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
808  EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
809  EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
810  EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
811  EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
812  EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
813  EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
814  EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
815  EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
816  EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
817  EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
818  EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
819  EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
820  EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
821}
822
823TEST(Dump, OneExceptionARMOldFlags) {
824  Dump dump(0, kLittleEndian);
825
826  MDRawContextARM raw_context;
827  // MD_CONTEXT_ARM_INTEGER, but with _OLD
828  raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
829  raw_context.iregs[0] = 0x3ecba80d;
830  raw_context.iregs[1] = 0x382583b9;
831  raw_context.iregs[2] = 0x7fccc03f;
832  raw_context.iregs[3] = 0xf62f8ec2;
833  raw_context.iregs[4] = 0x46a6a6a8;
834  raw_context.iregs[5] = 0x6a5025e2;
835  raw_context.iregs[6] = 0xd9fabb4a;
836  raw_context.iregs[7] = 0x6913f540;
837  raw_context.iregs[8] = 0xbffe6eda;
838  raw_context.iregs[9] = 0xb2ce1e2d;
839  raw_context.iregs[10] = 0x659caaa4;
840  raw_context.iregs[11] = 0xf0e0d0c0;
841  raw_context.iregs[12] = 0xa9b8c7d6;
842  raw_context.iregs[13] = 0x12345678;
843  raw_context.iregs[14] = 0xabcd1234;
844  raw_context.iregs[15] = 0x10203040;
845  raw_context.cpsr = 0x2e951ef7;
846  Context context(dump, raw_context);
847
848  Exception exception(dump, context,
849                      0x1234abcd, // thread id
850                      0xdcba4321, // exception code
851                      0xf0e0d0c0, // exception flags
852                      0x0919a9b9c9d9e9f9ULL); // exception address
853  
854  dump.Add(&context);
855  dump.Add(&exception);
856  dump.Finish();
857
858  string contents;
859  ASSERT_TRUE(dump.GetContents(&contents));
860
861  istringstream minidump_stream(contents);
862  Minidump minidump(minidump_stream);
863  ASSERT_TRUE(minidump.Read());
864  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
865
866  MinidumpException *md_exception = minidump.GetException();
867  ASSERT_TRUE(md_exception != NULL);
868
869  u_int32_t thread_id;
870  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
871  ASSERT_EQ(0x1234abcd, thread_id);
872
873  const MDRawExceptionStream* raw_exception = md_exception->exception();
874  ASSERT_TRUE(raw_exception != NULL);
875  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
876  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
877  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
878            raw_exception->exception_record.exception_address);
879
880  MinidumpContext *md_context = md_exception->GetContext();
881  ASSERT_TRUE(md_context != NULL);
882  ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
883  const MDRawContextARM *md_raw_context = md_context->GetContextARM();
884  ASSERT_TRUE(md_raw_context != NULL);
885  ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM_INTEGER,
886            (md_raw_context->context_flags
887             & MD_CONTEXT_ARM_INTEGER));
888  EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
889  EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
890  EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
891  EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
892  EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
893  EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
894  EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
895  EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
896  EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
897  EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
898  EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
899  EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
900  EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
901  EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
902  EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
903  EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
904  EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
905}
906
907}  // namespace