minidump.cc revision 746f65a45e1cf52110ed677da19f87fa2eb6aefa
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"
64c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org#include "google_breakpad/processor/dump_context.h"
65db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_module.h"
66db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_modules.h"
67af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai#include "processor/logging.h"
682cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com
69e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
703261e8b6eac44a41341f112821482bee6c940c98mmentovai
713261e8b6eac44a41341f112821482bee6c940c98mmentovai
720cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::istream;
730cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::ifstream;
74fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovaiusing std::numeric_limits;
753261e8b6eac44a41341f112821482bee6c940c98mmentovaiusing std::vector;
763261e8b6eac44a41341f112821482bee6c940c98mmentovai
7739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// Returns true iff |context_size| matches exactly one of the sizes of the
7839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// various MDRawContext* types.
7939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// TODO(blundell): This function can be removed once
8039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org// http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed.
8139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.orgstatic bool IsContextSizeUnique(uint32_t context_size) {
8239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  int num_matching_contexts = 0;
8339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextX86))
8439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextPPC))
8639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextPPC64))
8839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
8939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextAMD64))
9039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextSPARC))
9239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextARM))
9439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextARM64))
9639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (context_size == sizeof(MDRawContextMIPS))
9839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    num_matching_contexts++;
9939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  return num_matching_contexts == 1;
10039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org}
1013261e8b6eac44a41341f112821482bee6c940c98mmentovai
1023261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1033261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping routines
1043261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1053261e8b6eac44a41341f112821482bee6c940c98mmentovai// Inlining these doesn't increase code size significantly, and it saves
1063261e8b6eac44a41341f112821482bee6c940c98mmentovai// a whole lot of unnecessary jumping back and forth.
1073261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1083261e8b6eac44a41341f112821482bee6c940c98mmentovai
1093261e8b6eac44a41341f112821482bee6c940c98mmentovai
1103261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping an 8-bit quantity is a no-op.  This function is only provided
1113261e8b6eac44a41341f112821482bee6c940c98mmentovai// to account for certain templatized operations that require swapping for
1126162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com// wider types but handle uint8_t too
1133261e8b6eac44a41341f112821482bee6c940c98mmentovai// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
1146162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint8_t* value) {
1153261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1163261e8b6eac44a41341f112821482bee6c940c98mmentovai
1173261e8b6eac44a41341f112821482bee6c940c98mmentovai
1183261e8b6eac44a41341f112821482bee6c940c98mmentovai// Optimization: don't need to AND the furthest right shift, because we're
1193261e8b6eac44a41341f112821482bee6c940c98mmentovai// shifting an unsigned quantity.  The standard requires zero-filling in this
1203261e8b6eac44a41341f112821482bee6c940c98mmentovai// case.  If the quantities were signed, a bitmask whould be needed for this
1213261e8b6eac44a41341f112821482bee6c940c98mmentovai// right shift to avoid an arithmetic shift (which retains the sign bit).
1223261e8b6eac44a41341f112821482bee6c940c98mmentovai// The furthest left shift never needs to be ANDed bitmask.
1233261e8b6eac44a41341f112821482bee6c940c98mmentovai
1243261e8b6eac44a41341f112821482bee6c940c98mmentovai
1256162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint16_t* value) {
1263261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = (*value >> 8) |
1273261e8b6eac44a41341f112821482bee6c940c98mmentovai           (*value << 8);
1283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1293261e8b6eac44a41341f112821482bee6c940c98mmentovai
1303261e8b6eac44a41341f112821482bee6c940c98mmentovai
1316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint32_t* value) {
1323261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 24) |
1333261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x0000ff00) |
1343261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x00ff0000) |
1353261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 24);
1363261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1373261e8b6eac44a41341f112821482bee6c940c98mmentovai
1383261e8b6eac44a41341f112821482bee6c940c98mmentovai
1396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint64_t* value) {
1406162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t* value32 = reinterpret_cast<uint32_t*>(value);
1412e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[0]);
1422e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[1]);
1436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t temp = value32[0];
1442e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[0] = value32[1];
1452e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[1] = temp;
1463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1473261e8b6eac44a41341f112821482bee6c940c98mmentovai
1483261e8b6eac44a41341f112821482bee6c940c98mmentovai
1491d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// Given a pointer to a 128-bit int in the minidump data, set the "low"
1501d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// and "high" fields appropriately.
1516162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Normalize128(uint128_struct* value, bool is_big_endian) {
1521d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // The struct format is [high, low], so if the format is big-endian,
1531d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // the most significant bytes will already be in the high field.
1541d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  if (!is_big_endian) {
1556162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t temp = value->low;
1561d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->low = value->high;
1571d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->high = temp;
1581d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  }
1591d78cad82e3c7aa2315ed7438211a1901a91ed34bryner}
1603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1611d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// This just swaps each int64 half of the 128-bit value.
1621d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// The value should also be normalized by calling Normalize128().
1636162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Swap(uint128_struct* value) {
1641d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->low);
1651d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->high);
1663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
1673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com// Swapping signed integers
1693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int16_t* value) {
1703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint16_t*>(value));
1713562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1723562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1733562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int32_t* value) {
1743562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint32_t*>(value));
1753562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int64_t* value) {
1783562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint64_t*>(value));
1793562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1803562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1823261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDLocationDescriptor* location_descriptor) {
1833261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->data_size);
1843261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->rva);
1853261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1863261e8b6eac44a41341f112821482bee6c940c98mmentovai
1873261e8b6eac44a41341f112821482bee6c940c98mmentovai
1883261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDMemoryDescriptor* memory_descriptor) {
1893261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->start_of_memory_range);
1903261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->memory);
1913261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1923261e8b6eac44a41341f112821482bee6c940c98mmentovai
1933261e8b6eac44a41341f112821482bee6c940c98mmentovai
1943261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDGUID* guid) {
1953261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data1);
1963261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data2);
1973261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data3);
1983261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't swap guid->data4[] because it contains 8-bit quantities.
1993261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2003261e8b6eac44a41341f112821482bee6c940c98mmentovai
2013562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDSystemTime* system_time) {
2023562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->year);
2033562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->month);
2043562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day_of_week);
2053562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day);
2063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->hour);
2073562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->minute);
2083562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->second);
2093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->milliseconds);
2103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
2113562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
2123562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(uint16_t* data, size_t size_in_bytes) {
2133562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t data_length = size_in_bytes / sizeof(data[0]);
2143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  for (size_t i = 0; i < data_length; i++) {
2153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    Swap(&data[i]);
2163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
2173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
2183261e8b6eac44a41341f112821482bee6c940c98mmentovai
2193261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2203261e8b6eac44a41341f112821482bee6c940c98mmentovai// Character conversion routines
2213261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2223261e8b6eac44a41341f112821482bee6c940c98mmentovai
2233261e8b6eac44a41341f112821482bee6c940c98mmentovai
2243261e8b6eac44a41341f112821482bee6c940c98mmentovai// Standard wide-character conversion routines depend on the system's own
2253261e8b6eac44a41341f112821482bee6c940c98mmentovai// idea of what width a wide character should be: some use 16 bits, and
2263261e8b6eac44a41341f112821482bee6c940c98mmentovai// some use 32 bits.  For the purposes of a minidump, wide strings are
2273261e8b6eac44a41341f112821482bee6c940c98mmentovai// always represented with 16-bit UTF-16 chracters.  iconv isn't available
2283261e8b6eac44a41341f112821482bee6c940c98mmentovai// everywhere, and its interface varies where it is available.  iconv also
2293261e8b6eac44a41341f112821482bee6c940c98mmentovai// deals purely with char* pointers, so in addition to considering the swap
2303261e8b6eac44a41341f112821482bee6c940c98mmentovai// parameter, a converter that uses iconv would also need to take the host
2313261e8b6eac44a41341f112821482bee6c940c98mmentovai// CPU's endianness into consideration.  It doesn't seems worth the trouble
2323261e8b6eac44a41341f112821482bee6c940c98mmentovai// of making it a dependency when we don't care about anything but UTF-16.
2336162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic string* UTF16ToUTF8(const vector<uint16_t>& in,
2343562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                           bool swap) {
2352466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<string> out(new string());
2363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2373261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Set the string's initial capacity to the number of UTF-16 characters,
2383261e8b6eac44a41341f112821482bee6c940c98mmentovai  // because the UTF-8 representation will always be at least this long.
2393261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the UTF-8 representation is longer, the string will grow dynamically.
2403261e8b6eac44a41341f112821482bee6c940c98mmentovai  out->reserve(in.size());
2413261e8b6eac44a41341f112821482bee6c940c98mmentovai
2426162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  for (vector<uint16_t>::const_iterator iterator = in.begin();
2433261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != in.end();
2443261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
2453261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Get a 16-bit value from the input
2466162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint16_t in_word = *iterator;
2473261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (swap)
2483261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&in_word);
2493261e8b6eac44a41341f112821482bee6c940c98mmentovai
2503261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the input value (in_word) into a Unicode code point (unichar).
2516162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t unichar;
2523261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (in_word >= 0xdc00 && in_word <= 0xdcff) {
253af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
254af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(in_word) << " without high";
2553261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2563261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
2573261e8b6eac44a41341f112821482bee6c940c98mmentovai      // High surrogate.
2583261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = (in_word - 0xd7c0) << 10;
2593261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (++iterator == in.end()) {
260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
261af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word) << " at end of string";
2623261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2633261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2646162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t high_word = in_word;
2653261e8b6eac44a41341f112821482bee6c940c98mmentovai      in_word = *iterator;
2663261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (in_word < 0xdc00 || in_word > 0xdcff) {
267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
268af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(high_word) << " without low " <<
269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word);
2703261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2713261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2723261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar |= in_word & 0x03ff;
2733261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
2743261e8b6eac44a41341f112821482bee6c940c98mmentovai      // The ordinary case, a single non-surrogate Unicode character encoded
2753261e8b6eac44a41341f112821482bee6c940c98mmentovai      // as a single 16-bit value.
2763261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = in_word;
2773261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2783261e8b6eac44a41341f112821482bee6c940c98mmentovai
2793261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the Unicode code point (unichar) into its UTF-8 representation,
2803261e8b6eac44a41341f112821482bee6c940c98mmentovai    // appending it to the out string.
2813261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (unichar < 0x80) {
282f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += static_cast<char>(unichar);
2833261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x800) {
284f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xc0 | static_cast<char>(unichar >> 6);
285f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2863261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x10000) {
287f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xe0 | static_cast<char>(unichar >> 12);
288f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
289f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2903261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x200000) {
291f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xf0 | static_cast<char>(unichar >> 18);
292f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f);
293f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
294f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2953261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
296af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
297af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(unichar) << " in UTF-8";
2983261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2993261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
3003261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
3013261e8b6eac44a41341f112821482bee6c940c98mmentovai
3023261e8b6eac44a41341f112821482bee6c940c98mmentovai  return out.release();
3033261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3043261e8b6eac44a41341f112821482bee6c940c98mmentovai
3050314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// Return the smaller of the number of code units in the UTF-16 string,
3060314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// not including the terminating null word, or maxlen.
3076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic size_t UTF16codeunits(const uint16_t *string, size_t maxlen) {
3080314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  size_t count = 0;
3090314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  while (count < maxlen && string[count] != 0)
3100314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    count++;
3110314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return count;
3120314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
3130314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
3143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDTimeZoneInformation* time_zone) {
3153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->bias);
3163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->standard_name.  No need to swap UTF-16 fields.
3173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
3183562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_date);
3193562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_bias);
3203562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->daylight_name.  No need to swap UTF-16 fields.
3213562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
3223562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_date);
3233562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_bias);
3243562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3253562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
3263562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data,
3273562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           size_t max_length_in_bytes,
3283562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           string* utf8_result,
3293562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           bool swap) {
3303562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Since there is no explicit byte length for each string, use
3313562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // UTF16codeunits to calculate word length, then derive byte
3323562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // length from that.
3333562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]);
3343562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t word_length = UTF16codeunits(utf16_data, max_word_length);
3353562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (word_length > 0) {
3363562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    size_t byte_length = word_length * sizeof(utf16_data[0]);
3373562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    vector<uint16_t> utf16_vector(word_length);
3383562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    memcpy(&utf16_vector[0], &utf16_data[0], byte_length);
3393562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap));
3403562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (temp.get()) {
3413562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      utf8_result->assign(*temp);
3423562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
3433562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  } else {
3443562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    utf8_result->clear();
3453562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
3463562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3473261e8b6eac44a41341f112821482bee6c940c98mmentovai
3481b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org
3491b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org// For fields that may or may not be valid, PrintValueOrInvalid will print the
3501b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org// string "(invalid)" if the field is not valid, and will print the value if
3511b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org// the field is valid. The value is printed as hexadecimal or decimal.
3521b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org
3531b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.orgenum NumberFormat {
3541b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  kNumberFormatDecimal,
3551b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  kNumberFormatHexadecimal,
3561b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org};
3571b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org
3581b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.orgstatic void PrintValueOrInvalid(bool valid,
3591b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                                NumberFormat number_format,
3601b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                                uint32_t value) {
3611b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  if (!valid) {
3621b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("(invalid)\n");
3631b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  } else if (number_format == kNumberFormatDecimal) {
3641b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("%d\n", value);
3651b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  } else {
3661b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("0x%x\n", value);
3671b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  }
3681b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org}
3691b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org
3709c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org// Converts a time_t to a string showing the time in UTC.
3719c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.orgstring TimeTToUTCString(time_t tt) {
3729c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  struct tm timestruct;
3739c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org#ifdef _WIN32
3749c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  gmtime_s(&timestruct, &tt);
3759c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org#else
3769c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  gmtime_r(&tt, &timestruct);
3779c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org#endif
3789c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org
3799c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  char timestr[20];
3809c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  int rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
3819c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  if (rv == 0) {
3829c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    return string();
3839c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  }
3849c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org
3859c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  return string(timestr);
3869c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org}
3879c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org
3881b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org
3893261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3903261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpObject
3913261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3923261e8b6eac44a41341f112821482bee6c940c98mmentovai
3933261e8b6eac44a41341f112821482bee6c940c98mmentovai
3943261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpObject::MinidumpObject(Minidump* minidump)
395c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    : DumpObject(),
396c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org      minidump_(minidump) {
3973261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3983261e8b6eac44a41341f112821482bee6c940c98mmentovai
3993261e8b6eac44a41341f112821482bee6c940c98mmentovai
4003261e8b6eac44a41341f112821482bee6c940c98mmentovai//
4013261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpStream
4023261e8b6eac44a41341f112821482bee6c940c98mmentovai//
4033261e8b6eac44a41341f112821482bee6c940c98mmentovai
4043261e8b6eac44a41341f112821482bee6c940c98mmentovai
4053261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpStream::MinidumpStream(Minidump* minidump)
4063261e8b6eac44a41341f112821482bee6c940c98mmentovai    : MinidumpObject(minidump) {
4073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
4083261e8b6eac44a41341f112821482bee6c940c98mmentovai
4093261e8b6eac44a41341f112821482bee6c940c98mmentovai
4103261e8b6eac44a41341f112821482bee6c940c98mmentovai//
4113261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpContext
4123261e8b6eac44a41341f112821482bee6c940c98mmentovai//
4133261e8b6eac44a41341f112821482bee6c940c98mmentovai
4143261e8b6eac44a41341f112821482bee6c940c98mmentovai
4153261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext::MinidumpContext(Minidump* minidump)
416c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    : DumpContext(),
417c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org      minidump_(minidump) {
4183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
4193261e8b6eac44a41341f112821482bee6c940c98mmentovai
4203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiMinidumpContext::~MinidumpContext() {
4213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
4223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::Read(uint32_t expected_size) {
4243261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
4253261e8b6eac44a41341f112821482bee6c940c98mmentovai
42639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  // Certain raw context types are currently assumed to have unique sizes.
42739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) {
42839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any "
42939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
43039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
43139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
43239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
43339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
43439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
43539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
43639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
43739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  if (!IsContextSizeUnique(sizeof(MDRawContextARM64))) {
43839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(ERROR) << "sizeof(MDRawContextARM64) cannot match the size of any "
43939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                 << "other raw context";
44039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    return false;
44139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  }
44239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
4433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
4443261e8b6eac44a41341f112821482bee6c940c98mmentovai
4453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // First, figure out what type of CPU this context structure is for.
4468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // For some reason, the AMD64 Context doesn't have context_flags
4478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // at the beginning of the structure, so special case it here.
4488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (expected_size == sizeof(MDRawContextAMD64)) {
4498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
4508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
4528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(context_amd64.get(),
4538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                              sizeof(MDRawContextAMD64))) {
4548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
4558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
4598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->context_flags);
4603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4616162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
462233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
463233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
464233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_amd64->context_flags |= cpu_type;
465233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
466233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
467233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
468233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
469233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
4703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (cpu_type != MD_CONTEXT_AMD64) {
47239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
47339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
4748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
4758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Do this after reading the entire MDRawContext structure because
4798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // GetSystemInfo may seek minidump to a new position.
4808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!CheckAgainstSystemInfo(cpu_type)) {
4818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
4828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4843261e8b6eac44a41341f112821482bee6c940c98mmentovai
4858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Normalize the 128-bit types in the dump.
4868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Since this is AMD64, by definition, the values are little-endian.
4878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    for (unsigned int vr_index = 0;
4888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         vr_index < MD_CONTEXT_AMD64_VR_COUNT;
4898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         ++vr_index)
4908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Normalize128(&context_amd64->vector_register[vr_index], false);
4918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap()) {
4938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p1_home);
4948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p2_home);
4958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p3_home);
4968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p4_home);
4978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p5_home);
4988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p6_home);
4998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // context_flags is already swapped
5008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->mx_csr);
5018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->cs);
5028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ds);
5038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->es);
5048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->fs);
5058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ss);
5068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->eflags);
5078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr0);
5088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr1);
5098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr2);
5108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr3);
5118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr6);
5128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr7);
5138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rax);
5148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rcx);
5158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdx);
5168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbx);
5178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsp);
5188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbp);
5198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsi);
5208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdi);
5218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r8);
5228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r9);
5238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r10);
5248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r11);
5258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r12);
5268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r13);
5278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r14);
5288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r15);
5298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rip);
530f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // FIXME: I'm not sure what actually determines
5318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // which member of the union {flt_save, sse_registers}
5328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // is valid.  We're not currently using either,
5338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // but it would be good to have them swapped properly.
5343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      for (unsigned int vr_index = 0;
5368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           vr_index < MD_CONTEXT_AMD64_VR_COUNT;
5378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           ++vr_index)
5388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        Swap(&context_amd64->vector_register[vr_index]);
5398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->vector_control);
5408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->debug_control);
5418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_to_rip);
5428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_from_rip);
5438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_to_rip);
5448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_from_rip);
5458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
5463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
547c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextFlags(context_amd64->context_flags);
5483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
549c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextAMD64(context_amd64.release());
550f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else if (expected_size == sizeof(MDRawContextPPC64)) {
551f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
552f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // in the else case have 32 bits |context_flags|, so special case it here.
553cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint64_t context_flags;
554cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
555cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read context flags";
556cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
557cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
558cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap())
559cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_flags);
560cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
561cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
562cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
563cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
56439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type == 0) {
56539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
56639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        context_ppc64->context_flags |= cpu_type;
56739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      } else {
56839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        BPLOG(ERROR) << "Failed to preserve the current stream position";
56939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return false;
57039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
57139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
57239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
57339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type != MD_CONTEXT_PPC64) {
57439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
57539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
57639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext not actually ppc64 context";
57739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
57839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
579f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
580cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Set the context_flags member, which has already been read, and
581cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // read the rest of the structure beginning with the first member
582cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // after context_flags.
583cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    context_ppc64->context_flags = context_flags;
584cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
585cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    size_t flags_size = sizeof(context_ppc64->context_flags);
586cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint8_t* context_after_flags =
587cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org          reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
588cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(context_after_flags,
589cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org                              sizeof(MDRawContextPPC64) - flags_size)) {
590cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
591cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
592cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
593cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
594cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Do this after reading the entire MDRawContext structure because
595cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // GetSystemInfo may seek minidump to a new position.
596cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!CheckAgainstSystemInfo(cpu_type)) {
597cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
598cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
599cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
600cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap()) {
601cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // context_ppc64->context_flags was already swapped.
602cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr0);
603cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr1);
604cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int gpr_index = 0;
605cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
606cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++gpr_index) {
607cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->gpr[gpr_index]);
608cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
609cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->cr);
610cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->xer);
611cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->lr);
612cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->ctr);
613cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vrsave);
614cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int fpr_index = 0;
615cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
616cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++fpr_index) {
617cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->float_save.fpregs[fpr_index]);
618cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
619cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap context_ppc64->float_save.fpscr_pad because it is only
620cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // used for padding.
621cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->float_save.fpscr);
622cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int vr_index = 0;
623cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
624cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++vr_index) {
625cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
626cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->vector_save.save_vr[vr_index]);
627cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
628cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vscr);
629cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap the padding fields in vector_save.
630cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vrvalid);
631cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
632cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
633c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags));
634f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
635f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // Check for data loss when converting context flags from uint64_t into
636f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // uint32_t
637c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    if (static_cast<uint64_t>(GetContextFlags()) !=
638f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        context_ppc64->context_flags) {
639f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
640f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      return false;
641f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    }
642cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
643c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextPPC64(context_ppc64.release());
64439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org  } else if (expected_size == sizeof(MDRawContextARM64)) {
64539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // |context_flags| of MDRawContextARM64 is 64 bits, but other MDRawContext
64639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // in the else case have 32 bits |context_flags|, so special case it here.
64739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint64_t context_flags;
64839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
64939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    BPLOG(INFO) << "MinidumpContext: looks like ARM64 context";
65039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
65139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
65239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read context flags";
65339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
65439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
65539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (minidump_->swap())
65639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_flags);
65739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
65839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64());
65939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
66039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
66139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type == 0) {
66239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
66339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        context_arm64->context_flags |= cpu_type;
66439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      } else {
66539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        BPLOG(ERROR) << "Failed to preserve the current stream position";
66639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return false;
66739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
66839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
66939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
67039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (cpu_type != MD_CONTEXT_ARM64) {
67139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // TODO: Fall through to switch below.
67239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // http://code.google.com/p/google-breakpad/issues/detail?id=550
67339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext not actually arm64 context";
67439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
67539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
67639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
67739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // Set the context_flags member, which has already been read, and
67839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // read the rest of the structure beginning with the first member
67939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // after context_flags.
68039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    context_arm64->context_flags = context_flags;
68139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
68239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    size_t flags_size = sizeof(context_arm64->context_flags);
68339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    uint8_t* context_after_flags =
68439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
68539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!minidump_->ReadBytes(context_after_flags,
68639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org                              sizeof(MDRawContextARM64) - flags_size)) {
68739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
68839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
68939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
69039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
69139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // Do this after reading the entire MDRawContext structure because
69239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    // GetSystemInfo may seek minidump to a new position.
69339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (!CheckAgainstSystemInfo(cpu_type)) {
69439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      BPLOG(ERROR) << "MinidumpContext arm64 does not match system info";
69539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      return false;
69639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
69739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
69839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    if (minidump_->swap()) {
69939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      // context_arm64->context_flags was already swapped.
70039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int ireg_index = 0;
70139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
70239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++ireg_index) {
70339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Swap(&context_arm64->iregs[ireg_index]);
70439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
70539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->cpsr);
70639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->float_save.fpsr);
70739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      Swap(&context_arm64->float_save.fpcr);
70839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      for (unsigned int fpr_index = 0;
70939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
71039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org           ++fpr_index) {
71139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // While ARM64 is bi-endian, iOS (currently the only platform
71239d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // for which ARM64 support has been brought up) uses ARM64 exclusively
71339d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        // in little-endian mode.
71439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Normalize128(&context_arm64->float_save.regs[fpr_index], false);
71539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        Swap(&context_arm64->float_save.regs[fpr_index]);
71639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      }
71739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    }
718c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextFlags(static_cast<uint32_t>(context_arm64->context_flags));
719ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org
720ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    // Check for data loss when converting context flags from uint64_t into
721ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    // uint32_t
722c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    if (static_cast<uint64_t>(GetContextFlags()) !=
723ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org        context_arm64->context_flags) {
724ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org      BPLOG(ERROR) << "Data loss detected when converting ARM64 context_flags";
725ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org      return false;
726ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org    }
727ce1a45e28cad26f9c0f34ae329b0fd694d004f0fthestig@chromium.org
728c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextARM64(context_arm64.release());
729f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
7306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t context_flags;
7318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
7328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read context flags";
7338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
7343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
7358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
7368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_flags);
7378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
7386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
7391a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    if (cpu_type == 0) {
7401a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // Unfortunately the flag for MD_CONTEXT_ARM that was taken
7411a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // from a Windows CE SDK header conflicts in practice with
7421a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
7431a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // but handle dumps with the legacy value gracefully here.
7441a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      if (context_flags & MD_CONTEXT_ARM_OLD) {
7451a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags |= MD_CONTEXT_ARM;
7461a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags &= ~MD_CONTEXT_ARM_OLD;
7471a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        cpu_type = MD_CONTEXT_ARM;
7481a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      }
7491a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    }
7508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
751233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
752233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
753233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_flags |= cpu_type;
754233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
755233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
756233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
757233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
758233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
759233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
7608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Allocate the context structure for the correct CPU and fill it.  The
7618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // casts are slightly unorthodox, but it seems better to do that than to
7628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // maintain a separate pointer for each type of CPU context structure
7638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // when only one of them will be used.
7648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    switch (cpu_type) {
7658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_X86: {
7668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextX86)) {
7678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
7688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextX86);
7698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
7733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
7758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
7768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
7778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_x86->context_flags = context_flags;
7783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_x86->context_flags);
7806162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
7816162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
7828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
7838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextX86) - flags_size)) {
7848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read x86 context";
7858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
7898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
7908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
7918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
7928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
7968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->context_flags was already swapped.
7978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr0);
7988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr1);
7998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr2);
8008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr3);
8018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr6);
8028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr7);
8038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.control_word);
8048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.status_word);
8058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.tag_word);
8068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_offset);
8078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_selector);
8088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_offset);
8098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_selector);
8108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->float_save.register_area[] contains 8-bit quantities
8118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // and does not need to be swapped.
8128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.cr0_npx_state);
8138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->gs);
8148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->fs);
8158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->es);
8168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ds);
8178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edi);
8188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esi);
8198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebx);
8208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edx);
8218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ecx);
8228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eax);
8238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebp);
8248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eip);
8258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->cs);
8268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eflags);
8278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esp);
8288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ss);
8298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->extended_registers[] contains 8-bit quantities and
8308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // does not need to be swapped.
8318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
8323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
833c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org        SetContextX86(context_x86.release());
8348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
8361d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      }
8371d78cad82e3c7aa2315ed7438211a1901a91ed34bryner
8388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_PPC: {
8398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextPPC)) {
8408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
8418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextPPC);
8428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
8448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
8468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
8488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
8498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
8508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_ppc->context_flags = context_flags;
8518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_ppc->context_flags);
8536162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
8546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
8558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
8568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextPPC) - flags_size)) {
8578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read ppc context";
8588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
8628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
8638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
8648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
8658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
8663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
8688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Normalize the 128-bit types in the dump.
8698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Since this is PowerPC, by definition, the values are big-endian.
8703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int vr_index = 0;
8713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
8723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++vr_index) {
8738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
8743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
8753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
8778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_ppc->context_flags was already swapped.
8788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr0);
8798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr1);
8808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
8818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
8828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
8838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->gpr[gpr_index]);
8848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
8858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->cr);
8868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->xer);
8878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->lr);
8888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->ctr);
8898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->mq);
8908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vrsave);
8918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
8928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
8938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
8948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->float_save.fpregs[fpr_index]);
8958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
8968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap context_ppc->float_save.fpscr_pad because it is only
8978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // used for padding.
8988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->float_save.fpscr);
8998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int vr_index = 0;
9008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
9018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++vr_index) {
9028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->vector_save.save_vr[vr_index]);
9038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
9048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vscr);
9058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap the padding fields in vector_save.
9068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vrvalid);
9078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
9083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
909c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org        SetContextPPC(context_ppc.release());
9103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
912ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
913ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_SPARC: {
9158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextSPARC)) {
9168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
9178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextSPARC);
9188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
9198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
920ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
922ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
9248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
9258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
9268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_sparc->context_flags = context_flags;
927ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_sparc->context_flags);
9296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
9306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
9318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
9328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextSPARC) - flags_size)) {
9338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read sparc context";
9348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
9358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
936ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
9388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
9398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
9408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
9418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
942ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
9438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
9448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
9458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_sparc->context_flags was already swapped.
9468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
9478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
9488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
9498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->g_r[gpr_index]);
9508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
9518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->ccr);
9528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->pc);
9538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->npc);
9548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->y);
9558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->asi);
9568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->fprs);
9578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
9588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
9598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
9608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->float_save.regs[fpr_index]);
9618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
9628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.filler);
9638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.fsr);
964ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
965c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org        SetContextSPARC(context_sparc.release());
966ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
9688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
969ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
9709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      case MD_CONTEXT_ARM: {
9719276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (expected_size != sizeof(MDRawContextARM)) {
9729276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
9739276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            expected_size << " != " << sizeof(MDRawContextARM);
9749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9769276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9779276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
9789276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9799276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Set the context_flags member, which has already been read, and
9809276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // read the rest of the structure beginning with the first member
9819276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // after context_flags.
9829276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_arm->context_flags = context_flags;
9839276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9849276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        size_t flags_size = sizeof(context_arm->context_flags);
9856162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
9866162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
9879276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
9889276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek                                  sizeof(MDRawContextARM) - flags_size)) {
9899276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read arm context";
9909276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9919276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9929276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
9939276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Do this after reading the entire MDRawContext structure because
9949276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // GetSystemInfo may seek minidump to a new position.
9959276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
9969276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm does not match system info";
9979276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
9989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
9999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (minidump_->swap()) {
10019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          // context_arm->context_flags was already swapped.
10029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int ireg_index = 0;
10039276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
10049276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++ireg_index) {
10059276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->iregs[ireg_index]);
10069276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
10079276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->cpsr);
10089276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->float_save.fpscr);
10099276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpr_index = 0;
10109276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
10119276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpr_index) {
10129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.regs[fpr_index]);
10139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
10149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpe_index = 0;
10159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
10169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpe_index) {
10179276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.extra[fpe_index]);
10189276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
10199276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
1020c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org        SetContextARM(context_arm.release());
10219276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10229276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        break;
10239276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
10249276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10255f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      case MD_CONTEXT_MIPS: {
10265f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (expected_size != sizeof(MDRawContextMIPS)) {
1027c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org          BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
1028c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org                       << expected_size
1029c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org                       << " != "
10305f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << sizeof(MDRawContextMIPS);
10315f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
10325f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10335f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10345f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
10355f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10365f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Set the context_flags member, which has already been read, and
10375f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // read the rest of the structure beginning with the first member
10385f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // after context_flags.
10395f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        context_mips->context_flags = context_flags;
10405f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10415f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        size_t flags_size = sizeof(context_mips->context_flags);
10425f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        uint8_t* context_after_flags =
10435f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
10445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!minidump_->ReadBytes(context_after_flags,
10455f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                                  sizeof(MDRawContextMIPS) - flags_size)) {
10465f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
10475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
10485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10495f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10505f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Do this after reading the entire MDRawContext structure because
10515f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // GetSystemInfo may seek minidump to a new position.
10525f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!CheckAgainstSystemInfo(cpu_type)) {
10535f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
10545f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
10555f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
10565f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10575f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (minidump_->swap()) {
10585f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          // context_mips->context_flags was already swapped.
10595f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int ireg_index = 0;
10605f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
10615f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++ireg_index) {
10625f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->iregs[ireg_index]);
10635f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10645f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdhi);
10655f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdlo);
10665f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int dsp_index = 0;
10675f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
10685f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++dsp_index) {
10695f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->hi[dsp_index]);
10705f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->lo[dsp_index]);
10715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10725f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->dsp_control);
10735f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->epc);
10745f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->badvaddr);
10755f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->status);
10765f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->cause);
10775f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int fpr_index = 0;
10785f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
10795f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++fpr_index) {
10805f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->float_save.regs[fpr_index]);
10815f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
10825f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fpcsr);
10835f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fir);
10845f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
1085c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org        SetContextMIPS(context_mips.release());
10865f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10875f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        break;
10885f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
10895f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      default: {
1091bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com        // Unknown context type - Don't log as an error yet. Let the
10925f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        // caller work that out.
10935f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        BPLOG(INFO) << "MinidumpContext unknown context type " <<
10948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          HexString(cpu_type);
10958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return false;
10968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
10978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
10983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
1099c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextFlags(context_flags);
11003261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
11013261e8b6eac44a41341f112821482bee6c940c98mmentovai
11023261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
11033261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
11043261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11053261e8b6eac44a41341f112821482bee6c940c98mmentovai
11066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
1107e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
11083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // as this function just implements a sanity check.
11093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
1110af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!system_info) {
1111af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1112af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MinidumpSystemInfo";
11133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return true;
1114af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1116e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
11173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  const MDRawSystemInfo* raw_system_info = system_info->system_info();
1118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1119af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1120af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MDRawSystemInfo";
11213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return false;
1122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
11253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      raw_system_info->processor_architecture);
11263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Compare the CPU type of the context record to the CPU type in the
11283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // minidump's system info stream.
1129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  bool return_value = false;
11303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (context_cpu_type) {
11313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
1132af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
1133299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
1134299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
1135af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
11363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
11373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
11383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
1140af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
1141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
11423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
1143ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1144cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64:
1145cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64)
1146cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        return_value = true;
1147cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1148cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
11498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
11508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
11518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return_value = true;
11528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
11538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1154ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
1155ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
1156ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return_value = true;
1157ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
11589276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
11599276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
11609276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
11619276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        return_value = true;
11629276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
11635f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
116439d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CONTEXT_ARM64:
116539d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64)
116639d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        return_value = true;
116739d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
116839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
11695f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS:
11705f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS)
11715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        return_value = true;
11725f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
11733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  }
11743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1175af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
1176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(context_cpu_type) <<
11770344a368deac6abaa280a298bcea9bb00a90df3fted.mielczarek@gmail.com                                    " wrong for MinidumpSystemInfo CPU " <<
1178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(system_info_cpu_type);
1179af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1180af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return return_value;
11813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
11823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11843261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11853261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryRegion
11863261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11873261e8b6eac44a41341f112821482bee6c940c98mmentovai
11883261e8b6eac44a41341f112821482bee6c940c98mmentovai
11896162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
1190e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1191e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
11923261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
119353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
119453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptor_(NULL),
119553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL) {
11963261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11973261e8b6eac44a41341f112821482bee6c940c98mmentovai
11983261e8b6eac44a41341f112821482bee6c940c98mmentovai
11993261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::~MinidumpMemoryRegion() {
12003261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
12013261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12023261e8b6eac44a41341f112821482bee6c940c98mmentovai
12033261e8b6eac44a41341f112821482bee6c940c98mmentovai
12043261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
12053261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptor_ = descriptor;
12063261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = descriptor &&
1207fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai           descriptor_->memory.data_size <=
12086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com               numeric_limits<uint64_t>::max() -
1209fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               descriptor_->start_of_memory_range;
12103261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12113261e8b6eac44a41341f112821482bee6c940c98mmentovai
12123261e8b6eac44a41341f112821482bee6c940c98mmentovai
12136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpMemoryRegion::GetMemory() const {
1214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
12163261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1217af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12183261e8b6eac44a41341f112821482bee6c940c98mmentovai
12193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!memory_) {
1220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (descriptor_->memory.data_size == 0) {
1221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
1222373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
1223af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
1224373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1225af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(descriptor_->memory.rva)) {
1226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
12273261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
12293261e8b6eac44a41341f112821482bee6c940c98mmentovai
1230e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (descriptor_->memory.data_size > max_bytes_) {
1231e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
1232e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      descriptor_->memory.data_size << " exceeds maximum " <<
1233e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_bytes_;
1234e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
1235e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
1236e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
12376162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > memory(
12386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(descriptor_->memory.data_size));
12393261e8b6eac44a41341f112821482bee6c940c98mmentovai
1240af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
1241af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
12423261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1243af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
12443261e8b6eac44a41341f112821482bee6c940c98mmentovai
12453261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory_ = memory.release();
12463261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
12473261e8b6eac44a41341f112821482bee6c940c98mmentovai
12483261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*memory_)[0];
12493261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12503261e8b6eac44a41341f112821482bee6c940c98mmentovai
12513261e8b6eac44a41341f112821482bee6c940c98mmentovai
12526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint64_t MinidumpMemoryRegion::GetBase() const {
1253af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1254af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
12556162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    return static_cast<uint64_t>(-1);
1256af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->start_of_memory_range;
12593261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12603261e8b6eac44a41341f112821482bee6c940c98mmentovai
12613261e8b6eac44a41341f112821482bee6c940c98mmentovai
12626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::GetSize() const {
1263af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1264af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
1265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
1266af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1268af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->memory.data_size;
12693261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12703261e8b6eac44a41341f112821482bee6c940c98mmentovai
12713261e8b6eac44a41341f112821482bee6c940c98mmentovai
12723261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::FreeMemory() {
12733261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
12743261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
12753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12763261e8b6eac44a41341f112821482bee6c940c98mmentovai
12773261e8b6eac44a41341f112821482bee6c940c98mmentovai
12783261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
12796162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address,
12802214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                                      T*        value) const {
1281af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
1282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                             "requires |value|";
1283af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(value);
1284af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *value = 0;
1285af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1286af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1287af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
1288af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "GetMemoryAtAddressInternal";
12893261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1290af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1292bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Common failure case
12933261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (address < descriptor_->start_of_memory_range ||
12946162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      sizeof(T) > numeric_limits<uint64_t>::max() - address ||
12953261e8b6eac44a41341f112821482bee6c940c98mmentovai      address + sizeof(T) > descriptor_->start_of_memory_range +
12963261e8b6eac44a41341f112821482bee6c940c98mmentovai                            descriptor_->memory.data_size) {
1297bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com    BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
1298af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(address) << "+" << sizeof(T) << "/" <<
1299af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->start_of_memory_range) << "+" <<
1300af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->memory.data_size);
13013261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
13023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
13033261e8b6eac44a41341f112821482bee6c940c98mmentovai
13046162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
1305af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!memory) {
1306af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // GetMemory already logged a perfectly good message.
13073261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1308af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13093261e8b6eac44a41341f112821482bee6c940c98mmentovai
13103261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the CPU requires memory accesses to be aligned, this can crash.
13113261e8b6eac44a41341f112821482bee6c940c98mmentovai  // x86 and ppc are able to cope, though.
13123261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = *reinterpret_cast<const T*>(
13133261e8b6eac44a41341f112821482bee6c940c98mmentovai      &memory[address - descriptor_->start_of_memory_range]);
13143261e8b6eac44a41341f112821482bee6c940c98mmentovai
13153261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
13163261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(value);
13173261e8b6eac44a41341f112821482bee6c940c98mmentovai
13183261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
13193261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13203261e8b6eac44a41341f112821482bee6c940c98mmentovai
13213261e8b6eac44a41341f112821482bee6c940c98mmentovai
13226162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
13236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint8_t*  value) const {
13243261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
13253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13263261e8b6eac44a41341f112821482bee6c940c98mmentovai
13273261e8b6eac44a41341f112821482bee6c940c98mmentovai
13286162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
13296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint16_t* value) const {
13303261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
13313261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13323261e8b6eac44a41341f112821482bee6c940c98mmentovai
13333261e8b6eac44a41341f112821482bee6c940c98mmentovai
13346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
13356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint32_t* value) const {
13363261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
13373261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13383261e8b6eac44a41341f112821482bee6c940c98mmentovai
13393261e8b6eac44a41341f112821482bee6c940c98mmentovai
13406162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
13416162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint64_t* value) const {
13423261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
13433261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13443261e8b6eac44a41341f112821482bee6c940c98mmentovai
13453261e8b6eac44a41341f112821482bee6c940c98mmentovai
1346c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.orgvoid MinidumpMemoryRegion::Print() const {
1347af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1348af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
13493261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1350af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13513261e8b6eac44a41341f112821482bee6c940c98mmentovai
13526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
13533261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
13543261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("0x");
13553261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int byte_index = 0;
13563261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index < descriptor_->memory.data_size;
13573261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index++) {
13583261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("%02x", memory[byte_index]);
13593261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
13603261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
13613261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
13623261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No memory\n");
13633261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
13643261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13653261e8b6eac44a41341f112821482bee6c940c98mmentovai
13663261e8b6eac44a41341f112821482bee6c940c98mmentovai
13673261e8b6eac44a41341f112821482bee6c940c98mmentovai//
13683261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThread
13693261e8b6eac44a41341f112821482bee6c940c98mmentovai//
13703261e8b6eac44a41341f112821482bee6c940c98mmentovai
13713261e8b6eac44a41341f112821482bee6c940c98mmentovai
13723261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::MinidumpThread(Minidump* minidump)
137353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
137453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_(),
137553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL),
137653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
13773261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13783261e8b6eac44a41341f112821482bee6c940c98mmentovai
13793261e8b6eac44a41341f112821482bee6c940c98mmentovai
13803261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::~MinidumpThread() {
13813261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
13823261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
13833261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13843261e8b6eac44a41341f112821482bee6c940c98mmentovai
13853261e8b6eac44a41341f112821482bee6c940c98mmentovai
13863261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThread::Read() {
13873261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
13883261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
13893261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
13903261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
13913261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
13923261e8b6eac44a41341f112821482bee6c940c98mmentovai
13933261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
13943261e8b6eac44a41341f112821482bee6c940c98mmentovai
1395af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
1396af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot read thread";
13973261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1398af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13993261e8b6eac44a41341f112821482bee6c940c98mmentovai
14003261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
14013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_id);
14023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.suspend_count);
14033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority_class);
14043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority);
14053261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.teb);
14063261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.stack);
14073261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_context);
14083261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14093261e8b6eac44a41341f112821482bee6c940c98mmentovai
1410fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
141102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (thread_.stack.memory.rva == 0 ||
141202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      thread_.stack.memory.data_size == 0 ||
14136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() -
1414fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                                       thread_.stack.start_of_memory_range) {
1415e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    // This is ok, but log an error anyway.
1416af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
1417af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(thread_.stack.start_of_memory_range) << "+" <<
141802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    HexString(thread_.stack.memory.data_size) <<
141902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    ", RVA 0x" << HexString(thread_.stack.memory.rva);
1420e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  } else {
1421e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_ = new MinidumpMemoryRegion(minidump_);
1422e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_->SetDescriptor(&thread_.stack);
1423af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
14243261e8b6eac44a41341f112821482bee6c940c98mmentovai
14253261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
14263261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
14273261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14283261e8b6eac44a41341f112821482bee6c940c98mmentovai
142902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.comuint64_t MinidumpThread::GetStartOfStackMemoryRange() const {
143002ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (!valid_) {
143102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread";
143202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    return 0;
143302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  }
143402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
143502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  return thread_.stack.start_of_memory_range;
143602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com}
14373261e8b6eac44a41341f112821482bee6c940c98mmentovai
14383261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpThread::GetMemory() {
1439af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1440af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
1441af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1442af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1443af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1444af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return memory_;
14453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14463261e8b6eac44a41341f112821482bee6c940c98mmentovai
14473261e8b6eac44a41341f112821482bee6c940c98mmentovai
14483261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpThread::GetContext() {
1449af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1450af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
14513261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1452af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
14533261e8b6eac44a41341f112821482bee6c940c98mmentovai
14543261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
1455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(thread_.thread_context.rva)) {
1456af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot seek to context";
14573261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1458af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
14593261e8b6eac44a41341f112821482bee6c940c98mmentovai
14602466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
14613261e8b6eac44a41341f112821482bee6c940c98mmentovai
1462af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(thread_.thread_context.data_size)) {
1463af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot read context";
14643261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1465af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
14663261e8b6eac44a41341f112821482bee6c940c98mmentovai
14673261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
14683261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14693261e8b6eac44a41341f112821482bee6c940c98mmentovai
14703261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
14713261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14723261e8b6eac44a41341f112821482bee6c940c98mmentovai
14733261e8b6eac44a41341f112821482bee6c940c98mmentovai
14746162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThread::GetThreadID(uint32_t *thread_id) const {
1475af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
1476af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
1477af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
1478af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
1479af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1480af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1481af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
148276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
1483af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
148476f052f8fbf8864dee5992b857229d06560a766ammentovai
148576f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = thread_.thread_id;
148676f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
14873261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14883261e8b6eac44a41341f112821482bee6c940c98mmentovai
14893261e8b6eac44a41341f112821482bee6c940c98mmentovai
14903261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThread::Print() {
1491af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1492af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
14933261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1494af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
14953261e8b6eac44a41341f112821482bee6c940c98mmentovai
14963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawThread\n");
14973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
14983261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suspend_count               = %d\n",     thread_.suspend_count);
14993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority_class              = 0x%x\n",   thread_.priority_class);
15003261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority                    = 0x%x\n",   thread_.priority);
1501c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
1502c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
15033261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.start_of_memory_range);
15043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.data_size      = 0x%x\n",
15053261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.memory.data_size);
15063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
15073261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size    = 0x%x\n",
15083261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.data_size);
15093261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva          = 0x%x\n",
15103261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.rva);
15113261e8b6eac44a41341f112821482bee6c940c98mmentovai
15123261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
15133261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
15143261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
15153261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
15163261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
15173261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
15183261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
15193261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
15203261e8b6eac44a41341f112821482bee6c940c98mmentovai
15213261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryRegion* memory = GetMemory();
15223261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
15233261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("Stack\n");
15243261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory->Print();
15253261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
15263261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No stack\n");
15273261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
15283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
15293261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15303261e8b6eac44a41341f112821482bee6c940c98mmentovai
15313261e8b6eac44a41341f112821482bee6c940c98mmentovai
15323261e8b6eac44a41341f112821482bee6c940c98mmentovai//
15333261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThreadList
15343261e8b6eac44a41341f112821482bee6c940c98mmentovai//
15353261e8b6eac44a41341f112821482bee6c940c98mmentovai
15363261e8b6eac44a41341f112821482bee6c940c98mmentovai
15376162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpThreadList::max_threads_ = 4096;
1538e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1539e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
15403261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::MinidumpThreadList(Minidump* minidump)
154153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
154253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      id_to_thread_map_(),
154353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      threads_(NULL),
154453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_count_(0) {
15453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15463261e8b6eac44a41341f112821482bee6c940c98mmentovai
15473261e8b6eac44a41341f112821482bee6c940c98mmentovai
15483261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::~MinidumpThreadList() {
15493261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
15503261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15513261e8b6eac44a41341f112821482bee6c940c98mmentovai
15523261e8b6eac44a41341f112821482bee6c940c98mmentovai
15536162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThreadList::Read(uint32_t expected_size) {
15543261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
15553261e8b6eac44a41341f112821482bee6c940c98mmentovai  id_to_thread_map_.clear();
15563261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
15573261e8b6eac44a41341f112821482bee6c940c98mmentovai  threads_ = NULL;
15583261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = 0;
15593261e8b6eac44a41341f112821482bee6c940c98mmentovai
15603261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
15613261e8b6eac44a41341f112821482bee6c940c98mmentovai
15626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t thread_count;
1563af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(thread_count)) {
1564af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
1565af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(thread_count);
15663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1567af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1568af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
1569af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
15703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
15723261e8b6eac44a41341f112821482bee6c940c98mmentovai
15733261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
15743261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_count);
15753261e8b6eac44a41341f112821482bee6c940c98mmentovai
15766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) {
1577fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
1578fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
1579fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
1580fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
1581fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
15823261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(thread_count) +
15833261e8b6eac44a41341f112821482bee6c940c98mmentovai                       thread_count * sizeof(MDRawThread)) {
1584ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
1585ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(thread_count) + 4 +
1586ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         thread_count * sizeof(MDRawThread)) {
15876162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
1588ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
1589f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded "
1590f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
1591ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
1592ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1593ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
1594ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
1595ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    " != " << sizeof(thread_count) +
1596ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    thread_count * sizeof(MDRawThread);
1597ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
1598ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
15993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1601bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com
1602e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count > max_threads_) {
1603e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
1604e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_threads_;
1605e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
1606e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
1607e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1608e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count != 0) {
1609373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpThreads> threads(
1610373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
16113261e8b6eac44a41341f112821482bee6c940c98mmentovai
1612373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int thread_index = 0;
1613373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         thread_index < thread_count;
1614373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++thread_index) {
1615373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpThread* thread = &(*threads)[thread_index];
16163261e8b6eac44a41341f112821482bee6c940c98mmentovai
1617373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
1618af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->Read()) {
1619af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
1620af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1621373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1622af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
16233261e8b6eac44a41341f112821482bee6c940c98mmentovai
16246162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t thread_id;
1625af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->GetThreadID(&thread_id)) {
1626af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
1627af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1628373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
163076f052f8fbf8864dee5992b857229d06560a766ammentovai
1631373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (GetThreadByID(thread_id)) {
1632373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        // Another thread with this ID is already in the list.  Data error.
1633af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
1634af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(thread_id) << " at thread " <<
1635af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1636373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1637373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
1638373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      id_to_thread_map_[thread_id] = thread;
16393261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
1640373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1641373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    threads_ = threads.release();
16423261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16433261e8b6eac44a41341f112821482bee6c940c98mmentovai
16443261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = thread_count;
16453261e8b6eac44a41341f112821482bee6c940c98mmentovai
16463261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
16473261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
16483261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16493261e8b6eac44a41341f112821482bee6c940c98mmentovai
16503261e8b6eac44a41341f112821482bee6c940c98mmentovai
16513261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
16523261e8b6eac44a41341f112821482bee6c940c98mmentovai    const {
1653af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1654af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
1655af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1656af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1657af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1658af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= thread_count_) {
1659af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
1660af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << thread_count_;
16613261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1662af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16633261e8b6eac44a41341f112821482bee6c940c98mmentovai
16643261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*threads_)[index];
16653261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16663261e8b6eac44a41341f112821482bee6c940c98mmentovai
16673261e8b6eac44a41341f112821482bee6c940c98mmentovai
16686162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comMinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) {
16693261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't check valid_.  Read calls this method before everything is
16703261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validated.  It is safe to not check valid_ here.
16713261e8b6eac44a41341f112821482bee6c940c98mmentovai  return id_to_thread_map_[thread_id];
16723261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16733261e8b6eac44a41341f112821482bee6c940c98mmentovai
16743261e8b6eac44a41341f112821482bee6c940c98mmentovai
16753261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThreadList::Print() {
1676af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1677af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
16783261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1679af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16803261e8b6eac44a41341f112821482bee6c940c98mmentovai
16813261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpThreadList\n");
16823261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_count = %d\n", thread_count_);
16833261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
16843261e8b6eac44a41341f112821482bee6c940c98mmentovai
16853261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int thread_index = 0;
16863261e8b6eac44a41341f112821482bee6c940c98mmentovai       thread_index < thread_count_;
16873261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++thread_index) {
16883261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("thread[%d]\n", thread_index);
16893261e8b6eac44a41341f112821482bee6c940c98mmentovai
16903261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*threads_)[thread_index].Print();
16913261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16933261e8b6eac44a41341f112821482bee6c940c98mmentovai
16943261e8b6eac44a41341f112821482bee6c940c98mmentovai
16953261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16963261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModule
16973261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16983261e8b6eac44a41341f112821482bee6c940c98mmentovai
16993261e8b6eac44a41341f112821482bee6c940c98mmentovai
17006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_cv_bytes_ = 32768;
17016162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_misc_bytes_ = 32768;
1702e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1703e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
17043261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::MinidumpModule(Minidump* minidump)
170553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
1706db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_valid_(false),
170711e180cd3e855796aee4239aa4b22dbda5de9c00mmentovai      has_debug_info_(false),
170853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_(),
170953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      name_(NULL),
171053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      cv_record_(NULL),
171148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
1712db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      misc_record_(NULL) {
17133261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17143261e8b6eac44a41341f112821482bee6c940c98mmentovai
17153261e8b6eac44a41341f112821482bee6c940c98mmentovai
17163261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::~MinidumpModule() {
17173261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
17183261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
17193261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
17203261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17213261e8b6eac44a41341f112821482bee6c940c98mmentovai
17223261e8b6eac44a41341f112821482bee6c940c98mmentovai
17233261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModule::Read() {
17243261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
17253261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
17263261e8b6eac44a41341f112821482bee6c940c98mmentovai  name_ = NULL;
17273261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
17283261e8b6eac44a41341f112821482bee6c940c98mmentovai  cv_record_ = NULL;
172948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
17303261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
17313261e8b6eac44a41341f112821482bee6c940c98mmentovai  misc_record_ = NULL;
17323261e8b6eac44a41341f112821482bee6c940c98mmentovai
1733db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = false;
1734d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = false;
17353261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
17363261e8b6eac44a41341f112821482bee6c940c98mmentovai
1737af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
1738af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot read module";
17393261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1740af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17413261e8b6eac44a41341f112821482bee6c940c98mmentovai
17423261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
17433261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.base_of_image);
17443261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.size_of_image);
17453261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.checksum);
17463261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.time_date_stamp);
17473261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.module_name_rva);
17483261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.signature);
17493261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.struct_version);
17503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_hi);
17513261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_lo);
17523261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_hi);
17533261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_lo);
17543261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags_mask);
17553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags);
17563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_os);
17573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_type);
17583261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_subtype);
17593261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_hi);
17603261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_lo);
17613261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.cv_record);
17623261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.misc_record);
17633261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't swap reserved fields because their contents are unknown (as
17643261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are their proper widths).
17653261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17663261e8b6eac44a41341f112821482bee6c940c98mmentovai
1767fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
1768fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_.size_of_image == 0 ||
1769fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      module_.size_of_image >
17706162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint64_t>::max() - module_.base_of_image) {
1771af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
1772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(module_.base_of_image) << "+" <<
1773fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(module_.size_of_image);
17743261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1775af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17763261e8b6eac44a41341f112821482bee6c940c98mmentovai
1777db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = true;
1778db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return true;
1779db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1780db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1781db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1782db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaibool MinidumpModule::ReadAuxiliaryData() {
1783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
1784af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
1785db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1786af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1787db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1788db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Each module must have a name.
1789db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  name_ = minidump_->ReadString(module_.module_name_rva);
1790af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!name_) {
1791af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule could not read name";
1792db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1793af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1794db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1795d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  // At this point, we have enough info for the module to be valid.
1796d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  valid_ = true;
1797d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1798db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // CodeView and miscellaneous debug records are only required if the
1799db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // module indicates that they exist.
1800af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
1801af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
1802af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1803db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1804af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1805db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1806af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
1807af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
1808af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1809db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1810af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1811db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1812d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = true;
18133261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
18143261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18153261e8b6eac44a41341f112821482bee6c940c98mmentovai
18163261e8b6eac44a41341f112821482bee6c940c98mmentovai
1817db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_file() const {
1818af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1819af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
1820db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1821af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1822db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1823db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return *name_;
1824db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
18253261e8b6eac44a41341f112821482bee6c940c98mmentovai
18263261e8b6eac44a41341f112821482bee6c940c98mmentovai
1827db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_identifier() const {
1828af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
1830db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1831af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1832db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1833d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1834d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1835d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1836db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
1837af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_system_info) {
1838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires "
1839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "MinidumpSystemInfo";
1840db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1841af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1842db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1843db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
1844af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1845af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
1846db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1847af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1848db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1849db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1850db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1851db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  switch (raw_system_info->platform_id) {
1852db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_NT:
1853db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_WINDOWS: {
1854c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1855c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1856db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
1857c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
1858db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               module_.time_date_stamp, module_.size_of_image);
1859db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
1860db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1861db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1862db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
18630e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_MAC_OS_X:
186463f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
1865ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
18665187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
1867f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    case MD_OS_LINUX:
1868a29f376a8bb9122f29ea1c53c02a188683fd5a72bradnelson@chromium.org    case MD_OS_NACL:
1869d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3: {
1870db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // TODO(mmentovai): support uuid extension if present, otherwise fall
1871db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // back to version (from LC_ID_DYLIB?), otherwise fall back to something
1872db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // else.
1873db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = "id";
1874db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1875db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1876db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1877db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    default: {
1878db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // Without knowing what OS generated the dump, we can't generate a good
1879db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // identifier.  Return an empty string, signalling failure.
1880af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
1881af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "found " << HexString(raw_system_info->platform_id);
1882db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1883db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1884db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1885db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1886db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
18873261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18883261e8b6eac44a41341f112821482bee6c940c98mmentovai
18893261e8b6eac44a41341f112821482bee6c940c98mmentovai
1890db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_file() const {
1891af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1892af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
1893db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1894af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1895db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1896d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1897d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1898d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1899db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string file;
1900db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Prefer the CodeView record if present.
190128e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
190248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
190348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
190448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
190548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
190648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
190748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1908db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1909db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
191048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
191148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
1912db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
1913db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
191448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1915db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1916db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1917db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
1918db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1919db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1920db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // If there's a CodeView record but it doesn't match a known signature,
192148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // try the miscellaneous record.
1922db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1923db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1924db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (file.empty()) {
1925db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // No usable CodeView record.  Try the miscellaneous debug record.
192628e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai    if (misc_record_) {
192728e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai      const MDImageDebugMisc* misc_record =
192828e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai          reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
1929db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      if (!misc_record->unicode) {
1930db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // If it's not Unicode, just stuff it into the string.  It's unclear
1931db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // if misc_record->data is 0-terminated, so use an explicit size.
1932db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        file = string(
1933db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            reinterpret_cast<const char*>(misc_record->data),
19342e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize);
1935db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      } else {
1936db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // There's a misc_record but it encodes the debug filename in UTF-16.
1937db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // (Actually, because miscellaneous records are so old, it's probably
1938db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
1939db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // that this method (and all other methods in the Minidump family)
1940db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // return.
1941db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1942db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        unsigned int bytes =
19432e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize;
1944db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        if (bytes % 2 == 0) {
1945db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          unsigned int utf16_words = bytes / 2;
1946db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
19476162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one
1948db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // and copy the UTF-16 data into it.
19496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          vector<uint16_t> string_utf16(utf16_words);
1950db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          if (utf16_words)
1951db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            memcpy(&string_utf16[0], &misc_record->data, bytes);
1952db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1953db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // GetMiscRecord already byte-swapped the data[] field if it contains
1954db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF-16, so pass false as the swap argument.
1955db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
1956db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          file = *new_file;
1957db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        }
1958db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      }
1959db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1960db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1961db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1962bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
1963bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
1964bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                  "debug_file for " << *name_;
1965af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1966db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return file;
1967db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1968db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1969db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1970db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_identifier() const {
1971af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1972af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
1973db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1974af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1975db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1976d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1977d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1978d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1979db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1980db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1981db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Use the CodeView record if present.
198228e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
198348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
198448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
198548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
198648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
198748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
198848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1989c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1990c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1991db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[41];
1992db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
1993c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
1994db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data1,
1995db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data2,
1996db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data3,
1997db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[0],
1998db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[1],
1999db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[2],
2000db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[3],
2001db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[4],
2002db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[5],
2003db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[6],
2004db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[7],
2005db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->age);
2006db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
200748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
200848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
2009db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
2010db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
201148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2012db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2013c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2014c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2015db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
2016db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
2017c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%x", cv_record_20->signature, cv_record_20->age);
2018db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
2019db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2020db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2021db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
202248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  // TODO(mmentovai): if there's no usable CodeView record, there might be a
2023db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // miscellaneous debug record.  It only carries a filename, though, and no
2024db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // identifier.  I'm not sure what the right thing to do for the identifier
2025db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // is in that case, but I don't expect to find many modules without a
2026e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  // CodeView record (or some other Breakpad extension structure in place of
2027db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a CodeView record).  Treat it as an error (empty identifier) for now.
2028db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2029db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
2030db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2031bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
2032bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
2033bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                        "debug_identifier for " << *name_;
2034af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2035db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
2036db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2037db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2038db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2039db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::version() const {
2040af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2041af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for version";
2042db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2043af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2044db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2045db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string version;
2046db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2047db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
2048db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
2049db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    char version_string[24];
2050db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
2051db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi >> 16,
2052db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi & 0xffff,
2053db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo >> 16,
2054db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo & 0xffff);
2055db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    version = version_string;
2056db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2057db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2058db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): possibly support other struct types in place of
2059db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
2060db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a different structure that better represents versioning facilities on
2061db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Mac OS X and Linux, instead of forcing them to adhere to the dotted
2062db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // quad of 16-bit ints that Windows uses.
2063db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2064af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
2065af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "version for " << *name_;
2066af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2067db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return version;
2068db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2069db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2070db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2071db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModule* MinidumpModule::Copy() const {
2072db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModule(this);
2073db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2074db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2075db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
20766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
2077af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2078af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
20793261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2080af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20813261e8b6eac44a41341f112821482bee6c940c98mmentovai
20823261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!cv_record_) {
208348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // This just guards against 0-sized CodeView records; more specific checks
208448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // are used when the signature is checked against various structure types.
2085af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.cv_record.data_size == 0) {
20863261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2087af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
20883261e8b6eac44a41341f112821482bee6c940c98mmentovai
2089af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.cv_record.rva)) {
2090af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
20913261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
20933261e8b6eac44a41341f112821482bee6c940c98mmentovai
2094e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.cv_record.data_size > max_cv_bytes_) {
2095e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
2096e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.cv_record.data_size << " exceeds maximum " <<
2097e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_cv_bytes_;
2098e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2099e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
21003261e8b6eac44a41341f112821482bee6c940c98mmentovai
21013261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDCVInfoPDB70 or
21026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment
21033261e8b6eac44a41341f112821482bee6c940c98mmentovai    // problems.  x86 and ppc are able to cope, though.  This allocation
21043261e8b6eac44a41341f112821482bee6c940c98mmentovai    // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
21053261e8b6eac44a41341f112821482bee6c940c98mmentovai    // variable-sized due to their pdb_file_name fields; these structures
21062e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
21073261e8b6eac44a41341f112821482bee6c940c98mmentovai    // them as such would result in incomplete structures or overruns.
21086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > cv_record(
21096162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.cv_record.data_size));
21103261e8b6eac44a41341f112821482bee6c940c98mmentovai
2111af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
2112af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
21133261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2114af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
21153261e8b6eac44a41341f112821482bee6c940c98mmentovai
21166162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
211748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (module_.cv_record.data_size > sizeof(signature)) {
211848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      MDCVInfoPDB70* cv_record_signature =
211948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
212048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      signature = cv_record_signature->cv_signature;
212148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      if (minidump_->swap())
212248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        Swap(&signature);
212348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    }
21243261e8b6eac44a41341f112821482bee6c940c98mmentovai
21253261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature == MD_CVINFOPDB70_SIGNATURE) {
21263261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Now that the structure type is known, recheck the size.
21272e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
2128af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
21292e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB70_minsize << " > " <<
2130af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
21313261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2132af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21333261e8b6eac44a41341f112821482bee6c940c98mmentovai
21343261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
213548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        MDCVInfoPDB70* cv_record_70 =
213648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
21373261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->cv_signature);
21383261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->signature);
21393261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->age);
21403261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
214148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        // quantities.  (It's a path, is it UTF-8?)
21423261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
214348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
214448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
214548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2146af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2147af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
2148af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
214948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2150af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21513261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
215248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // Now that the structure type is known, recheck the size.
21532e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
2154af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
21552e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB20_minsize << " > " <<
2156af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
215748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2158af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21593261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
21603261e8b6eac44a41341f112821482bee6c940c98mmentovai        MDCVInfoPDB20* cv_record_20 =
216148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
21623261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.signature);
21633261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.offset);
21643261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->signature);
21653261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->age);
21663261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
21673261e8b6eac44a41341f112821482bee6c940c98mmentovai        // quantities.  (It's a path, is it UTF-8?)
21683261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
216948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
217048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
217148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2172af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2173af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
2174af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
217548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21773261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
21783261e8b6eac44a41341f112821482bee6c940c98mmentovai
217948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // If the signature doesn't match something above, it's not something
2180e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    // that Breakpad can presently handle directly.  Because some modules in
218148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
218248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // don't bail out here - allow the data to be returned to the user,
218348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // although byte-swapping can't be done.
21843261e8b6eac44a41341f112821482bee6c940c98mmentovai
21853261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
21866162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // return it casted to uint8_t*.
21873261e8b6eac44a41341f112821482bee6c940c98mmentovai    cv_record_ = cv_record.release();
218848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    cv_record_signature_ = signature;
21893261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21903261e8b6eac44a41341f112821482bee6c940c98mmentovai
219148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
219248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.cv_record.data_size;
219348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
21943261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*cv_record_)[0];
21953261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21963261e8b6eac44a41341f112821482bee6c940c98mmentovai
21973261e8b6eac44a41341f112821482bee6c940c98mmentovai
21986162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) {
2199af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2200af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
22013261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2202af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22033261e8b6eac44a41341f112821482bee6c940c98mmentovai
22043261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!misc_record_) {
2205af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size == 0) {
22063261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2207af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
22083261e8b6eac44a41341f112821482bee6c940c98mmentovai
22092e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
2210af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
22112e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                      "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
2212af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      module_.misc_record.data_size;
22133261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
2215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2216af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.misc_record.rva)) {
2217af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
2218af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "debugging record";
2219af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      return NULL;
2220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
22213261e8b6eac44a41341f112821482bee6c940c98mmentovai
2222e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.misc_record.data_size > max_misc_bytes_) {
2223e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
2224e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.misc_record.data_size << " exceeds maximum " <<
2225e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_misc_bytes_;
2226e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2227e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
22283261e8b6eac44a41341f112821482bee6c940c98mmentovai
22293261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDImageDebugMisc but
22306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // is allocated as uint8_t[] can cause alignment problems.  x86 and
22313261e8b6eac44a41341f112821482bee6c940c98mmentovai    // ppc are able to cope, though.  This allocation style is needed
22323261e8b6eac44a41341f112821482bee6c940c98mmentovai    // because the MDImageDebugMisc is variable-sized due to its data field;
22332e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // this structure is not MDImageDebugMisc_minsize and treating it as such
22343261e8b6eac44a41341f112821482bee6c940c98mmentovai    // would result in an incomplete structure or an overrun.
22356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > misc_record_mem(
22366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.misc_record.data_size));
22373261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDImageDebugMisc* misc_record =
22383261e8b6eac44a41341f112821482bee6c940c98mmentovai        reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
22393261e8b6eac44a41341f112821482bee6c940c98mmentovai
2240af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
2241af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
2242af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "record";
22433261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2244af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
22453261e8b6eac44a41341f112821482bee6c940c98mmentovai
22463261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (minidump_->swap()) {
22473261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->data_type);
22483261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->length);
22493261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap misc_record.unicode because it's an 8-bit quantity.
22503261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap the reserved fields for the same reason, and because
22513261e8b6eac44a41341f112821482bee6c940c98mmentovai      // they don't contain any valid data.
22523261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (misc_record->unicode) {
22533261e8b6eac44a41341f112821482bee6c940c98mmentovai        // There is a potential alignment problem, but shouldn't be a problem
22543261e8b6eac44a41341f112821482bee6c940c98mmentovai        // in practice due to the layout of MDImageDebugMisc.
22556162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data));
22563261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataBytes = module_.misc_record.data_size -
22572e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                                 MDImageDebugMisc_minsize;
22583562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com        Swap(data16, dataBytes);
22593261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
22603261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
22613261e8b6eac44a41341f112821482bee6c940c98mmentovai
2262af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size != misc_record->length) {
2263af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
2264af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << module_.misc_record.data_size <<
2265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      " != " << misc_record->length;
22663261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
22683261e8b6eac44a41341f112821482bee6c940c98mmentovai
22693261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
22703261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to MDImageDebugMisc*.
22713261e8b6eac44a41341f112821482bee6c940c98mmentovai    misc_record_ = misc_record_mem.release();
22723261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
22733261e8b6eac44a41341f112821482bee6c940c98mmentovai
227448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
227548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.misc_record.data_size;
227648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
22773261e8b6eac44a41341f112821482bee6c940c98mmentovai  return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
22783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22793261e8b6eac44a41341f112821482bee6c940c98mmentovai
22803261e8b6eac44a41341f112821482bee6c940c98mmentovai
22813261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModule::Print() {
2282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2283af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
22843261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2285af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22863261e8b6eac44a41341f112821482bee6c940c98mmentovai
22873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawModule\n");
2288c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  base_of_image                   = 0x%" PRIx64 "\n",
22893261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.base_of_image);
22903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_image                   = 0x%x\n",
22913261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.size_of_image);
22923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum                        = 0x%x\n",
22933261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.checksum);
22949c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  printf("  time_date_stamp                 = 0x%x %s\n",
22959c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org         module_.time_date_stamp,
22969c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org         TimeTToUTCString(module_.time_date_stamp).c_str());
22973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_name_rva                 = 0x%x\n",
22983261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.module_name_rva);
22993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.signature          = 0x%x\n",
23003261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.signature);
23013261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.struct_version     = 0x%x\n",
23023261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.struct_version);
23033261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_version       = 0x%x:0x%x\n",
23043261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_hi,
23053261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_lo);
23063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.product_version    = 0x%x:0x%x\n",
23073261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_hi,
23083261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_lo);
23093261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags_mask    = 0x%x\n",
23103261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags_mask);
23113261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags         = 0x%x\n",
23123261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags);
23133261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_os            = 0x%x\n",
23143261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_os);
23153261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_type          = 0x%x\n",
23163261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_type);
23173261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_subtype       = 0x%x\n",
23183261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_subtype);
23193261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_date          = 0x%x:0x%x\n",
23203261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_hi,
23213261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_lo);
23223261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.data_size             = %d\n",
23233261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.data_size);
23243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.rva                   = 0x%x\n",
23253261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.rva);
23263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.data_size           = %d\n",
23273261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.data_size);
23283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.rva                 = 0x%x\n",
23293261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.rva);
23303261e8b6eac44a41341f112821482bee6c940c98mmentovai
2331db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
2332db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_identifier)               = \"%s\"\n",
2333db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         code_identifier().c_str());
23343261e8b6eac44a41341f112821482bee6c940c98mmentovai
23356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t cv_record_size;
23366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t *cv_record = GetCVRecord(&cv_record_size);
23373261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (cv_record) {
233848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
233948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
234048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
234148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
234248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
23433261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_signature        = 0x%x\n",
234448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->cv_signature);
23453261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
234648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data1,
234748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data2,
234848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data3,
234948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[0],
235048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[1]);
23513261e8b6eac44a41341f112821482bee6c940c98mmentovai      for (unsigned int guidIndex = 2;
23523261e8b6eac44a41341f112821482bee6c940c98mmentovai           guidIndex < 8;
23533261e8b6eac44a41341f112821482bee6c940c98mmentovai           ++guidIndex) {
235448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record_70->signature.data4[guidIndex]);
23553261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
23563261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("\n");
23573261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
235848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->age);
23593261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
236048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->pdb_file_name);
236148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
23623261e8b6eac44a41341f112821482bee6c940c98mmentovai      const MDCVInfoPDB20* cv_record_20 =
236348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
236448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
236548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
23663261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.signature = 0x%x\n",
23673261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.signature);
23683261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.offset    = 0x%x\n",
23693261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.offset);
23709c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      printf("  (cv_record).signature           = 0x%x %s\n",
23719c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org             cv_record_20->signature,
23729c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org             TimeTToUTCString(cv_record_20->signature).c_str());
23733261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
23743261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->age);
23753261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
23763261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->pdb_file_name);
237748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else {
237848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("  (cv_record)                     = ");
237948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      for (unsigned int cv_byte_index = 0;
238048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           cv_byte_index < cv_record_size;
238148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           ++cv_byte_index) {
238248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record[cv_byte_index]);
238348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      }
238448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("\n");
23853261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
23863261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
23873261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (cv_record)                     = (null)\n");
23883261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23893261e8b6eac44a41341f112821482bee6c940c98mmentovai
239048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
23913261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_record) {
23923261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).data_type         = 0x%x\n",
23933261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->data_type);
23943261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).length            = 0x%x\n",
23953261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->length);
23963261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).unicode           = %d\n",
23973261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->unicode);
23989c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    if (misc_record->unicode) {
23999c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      string misc_record_data_utf8;
24009c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      ConvertUTF16BufferToUTF8String(
24019c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org          reinterpret_cast<const uint16_t*>(misc_record->data),
24029c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org          misc_record->length - offsetof(MDImageDebugMisc, data),
24039c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org          &misc_record_data_utf8,
24049c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org          false);  // already swapped
24059c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      printf("  (misc_record).data              = \"%s\"\n",
24069c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org             misc_record_data_utf8.c_str());
24079c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    } else {
24083261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = \"%s\"\n",
24093261e8b6eac44a41341f112821482bee6c940c98mmentovai             misc_record->data);
24109c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    }
24113261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
24123261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record)                   = (null)\n");
24133261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
24143261e8b6eac44a41341f112821482bee6c940c98mmentovai
2415db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
2416db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_identifier)              = \"%s\"\n",
2417db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         debug_identifier().c_str());
2418db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (version)                       = \"%s\"\n", version().c_str());
24193261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
24203261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24213261e8b6eac44a41341f112821482bee6c940c98mmentovai
24223261e8b6eac44a41341f112821482bee6c940c98mmentovai
24233261e8b6eac44a41341f112821482bee6c940c98mmentovai//
24243261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModuleList
24253261e8b6eac44a41341f112821482bee6c940c98mmentovai//
24263261e8b6eac44a41341f112821482bee6c940c98mmentovai
24273261e8b6eac44a41341f112821482bee6c940c98mmentovai
24286162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModuleList::max_modules_ = 1024;
2429e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2430e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
24313261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::MinidumpModuleList(Minidump* minidump)
243253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
24336162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
243453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      modules_(NULL),
243553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_count_(0) {
24363261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24373261e8b6eac44a41341f112821482bee6c940c98mmentovai
24383261e8b6eac44a41341f112821482bee6c940c98mmentovai
24393261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::~MinidumpModuleList() {
2440fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
24413261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
24423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24433261e8b6eac44a41341f112821482bee6c940c98mmentovai
24443261e8b6eac44a41341f112821482bee6c940c98mmentovai
24456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpModuleList::Read(uint32_t expected_size) {
24463261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
2447fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
24483261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
24493261e8b6eac44a41341f112821482bee6c940c98mmentovai  modules_ = NULL;
24503261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = 0;
24513261e8b6eac44a41341f112821482bee6c940c98mmentovai
24523261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
24533261e8b6eac44a41341f112821482bee6c940c98mmentovai
24546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t module_count;
2455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(module_count)) {
2456af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
2457af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(module_count);
24583261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2459af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2460af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
2461af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList could not read module count";
24623261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2463af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
24643261e8b6eac44a41341f112821482bee6c940c98mmentovai
24653261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
24663261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_count);
24673261e8b6eac44a41341f112821482bee6c940c98mmentovai
24686162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) {
2469fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
2470fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2471fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2472fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2473fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
24743261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(module_count) +
24753261e8b6eac44a41341f112821482bee6c940c98mmentovai                       module_count * MD_MODULE_SIZE) {
2476ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2477ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(module_count) + 4 +
2478ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         module_count * MD_MODULE_SIZE) {
24796162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
2480ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2481f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded "
2482f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
2483ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2484ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2485ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2486ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
2487ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      " != " << sizeof(module_count) +
2488ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      module_count * MD_MODULE_SIZE;
2489ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2490ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
24913261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
24923261e8b6eac44a41341f112821482bee6c940c98mmentovai
2493e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count > max_modules_) {
2494e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
2495e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_modules_;
2496e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2497e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2498e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2499e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count != 0) {
2500373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpModules> modules(
2501373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpModules(module_count, MinidumpModule(minidump_)));
25023261e8b6eac44a41341f112821482bee6c940c98mmentovai
2503373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int module_index = 0;
2504373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         module_index < module_count;
2505373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++module_index) {
2506373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpModule* module = &(*modules)[module_index];
25073261e8b6eac44a41341f112821482bee6c940c98mmentovai
2508373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
2509af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->Read()) {
2510af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
2511af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
2512373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2513af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2514db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2515db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2516db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // Loop through the module list once more to read additional data and
2517db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // build the range map.  This is done in a second pass because
2518db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
2519db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // included in the loop above, additional seeks would be needed where
2520db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // none are now to read contiguous data.
2521db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    for (unsigned int module_index = 0;
2522db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         module_index < module_count;
2523db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         ++module_index) {
2524db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      MinidumpModule* module = &(*modules)[module_index];
2525db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
252661ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // ReadAuxiliaryData fails if any data that the module indicates should
252761ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // exist is missing, but we treat some such cases as valid anyway.  See
252861ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // issue #222: if a debugging record is of a format that's too large to
252961ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // handle, it shouldn't render the entire dump invalid.  Check module
253061ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // validity before giving up.
253161ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      if (!module->ReadAuxiliaryData() && !module->valid()) {
253261ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read required module "
253361ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        "auxiliary data for module " <<
253461ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        module_index << "/" << module_count;
253561ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        return false;
2536af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2537af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2538af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // It is safe to use module->code_file() after successfully calling
253961ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // module->ReadAuxiliaryData or noting that the module is valid.
25403261e8b6eac44a41341f112821482bee6c940c98mmentovai
25416162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = module->base_address();
25426162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t module_size = module->size();
25436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      if (base_address == static_cast<uint64_t>(-1)) {
2544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList found bad base address "
2545af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "for module " << module_index << "/" << module_count <<
2546af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << module->code_file();
2547373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2548af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
25493261e8b6eac44a41341f112821482bee6c940c98mmentovai
2550af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, module_size, module_index)) {
2551746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        // Android's shared memory implementation /dev/ashmem can contain
2552746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        // duplicate entries for JITted code, so ignore these.
2553746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        // TODO(wfh): Remove this code when Android is fixed.
2554746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        // See https://crbug.com/439531
2555746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        const string kDevAshmem("/dev/ashmem/");
2556746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        if (module->code_file().compare(
2557746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org            0, kDevAshmem.length(), kDevAshmem) != 0) {
2558746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org          BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
2559746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          module_index << "/" << module_count << ", " <<
2560746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          module->code_file() << ", " <<
2561746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          HexString(base_address) << "+" <<
2562746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          HexString(module_size);
2563746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org          return false;
2564746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        } else {
2565746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org          BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module " <<
2566746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          module_index << "/" << module_count << ", " <<
2567746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          module->code_file() << ", " <<
2568746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          HexString(base_address) << "+" <<
2569746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org                          HexString(module_size);
2570746f65a45e1cf52110ed677da19f87fa2eb6aefawfh@chromium.org        }
2571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2572373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
2573373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2574373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    modules_ = modules.release();
25753261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
25763261e8b6eac44a41341f112821482bee6c940c98mmentovai
25773261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = module_count;
25783261e8b6eac44a41341f112821482bee6c940c98mmentovai
25793261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
25803261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
25813261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25823261e8b6eac44a41341f112821482bee6c940c98mmentovai
25833261e8b6eac44a41341f112821482bee6c940c98mmentovai
2584db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleForAddress(
25856162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
2586af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2587af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
25883261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2589af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25903261e8b6eac44a41341f112821482bee6c940c98mmentovai
2591db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  unsigned int module_index;
2592af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
2593af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpModuleList has no module at " <<
2594af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
2595db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2596af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2597db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2598db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtIndex(module_index);
25993261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26003261e8b6eac44a41341f112821482bee6c940c98mmentovai
26013261e8b6eac44a41341f112821482bee6c940c98mmentovai
2602db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetMainModule() const {
2603af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2604af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
26053261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2606af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26073261e8b6eac44a41341f112821482bee6c940c98mmentovai
2608db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // The main code module is the first one present in a minidump file's
2609db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // MDRawModuleList.
2610327783c42fcc2062bfe6c118c54c431ac6b5ffcfmkrebs@chromium.org  return GetModuleAtIndex(0);
2611db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2612db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2613db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2614db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
2615db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int sequence) const {
2616af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2617af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
2618af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2619af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2620af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2621af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sequence >= module_count_) {
2622af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
2623af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sequence << "/" << module_count_;
2624db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2625af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2626db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
26273261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int module_index;
2628af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
2629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
26303261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2631af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26323261e8b6eac44a41341f112821482bee6c940c98mmentovai
26333261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetModuleAtIndex(module_index);
26343261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26353261e8b6eac44a41341f112821482bee6c940c98mmentovai
26363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2637db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
2638db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int index) const {
2639af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2640af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
2641af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2642af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2643af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2644af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= module_count_) {
2645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
2646af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << module_count_;
2647db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2648af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2649db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2650db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return &(*modules_)[index];
2651db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2652db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2653db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2654db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModules* MinidumpModuleList::Copy() const {
2655db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModules(this);
2656db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2657db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2658db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
26593261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModuleList::Print() {
2660af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2661af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
26623261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2663af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26643261e8b6eac44a41341f112821482bee6c940c98mmentovai
26653261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpModuleList\n");
26663261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_count = %d\n", module_count_);
26673261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
26683261e8b6eac44a41341f112821482bee6c940c98mmentovai
26693261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int module_index = 0;
26703261e8b6eac44a41341f112821482bee6c940c98mmentovai       module_index < module_count_;
26713261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++module_index) {
26723261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("module[%d]\n", module_index);
26733261e8b6eac44a41341f112821482bee6c940c98mmentovai
26743261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*modules_)[module_index].Print();
26753261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26763261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26773261e8b6eac44a41341f112821482bee6c940c98mmentovai
26783261e8b6eac44a41341f112821482bee6c940c98mmentovai
26793261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26803261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryList
26813261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26823261e8b6eac44a41341f112821482bee6c940c98mmentovai
26833261e8b6eac44a41341f112821482bee6c940c98mmentovai
26846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryList::max_regions_ = 4096;
2685e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2686e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
26873261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
268853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
26896162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
269053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptors_(NULL),
269153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      regions_(NULL),
269253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      region_count_(0) {
26933261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26943261e8b6eac44a41341f112821482bee6c940c98mmentovai
26953261e8b6eac44a41341f112821482bee6c940c98mmentovai
26963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::~MinidumpMemoryList() {
2697fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
26983261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
26993261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
27003261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27013261e8b6eac44a41341f112821482bee6c940c98mmentovai
27023261e8b6eac44a41341f112821482bee6c940c98mmentovai
27036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryList::Read(uint32_t expected_size) {
27043261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
27053261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
27063261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptors_ = NULL;
27073261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
27083261e8b6eac44a41341f112821482bee6c940c98mmentovai  regions_ = NULL;
2709fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
27103261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = 0;
27113261e8b6eac44a41341f112821482bee6c940c98mmentovai
27123261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
27133261e8b6eac44a41341f112821482bee6c940c98mmentovai
27146162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t region_count;
2715af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(region_count)) {
2716af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
2717af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(region_count);
27183261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2719af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2720af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
2721af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
27223261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27243261e8b6eac44a41341f112821482bee6c940c98mmentovai
27253261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
27263261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&region_count);
27273261e8b6eac44a41341f112821482bee6c940c98mmentovai
2728fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (region_count >
27296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) {
2730fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
2731fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2732fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2733fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2734fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
27353261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(region_count) +
27363261e8b6eac44a41341f112821482bee6c940c98mmentovai                       region_count * sizeof(MDMemoryDescriptor)) {
2737ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2738ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(region_count) + 4 +
2739ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         region_count * sizeof(MDMemoryDescriptor)) {
27406162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
2741ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2742f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded "
2743f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
2744ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2745ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2746ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2747ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
2748f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                      " != " << sizeof(region_count) +
2749ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      region_count * sizeof(MDMemoryDescriptor);
2750ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2751ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
27523261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
27533261e8b6eac44a41341f112821482bee6c940c98mmentovai
2754e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count > max_regions_) {
2755e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
2756e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_regions_;
2757e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2758e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2759e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2760e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count != 0) {
2761373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryDescriptors> descriptors(
2762373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryDescriptors(region_count));
27633261e8b6eac44a41341f112821482bee6c940c98mmentovai
2764373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
2765373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
2766373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!minidump_->ReadBytes(&(*descriptors)[0],
2767373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai                              sizeof(MDMemoryDescriptor) * region_count)) {
2768af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
2769373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
2770373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
27713261e8b6eac44a41341f112821482bee6c940c98mmentovai
2772373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryRegions> regions(
2773373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
27743261e8b6eac44a41341f112821482bee6c940c98mmentovai
2775373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int region_index = 0;
2776373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         region_index < region_count;
2777373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++region_index) {
2778373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
27793261e8b6eac44a41341f112821482bee6c940c98mmentovai
2780373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (minidump_->swap())
2781373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(descriptor);
27823261e8b6eac44a41341f112821482bee6c940c98mmentovai
27836162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = descriptor->start_of_memory_range;
27846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t region_size = descriptor->memory.data_size;
27853261e8b6eac44a41341f112821482bee6c940c98mmentovai
2786fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      // Check for base + size overflow or undersize.
2787fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      if (region_size == 0 ||
27886162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          region_size > numeric_limits<uint64_t>::max() - base_address) {
2789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
2790af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        " region " << region_index << "/" << region_count <<
2791af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << HexString(base_address) << "+" <<
2792fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                        HexString(region_size);
2793373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2794af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
27953261e8b6eac44a41341f112821482bee6c940c98mmentovai
2796af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, region_size, region_index)) {
2797af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
2798af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        region_index << "/" << region_count << ", " <<
2799af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
2800af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(region_size);
2801373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2802af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2803373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2804373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      (*regions)[region_index].SetDescriptor(descriptor);
2805373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
28063261e8b6eac44a41341f112821482bee6c940c98mmentovai
2807373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    descriptors_ = descriptors.release();
2808373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    regions_ = regions.release();
28093261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28103261e8b6eac44a41341f112821482bee6c940c98mmentovai
28113261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = region_count;
28123261e8b6eac44a41341f112821482bee6c940c98mmentovai
28133261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
28143261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
28153261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28163261e8b6eac44a41341f112821482bee6c940c98mmentovai
28173261e8b6eac44a41341f112821482bee6c940c98mmentovai
28183261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
28193261e8b6eac44a41341f112821482bee6c940c98mmentovai      unsigned int index) {
2820af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2821af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
2822af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2823af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2824af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2825af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= region_count_) {
2826af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
2827af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << region_count_;
28283261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28303261e8b6eac44a41341f112821482bee6c940c98mmentovai
28313261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*regions_)[index];
28323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28333261e8b6eac44a41341f112821482bee6c940c98mmentovai
28343261e8b6eac44a41341f112821482bee6c940c98mmentovai
28353261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
28366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) {
2837af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
28393261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28413261e8b6eac44a41341f112821482bee6c940c98mmentovai
28423261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int region_index;
2843af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
2844af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
2845af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
28463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2847af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28483261e8b6eac44a41341f112821482bee6c940c98mmentovai
28493261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryRegionAtIndex(region_index);
28503261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28513261e8b6eac44a41341f112821482bee6c940c98mmentovai
28523261e8b6eac44a41341f112821482bee6c940c98mmentovai
28533261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryList::Print() {
2854af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2855af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
28563261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2857af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28583261e8b6eac44a41341f112821482bee6c940c98mmentovai
28593261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpMemoryList\n");
28603261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  region_count = %d\n", region_count_);
28613261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
28623261e8b6eac44a41341f112821482bee6c940c98mmentovai
28633261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int region_index = 0;
28643261e8b6eac44a41341f112821482bee6c940c98mmentovai       region_index < region_count_;
28653261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++region_index) {
28663261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
28673261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("region[%d]\n", region_index);
28683261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDMemoryDescriptor\n");
2869c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  start_of_memory_range = 0x%" PRIx64 "\n",
28703261e8b6eac44a41341f112821482bee6c940c98mmentovai           descriptor->start_of_memory_range);
28713261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
28723261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
28733261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
28743261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (region) {
28753261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("Memory\n");
28763261e8b6eac44a41341f112821482bee6c940c98mmentovai      region->Print();
28773261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
28783261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("No memory\n");
28793261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
28803261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
28813261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28823261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28833261e8b6eac44a41341f112821482bee6c940c98mmentovai
28843261e8b6eac44a41341f112821482bee6c940c98mmentovai
28853261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28863261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpException
28873261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28883261e8b6eac44a41341f112821482bee6c940c98mmentovai
28893261e8b6eac44a41341f112821482bee6c940c98mmentovai
28903261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::MinidumpException(Minidump* minidump)
289153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
289253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      exception_(),
289353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
28943261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28953261e8b6eac44a41341f112821482bee6c940c98mmentovai
28963261e8b6eac44a41341f112821482bee6c940c98mmentovai
28973261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::~MinidumpException() {
28983261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
28993261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29003261e8b6eac44a41341f112821482bee6c940c98mmentovai
29013261e8b6eac44a41341f112821482bee6c940c98mmentovai
29026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::Read(uint32_t expected_size) {
29033261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
29043261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
29053261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
29063261e8b6eac44a41341f112821482bee6c940c98mmentovai
29073261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
29083261e8b6eac44a41341f112821482bee6c940c98mmentovai
2909af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(exception_)) {
2910af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
2911af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(exception_);
29123261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2913af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29143261e8b6eac44a41341f112821482bee6c940c98mmentovai
2915af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
2916af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot read exception";
29173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2918af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29193261e8b6eac44a41341f112821482bee6c940c98mmentovai
29203261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
29213261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_id);
29223261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.__align is for alignment only and does not need to be
29233261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapped.
29243261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_code);
29253261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_flags);
29263261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_record);
29273261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_address);
29283261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.number_parameters);
29293261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.exception_record.__align is for alignment only and does not
29303261e8b6eac44a41341f112821482bee6c940c98mmentovai    // need to be swapped.
29313261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int parameter_index = 0;
29323261e8b6eac44a41341f112821482bee6c940c98mmentovai         parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
29333261e8b6eac44a41341f112821482bee6c940c98mmentovai         ++parameter_index) {
29343261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&exception_.exception_record.exception_information[parameter_index]);
29353261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
29363261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_context);
29373261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29383261e8b6eac44a41341f112821482bee6c940c98mmentovai
29393261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
29403261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
29413261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29423261e8b6eac44a41341f112821482bee6c940c98mmentovai
29433261e8b6eac44a41341f112821482bee6c940c98mmentovai
29446162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::GetThreadID(uint32_t *thread_id) const {
2945af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
2946af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
2947af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
2948af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
2949af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2950af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2951af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
295276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
2953af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
295476f052f8fbf8864dee5992b857229d06560a766ammentovai
295576f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = exception_.thread_id;
295676f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
29573261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29583261e8b6eac44a41341f112821482bee6c940c98mmentovai
29593261e8b6eac44a41341f112821482bee6c940c98mmentovai
29603261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpException::GetContext() {
2961af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2962af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
29633261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2964af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29653261e8b6eac44a41341f112821482bee6c940c98mmentovai
29663261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
2967af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(exception_.thread_context.rva)) {
2968af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot seek to context";
29693261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2970af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
29713261e8b6eac44a41341f112821482bee6c940c98mmentovai
29722466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
29733261e8b6eac44a41341f112821482bee6c940c98mmentovai
29749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // Don't log as an error if we can still fall back on the thread's context
29759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // (which must be possible if we got this far.)
2976af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(exception_.thread_context.data_size)) {
29775f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org      BPLOG(INFO) << "MinidumpException cannot read context";
29783261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2979af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
29803261e8b6eac44a41341f112821482bee6c940c98mmentovai
29813261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
29823261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29833261e8b6eac44a41341f112821482bee6c940c98mmentovai
29843261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
29853261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29863261e8b6eac44a41341f112821482bee6c940c98mmentovai
29873261e8b6eac44a41341f112821482bee6c940c98mmentovai
29883261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpException::Print() {
2989af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2990af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot print invalid data";
29913261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2992af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29933261e8b6eac44a41341f112821482bee6c940c98mmentovai
29943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDException\n");
29953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                                  = 0x%x\n",
29963261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_id);
29973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_code            = 0x%x\n",
29983261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_code);
29993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_flags           = 0x%x\n",
30003261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_flags);
3001c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
30023261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_record);
3003c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
30043261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_address);
30053261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.number_parameters         = %d\n",
30063261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.number_parameters);
30073261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int parameterIndex = 0;
30083261e8b6eac44a41341f112821482bee6c940c98mmentovai       parameterIndex < exception_.exception_record.number_parameters;
30093261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++parameterIndex) {
3010c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
30113261e8b6eac44a41341f112821482bee6c940c98mmentovai           parameterIndex,
30123261e8b6eac44a41341f112821482bee6c940c98mmentovai           exception_.exception_record.exception_information[parameterIndex]);
30133261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30143261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size                   = %d\n",
30153261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.data_size);
30163261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva                         = 0x%x\n",
30173261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.rva);
30183261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
30193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
30203261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
30213261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
30223261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
30233261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
30243261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
30253261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30263261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30273261e8b6eac44a41341f112821482bee6c940c98mmentovai
30280314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
30290314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// MinidumpAssertion
30300314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
30310314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30320314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30330314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::MinidumpAssertion(Minidump* minidump)
30340314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    : MinidumpStream(minidump),
30350314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      assertion_(),
30360314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      expression_(),
30370314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      function_(),
30380314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      file_() {
30390314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
30400314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30410314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30420314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::~MinidumpAssertion() {
30430314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
30440314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30450314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30466162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpAssertion::Read(uint32_t expected_size) {
30470314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Invalidate cached data.
30480314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = false;
30490314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30500314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (expected_size != sizeof(assertion_)) {
30510314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
30520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                    " != " << sizeof(assertion_);
30530314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
30540314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
30570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
30580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
30590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30610314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Each of {expression, function, file} is a UTF-16 string,
30620314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // we'll convert them to UTF-8 for ease of use.
30633562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.expression,
30643562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.expression), &expression_,
30653562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
30663562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.function,
30673562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.function), &function_,
30683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
30693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file),
30703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 &file_, minidump_->swap());
30710314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30720314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (minidump_->swap()) {
30730314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.line);
30740314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.type);
30750314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30760314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30770314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = true;
30780314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return true;
30790314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
30800314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30810314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekvoid MinidumpAssertion::Print() {
30820314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!valid_) {
30830314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
30840314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return;
30850314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30860314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30870314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("MDAssertion\n");
30880314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  expression                                 = %s\n",
30890314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         expression_.c_str());
30900314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  function                                   = %s\n",
30910314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         function_.c_str());
30920314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  file                                       = %s\n",
30930314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         file_.c_str());
30940314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  line                                       = %u\n",
30950314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.line);
30960314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  type                                       = %u\n",
30970314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.type);
30980314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("\n");
30990314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
31003261e8b6eac44a41341f112821482bee6c940c98mmentovai
31013261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31023261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpSystemInfo
31033261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31043261e8b6eac44a41341f112821482bee6c940c98mmentovai
31053261e8b6eac44a41341f112821482bee6c940c98mmentovai
31063261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
310753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
310853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      system_info_(),
3109e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      csd_version_(NULL),
3110e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      cpu_vendor_(NULL) {
31113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31123261e8b6eac44a41341f112821482bee6c940c98mmentovai
31133261e8b6eac44a41341f112821482bee6c940c98mmentovai
31143261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::~MinidumpSystemInfo() {
31153261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
3116e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
31173261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31183261e8b6eac44a41341f112821482bee6c940c98mmentovai
31193261e8b6eac44a41341f112821482bee6c940c98mmentovai
31206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpSystemInfo::Read(uint32_t expected_size) {
31213261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
31223261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
31233261e8b6eac44a41341f112821482bee6c940c98mmentovai  csd_version_ = NULL;
3124e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
3125e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  cpu_vendor_ = NULL;
31263261e8b6eac44a41341f112821482bee6c940c98mmentovai
31273261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
31283261e8b6eac44a41341f112821482bee6c940c98mmentovai
3129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(system_info_)) {
3130af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
3131af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(system_info_);
31323261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3133af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31343261e8b6eac44a41341f112821482bee6c940c98mmentovai
3135af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
3136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
31373261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31393261e8b6eac44a41341f112821482bee6c940c98mmentovai
31403261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
31413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_architecture);
31423261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_level);
31433261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_revision);
31443261e8b6eac44a41341f112821482bee6c940c98mmentovai    // number_of_processors and product_type are 8-bit quantities and need no
31453261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapping.
31463261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.major_version);
31473261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.minor_version);
31483261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.build_number);
31493261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.platform_id);
31503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.csd_version_rva);
31513261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.suite_mask);
31523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    // Don't swap the reserved2 field because its contents are unknown.
31533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
31543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
31553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
31563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 3; ++i)
31573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
31583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.version_information);
31593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.feature_information);
31603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
31613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    } else {
31623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 2; ++i)
31633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
31643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
31653261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
31663261e8b6eac44a41341f112821482bee6c940c98mmentovai
31673261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
31683261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
31693261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31703261e8b6eac44a41341f112821482bee6c940c98mmentovai
31713261e8b6eac44a41341f112821482bee6c940c98mmentovai
317297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetOS() {
31734e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com  string os;
31744e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com
3175af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
31774e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com    return os;
3178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
317997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
318097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.platform_id) {
318197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_NT:
318297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_WINDOWS:
318397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "windows";
318497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
318597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
318697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_MAC_OS_X:
318797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "mac";
318897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
318997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
319063f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
319163f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      os = "ios";
319263f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      break;
319363f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org
319497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_LINUX:
319597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "linux";
319697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3197af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3198ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
3199ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      os = "solaris";
32005187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      break;
32015187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org
32025187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
32035187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      os = "android";
3204ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
3205ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
3206d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3:
3207d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      os = "ps3";
3208d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      break;
3209d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org
321042faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org    case MD_OS_NACL:
321142faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      os = "nacl";
321242faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      break;
321342faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org
3214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
3216af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.platform_id);
3217af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
321897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
321997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
322097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return os;
322197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
322297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
322397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
322497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetCPU() {
3225af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
322797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return "";
3228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
322997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
323097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string cpu;
323197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
323297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.processor_architecture) {
323397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86:
323497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86_WIN64:
323597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "x86";
323697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
323797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
32389276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_AMD64:
32399276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "x86-64";
32409276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
32419276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
324297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_PPC:
324397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "ppc";
324497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3245af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3246cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CPU_ARCHITECTURE_PPC64:
3247cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      cpu = "ppc64";
3248cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
3249cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
3250dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    case MD_CPU_ARCHITECTURE_SPARC:
3251dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      cpu = "sparc";
3252dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      break;
3253dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
32549276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_ARM:
32559276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "arm";
32569276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
32579276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
325839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org    case MD_CPU_ARCHITECTURE_ARM64:
325939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      cpu = "arm64";
326039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      break;
326139d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org
3262af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3263af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
3264af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.processor_architecture);
3265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
326697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
326797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
326897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return cpu;
326997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
327097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
327197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
32723261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst string* MinidumpSystemInfo::GetCSDVersion() {
3273af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3274af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
32753261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3276af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32773261e8b6eac44a41341f112821482bee6c940c98mmentovai
32783261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!csd_version_)
32793261e8b6eac44a41341f112821482bee6c940c98mmentovai    csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
32803261e8b6eac44a41341f112821482bee6c940c98mmentovai
3281af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
3282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    "CSD version";
3283af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
32843261e8b6eac44a41341f112821482bee6c940c98mmentovai  return csd_version_;
32853261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32863261e8b6eac44a41341f112821482bee6c940c98mmentovai
32873261e8b6eac44a41341f112821482bee6c940c98mmentovai
3288e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovaiconst string* MinidumpSystemInfo::GetCPUVendor() {
3289af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3290af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
3291e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    return NULL;
3292af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3293e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3294e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  // CPU vendor information can only be determined from x86 minidumps.
3295e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (!cpu_vendor_ &&
3296e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
3297e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
3298e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    char cpu_vendor_string[13];
3299e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
3300e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             "%c%c%c%c%c%c%c%c%c%c%c%c",
3301e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
3302e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
3303e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
3304e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
3305e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
3306e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
3307e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
3308e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
3309e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
3310e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
3311e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
3312e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
3313e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    cpu_vendor_ = new string(cpu_vendor_string);
3314e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3315e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3316e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  return cpu_vendor_;
3317e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai}
3318e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3319e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
33203261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpSystemInfo::Print() {
3321af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3322af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
33233261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3324af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33253261e8b6eac44a41341f112821482bee6c940c98mmentovai
33263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawSystemInfo\n");
33271b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  processor_architecture                     = 0x%x\n",
33283261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_architecture);
33293261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_level                            = %d\n",
33303261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_level);
33310a7e6bf16cad354710df60929c2ac82f647cb54emmentovai  printf("  processor_revision                         = 0x%x\n",
33320a7e6bf16cad354710df60929c2ac82f647cb54emmentovai         system_info_.processor_revision);
33333261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  number_of_processors                       = %d\n",
33343261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.number_of_processors);
33353261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  product_type                               = %d\n",
33363261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.product_type);
33373261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  major_version                              = %d\n",
33383261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.major_version);
33393261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  minor_version                              = %d\n",
33403261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.minor_version);
33413261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  build_number                               = %d\n",
33423261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.build_number);
33431b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  platform_id                                = 0x%x\n",
33443261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.platform_id);
33453261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  csd_version_rva                            = 0x%x\n",
33463261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.csd_version_rva);
33473261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suite_mask                                 = 0x%x\n",
33483261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.suite_mask);
33499c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
33509c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
33519c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    printf("  cpu.x86_cpu_info (valid):\n");
33529c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  } else {
33539c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    printf("  cpu.x86_cpu_info (invalid):\n");
33549c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  }
33553261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int i = 0; i < 3; ++i) {
33563261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
33573261e8b6eac44a41341f112821482bee6c940c98mmentovai           i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
33583261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33593261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
33603261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.version_information);
33613261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
33623261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.feature_information);
33633261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
33643261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
33659c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 &&
33669c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) {
33679c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    printf("  cpu.other_cpu_info (valid):\n");
33689c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    for (unsigned int i = 0; i < 2; ++i) {
33699c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org      printf("  cpu.other_cpu_info.processor_features[%d]   = 0x%" PRIx64 "\n",
33709c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org             i, system_info_.cpu.other_cpu_info.processor_features[i]);
33719c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org    }
33729c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  }
3373e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* csd_version = GetCSDVersion();
3374e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (csd_version) {
33753261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = \"%s\"\n",
3376e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           csd_version->c_str());
3377e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
33783261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = (null)\n");
3379e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3380e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* cpu_vendor = GetCPUVendor();
3381e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (cpu_vendor) {
3382e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = \"%s\"\n",
3383e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           cpu_vendor->c_str());
3384e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
3385e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = (null)\n");
3386e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
33873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
33883261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33893261e8b6eac44a41341f112821482bee6c940c98mmentovai
33903261e8b6eac44a41341f112821482bee6c940c98mmentovai
33913261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33923261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMiscInfo
33933261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33943261e8b6eac44a41341f112821482bee6c940c98mmentovai
33953261e8b6eac44a41341f112821482bee6c940c98mmentovai
33963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
339753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
339853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      misc_info_() {
33993261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34003261e8b6eac44a41341f112821482bee6c940c98mmentovai
34013261e8b6eac44a41341f112821482bee6c940c98mmentovai
34026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMiscInfo::Read(uint32_t expected_size) {
34033261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
34043261e8b6eac44a41341f112821482bee6c940c98mmentovai
34053261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != MD_MISCINFO_SIZE &&
34063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO2_SIZE &&
34073562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO3_SIZE &&
34083562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO4_SIZE) {
34093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
34103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
34113562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
34123562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ")";
34133261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
34143261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34153261e8b6eac44a41341f112821482bee6c940c98mmentovai
3416af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
3417af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
34183261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3419af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34203261e8b6eac44a41341f112821482bee6c940c98mmentovai
34213261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
34223562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Swap version 1 fields
34233261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.size_of_info);
34243261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.flags1);
34253261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_id);
34263261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_create_time);
34273261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_user_time);
34283261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_kernel_time);
34293261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
34303562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 2 fields
34313261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_mhz);
34323261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_mhz);
34333261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_mhz_limit);
34343261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_idle_state);
34353261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_idle_state);
34363261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
34373562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
34383562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 3 fields
34393562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_integrity_level);
34403562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_execute_flags);
34413562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.protected_process);
34423562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone_id);
34433562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone);
34443562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
34453562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
34463562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 4 fields.
34473562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Do not swap UTF-16 strings.  The swap is done as part of the
34483562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // conversion to UTF-8 (code follows below).
34493562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
34503261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34513261e8b6eac44a41341f112821482bee6c940c98mmentovai
345265571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai  if (expected_size != misc_info_.size_of_info) {
3453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
345465571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai                    expected_size << " != " << misc_info_.size_of_info;
34553261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3456af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34573261e8b6eac44a41341f112821482bee6c940c98mmentovai
34583562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Convert UTF-16 strings
34593562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
34603562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 3 fields
34613562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name,
34623562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.standard_name),
34633562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &standard_name_, minidump_->swap());
34643562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name,
34653562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.daylight_name),
34663562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &daylight_name_, minidump_->swap());
34673562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
34683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
34693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 4 fields
34703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.build_string,
34713562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.build_string),
34723562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &build_string_, minidump_->swap());
34733562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str,
34743562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.dbg_bld_str),
34753562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &dbg_bld_str_, minidump_->swap());
34763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
34773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
34783261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
34793261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
34803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34813261e8b6eac44a41341f112821482bee6c940c98mmentovai
34823261e8b6eac44a41341f112821482bee6c940c98mmentovai
34833261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMiscInfo::Print() {
3484af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3485af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
34863261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3487af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34883261e8b6eac44a41341f112821482bee6c940c98mmentovai
34893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawMiscInfo\n");
34903562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Print version 1 fields
34913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
34923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags1                       = 0x%x\n", misc_info_.flags1);
34931b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  process_id                   = ");
34941b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID,
34951b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      kNumberFormatDecimal, misc_info_.process_id);
34961b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) {
34971b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  process_create_time          = 0x%x %s\n",
34981b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org           misc_info_.process_create_time,
34999c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org           TimeTToUTCString(misc_info_.process_create_time).c_str());
35001b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  } else {
35011b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  process_create_time          = (invalid)\n");
35021b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  }
35031b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  process_user_time            = ");
35041b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
35051b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      kNumberFormatDecimal, misc_info_.process_user_time);
35061b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  process_kernel_time          = ");
35071b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
35081b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      kNumberFormatDecimal, misc_info_.process_kernel_time);
35093261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
35103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 2 fields
35111b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  processor_max_mhz            = ");
35121b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35131b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
35141b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal, misc_info_.processor_max_mhz);
35151b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  processor_current_mhz        = ");
35161b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35171b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
35181b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal, misc_info_.processor_current_mhz);
35191b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  processor_mhz_limit          = ");
35201b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35211b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
35221b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal, misc_info_.processor_mhz_limit);
35231b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  processor_max_idle_state     = ");
35241b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35251b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
35261b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal,
35271b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        misc_info_.processor_max_idle_state);
35281b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  processor_current_idle_state = ");
35291b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35301b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
35311b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal,
35321b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        misc_info_.processor_current_idle_state);
35333261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
35343562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
35353562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 3 fields
35361b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  process_integrity_level      = ");
35371b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35381b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY,
35391b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatHexadecimal,
35401b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        misc_info_.process_integrity_level);
35411b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  process_execute_flags        = ");
35421b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35431b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS,
35441b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatHexadecimal,
35451b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        misc_info_.process_execute_flags);
35461b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  protected_process            = ");
35471b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 &
35481b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                            MD_MISCINFO_FLAGS1_PROTECTED_PROCESS,
35491b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal, misc_info_.protected_process);
35501b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    printf("  time_zone_id                 = ");
35511b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE,
35521b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                        kNumberFormatDecimal, misc_info_.time_zone_id);
35531b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) {
35541b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.bias               = %d\n",
35551b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.bias);
35561b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_name      = %s\n", standard_name_.c_str());
35571b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_date      = "
35581b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                 "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
35591b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.year,
35601b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.month,
35611b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.day,
35621b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.day_of_week,
35631b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.hour,
35641b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.minute,
35651b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.second,
35661b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_date.milliseconds);
35671b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_bias      = %d\n",
35681b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.standard_bias);
35691b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_name      = %s\n", daylight_name_.c_str());
35701b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_date      = "
35711b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                 "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
35721b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.year,
35731b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.month,
35741b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.day,
35751b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.day_of_week,
35761b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.hour,
35771b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.minute,
35781b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.second,
35791b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_date.milliseconds);
35801b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_bias      = %d\n",
35811b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org             misc_info_.time_zone.daylight_bias);
35821b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    } else {
35831b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.bias               = (invalid)\n");
35841b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_name      = (invalid)\n");
35851b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_date      = (invalid)\n");
35861b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.standard_bias      = (invalid)\n");
35871b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_name      = (invalid)\n");
35881b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_date      = (invalid)\n");
35891b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  time_zone.daylight_bias      = (invalid)\n");
35901b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    }
35913562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
35923562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
35933562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 4 fields
35941b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) {
35951b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  build_string                 = %s\n", build_string_.c_str());
35961b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  dbg_bld_str                  = %s\n", dbg_bld_str_.c_str());
35971b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    } else {
35981b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  build_string                 = (invalid)\n");
35991b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org      printf("  dbg_bld_str                  = (invalid)\n");
36001b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org    }
36013562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
360276f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
360376f052f8fbf8864dee5992b857229d06560a766ammentovai}
360476f052f8fbf8864dee5992b857229d06560a766ammentovai
360576f052f8fbf8864dee5992b857229d06560a766ammentovai
360676f052f8fbf8864dee5992b857229d06560a766ammentovai//
3607e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// MinidumpBreakpadInfo
360876f052f8fbf8864dee5992b857229d06560a766ammentovai//
360976f052f8fbf8864dee5992b857229d06560a766ammentovai
361076f052f8fbf8864dee5992b857229d06560a766ammentovai
3611e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
361276f052f8fbf8864dee5992b857229d06560a766ammentovai    : MinidumpStream(minidump),
3613e5dc60822e5938fea2ae892ccddb906641ba174emmentovai      breakpad_info_() {
361476f052f8fbf8864dee5992b857229d06560a766ammentovai}
361576f052f8fbf8864dee5992b857229d06560a766ammentovai
361676f052f8fbf8864dee5992b857229d06560a766ammentovai
36176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::Read(uint32_t expected_size) {
361876f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = false;
361976f052f8fbf8864dee5992b857229d06560a766ammentovai
3620af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(breakpad_info_)) {
3621af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
3622af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(breakpad_info_);
362376f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3624af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
362576f052f8fbf8864dee5992b857229d06560a766ammentovai
3626af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
3627af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
362876f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
363076f052f8fbf8864dee5992b857229d06560a766ammentovai
363176f052f8fbf8864dee5992b857229d06560a766ammentovai  if (minidump_->swap()) {
3632e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.validity);
3633e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.dump_thread_id);
3634e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.requesting_thread_id);
363576f052f8fbf8864dee5992b857229d06560a766ammentovai  }
363676f052f8fbf8864dee5992b857229d06560a766ammentovai
363776f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = true;
363876f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
363976f052f8fbf8864dee5992b857229d06560a766ammentovai}
364076f052f8fbf8864dee5992b857229d06560a766ammentovai
364176f052f8fbf8864dee5992b857229d06560a766ammentovai
36426162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const {
3643af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
3644af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3646af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3647af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3648af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3649af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
3650af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3651af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3652af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3653af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
3654af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
365576f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
365676f052f8fbf8864dee5992b857229d06560a766ammentovai  }
365776f052f8fbf8864dee5992b857229d06560a766ammentovai
3658e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.dump_thread_id;
365976f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
366076f052f8fbf8864dee5992b857229d06560a766ammentovai}
366176f052f8fbf8864dee5992b857229d06560a766ammentovai
366276f052f8fbf8864dee5992b857229d06560a766ammentovai
36636162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id)
366476f052f8fbf8864dee5992b857229d06560a766ammentovai    const {
3665af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
3666af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3667af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3668af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3669af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3670af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!thread_id || !valid_) {
3671af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
3672af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3673af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3674af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3675af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity &
3676af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
3677af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
367876f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
367976f052f8fbf8864dee5992b857229d06560a766ammentovai  }
368076f052f8fbf8864dee5992b857229d06560a766ammentovai
3681e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.requesting_thread_id;
368276f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
368376f052f8fbf8864dee5992b857229d06560a766ammentovai}
368476f052f8fbf8864dee5992b857229d06560a766ammentovai
368576f052f8fbf8864dee5992b857229d06560a766ammentovai
3686e5dc60822e5938fea2ae892ccddb906641ba174emmentovaivoid MinidumpBreakpadInfo::Print() {
3687af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3688af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
368976f052f8fbf8864dee5992b857229d06560a766ammentovai    return;
3690af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
369176f052f8fbf8864dee5992b857229d06560a766ammentovai
3692e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("MDRawBreakpadInfo\n");
3693e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("  validity             = 0x%x\n", breakpad_info_.validity);
36941b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  dump_thread_id       = ");
36951b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  PrintValueOrInvalid(breakpad_info_.validity &
36961b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                          MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID,
36971b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      kNumberFormatHexadecimal, breakpad_info_.dump_thread_id);
36981b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  printf("  requesting_thread_id = ");
36991b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org  PrintValueOrInvalid(breakpad_info_.validity &
37001b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                          MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID,
37011b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      kNumberFormatHexadecimal,
37021b9922ced527aeee4b085aa58916af43d86b99eemark@chromium.org                      breakpad_info_.requesting_thread_id);
370376f052f8fbf8864dee5992b857229d06560a766ammentovai
370476f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
37053261e8b6eac44a41341f112821482bee6c940c98mmentovai}
37063261e8b6eac44a41341f112821482bee6c940c98mmentovai
37073261e8b6eac44a41341f112821482bee6c940c98mmentovai
37083261e8b6eac44a41341f112821482bee6c940c98mmentovai//
37097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfo
37107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
37117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
37147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpObject(minidump),
37157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_() {
37167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsExecutable() const {
37206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
37217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
37227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_EXECUTE ||
37237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
37247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
37257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsWritable() const {
37296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
37307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
37317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_READWRITE ||
37327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_WRITECOPY ||
37337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
37347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
37357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::Read() {
37397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
37407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
37427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
37437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
37447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
37477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.base_address);
37487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_base);
37497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_protection);
37507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.region_size);
37517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.state);
37527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.protection);
37537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.type);
37547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Check for base + size overflow or undersize.
37577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (memory_info_.region_size == 0 ||
37586162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      memory_info_.region_size > numeric_limits<uint64_t>::max() -
37597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                     memory_info_.base_address) {
37607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
37617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.base_address) << "+" <<
37627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.region_size);
37637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
37647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
37677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
37687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfo::Print() {
37727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
37737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
37747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
37757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MDRawMemoryInfo\n");
37787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  base_address          = 0x%" PRIx64 "\n",
37797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.base_address);
37807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_base       = 0x%" PRIx64 "\n",
37817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_base);
37827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_protection = 0x%x\n",
37837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_protection);
37847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  region_size           = 0x%" PRIx64 "\n", memory_info_.region_size);
37857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  state                 = 0x%x\n", memory_info_.state);
37867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  protection            = 0x%x\n", memory_info_.protection);
37877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  type                  = 0x%x\n", memory_info_.type);
37887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
37927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfoList
37937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
37947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
37977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpStream(minidump),
37986162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
37997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      infos_(NULL),
38007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      info_count_(0) {
38017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
38027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
38057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete range_map_;
38067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
38077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
38087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38106162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryInfoList::Read(uint32_t expected_size) {
38117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Invalidate cached data.
38127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
38137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  infos_ = NULL;
38147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  range_map_->Clear();
38157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  info_count_ = 0;
38167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
38187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MDRawMemoryInfoList header;
38207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size < sizeof(MDRawMemoryInfoList)) {
38217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
38227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    expected_size << " < " << sizeof(MDRawMemoryInfoList);
38237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&header, sizeof(header))) {
38267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
38277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
38317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_header);
38327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_entry);
38337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.number_of_entries);
38347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the header is the expected size.
3837f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // TODO(ted): could possibly handle this more gracefully, assuming
38387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // that future versions of the structs would be backwards-compatible.
38397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
38407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
38417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_header << " != " <<
38427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfoList);
38437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the entries are the expected size.
38477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
38487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
38497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_entry << " != " <<
38507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfo);
38517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries >
38556162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) {
38567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
38577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.number_of_entries <<
38587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " would cause multiplication overflow";
38597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size != sizeof(MDRawMemoryInfoList) +
38637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo)) {
38647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
38657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " != " << sizeof(MDRawMemoryInfoList) +
38667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo);
38677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
38687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
38697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
3870f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for data loss when converting header.number_of_entries from
3871f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // uint64_t into MinidumpMemoryInfos::size_type (uint32_t)
3872f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  MinidumpMemoryInfos::size_type header_number_of_entries =
3873f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      static_cast<unsigned int>(header.number_of_entries);
3874f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<uint64_t>(header_number_of_entries) !=
3875f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      header.number_of_entries) {
3876f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected when converting "
3877f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                    "the header's number_of_entries";
3878f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
3879f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
3880f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
38817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries != 0) {
38827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    scoped_ptr<MinidumpMemoryInfos> infos(
3883f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        new MinidumpMemoryInfos(header_number_of_entries,
38847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                MinidumpMemoryInfo(minidump_)));
38857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    for (unsigned int index = 0;
38877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         index < header.number_of_entries;
38887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         ++index) {
38897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      MinidumpMemoryInfo* info = &(*infos)[index];
38907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      // Assume that the file offset is correct after the last read.
38927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!info->Read()) {
38937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
38947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries;
38957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
38967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
38977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
38986162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = info->GetBase();
3899f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      uint64_t region_size = info->GetSize();
39007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!range_map_->StoreRange(base_address, region_size, index)) {
39027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
39037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        " memory region " <<
39047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries << ", " <<
39057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(base_address) << "+" <<
39067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(region_size);
39077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
39087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
39097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    }
39107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    infos_ = infos.release();
39127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
3914f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  info_count_ = header_number_of_entries;
39157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
39177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
39187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
39227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      unsigned int index) const {
39237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
39247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
39257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
39267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (index >= info_count_) {
39297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
39307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    index << "/" << info_count_;
39317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
39327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return &(*infos_)[index];
39357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
39396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
39407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
39417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
39427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " GetMemoryInfoForAddress";
39437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
39447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  unsigned int info_index;
39477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
39487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
39497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                   HexString(address);
39507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
39517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetMemoryInfoAtIndex(info_index);
39547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfoList::Print() {
39587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
39597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
39607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
39617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MinidumpMemoryInfoList\n");
39647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  info_count = %d\n", info_count_);
39657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("\n");
39667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  for (unsigned int info_index = 0;
39687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       info_index < info_count_;
39697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       ++info_index) {
39707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("info[%d]\n", info_index);
39717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    (*infos_)[info_index].Print();
39727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("\n");
39737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
39783261e8b6eac44a41341f112821482bee6c940c98mmentovai// Minidump
39793261e8b6eac44a41341f112821482bee6c940c98mmentovai//
39803261e8b6eac44a41341f112821482bee6c940c98mmentovai
39813261e8b6eac44a41341f112821482bee6c940c98mmentovai
39826162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t Minidump::max_streams_ = 128;
3983e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiunsigned int Minidump::max_string_length_ = 1024;
3984e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3985e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
39866dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaiMinidump::Minidump(const string& path)
398753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : header_(),
398853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      directory_(NULL),
3989373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      stream_map_(new MinidumpStreamMap()),
39906dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      path_(path),
39910cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(NULL),
399253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      swap_(false),
399353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
39943261e8b6eac44a41341f112821482bee6c940c98mmentovai}
39953261e8b6eac44a41341f112821482bee6c940c98mmentovai
39960cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekMinidump::Minidump(istream& stream)
39970cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    : header_(),
39980cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      directory_(NULL),
39990cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_map_(new MinidumpStreamMap()),
40000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      path_(),
40010cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(&stream),
40020cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      swap_(false),
40030cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      valid_(false) {
40040cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
40053261e8b6eac44a41341f112821482bee6c940c98mmentovai
40063261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidump::~Minidump() {
40070cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_) {
40080cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump closing minidump";
40090cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
40100cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!path_.empty()) {
40110cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    delete stream_;
40120cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
40133261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
40143261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete stream_map_;
40156dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai}
40166dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
40176dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
40186dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaibool Minidump::Open() {
40190cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_ != NULL) {
40200cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump reopening minidump " << path_;
4021af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
40226dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // The file is already open.  Seek to the beginning, which is the position
40236dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // the file would be at if it were opened anew.
40246dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return SeekSet(0);
40256dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  }
40266dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
40270cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
40280cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_ || !stream_->good()) {
4029af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    string error_string;
4030af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    int error_code = ErrnoString(&error_string);
4031af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
4032af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ", error " << error_code << ": " << error_string;
40336dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4034af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
40356dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
40360cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  BPLOG(INFO) << "Minidump opened minidump " << path_;
40376dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  return true;
40383261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40393261e8b6eac44a41341f112821482bee6c940c98mmentovai
40406162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) {
4041233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Initialize output parameters
4042233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  *context_cpu_flags = 0;
4043233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4044233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Save the current stream position
4045233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  off_t saved_position = Tell();
4046233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (saved_position == -1) {
4047233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Failed to save the current stream position.
4048233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Returns true because the current position of the stream is preserved.
4049233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    return true;
4050233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4051233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4052233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  const MDRawSystemInfo* system_info =
4053233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
4054233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4055233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (system_info != NULL) {
4056233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    switch (system_info->processor_architecture) {
4057233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86:
4058233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_X86;
4059233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4060233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MIPS:
4061233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_MIPS;
4062233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4063233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA:
4064233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ALPHA;
4065233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4066233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_PPC:
4067233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_PPC;
4068233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4069cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      case MD_CPU_ARCHITECTURE_PPC64:
4070cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        *context_cpu_flags = MD_CONTEXT_PPC64;
4071cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        break;
4072233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SHX:
4073233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SHX;
4074233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4075233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ARM:
4076233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ARM;
4077233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
407839d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org      case MD_CPU_ARCHITECTURE_ARM64:
407939d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        *context_cpu_flags = MD_CONTEXT_ARM64;
408039d7964df5d3ba7c3889bf19004f6e18eee5cfc6mark@chromium.org        break;
4081233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_IA64:
4082233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_IA64;
4083233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4084233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA64:
4085233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4086233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4087233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MSIL:
4088233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4089233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4090233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_AMD64:
4091233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_AMD64;
4092233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4093233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86_WIN64:
4094233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4095233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4096233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SPARC:
4097233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SPARC;
4098233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4099233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_UNKNOWN:
4100233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4101233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4102233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      default:
4103233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4104233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4105233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
4106233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4107233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4108233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Restore position and return
4109233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  return SeekSet(saved_position);
4110233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com}
4111233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
41123261e8b6eac44a41341f112821482bee6c940c98mmentovai
41133261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::Read() {
41143261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
41153261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
41163261e8b6eac44a41341f112821482bee6c940c98mmentovai  directory_ = NULL;
4117373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  stream_map_->clear();
41183261e8b6eac44a41341f112821482bee6c940c98mmentovai
41193261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
41203261e8b6eac44a41341f112821482bee6c940c98mmentovai
4121af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!Open()) {
4122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot open minidump";
41236dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4124af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41256dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
4126af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
4127af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot read header";
41283261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41303261e8b6eac44a41341f112821482bee6c940c98mmentovai
41313261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (header_.signature != MD_HEADER_SIGNATURE) {
41323261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file may be byte-swapped.  Under the present architecture, these
41333261e8b6eac44a41341f112821482bee6c940c98mmentovai    // classes don't know or need to know what CPU (or endianness) the
41343261e8b6eac44a41341f112821482bee6c940c98mmentovai    // minidump was produced on in order to parse it.  Use the signature as
41353261e8b6eac44a41341f112821482bee6c940c98mmentovai    // a byte order marker.
41366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature_swapped = header_.signature;
41373261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&signature_swapped);
41383261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature_swapped != MD_HEADER_SIGNATURE) {
41393261e8b6eac44a41341f112821482bee6c940c98mmentovai      // This isn't a minidump or a byte-swapped minidump.
4140af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
4141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(header_.signature) << ", " <<
4142af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(signature_swapped) << ") != " <<
4143af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(MD_HEADER_SIGNATURE);
41443261e8b6eac44a41341f112821482bee6c940c98mmentovai      return false;
41453261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
41463261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = true;
41473261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
41483261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file is not byte-swapped.  Set swap_ false (it may have been true
41493261e8b6eac44a41341f112821482bee6c940c98mmentovai    // if the object is being reused?)
41503261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = false;
41513261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
41523261e8b6eac44a41341f112821482bee6c940c98mmentovai
4153af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
4154af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                 "byte-swapping minidump";
4155af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
41563261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_) {
41573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.signature);
41583261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.version);
41593261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_count);
41603261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_directory_rva);
41613261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.checksum);
41623261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.time_date_stamp);
41633261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.flags);
41643261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
41653261e8b6eac44a41341f112821482bee6c940c98mmentovai
41663261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Version check.  The high 16 bits of header_.version contain something
41673261e8b6eac44a41341f112821482bee6c940c98mmentovai  // else "implementation specific."
41683261e8b6eac44a41341f112821482bee6c940c98mmentovai  if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
4169af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump version mismatch: " <<
4170af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(header_.version & 0x0000ffff) << " != " <<
4171af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(MD_HEADER_VERSION);
41723261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
41733261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
41743261e8b6eac44a41341f112821482bee6c940c98mmentovai
4175af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(header_.stream_directory_rva)) {
4176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
41773261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41793261e8b6eac44a41341f112821482bee6c940c98mmentovai
4180e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count > max_streams_) {
4181e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
4182e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_streams_;
4183e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
4184e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4185e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
4186e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count != 0) {
4187373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpDirectoryEntries> directory(
4188373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpDirectoryEntries(header_.stream_count));
41893261e8b6eac44a41341f112821482bee6c940c98mmentovai
4190373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
4191373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
4192373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&(*directory)[0],
4193af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   sizeof(MDRawDirectory) * header_.stream_count)) {
4194af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump cannot read stream directory";
4195373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
4196af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
41973261e8b6eac44a41341f112821482bee6c940c98mmentovai
4198373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int stream_index = 0;
4199373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         stream_index < header_.stream_count;
4200373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++stream_index) {
4201373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDRawDirectory* directory_entry = &(*directory)[stream_index];
42023261e8b6eac44a41341f112821482bee6c940c98mmentovai
4203373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (swap_) {
4204373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->stream_type);
4205373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->location);
4206373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
42073261e8b6eac44a41341f112821482bee6c940c98mmentovai
4208373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Initialize the stream_map_ map, which speeds locating a stream by
4209373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // type.
4210373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      unsigned int stream_type = directory_entry->stream_type;
4211373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      switch (stream_type) {
4212373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_THREAD_LIST_STREAM:
4213373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MODULE_LIST_STREAM:
4214373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MEMORY_LIST_STREAM:
4215373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_EXCEPTION_STREAM:
4216373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_SYSTEM_INFO_STREAM:
4217373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MISC_INFO_STREAM:
4218e5dc60822e5938fea2ae892ccddb906641ba174emmentovai        case MD_BREAKPAD_INFO_STREAM: {
4219373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          if (stream_map_->find(stream_type) != stream_map_->end()) {
4220373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // Another stream with this type was already found.  A minidump
4221373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // file should contain at most one of each of these stream types.
4222af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            BPLOG(ERROR) << "Minidump found multiple streams of type " <<
4223af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                            stream_type << ", but can only deal with one";
4224373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            return false;
4225373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          }
4226373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Fall through to default
42273261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
42283261e8b6eac44a41341f112821482bee6c940c98mmentovai
4229373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        default: {
4230373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Overwrites for stream types other than those above, but it's
4231373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // expected to be the user's burden in that case.
4232373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          (*stream_map_)[stream_type].stream_index = stream_index;
4233373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        }
42343261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
42353261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
42363261e8b6eac44a41341f112821482bee6c940c98mmentovai
4237373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    directory_ = directory.release();
4238373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
42393261e8b6eac44a41341f112821482bee6c940c98mmentovai
42403261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
42413261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
42423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42433261e8b6eac44a41341f112821482bee6c940c98mmentovai
42443261e8b6eac44a41341f112821482bee6c940c98mmentovai
42453261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList* Minidump::GetThreadList() {
42463261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpThreadList* thread_list;
42473261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&thread_list);
42483261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42493261e8b6eac44a41341f112821482bee6c940c98mmentovai
42503261e8b6eac44a41341f112821482bee6c940c98mmentovai
42513261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList* Minidump::GetModuleList() {
42523261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpModuleList* module_list;
42533261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&module_list);
42543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42553261e8b6eac44a41341f112821482bee6c940c98mmentovai
42563261e8b6eac44a41341f112821482bee6c940c98mmentovai
42573261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList* Minidump::GetMemoryList() {
42583261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryList* memory_list;
42593261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&memory_list);
42603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42613261e8b6eac44a41341f112821482bee6c940c98mmentovai
42623261e8b6eac44a41341f112821482bee6c940c98mmentovai
42633261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException* Minidump::GetException() {
42643261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpException* exception;
42653261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&exception);
42663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42673261e8b6eac44a41341f112821482bee6c940c98mmentovai
42680314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion* Minidump::GetAssertion() {
42690314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  MinidumpAssertion* assertion;
42700314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return GetStream(&assertion);
42710314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
42720314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
42733261e8b6eac44a41341f112821482bee6c940c98mmentovai
42743261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo* Minidump::GetSystemInfo() {
42753261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpSystemInfo* system_info;
42763261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&system_info);
42773261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42783261e8b6eac44a41341f112821482bee6c940c98mmentovai
42793261e8b6eac44a41341f112821482bee6c940c98mmentovai
42803261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo* Minidump::GetMiscInfo() {
42813261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMiscInfo* misc_info;
42823261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&misc_info);
42833261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42843261e8b6eac44a41341f112821482bee6c940c98mmentovai
42853261e8b6eac44a41341f112821482bee6c940c98mmentovai
4286e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
4287e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  MinidumpBreakpadInfo* breakpad_info;
4288e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  return GetStream(&breakpad_info);
428976f052f8fbf8864dee5992b857229d06560a766ammentovai}
429076f052f8fbf8864dee5992b857229d06560a766ammentovai
42917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
42927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MinidumpMemoryInfoList* memory_info_list;
42937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetStream(&memory_info_list);
42947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
42957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
42966f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.comstatic const char* get_stream_name(uint32_t stream_type) {
42976f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  switch (stream_type) {
42986f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_UNUSED_STREAM:
42996f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_UNUSED_STREAM";
43006f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_RESERVED_STREAM_0:
43016f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_RESERVED_STREAM_0";
43026f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_RESERVED_STREAM_1:
43036f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_RESERVED_STREAM_1";
43046f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_THREAD_LIST_STREAM:
43056f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_THREAD_LIST_STREAM";
43066f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_MODULE_LIST_STREAM:
43076f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_MODULE_LIST_STREAM";
43086f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_MEMORY_LIST_STREAM:
43096f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_MEMORY_LIST_STREAM";
43106f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_EXCEPTION_STREAM:
43116f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_EXCEPTION_STREAM";
43126f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_SYSTEM_INFO_STREAM:
43136f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_SYSTEM_INFO_STREAM";
43146f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_THREAD_EX_LIST_STREAM:
43156f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_THREAD_EX_LIST_STREAM";
43166f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_MEMORY_64_LIST_STREAM:
43176f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_MEMORY_64_LIST_STREAM";
43186f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_COMMENT_STREAM_A:
43196f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_COMMENT_STREAM_A";
43206f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_COMMENT_STREAM_W:
43216f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_COMMENT_STREAM_W";
43226f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_HANDLE_DATA_STREAM:
43236f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_HANDLE_DATA_STREAM";
43246f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_FUNCTION_TABLE_STREAM:
43256f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_FUNCTION_TABLE_STREAM";
43266f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_UNLOADED_MODULE_LIST_STREAM:
43276f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_UNLOADED_MODULE_LIST_STREAM";
43286f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_MISC_INFO_STREAM:
43296f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_MISC_INFO_STREAM";
43306f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_MEMORY_INFO_LIST_STREAM:
43316f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_MEMORY_INFO_LIST_STREAM";
43326f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_THREAD_INFO_LIST_STREAM:
43336f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_THREAD_INFO_LIST_STREAM";
43346f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_HANDLE_OPERATION_LIST_STREAM:
43356f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_HANDLE_OPERATION_LIST_STREAM";
43366f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LAST_RESERVED_STREAM:
43376f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LAST_RESERVED_STREAM";
43386f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_BREAKPAD_INFO_STREAM:
43396f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_BREAKPAD_INFO_STREAM";
43406f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_ASSERTION_INFO_STREAM:
43416f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_ASSERTION_INFO_STREAM";
43426f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_CPU_INFO:
43436f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_CPU_INFO";
43446f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_PROC_STATUS:
43456f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_PROC_STATUS";
43466f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_LSB_RELEASE:
43476f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_LSB_RELEASE";
43486f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_CMD_LINE:
43496f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_CMD_LINE";
43506f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_ENVIRON:
43516f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_ENVIRON";
43526f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_AUXV:
43536f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_AUXV";
43546f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_MAPS:
43556f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_MAPS";
43566f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  case MD_LINUX_DSO_DEBUG:
43576f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "MD_LINUX_DSO_DEBUG";
43586f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  default:
43596f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    return "unknown";
43606f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com  }
43616f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com}
436276f052f8fbf8864dee5992b857229d06560a766ammentovai
43633261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid Minidump::Print() {
4364af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4365af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot print invalid data";
43663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
4367af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43683261e8b6eac44a41341f112821482bee6c940c98mmentovai
43693261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawHeader\n");
43703261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  signature            = 0x%x\n",    header_.signature);
43713261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version              = 0x%x\n",    header_.version);
43723261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_count         = %d\n",      header_.stream_count);
43733261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
43743261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum             = 0x%x\n",    header_.checksum);
43759c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org  printf("  time_date_stamp      = 0x%x %s\n",
43769c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org         header_.time_date_stamp,
43779c98e0ff65fc324ce34f4133b63a1201080f5c02mark@chromium.org         TimeTToUTCString(header_.time_date_stamp).c_str());
4378c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
43793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
43803261e8b6eac44a41341f112821482bee6c940c98mmentovai
43813261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int stream_index = 0;
43823261e8b6eac44a41341f112821482bee6c940c98mmentovai       stream_index < header_.stream_count;
43833261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++stream_index) {
43843261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDRawDirectory* directory_entry = &(*directory_)[stream_index];
43853261e8b6eac44a41341f112821482bee6c940c98mmentovai
43863261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("mDirectory[%d]\n", stream_index);
43873261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDRawDirectory\n");
43886f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    printf("  stream_type        = 0x%x (%s)\n", directory_entry->stream_type,
43896f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com           get_stream_name(directory_entry->stream_type));
43903261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.data_size = %d\n",
43913261e8b6eac44a41341f112821482bee6c940c98mmentovai           directory_entry->location.data_size);
43923261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
43933261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
43943261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43953261e8b6eac44a41341f112821482bee6c940c98mmentovai
43963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("Streams:\n");
43973261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
43983261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != stream_map_->end();
43993261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
44006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t stream_type = iterator->first;
44013261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpStreamInfo info = iterator->second;
44026f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com    printf("  stream type 0x%x (%s) at index %d\n", stream_type,
44036f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com           get_stream_name(stream_type),
44046f1bd8c271098d15a63ee8ec3d3d0fb625e6c2c8ted.mielczarek@gmail.com           info.stream_index);
44053261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
44063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
44073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44083261e8b6eac44a41341f112821482bee6c940c98mmentovai
44093261e8b6eac44a41341f112821482bee6c940c98mmentovai
44103261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
44113261e8b6eac44a41341f112821482bee6c940c98mmentovai      const {
4412af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4413af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
44143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4415af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4416af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4417af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= header_.stream_count) {
4418af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
4419af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << header_.stream_count;
4420af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
4421af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
44223261e8b6eac44a41341f112821482bee6c940c98mmentovai
44233261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*directory_)[index];
44243261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44253261e8b6eac44a41341f112821482bee6c940c98mmentovai
44263261e8b6eac44a41341f112821482bee6c940c98mmentovai
44273261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::ReadBytes(void* bytes, size_t count) {
44283261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
44290cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
44300cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
44310cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
44320cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
44330cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->read(static_cast<char*>(bytes), count);
4434f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamsize bytes_read = stream_->gcount();
4435f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read == -1) {
4436f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    string error_string;
4437f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    int error_code = ErrnoString(&error_string);
4438f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
4439f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4440f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4441f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4442f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Convert to size_t and check for data loss
4443f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  size_t bytes_read_converted = static_cast<size_t>(bytes_read);
4444f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) {
4445f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting "
4446f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                 << bytes_read << " to " << bytes_read_converted;
44473261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4448af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4449f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4450f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read_converted != count) {
4451f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count;
4452f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4453f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4454f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
44553261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
44563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44573261e8b6eac44a41341f112821482bee6c940c98mmentovai
44583261e8b6eac44a41341f112821482bee6c940c98mmentovai
44593261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekSet(off_t offset) {
44603261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
44610cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
44620cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
44630cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
44640cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
44650cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->seekg(offset, std::ios_base::beg);
44660cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_->good()) {
44670cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    string error_string;
44680cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    int error_code = ErrnoString(&error_string);
44690cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
44703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4471af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
44723261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
44733261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44743261e8b6eac44a41341f112821482bee6c940c98mmentovai
44750cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekoff_t Minidump::Tell() {
44760cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!valid_ || !stream_) {
44770cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return (off_t)-1;
44780cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
44790cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
4480f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for conversion data loss
4481f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamoff std_streamoff = stream_->tellg();
4482f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  off_t rv = static_cast<off_t>(std_streamoff);
4483f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamoff>(rv) == std_streamoff) {
4484f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return rv;
4485f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
4486f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected";
4487f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return (off_t)-1;
4488f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
44890cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
44900cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
44913261e8b6eac44a41341f112821482bee6c940c98mmentovai
44923261e8b6eac44a41341f112821482bee6c940c98mmentovaistring* Minidump::ReadString(off_t offset) {
4493af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4494af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for ReadString";
44953261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4496af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4497af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(offset)) {
4498e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
44993261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4500af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45013261e8b6eac44a41341f112821482bee6c940c98mmentovai
45026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t bytes;
4503af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&bytes, sizeof(bytes))) {
4504e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not read string size at offset " <<
4505e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    offset;
45063261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4507af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45083261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_)
45093261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&bytes);
45103261e8b6eac44a41341f112821482bee6c940c98mmentovai
4511af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (bytes % 2 != 0) {
4512e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
4513e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    "-byte string at offset " << offset;
45143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4515af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45163261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int utf16_words = bytes / 2;
45173261e8b6eac44a41341f112821482bee6c940c98mmentovai
4518e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (utf16_words > max_string_length_) {
4519e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString string length " << utf16_words <<
4520e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_string_length_ <<
4521e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " at offset " << offset;
4522e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return NULL;
4523e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4524e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
45256162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  vector<uint16_t> string_utf16(utf16_words);
45263261e8b6eac44a41341f112821482bee6c940c98mmentovai
4527373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (utf16_words) {
4528373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&string_utf16[0], bytes)) {
4529e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "ReadString could not read " << bytes <<
4530e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      "-byte string at offset " << offset;
4531373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
4532373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
4533373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
45343261e8b6eac44a41341f112821482bee6c940c98mmentovai
45353261e8b6eac44a41341f112821482bee6c940c98mmentovai  return UTF16ToUTF8(string_utf16, swap_);
45363261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45373261e8b6eac44a41341f112821482bee6c940c98mmentovai
45383261e8b6eac44a41341f112821482bee6c940c98mmentovai
45396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::SeekToStreamType(uint32_t  stream_type,
45406162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                uint32_t* stream_length) {
4541af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
4542af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "|stream_length|";
4543af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream_length);
4544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *stream_length = 0;
4545af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4546af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4547af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
45483261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4549af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45503261e8b6eac44a41341f112821482bee6c940c98mmentovai
45513261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
45523261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
45533261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4554af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
45553261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
45563261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45573261e8b6eac44a41341f112821482bee6c940c98mmentovai
45583261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo info = iterator->second;
4559af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (info.stream_index >= header_.stream_count) {
4560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
4561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " out of range: " <<
4562af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    info.stream_index << "/" << header_.stream_count;
45633261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4564af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45653261e8b6eac44a41341f112821482bee6c940c98mmentovai
45663261e8b6eac44a41341f112821482bee6c940c98mmentovai  MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
4567af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(directory_entry->location.rva)) {
4568af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
4569af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    stream_type;
45703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45723261e8b6eac44a41341f112821482bee6c940c98mmentovai
45733261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream_length = directory_entry->location.data_size;
45743261e8b6eac44a41341f112821482bee6c940c98mmentovai
45753261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
45763261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45773261e8b6eac44a41341f112821482bee6c940c98mmentovai
45783261e8b6eac44a41341f112821482bee6c940c98mmentovai
45793261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
45803261e8b6eac44a41341f112821482bee6c940c98mmentovaiT* Minidump::GetStream(T** stream) {
45813261e8b6eac44a41341f112821482bee6c940c98mmentovai  // stream is a garbage parameter that's present only to account for C++'s
45823261e8b6eac44a41341f112821482bee6c940c98mmentovai  // inability to overload a method based solely on its return type.
45833261e8b6eac44a41341f112821482bee6c940c98mmentovai
45846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t stream_type = T::kStreamType;
4585af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4586af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
4587af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                              " requires |stream|";
4588af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream);
45893261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = NULL;
45903261e8b6eac44a41341f112821482bee6c940c98mmentovai
4591af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4592af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
45933261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4594af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45953261e8b6eac44a41341f112821482bee6c940c98mmentovai
45963261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
45973261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
45983261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4599af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
46003261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
46013261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
46023261e8b6eac44a41341f112821482bee6c940c98mmentovai
46033261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Get a pointer so that the stored stream field can be altered.
46043261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo* info = &iterator->second;
46053261e8b6eac44a41341f112821482bee6c940c98mmentovai
46063261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (info->stream) {
46073261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This cast is safe because info.stream is only populated by this
46083261e8b6eac44a41341f112821482bee6c940c98mmentovai    // method, and there is a direct correlation between T and stream_type.
46093261e8b6eac44a41341f112821482bee6c940c98mmentovai    *stream = static_cast<T*>(info->stream);
46103261e8b6eac44a41341f112821482bee6c940c98mmentovai    return *stream;
46113261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
46123261e8b6eac44a41341f112821482bee6c940c98mmentovai
46136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t stream_length;
4614af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekToStreamType(stream_type, &stream_length)) {
4615af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
46163261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4617af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46183261e8b6eac44a41341f112821482bee6c940c98mmentovai
46192466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<T> new_stream(new T(this));
46203261e8b6eac44a41341f112821482bee6c940c98mmentovai
4621af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!new_stream->Read(stream_length)) {
4622af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
46233261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4624af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46253261e8b6eac44a41341f112821482bee6c940c98mmentovai
46263261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = new_stream.release();
46273261e8b6eac44a41341f112821482bee6c940c98mmentovai  info->stream = *stream;
46283261e8b6eac44a41341f112821482bee6c940c98mmentovai  return *stream;
46293261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46303261e8b6eac44a41341f112821482bee6c940c98mmentovai
46313261e8b6eac44a41341f112821482bee6c940c98mmentovai
4632e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
4633