minidump.cc revision ce1a45e28cad26f9c0f34ae329b0fd694d004f0f
183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc.
27daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// All rights reserved.
33261e8b6eac44a41341f112821482bee6c940c98mmentovai//
47daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Redistribution and use in source and binary forms, with or without
57daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// modification, are permitted provided that the following conditions are
67daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// met:
73261e8b6eac44a41341f112821482bee6c940c98mmentovai//
87daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions of source code must retain the above copyright
97daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// notice, this list of conditions and the following disclaimer.
107daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions in binary form must reproduce the above
117daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// copyright notice, this list of conditions and the following disclaimer
127daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// in the documentation and/or other materials provided with the
137daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// distribution.
147daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Neither the name of Google Inc. nor the names of its
157daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// contributors may be used to endorse or promote products derived from
167daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// this software without specific prior written permission.
173261e8b6eac44a41341f112821482bee6c940c98mmentovai//
187daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
237daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
247daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
267daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
277daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
287daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293261e8b6eac44a41341f112821482bee6c940c98mmentovai
303261e8b6eac44a41341f112821482bee6c940c98mmentovai// minidump.cc: A minidump reader.
313261e8b6eac44a41341f112821482bee6c940c98mmentovai//
323261e8b6eac44a41341f112821482bee6c940c98mmentovai// See minidump.h for documentation.
333261e8b6eac44a41341f112821482bee6c940c98mmentovai//
343261e8b6eac44a41341f112821482bee6c940c98mmentovai// Author: Mark Mentovai
353261e8b6eac44a41341f112821482bee6c940c98mmentovai
36e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include "google_breakpad/processor/minidump.h"
373261e8b6eac44a41341f112821482bee6c940c98mmentovai
38e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h>
396dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#include <fcntl.h>
40f2e56b1fde88a521971cb6e74d53ce6ac04aa186ted.mielczarek@gmail.com#include <stddef.h>
413261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <stdio.h>
429fcf4db315427032a92078d1212fece2655bf049mmentovai#include <string.h>
433261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <time.h>
44c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek
453261e8b6eac44a41341f112821482bee6c940c98mmentovai#ifdef _WIN32
463261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <io.h>
47c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx64 "llx"
48c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx32 "lx"
49c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define snprintf _snprintf
5080e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#else  // _WIN32
51c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#include <unistd.h>
526dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#define O_BINARY 0
5380e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#endif  // _WIN32
543261e8b6eac44a41341f112821482bee6c940c98mmentovai
550cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <fstream>
560cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <iostream>
57fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai#include <limits>
583261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <map>
593261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <vector>
603261e8b6eac44a41341f112821482bee6c940c98mmentovai
618c2a4def4ecfbf6293b27eff4359a274e9774b4emmentovai#include "processor/range_map-inl.h"
6280e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai
632cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
64db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_module.h"
65db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_modules.h"
66af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai#include "processor/logging.h"
672cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com
68e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
693261e8b6eac44a41341f112821482bee6c940c98mmentovai
703261e8b6eac44a41341f112821482bee6c940c98mmentovai
710cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::istream;
720cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::ifstream;
73fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovaiusing std::numeric_limits;
743261e8b6eac44a41341f112821482bee6c940c98mmentovaiusing std::vector;
753261e8b6eac44a41341f112821482bee6c940c98mmentovai
7639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// Returns true iff |context_size| matches exactly one of the sizes of the
7739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// various MDRawContext* types.
7839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// TODO(blundell): This function can be removed once
7939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed.
8039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.orgstatic bool IsContextSizeUnique(uint32_t context_size) {
8139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  int num_matching_contexts = 0;
8239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextX86))
8339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextPPC))
8539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextPPC64))
8739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextAMD64))
8939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextSPARC))
9139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextARM))
9339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextARM64))
9539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextMIPS))
9739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  return num_matching_contexts == 1;
9939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org}
1003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1013261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1023261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping routines
1033261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1043261e8b6eac44a41341f112821482bee6c940c98mmentovai// Inlining these doesn't increase code size significantly, and it saves
1053261e8b6eac44a41341f112821482bee6c940c98mmentovai// a whole lot of unnecessary jumping back and forth.
1063261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1073261e8b6eac44a41341f112821482bee6c940c98mmentovai
1083261e8b6eac44a41341f112821482bee6c940c98mmentovai
1093261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping an 8-bit quantity is a no-op.  This function is only provided
1103261e8b6eac44a41341f112821482bee6c940c98mmentovai// to account for certain templatized operations that require swapping for
1116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com// wider types but handle uint8_t too
1123261e8b6eac44a41341f112821482bee6c940c98mmentovai// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
1136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint8_t* value) {
1143261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1153261e8b6eac44a41341f112821482bee6c940c98mmentovai
1163261e8b6eac44a41341f112821482bee6c940c98mmentovai
1173261e8b6eac44a41341f112821482bee6c940c98mmentovai// Optimization: don't need to AND the furthest right shift, because we're
1183261e8b6eac44a41341f112821482bee6c940c98mmentovai// shifting an unsigned quantity.  The standard requires zero-filling in this
1193261e8b6eac44a41341f112821482bee6c940c98mmentovai// case.  If the quantities were signed, a bitmask whould be needed for this
1203261e8b6eac44a41341f112821482bee6c940c98mmentovai// right shift to avoid an arithmetic shift (which retains the sign bit).
1213261e8b6eac44a41341f112821482bee6c940c98mmentovai// The furthest left shift never needs to be ANDed bitmask.
1223261e8b6eac44a41341f112821482bee6c940c98mmentovai
1233261e8b6eac44a41341f112821482bee6c940c98mmentovai
1246162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint16_t* value) {
1253261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = (*value >> 8) |
1263261e8b6eac44a41341f112821482bee6c940c98mmentovai           (*value << 8);
1273261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1283261e8b6eac44a41341f112821482bee6c940c98mmentovai
1293261e8b6eac44a41341f112821482bee6c940c98mmentovai
1306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint32_t* value) {
1313261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 24) |
1323261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x0000ff00) |
1333261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x00ff0000) |
1343261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 24);
1353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1363261e8b6eac44a41341f112821482bee6c940c98mmentovai
1373261e8b6eac44a41341f112821482bee6c940c98mmentovai
1386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint64_t* value) {
1396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t* value32 = reinterpret_cast<uint32_t*>(value);
1402e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[0]);
1412e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[1]);
1426162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t temp = value32[0];
1432e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[0] = value32[1];
1442e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[1] = temp;
1453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1463261e8b6eac44a41341f112821482bee6c940c98mmentovai
1473261e8b6eac44a41341f112821482bee6c940c98mmentovai
1481d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// Given a pointer to a 128-bit int in the minidump data, set the "low"
1491d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// and "high" fields appropriately.
1506162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Normalize128(uint128_struct* value, bool is_big_endian) {
1511d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // The struct format is [high, low], so if the format is big-endian,
1521d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // the most significant bytes will already be in the high field.
1531d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  if (!is_big_endian) {
1546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t temp = value->low;
1551d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->low = value->high;
1561d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->high = temp;
1571d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  }
1581d78cad82e3c7aa2315ed7438211a1901a91ed34bryner}
1593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1601d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// This just swaps each int64 half of the 128-bit value.
1611d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// The value should also be normalized by calling Normalize128().
1626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Swap(uint128_struct* value) {
1631d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->low);
1641d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->high);
1653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
1663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1673562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com// Swapping signed integers
1683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int16_t* value) {
1693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint16_t*>(value));
1703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1713562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1723562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int32_t* value) {
1733562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint32_t*>(value));
1743562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1753562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int64_t* value) {
1773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint64_t*>(value));
1783562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1793562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1813261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDLocationDescriptor* location_descriptor) {
1823261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->data_size);
1833261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->rva);
1843261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1853261e8b6eac44a41341f112821482bee6c940c98mmentovai
1863261e8b6eac44a41341f112821482bee6c940c98mmentovai
1873261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDMemoryDescriptor* memory_descriptor) {
1883261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->start_of_memory_range);
1893261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->memory);
1903261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1923261e8b6eac44a41341f112821482bee6c940c98mmentovai
1933261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDGUID* guid) {
1943261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data1);
1953261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data2);
1963261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data3);
1973261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't swap guid->data4[] because it contains 8-bit quantities.
1983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1993261e8b6eac44a41341f112821482bee6c940c98mmentovai
2003562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDSystemTime* system_time) {
2013562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->year);
2023562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->month);
2033562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day_of_week);
2043562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day);
2053562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->hour);
2063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->minute);
2073562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->second);
2083562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->milliseconds);
2093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
2103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
2113562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(uint16_t* data, size_t size_in_bytes) {
2123562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t data_length = size_in_bytes / sizeof(data[0]);
2133562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  for (size_t i = 0; i < data_length; i++) {
2143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    Swap(&data[i]);
2153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
2163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
2173261e8b6eac44a41341f112821482bee6c940c98mmentovai
2183261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2193261e8b6eac44a41341f112821482bee6c940c98mmentovai// Character conversion routines
2203261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2213261e8b6eac44a41341f112821482bee6c940c98mmentovai
2223261e8b6eac44a41341f112821482bee6c940c98mmentovai
2233261e8b6eac44a41341f112821482bee6c940c98mmentovai// Standard wide-character conversion routines depend on the system's own
2243261e8b6eac44a41341f112821482bee6c940c98mmentovai// idea of what width a wide character should be: some use 16 bits, and
2253261e8b6eac44a41341f112821482bee6c940c98mmentovai// some use 32 bits.  For the purposes of a minidump, wide strings are
2263261e8b6eac44a41341f112821482bee6c940c98mmentovai// always represented with 16-bit UTF-16 chracters.  iconv isn't available
2273261e8b6eac44a41341f112821482bee6c940c98mmentovai// everywhere, and its interface varies where it is available.  iconv also
2283261e8b6eac44a41341f112821482bee6c940c98mmentovai// deals purely with char* pointers, so in addition to considering the swap
2293261e8b6eac44a41341f112821482bee6c940c98mmentovai// parameter, a converter that uses iconv would also need to take the host
2303261e8b6eac44a41341f112821482bee6c940c98mmentovai// CPU's endianness into consideration.  It doesn't seems worth the trouble
2313261e8b6eac44a41341f112821482bee6c940c98mmentovai// of making it a dependency when we don't care about anything but UTF-16.
2326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic string* UTF16ToUTF8(const vector<uint16_t>& in,
2333562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                           bool swap) {
2342466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<string> out(new string());
2353261e8b6eac44a41341f112821482bee6c940c98mmentovai
2363261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Set the string's initial capacity to the number of UTF-16 characters,
2373261e8b6eac44a41341f112821482bee6c940c98mmentovai  // because the UTF-8 representation will always be at least this long.
2383261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the UTF-8 representation is longer, the string will grow dynamically.
2393261e8b6eac44a41341f112821482bee6c940c98mmentovai  out->reserve(in.size());
2403261e8b6eac44a41341f112821482bee6c940c98mmentovai
2416162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  for (vector<uint16_t>::const_iterator iterator = in.begin();
2423261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != in.end();
2433261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
2443261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Get a 16-bit value from the input
2456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint16_t in_word = *iterator;
2463261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (swap)
2473261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&in_word);
2483261e8b6eac44a41341f112821482bee6c940c98mmentovai
2493261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the input value (in_word) into a Unicode code point (unichar).
2506162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t unichar;
2513261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (in_word >= 0xdc00 && in_word <= 0xdcff) {
252af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
253af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(in_word) << " without high";
2543261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2553261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
2563261e8b6eac44a41341f112821482bee6c940c98mmentovai      // High surrogate.
2573261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = (in_word - 0xd7c0) << 10;
2583261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (++iterator == in.end()) {
259af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word) << " at end of string";
2613261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2623261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2636162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t high_word = in_word;
2643261e8b6eac44a41341f112821482bee6c940c98mmentovai      in_word = *iterator;
2653261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (in_word < 0xdc00 || in_word > 0xdcff) {
266af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(high_word) << " without low " <<
268af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word);
2693261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2703261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2713261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar |= in_word & 0x03ff;
2723261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
2733261e8b6eac44a41341f112821482bee6c940c98mmentovai      // The ordinary case, a single non-surrogate Unicode character encoded
2743261e8b6eac44a41341f112821482bee6c940c98mmentovai      // as a single 16-bit value.
2753261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = in_word;
2763261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2773261e8b6eac44a41341f112821482bee6c940c98mmentovai
2783261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the Unicode code point (unichar) into its UTF-8 representation,
2793261e8b6eac44a41341f112821482bee6c940c98mmentovai    // appending it to the out string.
2803261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (unichar < 0x80) {
281f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += static_cast<char>(unichar);
2823261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x800) {
283f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xc0 | static_cast<char>(unichar >> 6);
284f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2853261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x10000) {
286f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xe0 | static_cast<char>(unichar >> 12);
287f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
288f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2893261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x200000) {
290f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xf0 | static_cast<char>(unichar >> 18);
291f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f);
292f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
293f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2943261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
295af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
296af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(unichar) << " in UTF-8";
2973261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2983261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
3003261e8b6eac44a41341f112821482bee6c940c98mmentovai
3013261e8b6eac44a41341f112821482bee6c940c98mmentovai  return out.release();
3023261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3033261e8b6eac44a41341f112821482bee6c940c98mmentovai
3040314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// Return the smaller of the number of code units in the UTF-16 string,
3050314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// not including the terminating null word, or maxlen.
3066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic size_t UTF16codeunits(const uint16_t *string, size_t maxlen) {
3070314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  size_t count = 0;
3080314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  while (count < maxlen && string[count] != 0)
3090314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    count++;
3100314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return count;
3110314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
3120314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
3133562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDTimeZoneInformation* time_zone) {
3143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->bias);
3153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->standard_name.  No need to swap UTF-16 fields.
3163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
3173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_date);
3183562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_bias);
3193562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->daylight_name.  No need to swap UTF-16 fields.
3203562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
3213562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_date);
3223562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_bias);
3233562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3243562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
3253562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data,
3263562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           size_t max_length_in_bytes,
3273562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           string* utf8_result,
3283562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           bool swap) {
3293562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Since there is no explicit byte length for each string, use
3303562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // UTF16codeunits to calculate word length, then derive byte
3313562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // length from that.
3323562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]);
3333562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t word_length = UTF16codeunits(utf16_data, max_word_length);
3343562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (word_length > 0) {
3353562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    size_t byte_length = word_length * sizeof(utf16_data[0]);
3363562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    vector<uint16_t> utf16_vector(word_length);
3373562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    memcpy(&utf16_vector[0], &utf16_data[0], byte_length);
3383562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap));
3393562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (temp.get()) {
3403562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      utf8_result->assign(*temp);
3413562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
3423562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  } else {
3433562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    utf8_result->clear();
3443562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
3453562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3463261e8b6eac44a41341f112821482bee6c940c98mmentovai
3473261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3483261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpObject
3493261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3503261e8b6eac44a41341f112821482bee6c940c98mmentovai
3513261e8b6eac44a41341f112821482bee6c940c98mmentovai
3523261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpObject::MinidumpObject(Minidump* minidump)
35353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : minidump_(minidump),
35453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
3553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3563261e8b6eac44a41341f112821482bee6c940c98mmentovai
3573261e8b6eac44a41341f112821482bee6c940c98mmentovai
3583261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3593261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpStream
3603261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3613261e8b6eac44a41341f112821482bee6c940c98mmentovai
3623261e8b6eac44a41341f112821482bee6c940c98mmentovai
3633261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpStream::MinidumpStream(Minidump* minidump)
3643261e8b6eac44a41341f112821482bee6c940c98mmentovai    : MinidumpObject(minidump) {
3653261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3663261e8b6eac44a41341f112821482bee6c940c98mmentovai
3673261e8b6eac44a41341f112821482bee6c940c98mmentovai
3683261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3693261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpContext
3703261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3713261e8b6eac44a41341f112821482bee6c940c98mmentovai
3723261e8b6eac44a41341f112821482bee6c940c98mmentovai
3733261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext::MinidumpContext(Minidump* minidump)
37453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
375233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_(),
376233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_flags_(0) {
3773261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3783261e8b6eac44a41341f112821482bee6c940c98mmentovai
3793261e8b6eac44a41341f112821482bee6c940c98mmentovai
3803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiMinidumpContext::~MinidumpContext() {
3813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
3823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
3833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3856162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::Read(uint32_t expected_size) {
3863261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
3873261e8b6eac44a41341f112821482bee6c940c98mmentovai
38839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  // Certain raw context types are currently assumed to have unique sizes.
38939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) {
39039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any "
39139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
39239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
39339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
39439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
39539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
39639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
39739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
39839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
39939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextARM64))) {
40039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextARM64) cannot match the size of any "
40139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
40239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
40339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
40439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
4053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
4063261e8b6eac44a41341f112821482bee6c940c98mmentovai
4073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // First, figure out what type of CPU this context structure is for.
4088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // For some reason, the AMD64 Context doesn't have context_flags
4098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // at the beginning of the structure, so special case it here.
4108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (expected_size == sizeof(MDRawContextAMD64)) {
4118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
4128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
4148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(context_amd64.get(),
4158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                              sizeof(MDRawContextAMD64))) {
4168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
4178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
4218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->context_flags);
4223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
424233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
425233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
426233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_amd64->context_flags |= cpu_type;
427233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
428233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
429233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
430233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
431233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
4323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (cpu_type != MD_CONTEXT_AMD64) {
43439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
43539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
4368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
4378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Do this after reading the entire MDRawContext structure because
4418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // GetSystemInfo may seek minidump to a new position.
4428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!CheckAgainstSystemInfo(cpu_type)) {
4438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
4448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4463261e8b6eac44a41341f112821482bee6c940c98mmentovai
4478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Normalize the 128-bit types in the dump.
4488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Since this is AMD64, by definition, the values are little-endian.
4498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    for (unsigned int vr_index = 0;
4508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         vr_index < MD_CONTEXT_AMD64_VR_COUNT;
4518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         ++vr_index)
4528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Normalize128(&context_amd64->vector_register[vr_index], false);
4538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap()) {
4558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p1_home);
4568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p2_home);
4578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p3_home);
4588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p4_home);
4598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p5_home);
4608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p6_home);
4618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // context_flags is already swapped
4628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->mx_csr);
4638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->cs);
4648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ds);
4658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->es);
4668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->fs);
4678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ss);
4688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->eflags);
4698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr0);
4708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr1);
4718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr2);
4728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr3);
4738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr6);
4748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr7);
4758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rax);
4768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rcx);
4778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdx);
4788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbx);
4798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsp);
4808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbp);
4818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsi);
4828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdi);
4838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r8);
4848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r9);
4858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r10);
4868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r11);
4878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r12);
4888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r13);
4898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r14);
4908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r15);
4918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rip);
492f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // FIXME: I'm not sure what actually determines
4938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // which member of the union {flt_save, sse_registers}
4948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // is valid.  We're not currently using either,
4958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // but it would be good to have them swapped properly.
4963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      for (unsigned int vr_index = 0;
4988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           vr_index < MD_CONTEXT_AMD64_VR_COUNT;
4998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           ++vr_index)
5008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        Swap(&context_amd64->vector_register[vr_index]);
5018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->vector_control);
5028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->debug_control);
5038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_to_rip);
5048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_from_rip);
5058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_to_rip);
5068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_from_rip);
5078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
5083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_amd64->context_flags;
5103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_.amd64 = context_amd64.release();
512f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else if (expected_size == sizeof(MDRawContextPPC64)) {
513f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
514f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // in the else case have 32 bits |context_flags|, so special case it here.
515cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint64_t context_flags;
516cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
517cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read context flags";
518cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
519cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
520cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap())
521cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_flags);
522cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
523cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
524cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
525cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
52639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type == 0) {
52739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
52839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        context_ppc64->context_flags |= cpu_type;
52939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      } else {
53039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        BPLOG(ERROR) << "Failed to preserve the current stream position";
53139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return false;
53239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
53339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
53439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
53539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type != MD_CONTEXT_PPC64) {
53639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
53739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
53839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext not actually ppc64 context";
53939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
54039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
541f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
542cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Set the context_flags member, which has already been read, and
543cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // read the rest of the structure beginning with the first member
544cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // after context_flags.
545cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    context_ppc64->context_flags = context_flags;
546cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
547cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    size_t flags_size = sizeof(context_ppc64->context_flags);
548cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint8_t* context_after_flags =
549cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org          reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
550cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(context_after_flags,
551cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org                              sizeof(MDRawContextPPC64) - flags_size)) {
552cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
553cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
554cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
555cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
556cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Do this after reading the entire MDRawContext structure because
557cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // GetSystemInfo may seek minidump to a new position.
558cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!CheckAgainstSystemInfo(cpu_type)) {
559cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
560cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
561cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
562cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap()) {
563cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // context_ppc64->context_flags was already swapped.
564cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr0);
565cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr1);
566cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int gpr_index = 0;
567cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
568cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++gpr_index) {
569cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->gpr[gpr_index]);
570cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
571cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->cr);
572cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->xer);
573cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->lr);
574cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->ctr);
575cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vrsave);
576cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int fpr_index = 0;
577cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
578cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++fpr_index) {
579cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->float_save.fpregs[fpr_index]);
580cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
581cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap context_ppc64->float_save.fpscr_pad because it is only
582cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // used for padding.
583cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->float_save.fpscr);
584cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int vr_index = 0;
585cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
586cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++vr_index) {
587cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
588cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->vector_save.save_vr[vr_index]);
589cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
590cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vscr);
591cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap the padding fields in vector_save.
592cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vrvalid);
593cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
594cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
595f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    context_flags_ = static_cast<uint32_t>(context_ppc64->context_flags);
596f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
597f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // Check for data loss when converting context flags from uint64_t into
598f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // uint32_t
599f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    if (static_cast<uint64_t>(context_flags_) !=
600f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        context_ppc64->context_flags) {
601f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
602f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      return false;
603f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    }
604cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
605f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    context_.ppc64 = context_ppc64.release();
60639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  } else if (expected_size == sizeof(MDRawContextARM64)) {
60739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // |context_flags| of MDRawContextARM64 is 64 bits, but other MDRawContext
60839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // in the else case have 32 bits |context_flags|, so special case it here.
60939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint64_t context_flags;
61039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
61139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(INFO) << "MinidumpContext: looks like ARM64 context";
61239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
61339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
61439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read context flags";
61539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
61639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
61739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (minidump_->swap())
61839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_flags);
61939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
62039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64());
62139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
62239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
62339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type == 0) {
62439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
62539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        context_arm64->context_flags |= cpu_type;
62639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      } else {
62739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        BPLOG(ERROR) << "Failed to preserve the current stream position";
62839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return false;
62939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
63039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
63139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
63239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type != MD_CONTEXT_ARM64) {
63339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
63439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
63539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext not actually arm64 context";
63639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
63739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
63839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
63939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // Set the context_flags member, which has already been read, and
64039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // read the rest of the structure beginning with the first member
64139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // after context_flags.
64239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    context_arm64->context_flags = context_flags;
64339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
64439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    size_t flags_size = sizeof(context_arm64->context_flags);
64539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint8_t* context_after_flags =
64639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
64739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!minidump_->ReadBytes(context_after_flags,
64839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                              sizeof(MDRawContextARM64) - flags_size)) {
64939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
65039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
65139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
65239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
65339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // Do this after reading the entire MDRawContext structure because
65439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // GetSystemInfo may seek minidump to a new position.
65539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!CheckAgainstSystemInfo(cpu_type)) {
65639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext arm64 does not match system info";
65739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
65839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
65939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
66039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (minidump_->swap()) {
66139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // context_arm64->context_flags was already swapped.
66239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int ireg_index = 0;
66339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
66439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++ireg_index) {
66539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Swap(&context_arm64->iregs[ireg_index]);
66639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
66739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->cpsr);
66839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->float_save.fpsr);
66939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->float_save.fpcr);
67039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int fpr_index = 0;
67139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
67239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++fpr_index) {
67339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // While ARM64 is bi-endian, iOS (currently the only platform
67439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // for which ARM64 support has been brought up) uses ARM64 exclusively
67539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // in little-endian mode.
67639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Normalize128(&context_arm64->float_save.regs[fpr_index], false);
67739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Swap(&context_arm64->float_save.regs[fpr_index]);
67839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
67939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
680ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    context_flags_ = static_cast<uint32_t>(context_arm64->context_flags);
681ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org
682ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    // Check for data loss when converting context flags from uint64_t into
683ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    // uint32_t
684ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    if (static_cast<uint64_t>(context_flags_) !=
685ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org        context_arm64->context_flags) {
686ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org      BPLOG(ERROR) << "Data loss detected when converting ARM64 context_flags";
687ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org      return false;
688ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    }
689ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org
69039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    context_.arm64 = context_arm64.release();
691f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
6926162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t context_flags;
6938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
6948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read context flags";
6958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
6963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
6978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
6988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_flags);
6998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
7006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
7011a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    if (cpu_type == 0) {
7021a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // Unfortunately the flag for MD_CONTEXT_ARM that was taken
7031a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // from a Windows CE SDK header conflicts in practice with
7041a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
7051a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // but handle dumps with the legacy value gracefully here.
7061a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      if (context_flags & MD_CONTEXT_ARM_OLD) {
7071a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags |= MD_CONTEXT_ARM;
7081a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags &= ~MD_CONTEXT_ARM_OLD;
7091a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        cpu_type = MD_CONTEXT_ARM;
7101a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      }
7111a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    }
7128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
713233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
714233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
715233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_flags |= cpu_type;
716233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
717233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
718233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
719233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
720233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
721233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
7228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Allocate the context structure for the correct CPU and fill it.  The
7238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // casts are slightly unorthodox, but it seems better to do that than to
7248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // maintain a separate pointer for each type of CPU context structure
7258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // when only one of them will be used.
7268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    switch (cpu_type) {
7278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_X86: {
7288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextX86)) {
7298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
7308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextX86);
7318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
7353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
7378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
7388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
7398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_x86->context_flags = context_flags;
7403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_x86->context_flags);
7426162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
7436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
7448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
7458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextX86) - flags_size)) {
7468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read x86 context";
7478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
7518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
7528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
7538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
7548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
7588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->context_flags was already swapped.
7598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr0);
7608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr1);
7618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr2);
7628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr3);
7638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr6);
7648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr7);
7658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.control_word);
7668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.status_word);
7678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.tag_word);
7688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_offset);
7698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_selector);
7708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_offset);
7718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_selector);
7728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->float_save.register_area[] contains 8-bit quantities
7738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // and does not need to be swapped.
7748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.cr0_npx_state);
7758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->gs);
7768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->fs);
7778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->es);
7788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ds);
7798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edi);
7808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esi);
7818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebx);
7828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edx);
7838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ecx);
7848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eax);
7858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebp);
7868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eip);
7878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->cs);
7888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eflags);
7898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esp);
7908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ss);
7918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->extended_registers[] contains 8-bit quantities and
7928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // does not need to be swapped.
7938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.x86 = context_x86.release();
7968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
7978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
7981d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      }
7991d78cad82e3c7aa2315ed7438211a1901a91ed34bryner
8008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_PPC: {
8018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextPPC)) {
8028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
8038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextPPC);
8048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
8068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
8088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
8108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
8118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
8128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_ppc->context_flags = context_flags;
8138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_ppc->context_flags);
8156162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
8166162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
8178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
8188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextPPC) - flags_size)) {
8198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read ppc context";
8208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
8248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
8258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
8268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
8278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Normalize the 128-bit types in the dump.
8318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Since this is PowerPC, by definition, the values are big-endian.
8323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int vr_index = 0;
8333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
8343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++vr_index) {
8358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
8363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
8398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_ppc->context_flags was already swapped.
8408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr0);
8418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr1);
8428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
8438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
8448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
8458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->gpr[gpr_index]);
8468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
8478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->cr);
8488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->xer);
8498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->lr);
8508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->ctr);
8518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->mq);
8528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vrsave);
8538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
8548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
8558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
8568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->float_save.fpregs[fpr_index]);
8578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
8588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap context_ppc->float_save.fpscr_pad because it is only
8598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // used for padding.
8608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->float_save.fpscr);
8618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int vr_index = 0;
8628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
8638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++vr_index) {
8648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->vector_save.save_vr[vr_index]);
8658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
8668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vscr);
8678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap the padding fields in vector_save.
8688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vrvalid);
8698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
8703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ppc = context_ppc.release();
8723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
874ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
875ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_SPARC: {
8778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextSPARC)) {
8788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
8798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextSPARC);
8808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
882ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
884ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
8868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
8878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
8888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_sparc->context_flags = context_flags;
889ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_sparc->context_flags);
8916162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
8926162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
8938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
8948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextSPARC) - flags_size)) {
8958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read sparc context";
8968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
898ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
9008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
9018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
9028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
9038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
904ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
9058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
9068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
9078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_sparc->context_flags was already swapped.
9088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
9098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
9108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
9118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->g_r[gpr_index]);
9128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
9138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->ccr);
9148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->pc);
9158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->npc);
9168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->y);
9178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->asi);
9188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->fprs);
9198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
9208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
9218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
9228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->float_save.regs[fpr_index]);
9238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
9248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.filler);
9258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.fsr);
926ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
9278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ctx_sparc = context_sparc.release();
928ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
9308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
931ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9329276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      case MD_CONTEXT_ARM: {
9339276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (expected_size != sizeof(MDRawContextARM)) {
9349276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
9359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            expected_size << " != " << sizeof(MDRawContextARM);
9369276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9379276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9389276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9399276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
9409276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9419276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Set the context_flags member, which has already been read, and
9429276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // read the rest of the structure beginning with the first member
9439276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // after context_flags.
9449276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_arm->context_flags = context_flags;
9459276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9469276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        size_t flags_size = sizeof(context_arm->context_flags);
9476162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
9486162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
9499276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
9509276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek                                  sizeof(MDRawContextARM) - flags_size)) {
9519276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read arm context";
9529276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9539276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9549276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9559276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Do this after reading the entire MDRawContext structure because
9569276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // GetSystemInfo may seek minidump to a new position.
9579276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
9589276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm does not match system info";
9599276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9609276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9619276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9629276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (minidump_->swap()) {
9639276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          // context_arm->context_flags was already swapped.
9649276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int ireg_index = 0;
9659276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
9669276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++ireg_index) {
9679276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->iregs[ireg_index]);
9689276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
9699276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->cpsr);
9709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->float_save.fpscr);
9719276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpr_index = 0;
9729276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
9739276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpr_index) {
9749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.regs[fpr_index]);
9759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
9769276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpe_index = 0;
9779276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
9789276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpe_index) {
9799276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.extra[fpe_index]);
9809276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
9819276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9829276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_.arm = context_arm.release();
9839276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9849276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        break;
9859276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
9869276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9875f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      case MD_CONTEXT_MIPS: {
9885f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (expected_size != sizeof(MDRawContextMIPS)) {
9895f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
9905f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << expected_size
9915f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << " != "
9925f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << sizeof(MDRawContextMIPS);
9935f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
9945f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
9955f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
9965f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
9975f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
9985f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Set the context_flags member, which has already been read, and
9995f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // read the rest of the structure beginning with the first member
10005f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // after context_flags.
10015f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        context_mips->context_flags = context_flags;
10025f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10035f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        size_t flags_size = sizeof(context_mips->context_flags);
10045f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        uint8_t* context_after_flags =
10055f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
10065f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!minidump_->ReadBytes(context_after_flags,
10075f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                                  sizeof(MDRawContextMIPS) - flags_size)) {
10085f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
10095f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
10105f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10115f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10125f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Do this after reading the entire MDRawContext structure because
10135f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // GetSystemInfo may seek minidump to a new position.
10145f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!CheckAgainstSystemInfo(cpu_type)) {
10155f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
10165f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
10175f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10185f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10195f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (minidump_->swap()) {
10205f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          // context_mips->context_flags was already swapped.
10215f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int ireg_index = 0;
10225f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
10235f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++ireg_index) {
10245f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->iregs[ireg_index]);
10255f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10265f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdhi);
10275f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdlo);
10285f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int dsp_index = 0;
10295f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
10305f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++dsp_index) {
10315f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->hi[dsp_index]);
10325f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->lo[dsp_index]);
10335f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10345f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->dsp_control);
10355f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->epc);
10365f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->badvaddr);
10375f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->status);
10385f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->cause);
10395f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int fpr_index = 0;
10405f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
10415f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++fpr_index) {
10425f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->float_save.regs[fpr_index]);
10435f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fpcsr);
10455f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fir);
10465f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        context_.ctx_mips = context_mips.release();
10485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10495f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        break;
10505f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
10515f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      default: {
1053bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com        // Unknown context type - Don't log as an error yet. Let the
10545f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        // caller work that out.
10555f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        BPLOG(INFO) << "MinidumpContext unknown context type " <<
10568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          HexString(cpu_type);
10578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return false;
10588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
10598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
10603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
10618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_flags;
10623261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
10633261e8b6eac44a41341f112821482bee6c940c98mmentovai
10643261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
10653261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
10663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
10673261e8b6eac44a41341f112821482bee6c940c98mmentovai
10683261e8b6eac44a41341f112821482bee6c940c98mmentovai
10696162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpContext::GetContextCPU() const {
1070af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1071af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // Don't log a message, GetContextCPU can be legitimately called with
1072af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // valid_ false by FreeContext, which is called by Read.
1073af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
1074af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1075af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
10768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_flags_ & MD_CONTEXT_CPU_MASK;
10773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
10783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10796162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::GetInstructionPointer(uint64_t* ip) const {
1080c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  BPLOG_IF(ERROR, !ip) << "MinidumpContext::GetInstructionPointer "
1081c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com                          "requires |ip|";
1082c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  assert(ip);
1083c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  *ip = 0;
1084c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
1085c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  if (!valid_) {
1086c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Invalid MinidumpContext for GetInstructionPointer";
1087c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
1088c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
1089c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
1090c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  switch (context_flags_ & MD_CONTEXT_CPU_MASK) {
1091c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_AMD64:
1092c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.amd64->rip;
1093c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
1094c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_ARM:
1095c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.arm->iregs[MD_CONTEXT_ARM_REG_PC];
1096c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
109739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  case MD_CONTEXT_ARM64:
109839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    *ip = context_.arm64->iregs[MD_CONTEXT_ARM64_REG_PC];
109939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    break;
1100c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_PPC:
1101c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ppc->srr0;
1102c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
1103cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  case MD_CONTEXT_PPC64:
1104cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    *ip = context_.ppc64->srr0;
1105cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    break;
1106c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_SPARC:
1107c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ctx_sparc->pc;
1108c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
1109c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_X86:
1110c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.x86->eip;
1111c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
11125f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  case MD_CONTEXT_MIPS:
11135f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    *ip = context_.ctx_mips->epc;
11145f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    break;
1115c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  default:
1116c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    // This should never happen.
1117c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer";
1118c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
1119c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
1120c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  return true;
1121c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com}
1122c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
11233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextX86* MinidumpContext::GetContextX86() const {
1125af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_X86) {
1126af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get x86 context";
1127af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1128af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1130af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.x86;
11313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
11323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextPPC* MinidumpContext::GetContextPPC() const {
1135af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_PPC) {
1136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get ppc context";
1137af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1139af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1140af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.ppc;
11413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
11423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1143cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.orgconst MDRawContextPPC64* MinidumpContext::GetContextPPC64() const {
1144cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  if (GetContextCPU() != MD_CONTEXT_PPC64) {
1145cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    BPLOG(ERROR) << "MinidumpContext cannot get ppc64 context";
1146cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    return NULL;
1147cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  }
1148cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
1149cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  return context_.ppc64;
1150cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org}
1151cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
11528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarekconst MDRawContextAMD64* MinidumpContext::GetContextAMD64() const {
11538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (GetContextCPU() != MD_CONTEXT_AMD64) {
11548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get amd64 context";
11558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    return NULL;
11568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  }
11578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
11588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_.amd64;
11598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek}
11608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1161ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovaiconst MDRawContextSPARC* MinidumpContext::GetContextSPARC() const {
1162ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (GetContextCPU() != MD_CONTEXT_SPARC) {
1163ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get sparc context";
1164ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return NULL;
1165ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  }
1166ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1167ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  return context_.ctx_sparc;
1168ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai}
11693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarekconst MDRawContextARM* MinidumpContext::GetContextARM() const {
11719276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  if (GetContextCPU() != MD_CONTEXT_ARM) {
11729276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get arm context";
11739276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    return NULL;
11749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  }
11759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
11769276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  return context_.arm;
11779276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek}
11789276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
117939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.orgconst MDRawContextARM64* MinidumpContext::GetContextARM64() const {
118039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (GetContextCPU() != MD_CONTEXT_ARM64) {
118139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "MinidumpContext cannot get arm64 context";
118239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return NULL;
118339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
118439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
118539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  return context_.arm64;
118639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org}
118739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
11885f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.comconst MDRawContextMIPS* MinidumpContext::GetContextMIPS() const {
11895f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  if (GetContextCPU() != MD_CONTEXT_MIPS) {
11905f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    BPLOG(ERROR) << "MinidumpContext cannot get MIPS context";
11915f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    return NULL;
11925f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  }
11935f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
11945f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  return context_.ctx_mips;
11955f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com}
11965f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
11973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::FreeContext() {
11983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
11993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
12003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.x86;
12013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12023261e8b6eac44a41341f112821482bee6c940c98mmentovai
12033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
12043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.ppc;
12053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1207cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64:
1208cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      delete context_.ppc64;
1209cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1210cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
12118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
12128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      delete context_.amd64;
12138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
12148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1215ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
1216ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      delete context_.ctx_sparc;
1217ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
1218ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
12199276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
12209276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      delete context_.arm;
12219276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
12229276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
122339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CONTEXT_ARM64:
122439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      delete context_.arm64;
122539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
122639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
12275f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS:
12285f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      delete context_.ctx_mips;
12295f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
12305f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
12313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default:
12323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // There is no context record (valid_ is false) or there's a
12333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context record for an unknown CPU (shouldn't happen, only known
12343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // records are stored by Read).
12353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12363261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
12373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  context_flags_ = 0;
12393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  context_.base = NULL;
12403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
12413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
1244e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
12453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // as this function just implements a sanity check.
12463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
1247af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!system_info) {
1248af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1249af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MinidumpSystemInfo";
12503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return true;
1251af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1253e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
12543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  const MDRawSystemInfo* raw_system_info = system_info->system_info();
1255af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1256af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MDRawSystemInfo";
12583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return false;
1259af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
12623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      raw_system_info->processor_architecture);
12633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Compare the CPU type of the context record to the CPU type in the
12653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // minidump's system info stream.
1266af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  bool return_value = false;
12673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (context_cpu_type) {
12683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
1269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
1270299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
1271299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
1272af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
12733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
12743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
1277af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
1278af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
12793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
1280ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1281cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64:
1282cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64)
1283cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        return_value = true;
1284cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1285cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
12868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
12878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
12888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return_value = true;
12898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
12908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1291ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
1292ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
1293ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return_value = true;
1294ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
12959276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
12969276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
12979276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
12989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        return_value = true;
12999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
13005f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
130139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CONTEXT_ARM64:
130239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64)
130339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return_value = true;
130439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
130539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
13065f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS:
13075f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS)
13085f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        return_value = true;
13095f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
13103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  }
13113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1312af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
1313af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(context_cpu_type) <<
13140344a368deac6abaa280a298bcea9bb00a90df3fted.mielczarek@gmail.com                                    " wrong for MinidumpSystemInfo CPU " <<
1315af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(system_info_cpu_type);
1316af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1317af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return return_value;
13183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
13193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
13203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
13213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::Print() {
1322af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1323af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot print invalid data";
1324af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return;
1325af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1326af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
13273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
13283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86: {
13293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextX86* context_x86 = GetContextX86();
13303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextX86\n");
13313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags                = 0x%x\n",
13323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->context_flags);
13333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr0                          = 0x%x\n", context_x86->dr0);
13343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr1                          = 0x%x\n", context_x86->dr1);
13353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr2                          = 0x%x\n", context_x86->dr2);
13363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr3                          = 0x%x\n", context_x86->dr3);
13373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr6                          = 0x%x\n", context_x86->dr6);
13383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr7                          = 0x%x\n", context_x86->dr7);
13393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.control_word      = 0x%x\n",
13403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.control_word);
13413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.status_word       = 0x%x\n",
13423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.status_word);
13433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.tag_word          = 0x%x\n",
13443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.tag_word);
13453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_offset      = 0x%x\n",
13463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_offset);
13473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_selector    = 0x%x\n",
13483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_selector);
13493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_offset       = 0x%x\n",
13503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_offset);
13513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_selector     = 0x%x\n",
13523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_selector);
13533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.register_area[%2d] = 0x",
13543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
13553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
13563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
13573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
13583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->float_save.register_area[register_index]);
13593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
13603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
13613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.cr0_npx_state     = 0x%x\n",
13623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.cr0_npx_state);
13633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  gs                           = 0x%x\n", context_x86->gs);
13643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  fs                           = 0x%x\n", context_x86->fs);
13653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  es                           = 0x%x\n", context_x86->es);
13663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ds                           = 0x%x\n", context_x86->ds);
13673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edi                          = 0x%x\n", context_x86->edi);
13683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esi                          = 0x%x\n", context_x86->esi);
13693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebx                          = 0x%x\n", context_x86->ebx);
13703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edx                          = 0x%x\n", context_x86->edx);
13713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ecx                          = 0x%x\n", context_x86->ecx);
13723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eax                          = 0x%x\n", context_x86->eax);
13733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebp                          = 0x%x\n", context_x86->ebp);
13743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eip                          = 0x%x\n", context_x86->eip);
13753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cs                           = 0x%x\n", context_x86->cs);
13763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eflags                       = 0x%x\n", context_x86->eflags);
13773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esp                          = 0x%x\n", context_x86->esp);
13783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ss                           = 0x%x\n", context_x86->ss);
13793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  extended_registers[%3d]      = 0x",
13803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
13813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
13823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
13833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
13843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->extended_registers[register_index]);
13853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
13863402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n\n");
13873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
13883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
13893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
13903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
13913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC: {
13923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextPPC* context_ppc = GetContextPPC();
13933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextPPC\n");
13943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags            = 0x%x\n",
13953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->context_flags);
13963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr0                     = 0x%x\n", context_ppc->srr0);
13973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr1                     = 0x%x\n", context_ppc->srr1);
13983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int gpr_index = 0;
13993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
14003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++gpr_index) {
14013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("  gpr[%2d]                  = 0x%x\n",
14023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               gpr_index, context_ppc->gpr[gpr_index]);
14033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
14043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cr                       = 0x%x\n", context_ppc->cr);
14053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  xer                      = 0x%x\n", context_ppc->xer);
14063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  lr                       = 0x%x\n", context_ppc->lr);
14073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ctr                      = 0x%x\n", context_ppc->ctr);
14083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  mq                       = 0x%x\n", context_ppc->mq);
14093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vrsave                   = 0x%x\n", context_ppc->vrsave);
14103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int fpr_index = 0;
14113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
14123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++fpr_index) {
1413c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
14143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               fpr_index, context_ppc->float_save.fpregs[fpr_index]);
14153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
14163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.fpscr         = 0x%x\n",
14173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->float_save.fpscr);
14183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // TODO(mmentovai): print the 128-bit quantities in
14193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context_ppc->vector_save.  This isn't done yet because printf
14203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // doesn't support 128-bit quantities, and printing them using
1421c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
14223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // byte ordering.
14233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vector_save.save_vrvalid = 0x%x\n",
14243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->vector_save.save_vrvalid);
14253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
14263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
14273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
14283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
14293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1430cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64: {
1431cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      const MDRawContextPPC64* context_ppc64 = GetContextPPC64();
1432cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("MDRawContextPPC64\n");
143339b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  context_flags            = 0x%" PRIx64 "\n",
1434cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->context_flags);
143539b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  srr0                     = 0x%" PRIx64 "\n",
143639b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->srr0);
143739b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  srr1                     = 0x%" PRIx64 "\n",
143839b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->srr1);
1439cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int gpr_index = 0;
1440cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
1441cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++gpr_index) {
144239b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org        printf("  gpr[%2d]                  = 0x%" PRIx64 "\n",
1443cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org               gpr_index, context_ppc64->gpr[gpr_index]);
1444cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
144539b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  cr                       = 0x%" PRIx64 "\n", context_ppc64->cr);
144639b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  xer                      = 0x%" PRIx64 "\n",
144739b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->xer);
144839b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  lr                       = 0x%" PRIx64 "\n", context_ppc64->lr);
144939b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  ctr                      = 0x%" PRIx64 "\n",
145039b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->ctr);
145139b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  vrsave                   = 0x%" PRIx64 "\n",
145239b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->vrsave);
1453cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int fpr_index = 0;
1454cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
1455cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++fpr_index) {
1456cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
1457cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org               fpr_index, context_ppc64->float_save.fpregs[fpr_index]);
1458cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
1459cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("  float_save.fpscr         = 0x%x\n",
1460cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->float_save.fpscr);
1461cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // TODO(mmentovai): print the 128-bit quantities in
1462cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // context_ppc64->vector_save.  This isn't done yet because printf
1463cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // doesn't support 128-bit quantities, and printing them using
1464cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
1465cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // byte ordering.
1466cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("  vector_save.save_vrvalid = 0x%x\n",
1467cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->vector_save.save_vrvalid);
1468cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("\n");
1469cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
1470cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1471cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
1472cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
14738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64: {
14748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      const MDRawContextAMD64* context_amd64 = GetContextAMD64();
14758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("MDRawContextAMD64\n");
1476c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p1_home       = 0x%" PRIx64 "\n",
14778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p1_home);
1478c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p2_home       = 0x%" PRIx64 "\n",
14798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p2_home);
1480c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p3_home       = 0x%" PRIx64 "\n",
14818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p3_home);
1482c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p4_home       = 0x%" PRIx64 "\n",
14838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p4_home);
1484c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p5_home       = 0x%" PRIx64 "\n",
14858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p5_home);
1486c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p6_home       = 0x%" PRIx64 "\n",
14878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p6_home);
14888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  context_flags = 0x%x\n",
14898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->context_flags);
14908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  mx_csr        = 0x%x\n",
14918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->mx_csr);
14928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  cs            = 0x%x\n", context_amd64->cs);
14938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ds            = 0x%x\n", context_amd64->ds);
14948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  es            = 0x%x\n", context_amd64->es);
14958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  fs            = 0x%x\n", context_amd64->fs);
14968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  gs            = 0x%x\n", context_amd64->gs);
14978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ss            = 0x%x\n", context_amd64->ss);
14988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  eflags        = 0x%x\n", context_amd64->eflags);
1499c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr0           = 0x%" PRIx64 "\n", context_amd64->dr0);
1500c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr1           = 0x%" PRIx64 "\n", context_amd64->dr1);
1501c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr2           = 0x%" PRIx64 "\n", context_amd64->dr2);
1502c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr3           = 0x%" PRIx64 "\n", context_amd64->dr3);
1503c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr6           = 0x%" PRIx64 "\n", context_amd64->dr6);
1504c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr7           = 0x%" PRIx64 "\n", context_amd64->dr7);
1505c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rax           = 0x%" PRIx64 "\n", context_amd64->rax);
1506c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rcx           = 0x%" PRIx64 "\n", context_amd64->rcx);
1507c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdx           = 0x%" PRIx64 "\n", context_amd64->rdx);
1508c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbx           = 0x%" PRIx64 "\n", context_amd64->rbx);
1509c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsp           = 0x%" PRIx64 "\n", context_amd64->rsp);
1510c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbp           = 0x%" PRIx64 "\n", context_amd64->rbp);
1511c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsi           = 0x%" PRIx64 "\n", context_amd64->rsi);
1512c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdi           = 0x%" PRIx64 "\n", context_amd64->rdi);
1513c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r8            = 0x%" PRIx64 "\n", context_amd64->r8);
1514c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r9            = 0x%" PRIx64 "\n", context_amd64->r9);
1515c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r10           = 0x%" PRIx64 "\n", context_amd64->r10);
1516c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r11           = 0x%" PRIx64 "\n", context_amd64->r11);
1517c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r12           = 0x%" PRIx64 "\n", context_amd64->r12);
1518c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r13           = 0x%" PRIx64 "\n", context_amd64->r13);
1519c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r14           = 0x%" PRIx64 "\n", context_amd64->r14);
1520c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r15           = 0x%" PRIx64 "\n", context_amd64->r15);
1521c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rip           = 0x%" PRIx64 "\n", context_amd64->rip);
1522f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // TODO: print xmm, vector, debug registers
15238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("\n");
15248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
15258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
15268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1527ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC: {
1528ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      const MDRawContextSPARC* context_sparc = GetContextSPARC();
1529ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("MDRawContextSPARC\n");
1530ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("  context_flags       = 0x%x\n",
1531ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->context_flags);
1532ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int g_r_index = 0;
1533ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
1534ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++g_r_index) {
1535c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  g_r[%2d]             = 0x%" PRIx64 "\n",
1536ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               g_r_index, context_sparc->g_r[g_r_index]);
1537ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1538c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  ccr                 = 0x%" PRIx64 "\n", context_sparc->ccr);
1539c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  pc                  = 0x%" PRIx64 "\n", context_sparc->pc);
1540c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  npc                 = 0x%" PRIx64 "\n", context_sparc->npc);
1541c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  y                   = 0x%" PRIx64 "\n", context_sparc->y);
1542c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  asi                 = 0x%" PRIx64 "\n", context_sparc->asi);
1543c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  fprs                = 0x%" PRIx64 "\n", context_sparc->fprs);
1544ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1545ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int fpr_index = 0;
1546ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
1547ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++fpr_index) {
1548c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
1549ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               fpr_index, context_sparc->float_save.regs[fpr_index]);
1550ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1551c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.filler   = 0x%" PRIx64 "\n",
1552ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.filler);
1553c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.fsr      = 0x%" PRIx64 "\n",
1554ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.fsr);
1555ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
1556ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
1557ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
15589276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM: {
15599276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      const MDRawContextARM* context_arm = GetContextARM();
15609276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("MDRawContextARM\n");
15619276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  context_flags       = 0x%x\n",
15629276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek             context_arm->context_flags);
15639276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int ireg_index = 0;
15649276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
15659276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++ireg_index) {
15669276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  iregs[%2d]            = 0x%x\n",
15679276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index, context_arm->iregs[ireg_index]);
15689276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
15699276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  cpsr                = 0x%x\n", context_arm->cpsr);
15709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  float_save.fpscr     = 0x%" PRIx64 "\n",
15711adb184d420c6c5f2304fb945f8477557336f927ted.mielczarek             context_arm->float_save.fpscr);
15729276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpr_index = 0;
15739276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
15749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpr_index) {
15759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
15769276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index, context_arm->float_save.regs[fpr_index]);
15779276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
15789276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpe_index = 0;
15799276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
15809276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpe_index) {
15810441036f9ec45c3bc3037f2b407cf21a8006d66fjimblandy        printf("  float_save.extra[%2d] = 0x%" PRIx32 "\n",
15829276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index, context_arm->float_save.extra[fpe_index]);
15839276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
15849276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
15859276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
15869276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    }
158739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
158839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CONTEXT_ARM64: {
158939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      const MDRawContextARM64* context_arm64 = GetContextARM64();
159039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      printf("MDRawContextARM64\n");
1591e20c85fb4a6de1657f819dbf51d7047f917934a3ivan.penkov@gmail.com      printf("  context_flags       = 0x%" PRIx64 "\n",
159239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org             context_arm64->context_flags);
159339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int ireg_index = 0;
159439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
159539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++ireg_index) {
1596e20c85fb4a6de1657f819dbf51d7047f917934a3ivan.penkov@gmail.com        printf("  iregs[%2d]            = 0x%" PRIx64 "\n",
159739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org               ireg_index, context_arm64->iregs[ireg_index]);
159839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
159939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      printf("  cpsr                = 0x%x\n", context_arm64->cpsr);
160039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      printf("  float_save.fpsr     = 0x%x\n", context_arm64->float_save.fpsr);
160139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      printf("  float_save.fpcr     = 0x%x\n", context_arm64->float_save.fpcr);
160239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
160339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int freg_index = 0;
160439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
160539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++freg_index) {
160639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        uint128_struct fp_value = context_arm64->float_save.regs[freg_index];
1607e20c85fb4a6de1657f819dbf51d7047f917934a3ivan.penkov@gmail.com        printf("  float_save.regs[%2d]            = 0x%" PRIx64 "%" PRIx64 "\n",
160839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org               freg_index, fp_value.high, fp_value.low);
160939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
161039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
161139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
16129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
16135f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS: {
16145f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      const MDRawContextMIPS* context_mips = GetContextMIPS();
16155f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("MDRawContextMIPS\n");
16165f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  context_flags        = 0x%x\n",
16175f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->context_flags);
16185f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int ireg_index = 0;
16195f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
16205f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++ireg_index) {
16215f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  iregs[%2d]           = 0x%" PRIx64 "\n",
16225f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ireg_index, context_mips->iregs[ireg_index]);
16235f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
16245f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  mdhi                 = 0x%" PRIx64 "\n",
16255f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->mdhi);
16265f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  mdlo                 = 0x%" PRIx64 "\n",
16275f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->mdhi);
16285f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int dsp_index = 0;
16295f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
16305f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++dsp_index) {
16315f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  hi[%1d]              = 0x%" PRIx32 "\n",
16325f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index, context_mips->hi[dsp_index]);
16335f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  lo[%1d]              = 0x%" PRIx32 "\n",
16345f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index, context_mips->lo[dsp_index]);
16355f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
16365f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  dsp_control          = 0x%" PRIx32 "\n",
16375f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->dsp_control);
16385f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  epc                  = 0x%" PRIx64 "\n",
16395f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->epc);
16405f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  badvaddr             = 0x%" PRIx64 "\n",
16415f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->badvaddr);
16425f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  status               = 0x%" PRIx32 "\n",
16435f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->status);
16445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  cause                = 0x%" PRIx32 "\n",
16455f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->cause);
16465f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
16475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int fpr_index = 0;
16485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
16495f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++fpr_index) {
16505f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
16515f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               fpr_index, context_mips->float_save.regs[fpr_index]);
16525f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
16535f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  float_save.fpcsr     = 0x%" PRIx32 "\n",
16545f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->float_save.fpcsr);
16555f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  float_save.fir       = 0x%" PRIx32 "\n",
16565f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->float_save.fir);
16575f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
16585f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    }
16595f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
16603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default: {
16613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
16623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
16633261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16643261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16653261e8b6eac44a41341f112821482bee6c940c98mmentovai
16663261e8b6eac44a41341f112821482bee6c940c98mmentovai
16673261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16683261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryRegion
16693261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16703261e8b6eac44a41341f112821482bee6c940c98mmentovai
16713261e8b6eac44a41341f112821482bee6c940c98mmentovai
16726162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
1673e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1674e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
16753261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
167653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
167753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptor_(NULL),
167853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL) {
16793261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16803261e8b6eac44a41341f112821482bee6c940c98mmentovai
16813261e8b6eac44a41341f112821482bee6c940c98mmentovai
16823261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::~MinidumpMemoryRegion() {
16833261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
16843261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16853261e8b6eac44a41341f112821482bee6c940c98mmentovai
16863261e8b6eac44a41341f112821482bee6c940c98mmentovai
16873261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
16883261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptor_ = descriptor;
16893261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = descriptor &&
1690fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai           descriptor_->memory.data_size <=
16916162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com               numeric_limits<uint64_t>::max() -
1692fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               descriptor_->start_of_memory_range;
16933261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16943261e8b6eac44a41341f112821482bee6c940c98mmentovai
16953261e8b6eac44a41341f112821482bee6c940c98mmentovai
16966162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpMemoryRegion::GetMemory() const {
1697af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1698af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
16993261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1700af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17013261e8b6eac44a41341f112821482bee6c940c98mmentovai
17023261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!memory_) {
1703af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (descriptor_->memory.data_size == 0) {
1704af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
1705373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
1706af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
1707373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1708af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(descriptor_->memory.rva)) {
1709af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
17103261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1711af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
17123261e8b6eac44a41341f112821482bee6c940c98mmentovai
1713e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (descriptor_->memory.data_size > max_bytes_) {
1714e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
1715e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      descriptor_->memory.data_size << " exceeds maximum " <<
1716e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_bytes_;
1717e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
1718e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
1719e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
17206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > memory(
17216162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(descriptor_->memory.data_size));
17223261e8b6eac44a41341f112821482bee6c940c98mmentovai
1723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
1724af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
17253261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1726af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
17273261e8b6eac44a41341f112821482bee6c940c98mmentovai
17283261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory_ = memory.release();
17293261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17303261e8b6eac44a41341f112821482bee6c940c98mmentovai
17313261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*memory_)[0];
17323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17333261e8b6eac44a41341f112821482bee6c940c98mmentovai
17343261e8b6eac44a41341f112821482bee6c940c98mmentovai
17356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint64_t MinidumpMemoryRegion::GetBase() const {
1736af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1737af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
17386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    return static_cast<uint64_t>(-1);
1739af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1740af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1741af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->start_of_memory_range;
17423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17433261e8b6eac44a41341f112821482bee6c940c98mmentovai
17443261e8b6eac44a41341f112821482bee6c940c98mmentovai
17456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::GetSize() const {
1746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1747af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
1748af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
1749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1751af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->memory.data_size;
17523261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17533261e8b6eac44a41341f112821482bee6c940c98mmentovai
17543261e8b6eac44a41341f112821482bee6c940c98mmentovai
17553261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::FreeMemory() {
17563261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
17573261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
17583261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17593261e8b6eac44a41341f112821482bee6c940c98mmentovai
17603261e8b6eac44a41341f112821482bee6c940c98mmentovai
17613261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
17626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address,
17632214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                                      T*        value) const {
1764af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
1765af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                             "requires |value|";
1766af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(value);
1767af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *value = 0;
1768af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1769af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1770af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
1771af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "GetMemoryAtAddressInternal";
17723261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17743261e8b6eac44a41341f112821482bee6c940c98mmentovai
1775bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Common failure case
17763261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (address < descriptor_->start_of_memory_range ||
17776162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      sizeof(T) > numeric_limits<uint64_t>::max() - address ||
17783261e8b6eac44a41341f112821482bee6c940c98mmentovai      address + sizeof(T) > descriptor_->start_of_memory_range +
17793261e8b6eac44a41341f112821482bee6c940c98mmentovai                            descriptor_->memory.data_size) {
1780bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com    BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
1781af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(address) << "+" << sizeof(T) << "/" <<
1782af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->start_of_memory_range) << "+" <<
1783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->memory.data_size);
17843261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
17853261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17863261e8b6eac44a41341f112821482bee6c940c98mmentovai
17876162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
1788af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!memory) {
1789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // GetMemory already logged a perfectly good message.
17903261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1791af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17923261e8b6eac44a41341f112821482bee6c940c98mmentovai
17933261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the CPU requires memory accesses to be aligned, this can crash.
17943261e8b6eac44a41341f112821482bee6c940c98mmentovai  // x86 and ppc are able to cope, though.
17953261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = *reinterpret_cast<const T*>(
17963261e8b6eac44a41341f112821482bee6c940c98mmentovai      &memory[address - descriptor_->start_of_memory_range]);
17973261e8b6eac44a41341f112821482bee6c940c98mmentovai
17983261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
17993261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(value);
18003261e8b6eac44a41341f112821482bee6c940c98mmentovai
18013261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
18023261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18033261e8b6eac44a41341f112821482bee6c940c98mmentovai
18043261e8b6eac44a41341f112821482bee6c940c98mmentovai
18056162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
18066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint8_t*  value) const {
18073261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
18083261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18093261e8b6eac44a41341f112821482bee6c940c98mmentovai
18103261e8b6eac44a41341f112821482bee6c940c98mmentovai
18116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
18126162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint16_t* value) const {
18133261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
18143261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18153261e8b6eac44a41341f112821482bee6c940c98mmentovai
18163261e8b6eac44a41341f112821482bee6c940c98mmentovai
18176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
18186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint32_t* value) const {
18193261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
18203261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18213261e8b6eac44a41341f112821482bee6c940c98mmentovai
18223261e8b6eac44a41341f112821482bee6c940c98mmentovai
18236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
18246162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint64_t* value) const {
18253261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
18263261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18273261e8b6eac44a41341f112821482bee6c940c98mmentovai
18283261e8b6eac44a41341f112821482bee6c940c98mmentovai
18293261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::Print() {
1830af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1831af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
18323261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1833af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
18343261e8b6eac44a41341f112821482bee6c940c98mmentovai
18356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
18363261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
18373261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("0x");
18383261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int byte_index = 0;
18393261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index < descriptor_->memory.data_size;
18403261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index++) {
18413261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("%02x", memory[byte_index]);
18423261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
18433261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
18443261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
18453261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No memory\n");
18463261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18483261e8b6eac44a41341f112821482bee6c940c98mmentovai
18493261e8b6eac44a41341f112821482bee6c940c98mmentovai
18503261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18513261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThread
18523261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18533261e8b6eac44a41341f112821482bee6c940c98mmentovai
18543261e8b6eac44a41341f112821482bee6c940c98mmentovai
18553261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::MinidumpThread(Minidump* minidump)
185653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
185753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_(),
185853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL),
185953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
18603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18613261e8b6eac44a41341f112821482bee6c940c98mmentovai
18623261e8b6eac44a41341f112821482bee6c940c98mmentovai
18633261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::~MinidumpThread() {
18643261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
18653261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
18663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18673261e8b6eac44a41341f112821482bee6c940c98mmentovai
18683261e8b6eac44a41341f112821482bee6c940c98mmentovai
18693261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThread::Read() {
18703261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
18713261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
18723261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
18733261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
18743261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
18753261e8b6eac44a41341f112821482bee6c940c98mmentovai
18763261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
18773261e8b6eac44a41341f112821482bee6c940c98mmentovai
1878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
1879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot read thread";
18803261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1881af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
18823261e8b6eac44a41341f112821482bee6c940c98mmentovai
18833261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
18843261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_id);
18853261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.suspend_count);
18863261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority_class);
18873261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority);
18883261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.teb);
18893261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.stack);
18903261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_context);
18913261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18923261e8b6eac44a41341f112821482bee6c940c98mmentovai
1893fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
189402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (thread_.stack.memory.rva == 0 ||
189502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      thread_.stack.memory.data_size == 0 ||
18966162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() -
1897fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                                       thread_.stack.start_of_memory_range) {
1898e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    // This is ok, but log an error anyway.
1899af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
1900af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(thread_.stack.start_of_memory_range) << "+" <<
190102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    HexString(thread_.stack.memory.data_size) <<
190202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    ", RVA 0x" << HexString(thread_.stack.memory.rva);
1903e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  } else {
1904e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_ = new MinidumpMemoryRegion(minidump_);
1905e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_->SetDescriptor(&thread_.stack);
1906af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19073261e8b6eac44a41341f112821482bee6c940c98mmentovai
19083261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
19093261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
19103261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19113261e8b6eac44a41341f112821482bee6c940c98mmentovai
191202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.comuint64_t MinidumpThread::GetStartOfStackMemoryRange() const {
191302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (!valid_) {
191402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread";
191502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    return 0;
191602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  }
191702ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
191802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  return thread_.stack.start_of_memory_range;
191902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com}
19203261e8b6eac44a41341f112821482bee6c940c98mmentovai
19213261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpThread::GetMemory() {
1922af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1923af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
1924af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1925af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1926af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1927af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return memory_;
19283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19293261e8b6eac44a41341f112821482bee6c940c98mmentovai
19303261e8b6eac44a41341f112821482bee6c940c98mmentovai
19313261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpThread::GetContext() {
1932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1933af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
19343261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19363261e8b6eac44a41341f112821482bee6c940c98mmentovai
19373261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
1938af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(thread_.thread_context.rva)) {
1939af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot seek to context";
19403261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1941af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
19423261e8b6eac44a41341f112821482bee6c940c98mmentovai
19432466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
19443261e8b6eac44a41341f112821482bee6c940c98mmentovai
1945af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(thread_.thread_context.data_size)) {
1946af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot read context";
19473261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1948af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
19493261e8b6eac44a41341f112821482bee6c940c98mmentovai
19503261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
19513261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
19523261e8b6eac44a41341f112821482bee6c940c98mmentovai
19533261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
19543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19553261e8b6eac44a41341f112821482bee6c940c98mmentovai
19563261e8b6eac44a41341f112821482bee6c940c98mmentovai
19576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThread::GetThreadID(uint32_t *thread_id) const {
1958af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
1959af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
1960af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
1961af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
1962af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1963af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1964af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
196576f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
1966af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
196776f052f8fbf8864dee5992b857229d06560a766ammentovai
196876f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = thread_.thread_id;
196976f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
19703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19713261e8b6eac44a41341f112821482bee6c940c98mmentovai
19723261e8b6eac44a41341f112821482bee6c940c98mmentovai
19733261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThread::Print() {
1974af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1975af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
19763261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1977af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19783261e8b6eac44a41341f112821482bee6c940c98mmentovai
19793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawThread\n");
19803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
19813261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suspend_count               = %d\n",     thread_.suspend_count);
19823261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority_class              = 0x%x\n",   thread_.priority_class);
19833261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority                    = 0x%x\n",   thread_.priority);
1984c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
1985c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
19863261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.start_of_memory_range);
19873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.data_size      = 0x%x\n",
19883261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.memory.data_size);
19893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
19903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size    = 0x%x\n",
19913261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.data_size);
19923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva          = 0x%x\n",
19933261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.rva);
19943261e8b6eac44a41341f112821482bee6c940c98mmentovai
19953261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
19963261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
19973261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
19983261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
19993261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
20003261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
20013261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
20023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
20033261e8b6eac44a41341f112821482bee6c940c98mmentovai
20043261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryRegion* memory = GetMemory();
20053261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
20063261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("Stack\n");
20073261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory->Print();
20083261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
20093261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No stack\n");
20103261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
20113261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
20123261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20133261e8b6eac44a41341f112821482bee6c940c98mmentovai
20143261e8b6eac44a41341f112821482bee6c940c98mmentovai
20153261e8b6eac44a41341f112821482bee6c940c98mmentovai//
20163261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThreadList
20173261e8b6eac44a41341f112821482bee6c940c98mmentovai//
20183261e8b6eac44a41341f112821482bee6c940c98mmentovai
20193261e8b6eac44a41341f112821482bee6c940c98mmentovai
20206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpThreadList::max_threads_ = 4096;
2021e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2022e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
20233261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::MinidumpThreadList(Minidump* minidump)
202453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
202553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      id_to_thread_map_(),
202653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      threads_(NULL),
202753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_count_(0) {
20283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20293261e8b6eac44a41341f112821482bee6c940c98mmentovai
20303261e8b6eac44a41341f112821482bee6c940c98mmentovai
20313261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::~MinidumpThreadList() {
20323261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
20333261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20343261e8b6eac44a41341f112821482bee6c940c98mmentovai
20353261e8b6eac44a41341f112821482bee6c940c98mmentovai
20366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThreadList::Read(uint32_t expected_size) {
20373261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
20383261e8b6eac44a41341f112821482bee6c940c98mmentovai  id_to_thread_map_.clear();
20393261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
20403261e8b6eac44a41341f112821482bee6c940c98mmentovai  threads_ = NULL;
20413261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = 0;
20423261e8b6eac44a41341f112821482bee6c940c98mmentovai
20433261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
20443261e8b6eac44a41341f112821482bee6c940c98mmentovai
20456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t thread_count;
2046af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(thread_count)) {
2047af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
2048af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(thread_count);
20493261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2050af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2051af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
2052af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
20533261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2054af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20553261e8b6eac44a41341f112821482bee6c940c98mmentovai
20563261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
20573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_count);
20583261e8b6eac44a41341f112821482bee6c940c98mmentovai
20596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) {
2060fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
2061fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2062fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2063fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2064fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
20653261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(thread_count) +
20663261e8b6eac44a41341f112821482bee6c940c98mmentovai                       thread_count * sizeof(MDRawThread)) {
2067ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2068ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(thread_count) + 4 +
2069ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         thread_count * sizeof(MDRawThread)) {
20706162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
2071ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2072f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded "
2073f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
2074ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2075ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2076ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2077ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
2078ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    " != " << sizeof(thread_count) +
2079ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    thread_count * sizeof(MDRawThread);
2080ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2081ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
20823261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
20833261e8b6eac44a41341f112821482bee6c940c98mmentovai
2084bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com
2085e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count > max_threads_) {
2086e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
2087e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_threads_;
2088e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2089e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2090e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2091e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count != 0) {
2092373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpThreads> threads(
2093373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
20943261e8b6eac44a41341f112821482bee6c940c98mmentovai
2095373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int thread_index = 0;
2096373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         thread_index < thread_count;
2097373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++thread_index) {
2098373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpThread* thread = &(*threads)[thread_index];
20993261e8b6eac44a41341f112821482bee6c940c98mmentovai
2100373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
2101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->Read()) {
2102af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
2103af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
2104373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2105af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21063261e8b6eac44a41341f112821482bee6c940c98mmentovai
21076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t thread_id;
2108af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->GetThreadID(&thread_id)) {
2109af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
2110af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
2111373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2112af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
211376f052f8fbf8864dee5992b857229d06560a766ammentovai
2114373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (GetThreadByID(thread_id)) {
2115373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        // Another thread with this ID is already in the list.  Data error.
2116af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
2117af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(thread_id) << " at thread " <<
2118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
2119373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2120373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
2121373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      id_to_thread_map_[thread_id] = thread;
21223261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2123373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2124373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    threads_ = threads.release();
21253261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21263261e8b6eac44a41341f112821482bee6c940c98mmentovai
21273261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = thread_count;
21283261e8b6eac44a41341f112821482bee6c940c98mmentovai
21293261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
21303261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
21313261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21323261e8b6eac44a41341f112821482bee6c940c98mmentovai
21333261e8b6eac44a41341f112821482bee6c940c98mmentovai
21343261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
21353261e8b6eac44a41341f112821482bee6c940c98mmentovai    const {
2136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2137af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
2138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2139af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2140af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= thread_count_) {
2142af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
2143af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << thread_count_;
21443261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2145af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
21463261e8b6eac44a41341f112821482bee6c940c98mmentovai
21473261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*threads_)[index];
21483261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21493261e8b6eac44a41341f112821482bee6c940c98mmentovai
21503261e8b6eac44a41341f112821482bee6c940c98mmentovai
21516162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comMinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) {
21523261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't check valid_.  Read calls this method before everything is
21533261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validated.  It is safe to not check valid_ here.
21543261e8b6eac44a41341f112821482bee6c940c98mmentovai  return id_to_thread_map_[thread_id];
21553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21563261e8b6eac44a41341f112821482bee6c940c98mmentovai
21573261e8b6eac44a41341f112821482bee6c940c98mmentovai
21583261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThreadList::Print() {
2159af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2160af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
21613261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2162af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
21633261e8b6eac44a41341f112821482bee6c940c98mmentovai
21643261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpThreadList\n");
21653261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_count = %d\n", thread_count_);
21663261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
21673261e8b6eac44a41341f112821482bee6c940c98mmentovai
21683261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int thread_index = 0;
21693261e8b6eac44a41341f112821482bee6c940c98mmentovai       thread_index < thread_count_;
21703261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++thread_index) {
21713261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("thread[%d]\n", thread_index);
21723261e8b6eac44a41341f112821482bee6c940c98mmentovai
21733261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*threads_)[thread_index].Print();
21743261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21763261e8b6eac44a41341f112821482bee6c940c98mmentovai
21773261e8b6eac44a41341f112821482bee6c940c98mmentovai
21783261e8b6eac44a41341f112821482bee6c940c98mmentovai//
21793261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModule
21803261e8b6eac44a41341f112821482bee6c940c98mmentovai//
21813261e8b6eac44a41341f112821482bee6c940c98mmentovai
21823261e8b6eac44a41341f112821482bee6c940c98mmentovai
21836162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_cv_bytes_ = 32768;
21846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_misc_bytes_ = 32768;
2185e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2186e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
21873261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::MinidumpModule(Minidump* minidump)
218853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
2189db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_valid_(false),
219011e180cd3e855796aee4239aa4b22dbda5de9c00mmentovai      has_debug_info_(false),
219153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_(),
219253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      name_(NULL),
219353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      cv_record_(NULL),
219448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
2195db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      misc_record_(NULL) {
21963261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21973261e8b6eac44a41341f112821482bee6c940c98mmentovai
21983261e8b6eac44a41341f112821482bee6c940c98mmentovai
21993261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::~MinidumpModule() {
22003261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
22013261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
22023261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
22033261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22043261e8b6eac44a41341f112821482bee6c940c98mmentovai
22053261e8b6eac44a41341f112821482bee6c940c98mmentovai
22063261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModule::Read() {
22073261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
22083261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
22093261e8b6eac44a41341f112821482bee6c940c98mmentovai  name_ = NULL;
22103261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
22113261e8b6eac44a41341f112821482bee6c940c98mmentovai  cv_record_ = NULL;
221248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
22133261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
22143261e8b6eac44a41341f112821482bee6c940c98mmentovai  misc_record_ = NULL;
22153261e8b6eac44a41341f112821482bee6c940c98mmentovai
2216db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = false;
2217d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = false;
22183261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
22193261e8b6eac44a41341f112821482bee6c940c98mmentovai
2220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
2221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot read module";
22223261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2223af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22243261e8b6eac44a41341f112821482bee6c940c98mmentovai
22253261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
22263261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.base_of_image);
22273261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.size_of_image);
22283261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.checksum);
22293261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.time_date_stamp);
22303261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.module_name_rva);
22313261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.signature);
22323261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.struct_version);
22333261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_hi);
22343261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_lo);
22353261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_hi);
22363261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_lo);
22373261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags_mask);
22383261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags);
22393261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_os);
22403261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_type);
22413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_subtype);
22423261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_hi);
22433261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_lo);
22443261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.cv_record);
22453261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.misc_record);
22463261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't swap reserved fields because their contents are unknown (as
22473261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are their proper widths).
22483261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
22493261e8b6eac44a41341f112821482bee6c940c98mmentovai
2250fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
2251fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_.size_of_image == 0 ||
2252fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      module_.size_of_image >
22536162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint64_t>::max() - module_.base_of_image) {
2254af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
2255af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(module_.base_of_image) << "+" <<
2256fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(module_.size_of_image);
22573261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22593261e8b6eac44a41341f112821482bee6c940c98mmentovai
2260db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = true;
2261db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return true;
2262db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2263db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2264db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2265db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaibool MinidumpModule::ReadAuxiliaryData() {
2266af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
2268db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2270db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2271db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Each module must have a name.
2272db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  name_ = minidump_->ReadString(module_.module_name_rva);
2273af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!name_) {
2274af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule could not read name";
2275db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2276af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2277db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2278d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  // At this point, we have enough info for the module to be valid.
2279d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  valid_ = true;
2280d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2281db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // CodeView and miscellaneous debug records are only required if the
2282db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // module indicates that they exist.
2283af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
2284af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
2285af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
2286db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2287af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2288db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2289af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
2290af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
2291af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
2292db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2293af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2294db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2295d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = true;
22963261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
22973261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22983261e8b6eac44a41341f112821482bee6c940c98mmentovai
22993261e8b6eac44a41341f112821482bee6c940c98mmentovai
2300db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_file() const {
2301af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2302af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
2303db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2304af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2305db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2306db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return *name_;
2307db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
23083261e8b6eac44a41341f112821482bee6c940c98mmentovai
23093261e8b6eac44a41341f112821482bee6c940c98mmentovai
2310db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_identifier() const {
2311af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2312af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
2313db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2314af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2315db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2316d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2317d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2318d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2319db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
2320af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_system_info) {
2321af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires "
2322af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "MinidumpSystemInfo";
2323db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2324af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2325db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2326db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
2327af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
2328af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
2329db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2330af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2331db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2332db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
2333db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2334db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  switch (raw_system_info->platform_id) {
2335db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_NT:
2336db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_WINDOWS: {
2337c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2338c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2339db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
2340c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
2341db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               module_.time_date_stamp, module_.size_of_image);
2342db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
2343db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2344db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2345db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
23460e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_MAC_OS_X:
234763f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
2348ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
23495187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
2350f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    case MD_OS_LINUX:
2351a29f376a8bb9122f29ea1c53c02a188683fd5a72bradnelson@chromium.org    case MD_OS_NACL:
2352d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3: {
2353db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // TODO(mmentovai): support uuid extension if present, otherwise fall
2354db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // back to version (from LC_ID_DYLIB?), otherwise fall back to something
2355db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // else.
2356db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = "id";
2357db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2358db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2359db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2360db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    default: {
2361db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // Without knowing what OS generated the dump, we can't generate a good
2362db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // identifier.  Return an empty string, signalling failure.
2363af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
2364af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "found " << HexString(raw_system_info->platform_id);
2365db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2366db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2367db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2368db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2369db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
23703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23713261e8b6eac44a41341f112821482bee6c940c98mmentovai
23723261e8b6eac44a41341f112821482bee6c940c98mmentovai
2373db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_file() const {
2374af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2375af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
2376db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2377af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2378db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2379d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2380d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2381d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2382db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string file;
2383db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Prefer the CodeView record if present.
238428e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
238548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
238648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
238748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
238848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
238948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
239048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
2391db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
2392db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
239348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
239448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
2395db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
2396db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
239748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2398db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2399db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
2400db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
2401db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2402db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2403db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // If there's a CodeView record but it doesn't match a known signature,
240448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // try the miscellaneous record.
2405db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2406db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2407db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (file.empty()) {
2408db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // No usable CodeView record.  Try the miscellaneous debug record.
240928e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai    if (misc_record_) {
241028e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai      const MDImageDebugMisc* misc_record =
241128e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai          reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
2412db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      if (!misc_record->unicode) {
2413db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // If it's not Unicode, just stuff it into the string.  It's unclear
2414db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // if misc_record->data is 0-terminated, so use an explicit size.
2415db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        file = string(
2416db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            reinterpret_cast<const char*>(misc_record->data),
24172e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize);
2418db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      } else {
2419db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // There's a misc_record but it encodes the debug filename in UTF-16.
2420db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // (Actually, because miscellaneous records are so old, it's probably
2421db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
2422db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // that this method (and all other methods in the Minidump family)
2423db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // return.
2424db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2425db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        unsigned int bytes =
24262e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize;
2427db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        if (bytes % 2 == 0) {
2428db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          unsigned int utf16_words = bytes / 2;
2429db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
24306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one
2431db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // and copy the UTF-16 data into it.
24326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          vector<uint16_t> string_utf16(utf16_words);
2433db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          if (utf16_words)
2434db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            memcpy(&string_utf16[0], &misc_record->data, bytes);
2435db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2436db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // GetMiscRecord already byte-swapped the data[] field if it contains
2437db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF-16, so pass false as the swap argument.
2438db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
2439db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          file = *new_file;
2440db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        }
2441db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      }
2442db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2443db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2444db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2445bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
2446bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
2447bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                  "debug_file for " << *name_;
2448af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2449db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return file;
2450db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2451db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2452db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2453db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_identifier() const {
2454af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
2456db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2457af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2458db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2459d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2460d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2461d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2462db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
2463db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2464db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Use the CodeView record if present.
246528e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
246648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
246748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
246848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
246948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
247048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
247148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
2472c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2473c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2474db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[41];
2475db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
2476c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
2477db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data1,
2478db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data2,
2479db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data3,
2480db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[0],
2481db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[1],
2482db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[2],
2483db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[3],
2484db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[4],
2485db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[5],
2486db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[6],
2487db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[7],
2488db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->age);
2489db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
249048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
249148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
2492db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
2493db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
249448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2495db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2496c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2497c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2498db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
2499db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
2500c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%x", cv_record_20->signature, cv_record_20->age);
2501db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
2502db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2503db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2504db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
250548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  // TODO(mmentovai): if there's no usable CodeView record, there might be a
2506db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // miscellaneous debug record.  It only carries a filename, though, and no
2507db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // identifier.  I'm not sure what the right thing to do for the identifier
2508db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // is in that case, but I don't expect to find many modules without a
2509e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  // CodeView record (or some other Breakpad extension structure in place of
2510db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a CodeView record).  Treat it as an error (empty identifier) for now.
2511db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2512db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
2513db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2514bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
2515bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
2516bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                        "debug_identifier for " << *name_;
2517af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2518db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
2519db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2520db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2521db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2522db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::version() const {
2523af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2524af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for version";
2525db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2526af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2527db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2528db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string version;
2529db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2530db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
2531db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
2532db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    char version_string[24];
2533db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
2534db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi >> 16,
2535db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi & 0xffff,
2536db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo >> 16,
2537db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo & 0xffff);
2538db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    version = version_string;
2539db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2540db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2541db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): possibly support other struct types in place of
2542db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
2543db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a different structure that better represents versioning facilities on
2544db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Mac OS X and Linux, instead of forcing them to adhere to the dotted
2545db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // quad of 16-bit ints that Windows uses.
2546db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2547af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
2548af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "version for " << *name_;
2549af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2550db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return version;
2551db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2552db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2553db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2554db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModule* MinidumpModule::Copy() const {
2555db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModule(this);
2556db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2557db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2558db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
25596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
2560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
25623261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2563af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25643261e8b6eac44a41341f112821482bee6c940c98mmentovai
25653261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!cv_record_) {
256648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // This just guards against 0-sized CodeView records; more specific checks
256748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // are used when the signature is checked against various structure types.
2568af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.cv_record.data_size == 0) {
25693261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2570af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25713261e8b6eac44a41341f112821482bee6c940c98mmentovai
2572af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.cv_record.rva)) {
2573af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
25743261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2575af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25763261e8b6eac44a41341f112821482bee6c940c98mmentovai
2577e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.cv_record.data_size > max_cv_bytes_) {
2578e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
2579e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.cv_record.data_size << " exceeds maximum " <<
2580e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_cv_bytes_;
2581e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2582e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
25833261e8b6eac44a41341f112821482bee6c940c98mmentovai
25843261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDCVInfoPDB70 or
25856162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment
25863261e8b6eac44a41341f112821482bee6c940c98mmentovai    // problems.  x86 and ppc are able to cope, though.  This allocation
25873261e8b6eac44a41341f112821482bee6c940c98mmentovai    // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
25883261e8b6eac44a41341f112821482bee6c940c98mmentovai    // variable-sized due to their pdb_file_name fields; these structures
25892e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
25903261e8b6eac44a41341f112821482bee6c940c98mmentovai    // them as such would result in incomplete structures or overruns.
25916162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > cv_record(
25926162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.cv_record.data_size));
25933261e8b6eac44a41341f112821482bee6c940c98mmentovai
2594af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
2595af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
25963261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2597af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25983261e8b6eac44a41341f112821482bee6c940c98mmentovai
25996162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
260048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (module_.cv_record.data_size > sizeof(signature)) {
260148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      MDCVInfoPDB70* cv_record_signature =
260248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
260348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      signature = cv_record_signature->cv_signature;
260448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      if (minidump_->swap())
260548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        Swap(&signature);
260648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    }
26073261e8b6eac44a41341f112821482bee6c940c98mmentovai
26083261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature == MD_CVINFOPDB70_SIGNATURE) {
26093261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Now that the structure type is known, recheck the size.
26102e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
2611af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
26122e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB70_minsize << " > " <<
2613af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
26143261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2615af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
26163261e8b6eac44a41341f112821482bee6c940c98mmentovai
26173261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
261848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        MDCVInfoPDB70* cv_record_70 =
261948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
26203261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->cv_signature);
26213261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->signature);
26223261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->age);
26233261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
262448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        // quantities.  (It's a path, is it UTF-8?)
26253261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
262648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
262748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
262848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2630af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
2631af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
263248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2633af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
26343261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
263548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // Now that the structure type is known, recheck the size.
26362e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
2637af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
26382e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB20_minsize << " > " <<
2639af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
264048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2641af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
26423261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
26433261e8b6eac44a41341f112821482bee6c940c98mmentovai        MDCVInfoPDB20* cv_record_20 =
264448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
26453261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.signature);
26463261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.offset);
26473261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->signature);
26483261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->age);
26493261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
26503261e8b6eac44a41341f112821482bee6c940c98mmentovai        // quantities.  (It's a path, is it UTF-8?)
26513261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
265248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
265348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
265448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2655af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2656af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
2657af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
265848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2659af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
26603261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
26613261e8b6eac44a41341f112821482bee6c940c98mmentovai
266248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // If the signature doesn't match something above, it's not something
2663e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    // that Breakpad can presently handle directly.  Because some modules in
266448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
266548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // don't bail out here - allow the data to be returned to the user,
266648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // although byte-swapping can't be done.
26673261e8b6eac44a41341f112821482bee6c940c98mmentovai
26683261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
26696162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // return it casted to uint8_t*.
26703261e8b6eac44a41341f112821482bee6c940c98mmentovai    cv_record_ = cv_record.release();
267148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    cv_record_signature_ = signature;
26723261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26733261e8b6eac44a41341f112821482bee6c940c98mmentovai
267448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
267548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.cv_record.data_size;
267648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
26773261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*cv_record_)[0];
26783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26793261e8b6eac44a41341f112821482bee6c940c98mmentovai
26803261e8b6eac44a41341f112821482bee6c940c98mmentovai
26816162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) {
2682af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2683af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
26843261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2685af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26863261e8b6eac44a41341f112821482bee6c940c98mmentovai
26873261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!misc_record_) {
2688af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size == 0) {
26893261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2690af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
26913261e8b6eac44a41341f112821482bee6c940c98mmentovai
26922e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
2693af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
26942e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                      "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
2695af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      module_.misc_record.data_size;
26963261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2697af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
2698af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2699af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.misc_record.rva)) {
2700af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
2701af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "debugging record";
2702af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      return NULL;
2703af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
27043261e8b6eac44a41341f112821482bee6c940c98mmentovai
2705e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.misc_record.data_size > max_misc_bytes_) {
2706e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
2707e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.misc_record.data_size << " exceeds maximum " <<
2708e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_misc_bytes_;
2709e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2710e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
27113261e8b6eac44a41341f112821482bee6c940c98mmentovai
27123261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDImageDebugMisc but
27136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // is allocated as uint8_t[] can cause alignment problems.  x86 and
27143261e8b6eac44a41341f112821482bee6c940c98mmentovai    // ppc are able to cope, though.  This allocation style is needed
27153261e8b6eac44a41341f112821482bee6c940c98mmentovai    // because the MDImageDebugMisc is variable-sized due to its data field;
27162e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // this structure is not MDImageDebugMisc_minsize and treating it as such
27173261e8b6eac44a41341f112821482bee6c940c98mmentovai    // would result in an incomplete structure or an overrun.
27186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > misc_record_mem(
27196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.misc_record.data_size));
27203261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDImageDebugMisc* misc_record =
27213261e8b6eac44a41341f112821482bee6c940c98mmentovai        reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
27223261e8b6eac44a41341f112821482bee6c940c98mmentovai
2723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
2724af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
2725af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "record";
27263261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2727af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
27283261e8b6eac44a41341f112821482bee6c940c98mmentovai
27293261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (minidump_->swap()) {
27303261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->data_type);
27313261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->length);
27323261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap misc_record.unicode because it's an 8-bit quantity.
27333261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap the reserved fields for the same reason, and because
27343261e8b6eac44a41341f112821482bee6c940c98mmentovai      // they don't contain any valid data.
27353261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (misc_record->unicode) {
27363261e8b6eac44a41341f112821482bee6c940c98mmentovai        // There is a potential alignment problem, but shouldn't be a problem
27373261e8b6eac44a41341f112821482bee6c940c98mmentovai        // in practice due to the layout of MDImageDebugMisc.
27386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data));
27393261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataBytes = module_.misc_record.data_size -
27402e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                                 MDImageDebugMisc_minsize;
27413562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com        Swap(data16, dataBytes);
27423261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
27433261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
27443261e8b6eac44a41341f112821482bee6c940c98mmentovai
2745af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size != misc_record->length) {
2746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
2747af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << module_.misc_record.data_size <<
2748af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      " != " << misc_record->length;
27493261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
27513261e8b6eac44a41341f112821482bee6c940c98mmentovai
27523261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
27533261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to MDImageDebugMisc*.
27543261e8b6eac44a41341f112821482bee6c940c98mmentovai    misc_record_ = misc_record_mem.release();
27553261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
27563261e8b6eac44a41341f112821482bee6c940c98mmentovai
275748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
275848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.misc_record.data_size;
275948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
27603261e8b6eac44a41341f112821482bee6c940c98mmentovai  return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
27613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27623261e8b6eac44a41341f112821482bee6c940c98mmentovai
27633261e8b6eac44a41341f112821482bee6c940c98mmentovai
27643261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModule::Print() {
2765af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2766af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
27673261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2768af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27693261e8b6eac44a41341f112821482bee6c940c98mmentovai
27703261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawModule\n");
2771c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  base_of_image                   = 0x%" PRIx64 "\n",
27723261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.base_of_image);
27733261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_image                   = 0x%x\n",
27743261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.size_of_image);
27753261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum                        = 0x%x\n",
27763261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.checksum);
27773261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp                 = 0x%x\n",
27783261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.time_date_stamp);
27793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_name_rva                 = 0x%x\n",
27803261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.module_name_rva);
27813261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.signature          = 0x%x\n",
27823261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.signature);
27833261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.struct_version     = 0x%x\n",
27843261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.struct_version);
27853261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_version       = 0x%x:0x%x\n",
27863261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_hi,
27873261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_lo);
27883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.product_version    = 0x%x:0x%x\n",
27893261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_hi,
27903261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_lo);
27913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags_mask    = 0x%x\n",
27923261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags_mask);
27933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags         = 0x%x\n",
27943261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags);
27953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_os            = 0x%x\n",
27963261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_os);
27973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_type          = 0x%x\n",
27983261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_type);
27993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_subtype       = 0x%x\n",
28003261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_subtype);
28013261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_date          = 0x%x:0x%x\n",
28023261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_hi,
28033261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_lo);
28043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.data_size             = %d\n",
28053261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.data_size);
28063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.rva                   = 0x%x\n",
28073261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.rva);
28083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.data_size           = %d\n",
28093261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.data_size);
28103261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.rva                 = 0x%x\n",
28113261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.rva);
28123261e8b6eac44a41341f112821482bee6c940c98mmentovai
2813db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
2814db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_identifier)               = \"%s\"\n",
2815db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         code_identifier().c_str());
28163261e8b6eac44a41341f112821482bee6c940c98mmentovai
28176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t cv_record_size;
28186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t *cv_record = GetCVRecord(&cv_record_size);
28193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (cv_record) {
282048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
282148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
282248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
282348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
282448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
28253261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_signature        = 0x%x\n",
282648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->cv_signature);
28273261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
282848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data1,
282948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data2,
283048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data3,
283148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[0],
283248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[1]);
28333261e8b6eac44a41341f112821482bee6c940c98mmentovai      for (unsigned int guidIndex = 2;
28343261e8b6eac44a41341f112821482bee6c940c98mmentovai           guidIndex < 8;
28353261e8b6eac44a41341f112821482bee6c940c98mmentovai           ++guidIndex) {
283648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record_70->signature.data4[guidIndex]);
28373261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
28383261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("\n");
28393261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
284048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->age);
28413261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
284248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->pdb_file_name);
284348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
28443261e8b6eac44a41341f112821482bee6c940c98mmentovai      const MDCVInfoPDB20* cv_record_20 =
284548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
284648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
284748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
28483261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.signature = 0x%x\n",
28493261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.signature);
28503261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.offset    = 0x%x\n",
28513261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.offset);
28523261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = 0x%x\n",
28533261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->signature);
28543261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
28553261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->age);
28563261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
28573261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->pdb_file_name);
285848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else {
285948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("  (cv_record)                     = ");
286048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      for (unsigned int cv_byte_index = 0;
286148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           cv_byte_index < cv_record_size;
286248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           ++cv_byte_index) {
286348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record[cv_byte_index]);
286448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      }
286548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("\n");
28663261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
28673261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
28683261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (cv_record)                     = (null)\n");
28693261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28703261e8b6eac44a41341f112821482bee6c940c98mmentovai
287148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
28723261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_record) {
28733261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).data_type         = 0x%x\n",
28743261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->data_type);
28753261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).length            = 0x%x\n",
28763261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->length);
28773261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).unicode           = %d\n",
28783261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->unicode);
28793261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't bother printing the UTF-16, we don't really even expect to ever
28803261e8b6eac44a41341f112821482bee6c940c98mmentovai    // see this misc_record anyway.
28813261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_record->unicode)
28823261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = \"%s\"\n",
28833261e8b6eac44a41341f112821482bee6c940c98mmentovai             misc_record->data);
28843261e8b6eac44a41341f112821482bee6c940c98mmentovai    else
28853261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = (UTF-16)\n");
28863261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
28873261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record)                   = (null)\n");
28883261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28893261e8b6eac44a41341f112821482bee6c940c98mmentovai
2890db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
2891db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_identifier)              = \"%s\"\n",
2892db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         debug_identifier().c_str());
2893db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (version)                       = \"%s\"\n", version().c_str());
28943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
28953261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28963261e8b6eac44a41341f112821482bee6c940c98mmentovai
28973261e8b6eac44a41341f112821482bee6c940c98mmentovai
28983261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28993261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModuleList
29003261e8b6eac44a41341f112821482bee6c940c98mmentovai//
29013261e8b6eac44a41341f112821482bee6c940c98mmentovai
29023261e8b6eac44a41341f112821482bee6c940c98mmentovai
29036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModuleList::max_modules_ = 1024;
2904e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2905e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
29063261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::MinidumpModuleList(Minidump* minidump)
290753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
29086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
290953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      modules_(NULL),
291053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_count_(0) {
29113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29123261e8b6eac44a41341f112821482bee6c940c98mmentovai
29133261e8b6eac44a41341f112821482bee6c940c98mmentovai
29143261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::~MinidumpModuleList() {
2915fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
29163261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
29173261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29183261e8b6eac44a41341f112821482bee6c940c98mmentovai
29193261e8b6eac44a41341f112821482bee6c940c98mmentovai
29206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpModuleList::Read(uint32_t expected_size) {
29213261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
2922fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
29233261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
29243261e8b6eac44a41341f112821482bee6c940c98mmentovai  modules_ = NULL;
29253261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = 0;
29263261e8b6eac44a41341f112821482bee6c940c98mmentovai
29273261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
29283261e8b6eac44a41341f112821482bee6c940c98mmentovai
29296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t module_count;
2930af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(module_count)) {
2931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
2932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(module_count);
29333261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2934af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
2936af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList could not read module count";
29373261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2938af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29393261e8b6eac44a41341f112821482bee6c940c98mmentovai
29403261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
29413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_count);
29423261e8b6eac44a41341f112821482bee6c940c98mmentovai
29436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) {
2944fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
2945fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2946fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2947fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2948fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
29493261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(module_count) +
29503261e8b6eac44a41341f112821482bee6c940c98mmentovai                       module_count * MD_MODULE_SIZE) {
2951ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2952ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(module_count) + 4 +
2953ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         module_count * MD_MODULE_SIZE) {
29546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
2955ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2956f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded "
2957f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
2958ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2959ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2960ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2961ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
2962ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      " != " << sizeof(module_count) +
2963ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      module_count * MD_MODULE_SIZE;
2964ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2965ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
29663261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29673261e8b6eac44a41341f112821482bee6c940c98mmentovai
2968e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count > max_modules_) {
2969e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
2970e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_modules_;
2971e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2972e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2973e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2974e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count != 0) {
2975373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpModules> modules(
2976373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpModules(module_count, MinidumpModule(minidump_)));
29773261e8b6eac44a41341f112821482bee6c940c98mmentovai
2978373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int module_index = 0;
2979373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         module_index < module_count;
2980373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++module_index) {
2981373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpModule* module = &(*modules)[module_index];
29823261e8b6eac44a41341f112821482bee6c940c98mmentovai
2983373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
2984af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->Read()) {
2985af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
2986af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
2987373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2988af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2989db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2990db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2991db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // Loop through the module list once more to read additional data and
2992db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // build the range map.  This is done in a second pass because
2993db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
2994db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // included in the loop above, additional seeks would be needed where
2995db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // none are now to read contiguous data.
2996db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    for (unsigned int module_index = 0;
2997db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         module_index < module_count;
2998db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         ++module_index) {
2999db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      MinidumpModule* module = &(*modules)[module_index];
3000db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
300161ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // ReadAuxiliaryData fails if any data that the module indicates should
300261ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // exist is missing, but we treat some such cases as valid anyway.  See
300361ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // issue #222: if a debugging record is of a format that's too large to
300461ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // handle, it shouldn't render the entire dump invalid.  Check module
300561ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // validity before giving up.
300661ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      if (!module->ReadAuxiliaryData() && !module->valid()) {
300761ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read required module "
300861ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        "auxiliary data for module " <<
300961ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        module_index << "/" << module_count;
301061ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        return false;
3011af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3012af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3013af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // It is safe to use module->code_file() after successfully calling
301461ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // module->ReadAuxiliaryData or noting that the module is valid.
30153261e8b6eac44a41341f112821482bee6c940c98mmentovai
30166162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = module->base_address();
30176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t module_size = module->size();
30186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      if (base_address == static_cast<uint64_t>(-1)) {
3019af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList found bad base address "
3020af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "for module " << module_index << "/" << module_count <<
3021af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << module->code_file();
3022373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3023af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
30243261e8b6eac44a41341f112821482bee6c940c98mmentovai
3025af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, module_size, module_index)) {
3026af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
3027af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count << ", " <<
3028af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module->code_file() << ", " <<
3029af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
3030af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(module_size);
3031373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3032af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3033373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
3034373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
3035373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    modules_ = modules.release();
30363261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30373261e8b6eac44a41341f112821482bee6c940c98mmentovai
30383261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = module_count;
30393261e8b6eac44a41341f112821482bee6c940c98mmentovai
30403261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
30413261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
30423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30433261e8b6eac44a41341f112821482bee6c940c98mmentovai
30443261e8b6eac44a41341f112821482bee6c940c98mmentovai
3045db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleForAddress(
30466162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
3047af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3048af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
30493261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3050af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30513261e8b6eac44a41341f112821482bee6c940c98mmentovai
3052db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  unsigned int module_index;
3053af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
3054af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpModuleList has no module at " <<
3055af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
3056db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
3057af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3058db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3059db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtIndex(module_index);
30603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30613261e8b6eac44a41341f112821482bee6c940c98mmentovai
30623261e8b6eac44a41341f112821482bee6c940c98mmentovai
3063db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetMainModule() const {
3064af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3065af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
30663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3067af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30683261e8b6eac44a41341f112821482bee6c940c98mmentovai
3069db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // The main code module is the first one present in a minidump file's
3070db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // MDRawModuleList.
3071327783c42fcc2062bfe6c118c54c431ac6b5ffcfmkrebs@chromium.org  return GetModuleAtIndex(0);
3072db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
3073db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3074db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3075db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
3076db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int sequence) const {
3077af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3078af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
3079af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
3080af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3081af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3082af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sequence >= module_count_) {
3083af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
3084af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sequence << "/" << module_count_;
3085db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
3086af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3087db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
30883261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int module_index;
3089af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
3090af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
30913261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30933261e8b6eac44a41341f112821482bee6c940c98mmentovai
30943261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetModuleAtIndex(module_index);
30953261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30963261e8b6eac44a41341f112821482bee6c940c98mmentovai
30973261e8b6eac44a41341f112821482bee6c940c98mmentovai
3098db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
3099db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int index) const {
3100af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
3102af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
3103af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3104af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3105af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= module_count_) {
3106af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
3107af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << module_count_;
3108db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
3109af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3110db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3111db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return &(*modules_)[index];
3112db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
3113db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3114db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3115db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModules* MinidumpModuleList::Copy() const {
3116db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModules(this);
3117db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
3118db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
3119db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
31203261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModuleList::Print() {
3121af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
31233261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3124af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31253261e8b6eac44a41341f112821482bee6c940c98mmentovai
31263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpModuleList\n");
31273261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_count = %d\n", module_count_);
31283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
31293261e8b6eac44a41341f112821482bee6c940c98mmentovai
31303261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int module_index = 0;
31313261e8b6eac44a41341f112821482bee6c940c98mmentovai       module_index < module_count_;
31323261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++module_index) {
31333261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("module[%d]\n", module_index);
31343261e8b6eac44a41341f112821482bee6c940c98mmentovai
31353261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*modules_)[module_index].Print();
31363261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
31373261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31383261e8b6eac44a41341f112821482bee6c940c98mmentovai
31393261e8b6eac44a41341f112821482bee6c940c98mmentovai
31403261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31413261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryList
31423261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31433261e8b6eac44a41341f112821482bee6c940c98mmentovai
31443261e8b6eac44a41341f112821482bee6c940c98mmentovai
31456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryList::max_regions_ = 4096;
3146e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3147e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
31483261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
314953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
31506162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
315153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptors_(NULL),
315253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      regions_(NULL),
315353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      region_count_(0) {
31543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31553261e8b6eac44a41341f112821482bee6c940c98mmentovai
31563261e8b6eac44a41341f112821482bee6c940c98mmentovai
31573261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::~MinidumpMemoryList() {
3158fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
31593261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
31603261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
31613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31623261e8b6eac44a41341f112821482bee6c940c98mmentovai
31633261e8b6eac44a41341f112821482bee6c940c98mmentovai
31646162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryList::Read(uint32_t expected_size) {
31653261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
31663261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
31673261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptors_ = NULL;
31683261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
31693261e8b6eac44a41341f112821482bee6c940c98mmentovai  regions_ = NULL;
3170fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
31713261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = 0;
31723261e8b6eac44a41341f112821482bee6c940c98mmentovai
31733261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
31743261e8b6eac44a41341f112821482bee6c940c98mmentovai
31756162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t region_count;
3176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(region_count)) {
3177af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
3178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(region_count);
31793261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3180af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3181af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
3182af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
31833261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3184af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31853261e8b6eac44a41341f112821482bee6c940c98mmentovai
31863261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
31873261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&region_count);
31883261e8b6eac44a41341f112821482bee6c940c98mmentovai
3189fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (region_count >
31906162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) {
3191fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
3192fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
3193fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
3194fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
3195fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
31963261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(region_count) +
31973261e8b6eac44a41341f112821482bee6c940c98mmentovai                       region_count * sizeof(MDMemoryDescriptor)) {
3198ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
3199ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(region_count) + 4 +
3200ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         region_count * sizeof(MDMemoryDescriptor)) {
32016162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
3202ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
3203f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded "
3204f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
3205ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
3206ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
3207ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
3208ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
3209f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                      " != " << sizeof(region_count) +
3210ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      region_count * sizeof(MDMemoryDescriptor);
3211ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
3212ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
32133261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32143261e8b6eac44a41341f112821482bee6c940c98mmentovai
3215e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count > max_regions_) {
3216e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
3217e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_regions_;
3218e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
3219e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
3220e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3221e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count != 0) {
3222373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryDescriptors> descriptors(
3223373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryDescriptors(region_count));
32243261e8b6eac44a41341f112821482bee6c940c98mmentovai
3225373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
3226373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
3227373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!minidump_->ReadBytes(&(*descriptors)[0],
3228373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai                              sizeof(MDMemoryDescriptor) * region_count)) {
3229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
3230373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
3231373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
32323261e8b6eac44a41341f112821482bee6c940c98mmentovai
3233373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryRegions> regions(
3234373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
32353261e8b6eac44a41341f112821482bee6c940c98mmentovai
3236373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int region_index = 0;
3237373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         region_index < region_count;
3238373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++region_index) {
3239373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
32403261e8b6eac44a41341f112821482bee6c940c98mmentovai
3241373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (minidump_->swap())
3242373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(descriptor);
32433261e8b6eac44a41341f112821482bee6c940c98mmentovai
32446162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = descriptor->start_of_memory_range;
32456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t region_size = descriptor->memory.data_size;
32463261e8b6eac44a41341f112821482bee6c940c98mmentovai
3247fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      // Check for base + size overflow or undersize.
3248fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      if (region_size == 0 ||
32496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          region_size > numeric_limits<uint64_t>::max() - base_address) {
3250af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
3251af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        " region " << region_index << "/" << region_count <<
3252af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << HexString(base_address) << "+" <<
3253fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                        HexString(region_size);
3254373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3255af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
32563261e8b6eac44a41341f112821482bee6c940c98mmentovai
3257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, region_size, region_index)) {
3258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
3259af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        region_index << "/" << region_count << ", " <<
3260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
3261af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(region_size);
3262373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3263af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3264373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
3265373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      (*regions)[region_index].SetDescriptor(descriptor);
3266373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
32673261e8b6eac44a41341f112821482bee6c940c98mmentovai
3268373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    descriptors_ = descriptors.release();
3269373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    regions_ = regions.release();
32703261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32713261e8b6eac44a41341f112821482bee6c940c98mmentovai
32723261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = region_count;
32733261e8b6eac44a41341f112821482bee6c940c98mmentovai
32743261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
32753261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
32763261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32773261e8b6eac44a41341f112821482bee6c940c98mmentovai
32783261e8b6eac44a41341f112821482bee6c940c98mmentovai
32793261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
32803261e8b6eac44a41341f112821482bee6c940c98mmentovai      unsigned int index) {
3281af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
3283af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
3284af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3285af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3286af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= region_count_) {
3287af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
3288af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << region_count_;
32893261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3290af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32913261e8b6eac44a41341f112821482bee6c940c98mmentovai
32923261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*regions_)[index];
32933261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32943261e8b6eac44a41341f112821482bee6c940c98mmentovai
32953261e8b6eac44a41341f112821482bee6c940c98mmentovai
32963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
32976162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) {
3298af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3299af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
33003261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3301af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33023261e8b6eac44a41341f112821482bee6c940c98mmentovai
33033261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int region_index;
3304af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
3305af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
3306af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
33073261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3308af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33093261e8b6eac44a41341f112821482bee6c940c98mmentovai
33103261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryRegionAtIndex(region_index);
33113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33123261e8b6eac44a41341f112821482bee6c940c98mmentovai
33133261e8b6eac44a41341f112821482bee6c940c98mmentovai
33143261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryList::Print() {
3315af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3316af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
33173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3318af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33193261e8b6eac44a41341f112821482bee6c940c98mmentovai
33203261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpMemoryList\n");
33213261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  region_count = %d\n", region_count_);
33223261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
33233261e8b6eac44a41341f112821482bee6c940c98mmentovai
33243261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int region_index = 0;
33253261e8b6eac44a41341f112821482bee6c940c98mmentovai       region_index < region_count_;
33263261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++region_index) {
33273261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
33283261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("region[%d]\n", region_index);
33293261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDMemoryDescriptor\n");
3330c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  start_of_memory_range = 0x%" PRIx64 "\n",
33313261e8b6eac44a41341f112821482bee6c940c98mmentovai           descriptor->start_of_memory_range);
33323261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
33333261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
33343261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
33353261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (region) {
33363261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("Memory\n");
33373261e8b6eac44a41341f112821482bee6c940c98mmentovai      region->Print();
33383261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
33393261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("No memory\n");
33403261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
33413261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
33423261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33433261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33443261e8b6eac44a41341f112821482bee6c940c98mmentovai
33453261e8b6eac44a41341f112821482bee6c940c98mmentovai
33463261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33473261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpException
33483261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33493261e8b6eac44a41341f112821482bee6c940c98mmentovai
33503261e8b6eac44a41341f112821482bee6c940c98mmentovai
33513261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::MinidumpException(Minidump* minidump)
335253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
335353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      exception_(),
335453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
33553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33563261e8b6eac44a41341f112821482bee6c940c98mmentovai
33573261e8b6eac44a41341f112821482bee6c940c98mmentovai
33583261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::~MinidumpException() {
33593261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
33603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33613261e8b6eac44a41341f112821482bee6c940c98mmentovai
33623261e8b6eac44a41341f112821482bee6c940c98mmentovai
33636162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::Read(uint32_t expected_size) {
33643261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
33653261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
33663261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
33673261e8b6eac44a41341f112821482bee6c940c98mmentovai
33683261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
33693261e8b6eac44a41341f112821482bee6c940c98mmentovai
3370af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(exception_)) {
3371af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
3372af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(exception_);
33733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3374af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33753261e8b6eac44a41341f112821482bee6c940c98mmentovai
3376af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
3377af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot read exception";
33783261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3379af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33803261e8b6eac44a41341f112821482bee6c940c98mmentovai
33813261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
33823261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_id);
33833261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.__align is for alignment only and does not need to be
33843261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapped.
33853261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_code);
33863261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_flags);
33873261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_record);
33883261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_address);
33893261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.number_parameters);
33903261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.exception_record.__align is for alignment only and does not
33913261e8b6eac44a41341f112821482bee6c940c98mmentovai    // need to be swapped.
33923261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int parameter_index = 0;
33933261e8b6eac44a41341f112821482bee6c940c98mmentovai         parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
33943261e8b6eac44a41341f112821482bee6c940c98mmentovai         ++parameter_index) {
33953261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&exception_.exception_record.exception_information[parameter_index]);
33963261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
33973261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_context);
33983261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33993261e8b6eac44a41341f112821482bee6c940c98mmentovai
34003261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
34013261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
34023261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34033261e8b6eac44a41341f112821482bee6c940c98mmentovai
34043261e8b6eac44a41341f112821482bee6c940c98mmentovai
34056162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::GetThreadID(uint32_t *thread_id) const {
3406af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
3407af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
3408af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3409af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3410af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3411af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3412af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
341376f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3414af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
341576f052f8fbf8864dee5992b857229d06560a766ammentovai
341676f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = exception_.thread_id;
341776f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
34183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34193261e8b6eac44a41341f112821482bee6c940c98mmentovai
34203261e8b6eac44a41341f112821482bee6c940c98mmentovai
34213261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpException::GetContext() {
3422af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3423af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
34243261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3425af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34263261e8b6eac44a41341f112821482bee6c940c98mmentovai
34273261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
3428af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(exception_.thread_context.rva)) {
3429af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot seek to context";
34303261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
3431af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
34323261e8b6eac44a41341f112821482bee6c940c98mmentovai
34332466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
34343261e8b6eac44a41341f112821482bee6c940c98mmentovai
34359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // Don't log as an error if we can still fall back on the thread's context
34369276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // (which must be possible if we got this far.)
3437af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(exception_.thread_context.data_size)) {
34385f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org      BPLOG(INFO) << "MinidumpException cannot read context";
34393261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
3440af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
34413261e8b6eac44a41341f112821482bee6c940c98mmentovai
34423261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
34433261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34443261e8b6eac44a41341f112821482bee6c940c98mmentovai
34453261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
34463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34473261e8b6eac44a41341f112821482bee6c940c98mmentovai
34483261e8b6eac44a41341f112821482bee6c940c98mmentovai
34493261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpException::Print() {
3450af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3451af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot print invalid data";
34523261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34543261e8b6eac44a41341f112821482bee6c940c98mmentovai
34553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDException\n");
34563261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                                  = 0x%x\n",
34573261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_id);
34583261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_code            = 0x%x\n",
34593261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_code);
34603261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_flags           = 0x%x\n",
34613261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_flags);
3462c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
34633261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_record);
3464c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
34653261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_address);
34663261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.number_parameters         = %d\n",
34673261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.number_parameters);
34683261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int parameterIndex = 0;
34693261e8b6eac44a41341f112821482bee6c940c98mmentovai       parameterIndex < exception_.exception_record.number_parameters;
34703261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++parameterIndex) {
3471c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
34723261e8b6eac44a41341f112821482bee6c940c98mmentovai           parameterIndex,
34733261e8b6eac44a41341f112821482bee6c940c98mmentovai           exception_.exception_record.exception_information[parameterIndex]);
34743261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34753261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size                   = %d\n",
34763261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.data_size);
34773261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva                         = 0x%x\n",
34783261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.rva);
34793261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
34803261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
34813261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
34823261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
34833261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
34843261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
34853261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
34863261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34873261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34883261e8b6eac44a41341f112821482bee6c940c98mmentovai
34890314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
34900314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// MinidumpAssertion
34910314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
34920314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
34930314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
34940314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::MinidumpAssertion(Minidump* minidump)
34950314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    : MinidumpStream(minidump),
34960314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      assertion_(),
34970314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      expression_(),
34980314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      function_(),
34990314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      file_() {
35000314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
35010314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35020314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35030314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::~MinidumpAssertion() {
35040314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
35050314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35060314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpAssertion::Read(uint32_t expected_size) {
35080314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Invalidate cached data.
35090314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = false;
35100314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35110314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (expected_size != sizeof(assertion_)) {
35120314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
35130314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                    " != " << sizeof(assertion_);
35140314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
35150314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
35160314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35170314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
35180314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
35190314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
35200314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
35210314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35220314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Each of {expression, function, file} is a UTF-16 string,
35230314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // we'll convert them to UTF-8 for ease of use.
35243562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.expression,
35253562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.expression), &expression_,
35263562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
35273562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.function,
35283562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.function), &function_,
35293562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
35303562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file),
35313562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 &file_, minidump_->swap());
35320314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35330314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (minidump_->swap()) {
35340314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.line);
35350314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.type);
35360314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
35370314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35380314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = true;
35390314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return true;
35400314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
35410314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35420314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekvoid MinidumpAssertion::Print() {
35430314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!valid_) {
35440314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
35450314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return;
35460314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
35470314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
35480314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("MDAssertion\n");
35490314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  expression                                 = %s\n",
35500314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         expression_.c_str());
35510314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  function                                   = %s\n",
35520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         function_.c_str());
35530314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  file                                       = %s\n",
35540314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         file_.c_str());
35550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  line                                       = %u\n",
35560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.line);
35570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  type                                       = %u\n",
35580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.type);
35590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("\n");
35600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
35613261e8b6eac44a41341f112821482bee6c940c98mmentovai
35623261e8b6eac44a41341f112821482bee6c940c98mmentovai//
35633261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpSystemInfo
35643261e8b6eac44a41341f112821482bee6c940c98mmentovai//
35653261e8b6eac44a41341f112821482bee6c940c98mmentovai
35663261e8b6eac44a41341f112821482bee6c940c98mmentovai
35673261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
356853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
356953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      system_info_(),
3570e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      csd_version_(NULL),
3571e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      cpu_vendor_(NULL) {
35723261e8b6eac44a41341f112821482bee6c940c98mmentovai}
35733261e8b6eac44a41341f112821482bee6c940c98mmentovai
35743261e8b6eac44a41341f112821482bee6c940c98mmentovai
35753261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::~MinidumpSystemInfo() {
35763261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
3577e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
35783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
35793261e8b6eac44a41341f112821482bee6c940c98mmentovai
35803261e8b6eac44a41341f112821482bee6c940c98mmentovai
35816162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpSystemInfo::Read(uint32_t expected_size) {
35823261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
35833261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
35843261e8b6eac44a41341f112821482bee6c940c98mmentovai  csd_version_ = NULL;
3585e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
3586e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  cpu_vendor_ = NULL;
35873261e8b6eac44a41341f112821482bee6c940c98mmentovai
35883261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
35893261e8b6eac44a41341f112821482bee6c940c98mmentovai
3590af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(system_info_)) {
3591af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
3592af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(system_info_);
35933261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3594af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
35953261e8b6eac44a41341f112821482bee6c940c98mmentovai
3596af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
3597af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
35983261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3599af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
36003261e8b6eac44a41341f112821482bee6c940c98mmentovai
36013261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
36023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_architecture);
36033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_level);
36043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_revision);
36053261e8b6eac44a41341f112821482bee6c940c98mmentovai    // number_of_processors and product_type are 8-bit quantities and need no
36063261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapping.
36073261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.major_version);
36083261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.minor_version);
36093261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.build_number);
36103261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.platform_id);
36113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.csd_version_rva);
36123261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.suite_mask);
36133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    // Don't swap the reserved2 field because its contents are unknown.
36143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
36153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
36163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
36173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 3; ++i)
36183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
36193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.version_information);
36203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.feature_information);
36213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
36223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    } else {
36233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 2; ++i)
36243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
36253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
36263261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
36273261e8b6eac44a41341f112821482bee6c940c98mmentovai
36283261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
36293261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
36303261e8b6eac44a41341f112821482bee6c940c98mmentovai}
36313261e8b6eac44a41341f112821482bee6c940c98mmentovai
36323261e8b6eac44a41341f112821482bee6c940c98mmentovai
363397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetOS() {
36344e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com  string os;
36354e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com
3636af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3637af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
36384e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com    return os;
3639af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
364097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
364197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.platform_id) {
364297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_NT:
364397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_WINDOWS:
364497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "windows";
364597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
364697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
364797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_MAC_OS_X:
364897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "mac";
364997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
365097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
365163f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
365263f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      os = "ios";
365363f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      break;
365463f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org
365597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_LINUX:
365697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "linux";
365797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3658af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3659ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
3660ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      os = "solaris";
36615187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      break;
36625187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org
36635187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
36645187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      os = "android";
3665ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
3666ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
3667d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3:
3668d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      os = "ps3";
3669d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      break;
3670d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org
367142faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org    case MD_OS_NACL:
367242faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      os = "nacl";
367342faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      break;
367442faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org
3675af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3676af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
3677af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.platform_id);
3678af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
367997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
368097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
368197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return os;
368297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
368397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
368497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
368597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetCPU() {
3686af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3687af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
368897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return "";
3689af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
369097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
369197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string cpu;
369297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
369397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.processor_architecture) {
369497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86:
369597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86_WIN64:
369697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "x86";
369797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
369897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
36999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_AMD64:
37009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "x86-64";
37019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
37029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
370397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_PPC:
370497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "ppc";
370597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3706af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3707cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CPU_ARCHITECTURE_PPC64:
3708cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      cpu = "ppc64";
3709cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
3710cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
3711dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    case MD_CPU_ARCHITECTURE_SPARC:
3712dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      cpu = "sparc";
3713dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      break;
3714dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
37159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_ARM:
37169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "arm";
37179276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
37189276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
371939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CPU_ARCHITECTURE_ARM64:
372039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      cpu = "arm64";
372139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
372239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
3723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3724af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
3725af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.processor_architecture);
3726af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
372797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
372897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
372997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return cpu;
373097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
373197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
373297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
37333261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst string* MinidumpSystemInfo::GetCSDVersion() {
3734af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3735af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
37363261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3737af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
37383261e8b6eac44a41341f112821482bee6c940c98mmentovai
37393261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!csd_version_)
37403261e8b6eac44a41341f112821482bee6c940c98mmentovai    csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
37413261e8b6eac44a41341f112821482bee6c940c98mmentovai
3742af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
3743af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    "CSD version";
3744af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
37453261e8b6eac44a41341f112821482bee6c940c98mmentovai  return csd_version_;
37463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
37473261e8b6eac44a41341f112821482bee6c940c98mmentovai
37483261e8b6eac44a41341f112821482bee6c940c98mmentovai
3749e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovaiconst string* MinidumpSystemInfo::GetCPUVendor() {
3750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3751af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
3752e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    return NULL;
3753af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3754e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3755e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  // CPU vendor information can only be determined from x86 minidumps.
3756e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (!cpu_vendor_ &&
3757e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
3758e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
3759e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    char cpu_vendor_string[13];
3760e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
3761e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             "%c%c%c%c%c%c%c%c%c%c%c%c",
3762e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
3763e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
3764e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
3765e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
3766e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
3767e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
3768e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
3769e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
3770e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
3771e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
3772e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
3773e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
3774e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    cpu_vendor_ = new string(cpu_vendor_string);
3775e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3776e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3777e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  return cpu_vendor_;
3778e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai}
3779e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3780e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
37813261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpSystemInfo::Print() {
3782af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
37843261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3785af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
37863261e8b6eac44a41341f112821482bee6c940c98mmentovai
37873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawSystemInfo\n");
37883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_architecture                     = %d\n",
37893261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_architecture);
37903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_level                            = %d\n",
37913261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_level);
37920a7e6bf16cad354710df60929c2ac82f647cb54emmentovai  printf("  processor_revision                         = 0x%x\n",
37930a7e6bf16cad354710df60929c2ac82f647cb54emmentovai         system_info_.processor_revision);
37943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  number_of_processors                       = %d\n",
37953261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.number_of_processors);
37963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  product_type                               = %d\n",
37973261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.product_type);
37983261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  major_version                              = %d\n",
37993261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.major_version);
38003261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  minor_version                              = %d\n",
38013261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.minor_version);
38023261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  build_number                               = %d\n",
38033261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.build_number);
38043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  platform_id                                = %d\n",
38053261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.platform_id);
38063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  csd_version_rva                            = 0x%x\n",
38073261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.csd_version_rva);
38083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suite_mask                                 = 0x%x\n",
38093261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.suite_mask);
38103261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int i = 0; i < 3; ++i) {
38113261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
38123261e8b6eac44a41341f112821482bee6c940c98mmentovai           i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
38133261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
38143261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
38153261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.version_information);
38163261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
38173261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.feature_information);
38183261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
38193261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
3820e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* csd_version = GetCSDVersion();
3821e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (csd_version) {
38223261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = \"%s\"\n",
3823e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           csd_version->c_str());
3824e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
38253261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = (null)\n");
3826e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3827e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* cpu_vendor = GetCPUVendor();
3828e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (cpu_vendor) {
3829e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = \"%s\"\n",
3830e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           cpu_vendor->c_str());
3831e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
3832e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = (null)\n");
3833e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
38343261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
38353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
38363261e8b6eac44a41341f112821482bee6c940c98mmentovai
38373261e8b6eac44a41341f112821482bee6c940c98mmentovai
38383261e8b6eac44a41341f112821482bee6c940c98mmentovai//
38393261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMiscInfo
38403261e8b6eac44a41341f112821482bee6c940c98mmentovai//
38413261e8b6eac44a41341f112821482bee6c940c98mmentovai
38423261e8b6eac44a41341f112821482bee6c940c98mmentovai
38433261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
384453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
384553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      misc_info_() {
38463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
38473261e8b6eac44a41341f112821482bee6c940c98mmentovai
38483261e8b6eac44a41341f112821482bee6c940c98mmentovai
38496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMiscInfo::Read(uint32_t expected_size) {
38503261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
38513261e8b6eac44a41341f112821482bee6c940c98mmentovai
38523261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != MD_MISCINFO_SIZE &&
38533562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO2_SIZE &&
38543562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO3_SIZE &&
38553562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO4_SIZE) {
38563562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
38573562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
38583562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
38593562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ")";
38603261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
38613261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
38623261e8b6eac44a41341f112821482bee6c940c98mmentovai
3863af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
3864af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
38653261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3866af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
38673261e8b6eac44a41341f112821482bee6c940c98mmentovai
38683261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
38693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Swap version 1 fields
38703261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.size_of_info);
38713261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.flags1);
38723261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_id);
38733261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_create_time);
38743261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_user_time);
38753261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_kernel_time);
38763261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
38773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 2 fields
38783261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_mhz);
38793261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_mhz);
38803261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_mhz_limit);
38813261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_idle_state);
38823261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_idle_state);
38833261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
38843562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
38853562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 3 fields
38863562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_integrity_level);
38873562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_execute_flags);
38883562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.protected_process);
38893562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone_id);
38903562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone);
38913562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
38923562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
38933562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 4 fields.
38943562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Do not swap UTF-16 strings.  The swap is done as part of the
38953562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // conversion to UTF-8 (code follows below).
38963562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
38973261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
38983261e8b6eac44a41341f112821482bee6c940c98mmentovai
389965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai  if (expected_size != misc_info_.size_of_info) {
3900af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
390165571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai                    expected_size << " != " << misc_info_.size_of_info;
39023261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3903af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
39043261e8b6eac44a41341f112821482bee6c940c98mmentovai
39053562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Convert UTF-16 strings
39063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
39073562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 3 fields
39083562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name,
39093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.standard_name),
39103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &standard_name_, minidump_->swap());
39113562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name,
39123562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.daylight_name),
39133562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &daylight_name_, minidump_->swap());
39143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
39153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
39163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 4 fields
39173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.build_string,
39183562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.build_string),
39193562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &build_string_, minidump_->swap());
39203562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str,
39213562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.dbg_bld_str),
39223562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &dbg_bld_str_, minidump_->swap());
39233562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
39243562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
39253261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
39263261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
39273261e8b6eac44a41341f112821482bee6c940c98mmentovai}
39283261e8b6eac44a41341f112821482bee6c940c98mmentovai
39293261e8b6eac44a41341f112821482bee6c940c98mmentovai
39303261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMiscInfo::Print() {
3931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
39333261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3934af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
39353261e8b6eac44a41341f112821482bee6c940c98mmentovai
39363261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawMiscInfo\n");
39373562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Print version 1 fields
39383261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
39393261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags1                       = 0x%x\n", misc_info_.flags1);
39403261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_id                   = 0x%x\n", misc_info_.process_id);
39413261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_create_time          = 0x%x\n",
39423261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_create_time);
39433261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_user_time            = 0x%x\n",
39443261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_user_time);
39453261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_kernel_time          = 0x%x\n",
39463261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_kernel_time);
39473261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
39483562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 2 fields
39493261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_mhz            = %d\n",
39503261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_mhz);
39513261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_mhz        = %d\n",
39523261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_mhz);
39533261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_mhz_limit          = %d\n",
39543261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_mhz_limit);
39553261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_idle_state     = 0x%x\n",
39563261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_idle_state);
39573261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_idle_state = 0x%x\n",
39583261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_idle_state);
39593261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
39603562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
39613562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 3 fields
39623562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  process_integrity_level      = 0x%x\n",
39633562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.process_integrity_level);
39643562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  process_execute_flags        = 0x%x\n",
39653562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.process_execute_flags);
39663562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  protected_process            = %d\n",
39673562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.protected_process);
39683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone_id                 = %d\n", misc_info_.time_zone_id);
39693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.bias               = %d\n", misc_info_.time_zone.bias);
39703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.standard_name      = %s\n", standard_name_.c_str());
39713562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.daylight_name      = %s\n", daylight_name_.c_str());
39723562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
39733562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
39743562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 4 fields
39753562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  build_string                 = %s\n", build_string_.c_str());
39763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  dbg_bld_str                  = %s\n", dbg_bld_str_.c_str());
39773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
397876f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
397976f052f8fbf8864dee5992b857229d06560a766ammentovai}
398076f052f8fbf8864dee5992b857229d06560a766ammentovai
398176f052f8fbf8864dee5992b857229d06560a766ammentovai
398276f052f8fbf8864dee5992b857229d06560a766ammentovai//
3983e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// MinidumpBreakpadInfo
398476f052f8fbf8864dee5992b857229d06560a766ammentovai//
398576f052f8fbf8864dee5992b857229d06560a766ammentovai
398676f052f8fbf8864dee5992b857229d06560a766ammentovai
3987e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
398876f052f8fbf8864dee5992b857229d06560a766ammentovai    : MinidumpStream(minidump),
3989e5dc60822e5938fea2ae892ccddb906641ba174emmentovai      breakpad_info_() {
399076f052f8fbf8864dee5992b857229d06560a766ammentovai}
399176f052f8fbf8864dee5992b857229d06560a766ammentovai
399276f052f8fbf8864dee5992b857229d06560a766ammentovai
39936162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::Read(uint32_t expected_size) {
399476f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = false;
399576f052f8fbf8864dee5992b857229d06560a766ammentovai
3996af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(breakpad_info_)) {
3997af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
3998af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(breakpad_info_);
399976f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
4000af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
400176f052f8fbf8864dee5992b857229d06560a766ammentovai
4002af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
4003af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
400476f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
4005af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
400676f052f8fbf8864dee5992b857229d06560a766ammentovai
400776f052f8fbf8864dee5992b857229d06560a766ammentovai  if (minidump_->swap()) {
4008e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.validity);
4009e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.dump_thread_id);
4010e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.requesting_thread_id);
401176f052f8fbf8864dee5992b857229d06560a766ammentovai  }
401276f052f8fbf8864dee5992b857229d06560a766ammentovai
401376f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = true;
401476f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
401576f052f8fbf8864dee5992b857229d06560a766ammentovai}
401676f052f8fbf8864dee5992b857229d06560a766ammentovai
401776f052f8fbf8864dee5992b857229d06560a766ammentovai
40186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const {
4019af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
4020af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
4021af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
4022af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
4023af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4024af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4025af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
4026af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
4027af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4028af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4029af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
4030af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
403176f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
403276f052f8fbf8864dee5992b857229d06560a766ammentovai  }
403376f052f8fbf8864dee5992b857229d06560a766ammentovai
4034e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.dump_thread_id;
403576f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
403676f052f8fbf8864dee5992b857229d06560a766ammentovai}
403776f052f8fbf8864dee5992b857229d06560a766ammentovai
403876f052f8fbf8864dee5992b857229d06560a766ammentovai
40396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id)
404076f052f8fbf8864dee5992b857229d06560a766ammentovai    const {
4041af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
4042af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
4043af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
4044af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
4045af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4046af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!thread_id || !valid_) {
4047af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
4048af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
4049af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4050af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4051af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity &
4052af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
4053af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
405476f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
405576f052f8fbf8864dee5992b857229d06560a766ammentovai  }
405676f052f8fbf8864dee5992b857229d06560a766ammentovai
4057e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.requesting_thread_id;
405876f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
405976f052f8fbf8864dee5992b857229d06560a766ammentovai}
406076f052f8fbf8864dee5992b857229d06560a766ammentovai
406176f052f8fbf8864dee5992b857229d06560a766ammentovai
4062e5dc60822e5938fea2ae892ccddb906641ba174emmentovaivoid MinidumpBreakpadInfo::Print() {
4063af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4064af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
406576f052f8fbf8864dee5992b857229d06560a766ammentovai    return;
4066af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
406776f052f8fbf8864dee5992b857229d06560a766ammentovai
4068e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("MDRawBreakpadInfo\n");
4069e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("  validity             = 0x%x\n", breakpad_info_.validity);
407076f052f8fbf8864dee5992b857229d06560a766ammentovai
4071e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
4072e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    printf("  dump_thread_id       = 0x%x\n", breakpad_info_.dump_thread_id);
407376f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
407476f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  dump_thread_id       = (invalid)\n");
407576f052f8fbf8864dee5992b857229d06560a766ammentovai  }
407676f052f8fbf8864dee5992b857229d06560a766ammentovai
4077e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
407876f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = 0x%x\n",
4079e5dc60822e5938fea2ae892ccddb906641ba174emmentovai           breakpad_info_.requesting_thread_id);
408076f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
408176f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = (invalid)\n");
408276f052f8fbf8864dee5992b857229d06560a766ammentovai  }
408376f052f8fbf8864dee5992b857229d06560a766ammentovai
408476f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
40853261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40863261e8b6eac44a41341f112821482bee6c940c98mmentovai
40873261e8b6eac44a41341f112821482bee6c940c98mmentovai
40883261e8b6eac44a41341f112821482bee6c940c98mmentovai//
40897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfo
40907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
40917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
40947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpObject(minidump),
40957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_() {
40967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
40977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsExecutable() const {
41006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
41017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
41027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_EXECUTE ||
41037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
41047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
41057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsWritable() const {
41096162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
41107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
41117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_READWRITE ||
41127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_WRITECOPY ||
41137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
41147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
41157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::Read() {
41197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
41207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
41227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
41237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
41247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
41277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.base_address);
41287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_base);
41297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_protection);
41307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.region_size);
41317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.state);
41327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.protection);
41337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.type);
41347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Check for base + size overflow or undersize.
41377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (memory_info_.region_size == 0 ||
41386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      memory_info_.region_size > numeric_limits<uint64_t>::max() -
41397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                     memory_info_.base_address) {
41407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
41417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.base_address) << "+" <<
41427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.region_size);
41437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
41447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
41477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
41487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfo::Print() {
41527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
41537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
41547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
41557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MDRawMemoryInfo\n");
41587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  base_address          = 0x%" PRIx64 "\n",
41597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.base_address);
41607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_base       = 0x%" PRIx64 "\n",
41617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_base);
41627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_protection = 0x%x\n",
41637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_protection);
41647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  region_size           = 0x%" PRIx64 "\n", memory_info_.region_size);
41657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  state                 = 0x%x\n", memory_info_.state);
41667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  protection            = 0x%x\n", memory_info_.protection);
41677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  type                  = 0x%x\n", memory_info_.type);
41687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
41727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfoList
41737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
41747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
41777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpStream(minidump),
41786162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
41797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      infos_(NULL),
41807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      info_count_(0) {
41817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
41857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete range_map_;
41867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
41877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41906162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryInfoList::Read(uint32_t expected_size) {
41917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Invalidate cached data.
41927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
41937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  infos_ = NULL;
41947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  range_map_->Clear();
41957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  info_count_ = 0;
41967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
41987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MDRawMemoryInfoList header;
42007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size < sizeof(MDRawMemoryInfoList)) {
42017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
42027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    expected_size << " < " << sizeof(MDRawMemoryInfoList);
42037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&header, sizeof(header))) {
42067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
42077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
42117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_header);
42127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_entry);
42137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.number_of_entries);
42147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the header is the expected size.
4217f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // TODO(ted): could possibly handle this more gracefully, assuming
42187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // that future versions of the structs would be backwards-compatible.
42197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
42207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
42217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_header << " != " <<
42227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfoList);
42237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the entries are the expected size.
42277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
42287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
42297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_entry << " != " <<
42307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfo);
42317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries >
42356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) {
42367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
42377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.number_of_entries <<
42387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " would cause multiplication overflow";
42397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size != sizeof(MDRawMemoryInfoList) +
42437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo)) {
42447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
42457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " != " << sizeof(MDRawMemoryInfoList) +
42467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo);
42477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
42487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
4250f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for data loss when converting header.number_of_entries from
4251f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // uint64_t into MinidumpMemoryInfos::size_type (uint32_t)
4252f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  MinidumpMemoryInfos::size_type header_number_of_entries =
4253f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      static_cast<unsigned int>(header.number_of_entries);
4254f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<uint64_t>(header_number_of_entries) !=
4255f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      header.number_of_entries) {
4256f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected when converting "
4257f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                    "the header's number_of_entries";
4258f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4259f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4260f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
42617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries != 0) {
42627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    scoped_ptr<MinidumpMemoryInfos> infos(
4263f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        new MinidumpMemoryInfos(header_number_of_entries,
42647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                MinidumpMemoryInfo(minidump_)));
42657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    for (unsigned int index = 0;
42677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         index < header.number_of_entries;
42687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         ++index) {
42697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      MinidumpMemoryInfo* info = &(*infos)[index];
42707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      // Assume that the file offset is correct after the last read.
42727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!info->Read()) {
42737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
42747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries;
42757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
42767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
42777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42786162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = info->GetBase();
4279f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      uint64_t region_size = info->GetSize();
42807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!range_map_->StoreRange(base_address, region_size, index)) {
42827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
42837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        " memory region " <<
42847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries << ", " <<
42857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(base_address) << "+" <<
42867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(region_size);
42877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
42887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
42897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    }
42907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    infos_ = infos.release();
42927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
42937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
4294f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  info_count_ = header_number_of_entries;
42957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
42977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
42987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
42997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
43027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      unsigned int index) const {
43037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
43047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
43057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
43067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (index >= info_count_) {
43097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
43107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    index << "/" << info_count_;
43117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
43127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return &(*infos_)[index];
43157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
43167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
43196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
43207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
43217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
43227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " GetMemoryInfoForAddress";
43237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
43247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  unsigned int info_index;
43277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
43287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
43297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                   HexString(address);
43307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
43317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetMemoryInfoAtIndex(info_index);
43347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
43357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfoList::Print() {
43387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
43397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
43407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
43417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MinidumpMemoryInfoList\n");
43447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  info_count = %d\n", info_count_);
43457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("\n");
43467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  for (unsigned int info_index = 0;
43487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       info_index < info_count_;
43497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       ++info_index) {
43507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("info[%d]\n", info_index);
43517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    (*infos_)[info_index].Print();
43527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("\n");
43537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
43547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
43557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
43577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
43583261e8b6eac44a41341f112821482bee6c940c98mmentovai// Minidump
43593261e8b6eac44a41341f112821482bee6c940c98mmentovai//
43603261e8b6eac44a41341f112821482bee6c940c98mmentovai
43613261e8b6eac44a41341f112821482bee6c940c98mmentovai
43626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t Minidump::max_streams_ = 128;
4363e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiunsigned int Minidump::max_string_length_ = 1024;
4364e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
4365e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
43666dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaiMinidump::Minidump(const string& path)
436753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : header_(),
436853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      directory_(NULL),
4369373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      stream_map_(new MinidumpStreamMap()),
43706dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      path_(path),
43710cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(NULL),
437253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      swap_(false),
437353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
43743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
43753261e8b6eac44a41341f112821482bee6c940c98mmentovai
43760cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekMinidump::Minidump(istream& stream)
43770cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    : header_(),
43780cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      directory_(NULL),
43790cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_map_(new MinidumpStreamMap()),
43800cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      path_(),
43810cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(&stream),
43820cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      swap_(false),
43830cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      valid_(false) {
43840cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
43853261e8b6eac44a41341f112821482bee6c940c98mmentovai
43863261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidump::~Minidump() {
43870cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_) {
43880cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump closing minidump";
43890cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
43900cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!path_.empty()) {
43910cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    delete stream_;
43920cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
43933261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
43943261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete stream_map_;
43956dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai}
43966dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
43976dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
43986dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaibool Minidump::Open() {
43990cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_ != NULL) {
44000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump reopening minidump " << path_;
4401af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
44026dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // The file is already open.  Seek to the beginning, which is the position
44036dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // the file would be at if it were opened anew.
44046dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return SeekSet(0);
44056dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  }
44066dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
44070cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
44080cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_ || !stream_->good()) {
4409af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    string error_string;
4410af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    int error_code = ErrnoString(&error_string);
4411af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
4412af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ", error " << error_code << ": " << error_string;
44136dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4414af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
44156dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
44160cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  BPLOG(INFO) << "Minidump opened minidump " << path_;
44176dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  return true;
44183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44193261e8b6eac44a41341f112821482bee6c940c98mmentovai
44206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) {
4421233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Initialize output parameters
4422233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  *context_cpu_flags = 0;
4423233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4424233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Save the current stream position
4425233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  off_t saved_position = Tell();
4426233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (saved_position == -1) {
4427233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Failed to save the current stream position.
4428233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Returns true because the current position of the stream is preserved.
4429233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    return true;
4430233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4431233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4432233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  const MDRawSystemInfo* system_info =
4433233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
4434233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4435233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (system_info != NULL) {
4436233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    switch (system_info->processor_architecture) {
4437233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86:
4438233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_X86;
4439233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4440233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MIPS:
4441233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_MIPS;
4442233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4443233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA:
4444233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ALPHA;
4445233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4446233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_PPC:
4447233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_PPC;
4448233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4449cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      case MD_CPU_ARCHITECTURE_PPC64:
4450cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        *context_cpu_flags = MD_CONTEXT_PPC64;
4451cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        break;
4452233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SHX:
4453233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SHX;
4454233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4455233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ARM:
4456233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ARM;
4457233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
445839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      case MD_CPU_ARCHITECTURE_ARM64:
445939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        *context_cpu_flags = MD_CONTEXT_ARM64;
446039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        break;
4461233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_IA64:
4462233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_IA64;
4463233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4464233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA64:
4465233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4466233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4467233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MSIL:
4468233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4469233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4470233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_AMD64:
4471233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_AMD64;
4472233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4473233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86_WIN64:
4474233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4475233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4476233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SPARC:
4477233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SPARC;
4478233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4479233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_UNKNOWN:
4480233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4481233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4482233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      default:
4483233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4484233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4485233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
4486233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4487233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4488233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Restore position and return
4489233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  return SeekSet(saved_position);
4490233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com}
4491233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
44923261e8b6eac44a41341f112821482bee6c940c98mmentovai
44933261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::Read() {
44943261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
44953261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
44963261e8b6eac44a41341f112821482bee6c940c98mmentovai  directory_ = NULL;
4497373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  stream_map_->clear();
44983261e8b6eac44a41341f112821482bee6c940c98mmentovai
44993261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
45003261e8b6eac44a41341f112821482bee6c940c98mmentovai
4501af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!Open()) {
4502af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot open minidump";
45036dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4504af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45056dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
4506af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
4507af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot read header";
45083261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4509af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45103261e8b6eac44a41341f112821482bee6c940c98mmentovai
45113261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (header_.signature != MD_HEADER_SIGNATURE) {
45123261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file may be byte-swapped.  Under the present architecture, these
45133261e8b6eac44a41341f112821482bee6c940c98mmentovai    // classes don't know or need to know what CPU (or endianness) the
45143261e8b6eac44a41341f112821482bee6c940c98mmentovai    // minidump was produced on in order to parse it.  Use the signature as
45153261e8b6eac44a41341f112821482bee6c940c98mmentovai    // a byte order marker.
45166162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature_swapped = header_.signature;
45173261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&signature_swapped);
45183261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature_swapped != MD_HEADER_SIGNATURE) {
45193261e8b6eac44a41341f112821482bee6c940c98mmentovai      // This isn't a minidump or a byte-swapped minidump.
4520af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
4521af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(header_.signature) << ", " <<
4522af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(signature_swapped) << ") != " <<
4523af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(MD_HEADER_SIGNATURE);
45243261e8b6eac44a41341f112821482bee6c940c98mmentovai      return false;
45253261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
45263261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = true;
45273261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
45283261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file is not byte-swapped.  Set swap_ false (it may have been true
45293261e8b6eac44a41341f112821482bee6c940c98mmentovai    // if the object is being reused?)
45303261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = false;
45313261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45323261e8b6eac44a41341f112821482bee6c940c98mmentovai
4533af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
4534af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                 "byte-swapping minidump";
4535af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
45363261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_) {
45373261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.signature);
45383261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.version);
45393261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_count);
45403261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_directory_rva);
45413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.checksum);
45423261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.time_date_stamp);
45433261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.flags);
45443261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45453261e8b6eac44a41341f112821482bee6c940c98mmentovai
45463261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Version check.  The high 16 bits of header_.version contain something
45473261e8b6eac44a41341f112821482bee6c940c98mmentovai  // else "implementation specific."
45483261e8b6eac44a41341f112821482bee6c940c98mmentovai  if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
4549af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump version mismatch: " <<
4550af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(header_.version & 0x0000ffff) << " != " <<
4551af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(MD_HEADER_VERSION);
45523261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
45533261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45543261e8b6eac44a41341f112821482bee6c940c98mmentovai
4555af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(header_.stream_directory_rva)) {
4556af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
45573261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4558af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45593261e8b6eac44a41341f112821482bee6c940c98mmentovai
4560e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count > max_streams_) {
4561e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
4562e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_streams_;
4563e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
4564e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4565e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
4566e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count != 0) {
4567373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpDirectoryEntries> directory(
4568373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpDirectoryEntries(header_.stream_count));
45693261e8b6eac44a41341f112821482bee6c940c98mmentovai
4570373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
4571373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
4572373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&(*directory)[0],
4573af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   sizeof(MDRawDirectory) * header_.stream_count)) {
4574af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump cannot read stream directory";
4575373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
4576af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
45773261e8b6eac44a41341f112821482bee6c940c98mmentovai
4578373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int stream_index = 0;
4579373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         stream_index < header_.stream_count;
4580373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++stream_index) {
4581373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDRawDirectory* directory_entry = &(*directory)[stream_index];
45823261e8b6eac44a41341f112821482bee6c940c98mmentovai
4583373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (swap_) {
4584373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->stream_type);
4585373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->location);
4586373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
45873261e8b6eac44a41341f112821482bee6c940c98mmentovai
4588373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Initialize the stream_map_ map, which speeds locating a stream by
4589373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // type.
4590373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      unsigned int stream_type = directory_entry->stream_type;
4591373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      switch (stream_type) {
4592373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_THREAD_LIST_STREAM:
4593373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MODULE_LIST_STREAM:
4594373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MEMORY_LIST_STREAM:
4595373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_EXCEPTION_STREAM:
4596373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_SYSTEM_INFO_STREAM:
4597373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MISC_INFO_STREAM:
4598e5dc60822e5938fea2ae892ccddb906641ba174emmentovai        case MD_BREAKPAD_INFO_STREAM: {
4599373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          if (stream_map_->find(stream_type) != stream_map_->end()) {
4600373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // Another stream with this type was already found.  A minidump
4601373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // file should contain at most one of each of these stream types.
4602af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            BPLOG(ERROR) << "Minidump found multiple streams of type " <<
4603af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                            stream_type << ", but can only deal with one";
4604373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            return false;
4605373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          }
4606373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Fall through to default
46073261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
46083261e8b6eac44a41341f112821482bee6c940c98mmentovai
4609373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        default: {
4610373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Overwrites for stream types other than those above, but it's
4611373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // expected to be the user's burden in that case.
4612373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          (*stream_map_)[stream_type].stream_index = stream_index;
4613373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        }
46143261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
46153261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
46163261e8b6eac44a41341f112821482bee6c940c98mmentovai
4617373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    directory_ = directory.release();
4618373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
46193261e8b6eac44a41341f112821482bee6c940c98mmentovai
46203261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
46213261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
46223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46233261e8b6eac44a41341f112821482bee6c940c98mmentovai
46243261e8b6eac44a41341f112821482bee6c940c98mmentovai
46253261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList* Minidump::GetThreadList() {
46263261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpThreadList* thread_list;
46273261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&thread_list);
46283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46293261e8b6eac44a41341f112821482bee6c940c98mmentovai
46303261e8b6eac44a41341f112821482bee6c940c98mmentovai
46313261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList* Minidump::GetModuleList() {
46323261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpModuleList* module_list;
46333261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&module_list);
46343261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46353261e8b6eac44a41341f112821482bee6c940c98mmentovai
46363261e8b6eac44a41341f112821482bee6c940c98mmentovai
46373261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList* Minidump::GetMemoryList() {
46383261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryList* memory_list;
46393261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&memory_list);
46403261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46413261e8b6eac44a41341f112821482bee6c940c98mmentovai
46423261e8b6eac44a41341f112821482bee6c940c98mmentovai
46433261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException* Minidump::GetException() {
46443261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpException* exception;
46453261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&exception);
46463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46473261e8b6eac44a41341f112821482bee6c940c98mmentovai
46480314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion* Minidump::GetAssertion() {
46490314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  MinidumpAssertion* assertion;
46500314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return GetStream(&assertion);
46510314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
46520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
46533261e8b6eac44a41341f112821482bee6c940c98mmentovai
46543261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo* Minidump::GetSystemInfo() {
46553261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpSystemInfo* system_info;
46563261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&system_info);
46573261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46583261e8b6eac44a41341f112821482bee6c940c98mmentovai
46593261e8b6eac44a41341f112821482bee6c940c98mmentovai
46603261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo* Minidump::GetMiscInfo() {
46613261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMiscInfo* misc_info;
46623261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&misc_info);
46633261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46643261e8b6eac44a41341f112821482bee6c940c98mmentovai
46653261e8b6eac44a41341f112821482bee6c940c98mmentovai
4666e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
4667e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  MinidumpBreakpadInfo* breakpad_info;
4668e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  return GetStream(&breakpad_info);
466976f052f8fbf8864dee5992b857229d06560a766ammentovai}
467076f052f8fbf8864dee5992b857229d06560a766ammentovai
46717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
46727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MinidumpMemoryInfoList* memory_info_list;
46737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetStream(&memory_info_list);
46747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
46757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
467676f052f8fbf8864dee5992b857229d06560a766ammentovai
46773261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid Minidump::Print() {
4678af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4679af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot print invalid data";
46803261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
4681af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46823261e8b6eac44a41341f112821482bee6c940c98mmentovai
46833261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawHeader\n");
46843261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  signature            = 0x%x\n",    header_.signature);
46853261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version              = 0x%x\n",    header_.version);
46863261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_count         = %d\n",      header_.stream_count);
46873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
46883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum             = 0x%x\n",    header_.checksum);
4689042ca733d309f48d2987a81151cbf3c59b73e562bryner  struct tm timestruct;
4690c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#ifdef _WIN32
4691c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek  gmtime_s(&timestruct, reinterpret_cast<time_t*>(&header_.time_date_stamp));
4692c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#else
4693042ca733d309f48d2987a81151cbf3c59b73e562bryner  gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
4694c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#endif
46953261e8b6eac44a41341f112821482bee6c940c98mmentovai  char timestr[20];
4696042ca733d309f48d2987a81151cbf3c59b73e562bryner  strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
46973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
46983261e8b6eac44a41341f112821482bee6c940c98mmentovai                                               timestr);
4699c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
47003261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
47013261e8b6eac44a41341f112821482bee6c940c98mmentovai
47023261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int stream_index = 0;
47033261e8b6eac44a41341f112821482bee6c940c98mmentovai       stream_index < header_.stream_count;
47043261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++stream_index) {
47053261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDRawDirectory* directory_entry = &(*directory_)[stream_index];
47063261e8b6eac44a41341f112821482bee6c940c98mmentovai
47073261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("mDirectory[%d]\n", stream_index);
47083261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDRawDirectory\n");
47093261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  stream_type        = %d\n",   directory_entry->stream_type);
47103261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.data_size = %d\n",
47113261e8b6eac44a41341f112821482bee6c940c98mmentovai           directory_entry->location.data_size);
47123261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
47133261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
47143261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
47153261e8b6eac44a41341f112821482bee6c940c98mmentovai
47163261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("Streams:\n");
47173261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
47183261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != stream_map_->end();
47193261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
47206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t stream_type = iterator->first;
47213261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpStreamInfo info = iterator->second;
472276f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  stream type 0x%x at index %d\n", stream_type, info.stream_index);
47233261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
47243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
47253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47263261e8b6eac44a41341f112821482bee6c940c98mmentovai
47273261e8b6eac44a41341f112821482bee6c940c98mmentovai
47283261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
47293261e8b6eac44a41341f112821482bee6c940c98mmentovai      const {
4730af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4731af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
47323261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4733af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4734af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4735af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= header_.stream_count) {
4736af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
4737af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << header_.stream_count;
4738af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
4739af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
47403261e8b6eac44a41341f112821482bee6c940c98mmentovai
47413261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*directory_)[index];
47423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47433261e8b6eac44a41341f112821482bee6c940c98mmentovai
47443261e8b6eac44a41341f112821482bee6c940c98mmentovai
47453261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::ReadBytes(void* bytes, size_t count) {
47463261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
47470cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
47480cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
47490cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
47500cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
47510cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->read(static_cast<char*>(bytes), count);
4752f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamsize bytes_read = stream_->gcount();
4753f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read == -1) {
4754f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    string error_string;
4755f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    int error_code = ErrnoString(&error_string);
4756f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
4757f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4758f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4759f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4760f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Convert to size_t and check for data loss
4761f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  size_t bytes_read_converted = static_cast<size_t>(bytes_read);
4762f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) {
4763f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting "
4764f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                 << bytes_read << " to " << bytes_read_converted;
47653261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4766af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4767f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4768f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read_converted != count) {
4769f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count;
4770f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4771f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4772f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
47733261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
47743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47753261e8b6eac44a41341f112821482bee6c940c98mmentovai
47763261e8b6eac44a41341f112821482bee6c940c98mmentovai
47773261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekSet(off_t offset) {
47783261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
47790cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
47800cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
47810cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
47820cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
47830cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->seekg(offset, std::ios_base::beg);
47840cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_->good()) {
47850cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    string error_string;
47860cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    int error_code = ErrnoString(&error_string);
47870cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
47883261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
47903261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
47913261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47923261e8b6eac44a41341f112821482bee6c940c98mmentovai
47930cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekoff_t Minidump::Tell() {
47940cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!valid_ || !stream_) {
47950cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return (off_t)-1;
47960cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
47970cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
4798f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for conversion data loss
4799f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamoff std_streamoff = stream_->tellg();
4800f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  off_t rv = static_cast<off_t>(std_streamoff);
4801f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamoff>(rv) == std_streamoff) {
4802f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return rv;
4803f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
4804f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected";
4805f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return (off_t)-1;
4806f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
48070cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
48080cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
48093261e8b6eac44a41341f112821482bee6c940c98mmentovai
48103261e8b6eac44a41341f112821482bee6c940c98mmentovaistring* Minidump::ReadString(off_t offset) {
4811af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4812af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for ReadString";
48133261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4814af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4815af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(offset)) {
4816e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
48173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4818af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48193261e8b6eac44a41341f112821482bee6c940c98mmentovai
48206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t bytes;
4821af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&bytes, sizeof(bytes))) {
4822e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not read string size at offset " <<
4823e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    offset;
48243261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4825af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48263261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_)
48273261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&bytes);
48283261e8b6eac44a41341f112821482bee6c940c98mmentovai
4829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (bytes % 2 != 0) {
4830e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
4831e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    "-byte string at offset " << offset;
48323261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4833af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48343261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int utf16_words = bytes / 2;
48353261e8b6eac44a41341f112821482bee6c940c98mmentovai
4836e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (utf16_words > max_string_length_) {
4837e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString string length " << utf16_words <<
4838e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_string_length_ <<
4839e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " at offset " << offset;
4840e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return NULL;
4841e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4842e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
48436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  vector<uint16_t> string_utf16(utf16_words);
48443261e8b6eac44a41341f112821482bee6c940c98mmentovai
4845373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (utf16_words) {
4846373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&string_utf16[0], bytes)) {
4847e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "ReadString could not read " << bytes <<
4848e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      "-byte string at offset " << offset;
4849373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
4850373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
4851373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
48523261e8b6eac44a41341f112821482bee6c940c98mmentovai
48533261e8b6eac44a41341f112821482bee6c940c98mmentovai  return UTF16ToUTF8(string_utf16, swap_);
48543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
48553261e8b6eac44a41341f112821482bee6c940c98mmentovai
48563261e8b6eac44a41341f112821482bee6c940c98mmentovai
48576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::SeekToStreamType(uint32_t  stream_type,
48586162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                uint32_t* stream_length) {
4859af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
4860af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "|stream_length|";
4861af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream_length);
4862af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *stream_length = 0;
4863af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4864af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4865af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
48663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4867af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48683261e8b6eac44a41341f112821482bee6c940c98mmentovai
48693261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
48703261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
48713261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4872af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
48733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
48743261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
48753261e8b6eac44a41341f112821482bee6c940c98mmentovai
48763261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo info = iterator->second;
4877af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (info.stream_index >= header_.stream_count) {
4878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
4879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " out of range: " <<
4880af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    info.stream_index << "/" << header_.stream_count;
48813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4882af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48833261e8b6eac44a41341f112821482bee6c940c98mmentovai
48843261e8b6eac44a41341f112821482bee6c940c98mmentovai  MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
4885af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(directory_entry->location.rva)) {
4886af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
4887af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    stream_type;
48883261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4889af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
48903261e8b6eac44a41341f112821482bee6c940c98mmentovai
48913261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream_length = directory_entry->location.data_size;
48923261e8b6eac44a41341f112821482bee6c940c98mmentovai
48933261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
48943261e8b6eac44a41341f112821482bee6c940c98mmentovai}
48953261e8b6eac44a41341f112821482bee6c940c98mmentovai
48963261e8b6eac44a41341f112821482bee6c940c98mmentovai
48973261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
48983261e8b6eac44a41341f112821482bee6c940c98mmentovaiT* Minidump::GetStream(T** stream) {
48993261e8b6eac44a41341f112821482bee6c940c98mmentovai  // stream is a garbage parameter that's present only to account for C++'s
49003261e8b6eac44a41341f112821482bee6c940c98mmentovai  // inability to overload a method based solely on its return type.
49013261e8b6eac44a41341f112821482bee6c940c98mmentovai
49026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t stream_type = T::kStreamType;
4903af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4904af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
4905af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                              " requires |stream|";
4906af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream);
49073261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = NULL;
49083261e8b6eac44a41341f112821482bee6c940c98mmentovai
4909af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4910af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
49113261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4912af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
49133261e8b6eac44a41341f112821482bee6c940c98mmentovai
49143261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
49153261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
49163261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4917af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
49183261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
49193261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
49203261e8b6eac44a41341f112821482bee6c940c98mmentovai
49213261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Get a pointer so that the stored stream field can be altered.
49223261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo* info = &iterator->second;
49233261e8b6eac44a41341f112821482bee6c940c98mmentovai
49243261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (info->stream) {
49253261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This cast is safe because info.stream is only populated by this
49263261e8b6eac44a41341f112821482bee6c940c98mmentovai    // method, and there is a direct correlation between T and stream_type.
49273261e8b6eac44a41341f112821482bee6c940c98mmentovai    *stream = static_cast<T*>(info->stream);
49283261e8b6eac44a41341f112821482bee6c940c98mmentovai    return *stream;
49293261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
49303261e8b6eac44a41341f112821482bee6c940c98mmentovai
49316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t stream_length;
4932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekToStreamType(stream_type, &stream_length)) {
4933af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
49343261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
49363261e8b6eac44a41341f112821482bee6c940c98mmentovai
49372466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<T> new_stream(new T(this));
49383261e8b6eac44a41341f112821482bee6c940c98mmentovai
4939af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!new_stream->Read(stream_length)) {
4940af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
49413261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4942af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
49433261e8b6eac44a41341f112821482bee6c940c98mmentovai
49443261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = new_stream.release();
49453261e8b6eac44a41341f112821482bee6c940c98mmentovai  info->stream = *stream;
49463261e8b6eac44a41341f112821482bee6c940c98mmentovai  return *stream;
49473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
49483261e8b6eac44a41341f112821482bee6c940c98mmentovai
49493261e8b6eac44a41341f112821482bee6c940c98mmentovai
4950e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
4951