minidump.cc revision 2cc15ba4327831f917ff55b87e6d5fc3c7750085
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>
403261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <stdio.h>
419fcf4db315427032a92078d1212fece2655bf049mmentovai#include <string.h>
423261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <time.h>
43c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek
443261e8b6eac44a41341f112821482bee6c940c98mmentovai#ifdef _WIN32
453261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <io.h>
463261e8b6eac44a41341f112821482bee6c940c98mmentovaitypedef SSIZE_T ssize_t;
47c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx64 "llx"
48c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx32 "lx"
49c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define snprintf _snprintf
5080e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#else  // _WIN32
51c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#include <unistd.h>
526dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#define O_BINARY 0
5380e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#endif  // _WIN32
543261e8b6eac44a41341f112821482bee6c940c98mmentovai
550cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <fstream>
560cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <iostream>
57fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai#include <limits>
583261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <map>
593261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <vector>
603261e8b6eac44a41341f112821482bee6c940c98mmentovai
618c2a4def4ecfbf6293b27eff4359a274e9774b4emmentovai#include "processor/range_map-inl.h"
6280e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai
632cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
64db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_module.h"
65db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_modules.h"
66af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai#include "processor/logging.h"
672cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com
683261e8b6eac44a41341f112821482bee6c940c98mmentovai
693261e8b6eac44a41341f112821482bee6c940c98mmentovai
70e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
713261e8b6eac44a41341f112821482bee6c940c98mmentovai
723261e8b6eac44a41341f112821482bee6c940c98mmentovai
730cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::istream;
740cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::ifstream;
75fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovaiusing std::numeric_limits;
763261e8b6eac44a41341f112821482bee6c940c98mmentovaiusing std::vector;
773261e8b6eac44a41341f112821482bee6c940c98mmentovai
783261e8b6eac44a41341f112821482bee6c940c98mmentovai
793261e8b6eac44a41341f112821482bee6c940c98mmentovai//
803261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping routines
813261e8b6eac44a41341f112821482bee6c940c98mmentovai//
823261e8b6eac44a41341f112821482bee6c940c98mmentovai// Inlining these doesn't increase code size significantly, and it saves
833261e8b6eac44a41341f112821482bee6c940c98mmentovai// a whole lot of unnecessary jumping back and forth.
843261e8b6eac44a41341f112821482bee6c940c98mmentovai//
853261e8b6eac44a41341f112821482bee6c940c98mmentovai
863261e8b6eac44a41341f112821482bee6c940c98mmentovai
873261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping an 8-bit quantity is a no-op.  This function is only provided
883261e8b6eac44a41341f112821482bee6c940c98mmentovai// to account for certain templatized operations that require swapping for
893261e8b6eac44a41341f112821482bee6c940c98mmentovai// wider types but handle u_int8_t too
903261e8b6eac44a41341f112821482bee6c940c98mmentovai// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
913261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int8_t* value) {
923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
933261e8b6eac44a41341f112821482bee6c940c98mmentovai
943261e8b6eac44a41341f112821482bee6c940c98mmentovai
953261e8b6eac44a41341f112821482bee6c940c98mmentovai// Optimization: don't need to AND the furthest right shift, because we're
963261e8b6eac44a41341f112821482bee6c940c98mmentovai// shifting an unsigned quantity.  The standard requires zero-filling in this
973261e8b6eac44a41341f112821482bee6c940c98mmentovai// case.  If the quantities were signed, a bitmask whould be needed for this
983261e8b6eac44a41341f112821482bee6c940c98mmentovai// right shift to avoid an arithmetic shift (which retains the sign bit).
993261e8b6eac44a41341f112821482bee6c940c98mmentovai// The furthest left shift never needs to be ANDed bitmask.
1003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1013261e8b6eac44a41341f112821482bee6c940c98mmentovai
1023261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int16_t* value) {
1033261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = (*value >> 8) |
1043261e8b6eac44a41341f112821482bee6c940c98mmentovai           (*value << 8);
1053261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1063261e8b6eac44a41341f112821482bee6c940c98mmentovai
1073261e8b6eac44a41341f112821482bee6c940c98mmentovai
1083261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int32_t* value) {
1093261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 24) |
1103261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x0000ff00) |
1113261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x00ff0000) |
1123261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 24);
1133261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1143261e8b6eac44a41341f112821482bee6c940c98mmentovai
1153261e8b6eac44a41341f112821482bee6c940c98mmentovai
1160e6f5c95d7b791c2a7d2c4056d9746f3fa1ff166mmentovaistatic inline void Swap(u_int64_t* value) {
1172e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  u_int32_t* value32 = reinterpret_cast<u_int32_t*>(value);
1182e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[0]);
1192e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[1]);
1202e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  u_int32_t temp = value32[0];
1212e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[0] = value32[1];
1222e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[1] = temp;
1233261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1243261e8b6eac44a41341f112821482bee6c940c98mmentovai
1253261e8b6eac44a41341f112821482bee6c940c98mmentovai
1261d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// Given a pointer to a 128-bit int in the minidump data, set the "low"
1271d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// and "high" fields appropriately.
1281d78cad82e3c7aa2315ed7438211a1901a91ed34brynerstatic void Normalize128(u_int128_t* value, bool is_big_endian) {
1291d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // The struct format is [high, low], so if the format is big-endian,
1301d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // the most significant bytes will already be in the high field.
1311d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  if (!is_big_endian) {
1321d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    u_int64_t temp = value->low;
1331d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->low = value->high;
1341d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->high = temp;
1351d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  }
1361d78cad82e3c7aa2315ed7438211a1901a91ed34bryner}
1373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1381d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// This just swaps each int64 half of the 128-bit value.
1391d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// The value should also be normalized by calling Normalize128().
1401d78cad82e3c7aa2315ed7438211a1901a91ed34brynerstatic void Swap(u_int128_t* value) {
1411d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->low);
1421d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->high);
1433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
1443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1463261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDLocationDescriptor* location_descriptor) {
1473261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->data_size);
1483261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->rva);
1493261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1503261e8b6eac44a41341f112821482bee6c940c98mmentovai
1513261e8b6eac44a41341f112821482bee6c940c98mmentovai
1523261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDMemoryDescriptor* memory_descriptor) {
1533261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->start_of_memory_range);
1543261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->memory);
1553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1563261e8b6eac44a41341f112821482bee6c940c98mmentovai
1573261e8b6eac44a41341f112821482bee6c940c98mmentovai
1583261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDGUID* guid) {
1593261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data1);
1603261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data2);
1613261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data3);
1623261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't swap guid->data4[] because it contains 8-bit quantities.
1633261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1643261e8b6eac44a41341f112821482bee6c940c98mmentovai
1653261e8b6eac44a41341f112821482bee6c940c98mmentovai
1663261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1673261e8b6eac44a41341f112821482bee6c940c98mmentovai// Character conversion routines
1683261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1693261e8b6eac44a41341f112821482bee6c940c98mmentovai
1703261e8b6eac44a41341f112821482bee6c940c98mmentovai
1713261e8b6eac44a41341f112821482bee6c940c98mmentovai// Standard wide-character conversion routines depend on the system's own
1723261e8b6eac44a41341f112821482bee6c940c98mmentovai// idea of what width a wide character should be: some use 16 bits, and
1733261e8b6eac44a41341f112821482bee6c940c98mmentovai// some use 32 bits.  For the purposes of a minidump, wide strings are
1743261e8b6eac44a41341f112821482bee6c940c98mmentovai// always represented with 16-bit UTF-16 chracters.  iconv isn't available
1753261e8b6eac44a41341f112821482bee6c940c98mmentovai// everywhere, and its interface varies where it is available.  iconv also
1763261e8b6eac44a41341f112821482bee6c940c98mmentovai// deals purely with char* pointers, so in addition to considering the swap
1773261e8b6eac44a41341f112821482bee6c940c98mmentovai// parameter, a converter that uses iconv would also need to take the host
1783261e8b6eac44a41341f112821482bee6c940c98mmentovai// CPU's endianness into consideration.  It doesn't seems worth the trouble
1793261e8b6eac44a41341f112821482bee6c940c98mmentovai// of making it a dependency when we don't care about anything but UTF-16.
1803261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic string* UTF16ToUTF8(const vector<u_int16_t>& in,
1813261e8b6eac44a41341f112821482bee6c940c98mmentovai                           bool                     swap) {
1822466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<string> out(new string());
1833261e8b6eac44a41341f112821482bee6c940c98mmentovai
1843261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Set the string's initial capacity to the number of UTF-16 characters,
1853261e8b6eac44a41341f112821482bee6c940c98mmentovai  // because the UTF-8 representation will always be at least this long.
1863261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the UTF-8 representation is longer, the string will grow dynamically.
1873261e8b6eac44a41341f112821482bee6c940c98mmentovai  out->reserve(in.size());
1883261e8b6eac44a41341f112821482bee6c940c98mmentovai
1893261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (vector<u_int16_t>::const_iterator iterator = in.begin();
1903261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != in.end();
1913261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
1923261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Get a 16-bit value from the input
1933261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int16_t in_word = *iterator;
1943261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (swap)
1953261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&in_word);
1963261e8b6eac44a41341f112821482bee6c940c98mmentovai
1973261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the input value (in_word) into a Unicode code point (unichar).
1983261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t unichar;
1993261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (in_word >= 0xdc00 && in_word <= 0xdcff) {
200af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
201af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(in_word) << " without high";
2023261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2033261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
2043261e8b6eac44a41341f112821482bee6c940c98mmentovai      // High surrogate.
2053261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = (in_word - 0xd7c0) << 10;
2063261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (++iterator == in.end()) {
207af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
208af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word) << " at end of string";
2093261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2103261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      u_int32_t high_word = in_word;
2123261e8b6eac44a41341f112821482bee6c940c98mmentovai      in_word = *iterator;
2133261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (in_word < 0xdc00 || in_word > 0xdcff) {
214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(high_word) << " without low " <<
216af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word);
2173261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2183261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2193261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar |= in_word & 0x03ff;
2203261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
2213261e8b6eac44a41341f112821482bee6c940c98mmentovai      // The ordinary case, a single non-surrogate Unicode character encoded
2223261e8b6eac44a41341f112821482bee6c940c98mmentovai      // as a single 16-bit value.
2233261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = in_word;
2243261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2253261e8b6eac44a41341f112821482bee6c940c98mmentovai
2263261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the Unicode code point (unichar) into its UTF-8 representation,
2273261e8b6eac44a41341f112821482bee6c940c98mmentovai    // appending it to the out string.
2283261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (unichar < 0x80) {
2293261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += unichar;
2303261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x800) {
2313261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xc0 | (unichar >> 6);
2323261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2333261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x10000) {
2343261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xe0 | (unichar >> 12);
2353261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 6) & 0x3f);
2363261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2373261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x200000) {
2383261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xf0 | (unichar >> 18);
2393261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 12) & 0x3f);
2403261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 6) & 0x3f);
2413261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2423261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
243af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
244af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(unichar) << " in UTF-8";
2453261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2463261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2473261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
2483261e8b6eac44a41341f112821482bee6c940c98mmentovai
2493261e8b6eac44a41341f112821482bee6c940c98mmentovai  return out.release();
2503261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2513261e8b6eac44a41341f112821482bee6c940c98mmentovai
2520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// Return the smaller of the number of code units in the UTF-16 string,
2530314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// not including the terminating null word, or maxlen.
2540314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekstatic size_t UTF16codeunits(const u_int16_t *string, size_t maxlen) {
2550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  size_t count = 0;
2560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  while (count < maxlen && string[count] != 0)
2570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    count++;
2580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return count;
2590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
2600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
2613261e8b6eac44a41341f112821482bee6c940c98mmentovai
2623261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2633261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpObject
2643261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2653261e8b6eac44a41341f112821482bee6c940c98mmentovai
2663261e8b6eac44a41341f112821482bee6c940c98mmentovai
2673261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpObject::MinidumpObject(Minidump* minidump)
26853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : minidump_(minidump),
26953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
2703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2713261e8b6eac44a41341f112821482bee6c940c98mmentovai
2723261e8b6eac44a41341f112821482bee6c940c98mmentovai
2733261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2743261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpStream
2753261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2763261e8b6eac44a41341f112821482bee6c940c98mmentovai
2773261e8b6eac44a41341f112821482bee6c940c98mmentovai
2783261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpStream::MinidumpStream(Minidump* minidump)
2793261e8b6eac44a41341f112821482bee6c940c98mmentovai    : MinidumpObject(minidump) {
2803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2813261e8b6eac44a41341f112821482bee6c940c98mmentovai
2823261e8b6eac44a41341f112821482bee6c940c98mmentovai
2833261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2843261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpContext
2853261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2863261e8b6eac44a41341f112821482bee6c940c98mmentovai
2873261e8b6eac44a41341f112821482bee6c940c98mmentovai
2883261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext::MinidumpContext(Minidump* minidump)
28953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
290233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_(),
291233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_flags_(0) {
2923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2933261e8b6eac44a41341f112821482bee6c940c98mmentovai
2943261e8b6eac44a41341f112821482bee6c940c98mmentovai
2953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiMinidumpContext::~MinidumpContext() {
2963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
2973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
2983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
2993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3003261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpContext::Read(u_int32_t expected_size) {
3013261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
3023261e8b6eac44a41341f112821482bee6c940c98mmentovai
3033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
3043261e8b6eac44a41341f112821482bee6c940c98mmentovai
3053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // First, figure out what type of CPU this context structure is for.
3068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // For some reason, the AMD64 Context doesn't have context_flags
3078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // at the beginning of the structure, so special case it here.
3088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (expected_size == sizeof(MDRawContextAMD64)) {
3098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
3108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
3118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
3128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(context_amd64.get(),
3138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                              sizeof(MDRawContextAMD64))) {
3148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
3158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
3168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
3173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
3198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->context_flags);
3203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    u_int32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
322233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
323233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
324233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_amd64->context_flags |= cpu_type;
325233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
326233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
327233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
328233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
329233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
3303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (cpu_type != MD_CONTEXT_AMD64) {
3328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      //TODO: fall through to switch below?
3338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // need a Tell method to be able to SeekSet back to beginning
3348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // http://code.google.com/p/google-breakpad/issues/detail?id=224
3358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
3368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
3378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
3383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Do this after reading the entire MDRawContext structure because
3408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // GetSystemInfo may seek minidump to a new position.
3418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!CheckAgainstSystemInfo(cpu_type)) {
3428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
3438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
3448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
3453261e8b6eac44a41341f112821482bee6c940c98mmentovai
3468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Normalize the 128-bit types in the dump.
3478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Since this is AMD64, by definition, the values are little-endian.
3488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    for (unsigned int vr_index = 0;
3498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         vr_index < MD_CONTEXT_AMD64_VR_COUNT;
3508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         ++vr_index)
3518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Normalize128(&context_amd64->vector_register[vr_index], false);
3528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
3538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap()) {
3548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p1_home);
3558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p2_home);
3568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p3_home);
3578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p4_home);
3588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p5_home);
3598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p6_home);
3608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // context_flags is already swapped
3618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->mx_csr);
3628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->cs);
3638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ds);
3648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->es);
3658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->fs);
3668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ss);
3678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->eflags);
3688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr0);
3698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr1);
3708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr2);
3718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr3);
3728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr6);
3738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr7);
3748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rax);
3758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rcx);
3768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdx);
3778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbx);
3788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsp);
3798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbp);
3808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsi);
3818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdi);
3828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r8);
3838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r9);
3848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r10);
3858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r11);
3868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r12);
3878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r13);
3888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r14);
3898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r15);
3908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rip);
3918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      //FIXME: I'm not sure what actually determines
3928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // which member of the union {flt_save, sse_registers}
3938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // is valid.  We're not currently using either,
3948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // but it would be good to have them swapped properly.
3953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      for (unsigned int vr_index = 0;
3978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           vr_index < MD_CONTEXT_AMD64_VR_COUNT;
3988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           ++vr_index)
3998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        Swap(&context_amd64->vector_register[vr_index]);
4008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->vector_control);
4018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->debug_control);
4028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_to_rip);
4038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_from_rip);
4048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_to_rip);
4058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_from_rip);
4068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_amd64->context_flags;
4093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_.amd64 = context_amd64.release();
4118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  }
4128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  else {
4138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    u_int32_t context_flags;
4148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
4158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read context flags";
4168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
4188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
4198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_flags);
4208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
4221a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    if (cpu_type == 0) {
4231a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // Unfortunately the flag for MD_CONTEXT_ARM that was taken
4241a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // from a Windows CE SDK header conflicts in practice with
4251a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
4261a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // but handle dumps with the legacy value gracefully here.
4271a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      if (context_flags & MD_CONTEXT_ARM_OLD) {
4281a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags |= MD_CONTEXT_ARM;
4291a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags &= ~MD_CONTEXT_ARM_OLD;
4301a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        cpu_type = MD_CONTEXT_ARM;
4311a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      }
4321a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    }
4338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
434233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
435233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
436233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_flags |= cpu_type;
437233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
438233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
439233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
440233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
441233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
442233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Allocate the context structure for the correct CPU and fill it.  The
4448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // casts are slightly unorthodox, but it seems better to do that than to
4458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // maintain a separate pointer for each type of CPU context structure
4468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // when only one of them will be used.
4478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    switch (cpu_type) {
4488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_X86: {
4498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextX86)) {
4508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
4518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextX86);
4528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
4538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
4543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
4563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
4588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
4598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
4608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_x86->context_flags = context_flags;
4613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_x86->context_flags);
4638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        u_int8_t* context_after_flags =
4648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          reinterpret_cast<u_int8_t*>(context_x86.get()) + flags_size;
4658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
4668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextX86) - flags_size)) {
4678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read x86 context";
4688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
4698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
4703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
4728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
4738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
4748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
4758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
4768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
4773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
4798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->context_flags was already swapped.
4808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr0);
4818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr1);
4828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr2);
4838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr3);
4848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr6);
4858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr7);
4868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.control_word);
4878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.status_word);
4888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.tag_word);
4898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_offset);
4908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_selector);
4918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_offset);
4928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_selector);
4938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->float_save.register_area[] contains 8-bit quantities
4948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // and does not need to be swapped.
4958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.cr0_npx_state);
4968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->gs);
4978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->fs);
4988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->es);
4998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ds);
5008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edi);
5018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esi);
5028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebx);
5038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edx);
5048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ecx);
5058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eax);
5068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebp);
5078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eip);
5088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->cs);
5098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eflags);
5108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esp);
5118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ss);
5128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->extended_registers[] contains 8-bit quantities and
5138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // does not need to be swapped.
5148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
5153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.x86 = context_x86.release();
5178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
5191d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      }
5201d78cad82e3c7aa2315ed7438211a1901a91ed34bryner
5218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_PPC: {
5228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextPPC)) {
5238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
5248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextPPC);
5258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
5268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
5278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
5298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
5318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
5328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
5338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_ppc->context_flags = context_flags;
5348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_ppc->context_flags);
5368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        u_int8_t* context_after_flags =
5378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          reinterpret_cast<u_int8_t*>(context_ppc.get()) + flags_size;
5388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
5398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextPPC) - flags_size)) {
5408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read ppc context";
5418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
5423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
5438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
5458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
5468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
5478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
5488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
5493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
5508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Normalize the 128-bit types in the dump.
5528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Since this is PowerPC, by definition, the values are big-endian.
5533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int vr_index = 0;
5543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
5553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++vr_index) {
5568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
5573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
5583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
5608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_ppc->context_flags was already swapped.
5618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr0);
5628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr1);
5638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
5648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
5658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
5668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->gpr[gpr_index]);
5678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
5688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->cr);
5698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->xer);
5708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->lr);
5718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->ctr);
5728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->mq);
5738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vrsave);
5748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
5758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
5768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
5778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->float_save.fpregs[fpr_index]);
5788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
5798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap context_ppc->float_save.fpscr_pad because it is only
5808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // used for padding.
5818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->float_save.fpscr);
5828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int vr_index = 0;
5838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
5848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++vr_index) {
5858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->vector_save.save_vr[vr_index]);
5868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
5878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vscr);
5888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap the padding fields in vector_save.
5898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vrvalid);
5908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
5913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ppc = context_ppc.release();
5933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
595ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
596ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
5978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_SPARC: {
5988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextSPARC)) {
5998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
6008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextSPARC);
6018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
603ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
605ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
6078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
6088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
6098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_sparc->context_flags = context_flags;
610ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_sparc->context_flags);
6128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        u_int8_t* context_after_flags =
6138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            reinterpret_cast<u_int8_t*>(context_sparc.get()) + flags_size;
6148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
6158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextSPARC) - flags_size)) {
6168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read sparc context";
6178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
619ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
6218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
6228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
6238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
6248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
625ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
6268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
6288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_sparc->context_flags was already swapped.
6298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
6308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
6318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
6328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->g_r[gpr_index]);
6338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
6348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->ccr);
6358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->pc);
6368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->npc);
6378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->y);
6388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->asi);
6398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->fprs);
6408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
6418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
6428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
6438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->float_save.regs[fpr_index]);
6448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
6458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.filler);
6468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.fsr);
647ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
6488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ctx_sparc = context_sparc.release();
649ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
6518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
652ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
6539276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      case MD_CONTEXT_ARM: {
6549276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (expected_size != sizeof(MDRawContextARM)) {
6559276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
6569276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            expected_size << " != " << sizeof(MDRawContextARM);
6579276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
6589276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
6599276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
6609276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
6619276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
6629276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Set the context_flags member, which has already been read, and
6639276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // read the rest of the structure beginning with the first member
6649276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // after context_flags.
6659276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_arm->context_flags = context_flags;
6669276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
6679276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        size_t flags_size = sizeof(context_arm->context_flags);
6689276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        u_int8_t* context_after_flags =
6699276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            reinterpret_cast<u_int8_t*>(context_arm.get()) + flags_size;
6709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
6719276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek                                  sizeof(MDRawContextARM) - flags_size)) {
6729276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read arm context";
6739276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
6749276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
6759276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
6769276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Do this after reading the entire MDRawContext structure because
6779276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // GetSystemInfo may seek minidump to a new position.
6789276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
6799276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm does not match system info";
6809276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
6819276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
6829276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
6839276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (minidump_->swap()) {
6849276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          // context_arm->context_flags was already swapped.
6859276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int ireg_index = 0;
6869276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
6879276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++ireg_index) {
6889276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->iregs[ireg_index]);
6899276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
6909276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->cpsr);
6919276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->float_save.fpscr);
6929276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpr_index = 0;
6939276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
6949276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpr_index) {
6959276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.regs[fpr_index]);
6969276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
6979276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpe_index = 0;
6989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
6999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpe_index) {
7009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.extra[fpe_index]);
7019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
7029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
7039276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_.arm = context_arm.release();
7049276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
7059276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        break;
7069276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
7079276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
7088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      default: {
709bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com        // Unknown context type - Don't log as an error yet. Let the
7105f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        // caller work that out.
7115f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        BPLOG(INFO) << "MinidumpContext unknown context type " <<
7128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          HexString(cpu_type);
7138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return false;
7148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
7158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
7163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
7178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_flags;
7183261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
7193261e8b6eac44a41341f112821482bee6c940c98mmentovai
7203261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
7213261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
7223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7233261e8b6eac44a41341f112821482bee6c940c98mmentovai
7243261e8b6eac44a41341f112821482bee6c940c98mmentovai
7253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiu_int32_t MinidumpContext::GetContextCPU() const {
726af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
727af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // Don't log a message, GetContextCPU can be legitimately called with
728af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // valid_ false by FreeContext, which is called by Read.
729af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
730af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
731af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
7328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_flags_ & MD_CONTEXT_CPU_MASK;
7333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
7343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
735c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.combool MinidumpContext::GetInstructionPointer(u_int64_t* ip) const {
736c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  BPLOG_IF(ERROR, !ip) << "MinidumpContext::GetInstructionPointer "
737c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com                          "requires |ip|";
738c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  assert(ip);
739c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  *ip = 0;
740c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
741c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  if (!valid_) {
742c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Invalid MinidumpContext for GetInstructionPointer";
743c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
744c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
745c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
746c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  switch (context_flags_ & MD_CONTEXT_CPU_MASK) {
747c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_AMD64:
748c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.amd64->rip;
749c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
750c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_ARM:
751c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.arm->iregs[MD_CONTEXT_ARM_REG_PC];
752c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
753c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_PPC:
754c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ppc->srr0;
755c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
756c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_SPARC:
757c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ctx_sparc->pc;
758c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
759c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_X86:
760c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.x86->eip;
761c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
762c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  default:
763c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    // This should never happen.
764c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer";
765c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
766c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
767c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  return true;
768c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com}
769c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
7703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextX86* MinidumpContext::GetContextX86() const {
772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_X86) {
773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get x86 context";
774af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
775af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
776af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
777af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.x86;
7783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
7793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextPPC* MinidumpContext::GetContextPPC() const {
782af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_PPC) {
783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get ppc context";
784af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
785af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
786af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
787af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.ppc;
7883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
7893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarekconst MDRawContextAMD64* MinidumpContext::GetContextAMD64() const {
7918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (GetContextCPU() != MD_CONTEXT_AMD64) {
7928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get amd64 context";
7938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    return NULL;
7948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  }
7958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
7968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_.amd64;
7978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek}
7988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
799ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovaiconst MDRawContextSPARC* MinidumpContext::GetContextSPARC() const {
800ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (GetContextCPU() != MD_CONTEXT_SPARC) {
801ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get sparc context";
802ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return NULL;
803ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  }
804ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
805ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  return context_.ctx_sparc;
806ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai}
8073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8089276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarekconst MDRawContextARM* MinidumpContext::GetContextARM() const {
8099276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  if (GetContextCPU() != MD_CONTEXT_ARM) {
8109276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get arm context";
8119276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    return NULL;
8129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  }
8139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  return context_.arm;
8159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek}
8169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::FreeContext() {
8183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
8193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
8203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.x86;
8213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
8223261e8b6eac44a41341f112821482bee6c940c98mmentovai
8233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
8243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.ppc;
8253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
8263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
8288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      delete context_.amd64;
8298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
8308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
831ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
832ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      delete context_.ctx_sparc;
833ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
834ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
8369276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      delete context_.arm;
8379276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
8389276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default:
8403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // There is no context record (valid_ is false) or there's a
8413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context record for an unknown CPU (shouldn't happen, only known
8423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // records are stored by Read).
8433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
8443261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
8453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  context_flags_ = 0;
8473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  context_.base = NULL;
8483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
8493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaibool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) {
852e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
8533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // as this function just implements a sanity check.
8543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
855af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!system_info) {
856af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
857af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MinidumpSystemInfo";
8583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return true;
859af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
8603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
861e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
8623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  const MDRawSystemInfo* raw_system_info = system_info->system_info();
863af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
864af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
865af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MDRawSystemInfo";
8663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return false;
867af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
8683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
8703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      raw_system_info->processor_architecture);
8713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Compare the CPU type of the context record to the CPU type in the
8733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // minidump's system info stream.
874af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  bool return_value = false;
8753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (context_cpu_type) {
8763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
877af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
878299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
879299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
880af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
8813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
8823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
8833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
8843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
885af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
886af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
8873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
888ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
8898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
8908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
8918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return_value = true;
8928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
8938eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
894ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
895ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
896ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return_value = true;
897ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
8989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
9009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
9019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        return_value = true;
9029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
9033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  }
9043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
905af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
906af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(context_cpu_type) <<
9070344a368deac6abaa280a298bcea9bb00a90df3fted.mielczarek@gmail.com                                    " wrong for MinidumpSystemInfo CPU " <<
908af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(system_info_cpu_type);
909af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
910af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return return_value;
9113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
9123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::Print() {
915af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
916af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot print invalid data";
917af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return;
918af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
9203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
9213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86: {
9223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextX86* context_x86 = GetContextX86();
9233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextX86\n");
9243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags                = 0x%x\n",
9253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->context_flags);
9263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr0                          = 0x%x\n", context_x86->dr0);
9273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr1                          = 0x%x\n", context_x86->dr1);
9283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr2                          = 0x%x\n", context_x86->dr2);
9293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr3                          = 0x%x\n", context_x86->dr3);
9303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr6                          = 0x%x\n", context_x86->dr6);
9313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr7                          = 0x%x\n", context_x86->dr7);
9323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.control_word      = 0x%x\n",
9333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.control_word);
9343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.status_word       = 0x%x\n",
9353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.status_word);
9363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.tag_word          = 0x%x\n",
9373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.tag_word);
9383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_offset      = 0x%x\n",
9393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_offset);
9403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_selector    = 0x%x\n",
9413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_selector);
9423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_offset       = 0x%x\n",
9433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_offset);
9443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_selector     = 0x%x\n",
9453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_selector);
9463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.register_area[%2d] = 0x",
9473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
9483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
9493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
9503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
9513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->float_save.register_area[register_index]);
9523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
9533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
9543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.cr0_npx_state     = 0x%x\n",
9553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.cr0_npx_state);
9563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  gs                           = 0x%x\n", context_x86->gs);
9573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  fs                           = 0x%x\n", context_x86->fs);
9583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  es                           = 0x%x\n", context_x86->es);
9593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ds                           = 0x%x\n", context_x86->ds);
9603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edi                          = 0x%x\n", context_x86->edi);
9613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esi                          = 0x%x\n", context_x86->esi);
9623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebx                          = 0x%x\n", context_x86->ebx);
9633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edx                          = 0x%x\n", context_x86->edx);
9643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ecx                          = 0x%x\n", context_x86->ecx);
9653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eax                          = 0x%x\n", context_x86->eax);
9663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebp                          = 0x%x\n", context_x86->ebp);
9673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eip                          = 0x%x\n", context_x86->eip);
9683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cs                           = 0x%x\n", context_x86->cs);
9693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eflags                       = 0x%x\n", context_x86->eflags);
9703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esp                          = 0x%x\n", context_x86->esp);
9713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ss                           = 0x%x\n", context_x86->ss);
9723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  extended_registers[%3d]      = 0x",
9733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
9743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
9753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
9763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
9773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->extended_registers[register_index]);
9783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
9793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n\n");
9803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
9823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
9833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC: {
9853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextPPC* context_ppc = GetContextPPC();
9863402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextPPC\n");
9873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags            = 0x%x\n",
9883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->context_flags);
9893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr0                     = 0x%x\n", context_ppc->srr0);
9903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr1                     = 0x%x\n", context_ppc->srr1);
9913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int gpr_index = 0;
9923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
9933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++gpr_index) {
9943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("  gpr[%2d]                  = 0x%x\n",
9953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               gpr_index, context_ppc->gpr[gpr_index]);
9963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
9973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cr                       = 0x%x\n", context_ppc->cr);
9983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  xer                      = 0x%x\n", context_ppc->xer);
9993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  lr                       = 0x%x\n", context_ppc->lr);
10003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ctr                      = 0x%x\n", context_ppc->ctr);
10013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  mq                       = 0x%x\n", context_ppc->mq);
10023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vrsave                   = 0x%x\n", context_ppc->vrsave);
10033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int fpr_index = 0;
10043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
10053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++fpr_index) {
1006c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
10073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               fpr_index, context_ppc->float_save.fpregs[fpr_index]);
10083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
10093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.fpscr         = 0x%x\n",
10103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->float_save.fpscr);
10113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // TODO(mmentovai): print the 128-bit quantities in
10123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context_ppc->vector_save.  This isn't done yet because printf
10133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // doesn't support 128-bit quantities, and printing them using
1014c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
10153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // byte ordering.
10163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vector_save.save_vrvalid = 0x%x\n",
10173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->vector_save.save_vrvalid);
10183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
10193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
10213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
10223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64: {
10248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      const MDRawContextAMD64* context_amd64 = GetContextAMD64();
10258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("MDRawContextAMD64\n");
1026c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p1_home       = 0x%" PRIx64 "\n",
10278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p1_home);
1028c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p2_home       = 0x%" PRIx64 "\n",
10298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p2_home);
1030c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p3_home       = 0x%" PRIx64 "\n",
10318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p3_home);
1032c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p4_home       = 0x%" PRIx64 "\n",
10338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p4_home);
1034c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p5_home       = 0x%" PRIx64 "\n",
10358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p5_home);
1036c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p6_home       = 0x%" PRIx64 "\n",
10378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p6_home);
10388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  context_flags = 0x%x\n",
10398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->context_flags);
10408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  mx_csr        = 0x%x\n",
10418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->mx_csr);
10428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  cs            = 0x%x\n", context_amd64->cs);
10438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ds            = 0x%x\n", context_amd64->ds);
10448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  es            = 0x%x\n", context_amd64->es);
10458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  fs            = 0x%x\n", context_amd64->fs);
10468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  gs            = 0x%x\n", context_amd64->gs);
10478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ss            = 0x%x\n", context_amd64->ss);
10488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  eflags        = 0x%x\n", context_amd64->eflags);
1049c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr0           = 0x%" PRIx64 "\n", context_amd64->dr0);
1050c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr1           = 0x%" PRIx64 "\n", context_amd64->dr1);
1051c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr2           = 0x%" PRIx64 "\n", context_amd64->dr2);
1052c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr3           = 0x%" PRIx64 "\n", context_amd64->dr3);
1053c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr6           = 0x%" PRIx64 "\n", context_amd64->dr6);
1054c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr7           = 0x%" PRIx64 "\n", context_amd64->dr7);
1055c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rax           = 0x%" PRIx64 "\n", context_amd64->rax);
1056c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rcx           = 0x%" PRIx64 "\n", context_amd64->rcx);
1057c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdx           = 0x%" PRIx64 "\n", context_amd64->rdx);
1058c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbx           = 0x%" PRIx64 "\n", context_amd64->rbx);
1059c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsp           = 0x%" PRIx64 "\n", context_amd64->rsp);
1060c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbp           = 0x%" PRIx64 "\n", context_amd64->rbp);
1061c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsi           = 0x%" PRIx64 "\n", context_amd64->rsi);
1062c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdi           = 0x%" PRIx64 "\n", context_amd64->rdi);
1063c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r8            = 0x%" PRIx64 "\n", context_amd64->r8);
1064c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r9            = 0x%" PRIx64 "\n", context_amd64->r9);
1065c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r10           = 0x%" PRIx64 "\n", context_amd64->r10);
1066c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r11           = 0x%" PRIx64 "\n", context_amd64->r11);
1067c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r12           = 0x%" PRIx64 "\n", context_amd64->r12);
1068c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r13           = 0x%" PRIx64 "\n", context_amd64->r13);
1069c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r14           = 0x%" PRIx64 "\n", context_amd64->r14);
1070c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r15           = 0x%" PRIx64 "\n", context_amd64->r15);
1071c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rip           = 0x%" PRIx64 "\n", context_amd64->rip);
10728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      //TODO: print xmm, vector, debug registers
10738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("\n");
10748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
10758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
10768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1077ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC: {
1078ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      const MDRawContextSPARC* context_sparc = GetContextSPARC();
1079ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("MDRawContextSPARC\n");
1080ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("  context_flags       = 0x%x\n",
1081ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->context_flags);
1082ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int g_r_index = 0;
1083ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
1084ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++g_r_index) {
1085c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  g_r[%2d]             = 0x%" PRIx64 "\n",
1086ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               g_r_index, context_sparc->g_r[g_r_index]);
1087ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1088c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  ccr                 = 0x%" PRIx64 "\n", context_sparc->ccr);
1089c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  pc                  = 0x%" PRIx64 "\n", context_sparc->pc);
1090c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  npc                 = 0x%" PRIx64 "\n", context_sparc->npc);
1091c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  y                   = 0x%" PRIx64 "\n", context_sparc->y);
1092c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  asi                 = 0x%" PRIx64 "\n", context_sparc->asi);
1093c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  fprs                = 0x%" PRIx64 "\n", context_sparc->fprs);
1094ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1095ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int fpr_index = 0;
1096ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
1097ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++fpr_index) {
1098c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
1099ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               fpr_index, context_sparc->float_save.regs[fpr_index]);
1100ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1101c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.filler   = 0x%" PRIx64 "\n",
1102ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.filler);
1103c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.fsr      = 0x%" PRIx64 "\n",
1104ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.fsr);
1105ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
1106ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
1107ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
11089276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM: {
11099276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      const MDRawContextARM* context_arm = GetContextARM();
11109276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("MDRawContextARM\n");
11119276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  context_flags       = 0x%x\n",
11129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek             context_arm->context_flags);
11139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int ireg_index = 0;
11149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
11159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++ireg_index) {
11169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  iregs[%2d]            = 0x%x\n",
11179276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index, context_arm->iregs[ireg_index]);
11189276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
11199276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  cpsr                = 0x%x\n", context_arm->cpsr);
11209276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  float_save.fpscr     = 0x%" PRIx64 "\n",
11211adb184d420c6c5f2304fb945f8477557336f927ted.mielczarek             context_arm->float_save.fpscr);
11229276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpr_index = 0;
11239276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
11249276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpr_index) {
11259276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
11269276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index, context_arm->float_save.regs[fpr_index]);
11279276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
11289276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpe_index = 0;
11299276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
11309276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpe_index) {
11310441036f9ec45c3bc3037f2b407cf21a8006d66fjimblandy        printf("  float_save.extra[%2d] = 0x%" PRIx32 "\n",
11329276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index, context_arm->float_save.extra[fpe_index]);
11339276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
11349276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
11359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
11369276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    }
11379276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
11383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default: {
11393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
11403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
11413261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
11423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11433261e8b6eac44a41341f112821482bee6c940c98mmentovai
11443261e8b6eac44a41341f112821482bee6c940c98mmentovai
11453261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11463261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryRegion
11473261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11483261e8b6eac44a41341f112821482bee6c940c98mmentovai
11493261e8b6eac44a41341f112821482bee6c940c98mmentovai
1150e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiu_int32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
1151e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1152e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
11533261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
115453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
115553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptor_(NULL),
115653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL) {
11573261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11583261e8b6eac44a41341f112821482bee6c940c98mmentovai
11593261e8b6eac44a41341f112821482bee6c940c98mmentovai
11603261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::~MinidumpMemoryRegion() {
11613261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
11623261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11633261e8b6eac44a41341f112821482bee6c940c98mmentovai
11643261e8b6eac44a41341f112821482bee6c940c98mmentovai
11653261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
11663261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptor_ = descriptor;
11673261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = descriptor &&
1168fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai           descriptor_->memory.data_size <=
1169c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek               numeric_limits<u_int64_t>::max() -
1170fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               descriptor_->start_of_memory_range;
11713261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11723261e8b6eac44a41341f112821482bee6c940c98mmentovai
11733261e8b6eac44a41341f112821482bee6c940c98mmentovai
11742214cb9bc1872cafae9127778c0cba556c89e43djimblandyconst u_int8_t* MinidumpMemoryRegion::GetMemory() const {
1175af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1176af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
11773261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11793261e8b6eac44a41341f112821482bee6c940c98mmentovai
11803261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!memory_) {
1181af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (descriptor_->memory.data_size == 0) {
1182af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
1183373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
1184af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
1185373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1186af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(descriptor_->memory.rva)) {
1187af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
11883261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1189af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
11903261e8b6eac44a41341f112821482bee6c940c98mmentovai
1191e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (descriptor_->memory.data_size > max_bytes_) {
1192e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
1193e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      descriptor_->memory.data_size << " exceeds maximum " <<
1194e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_bytes_;
1195e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
1196e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
1197e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
11982466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > memory(
11993261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(descriptor_->memory.data_size));
12003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1201af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
1202af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
12033261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1204af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
12053261e8b6eac44a41341f112821482bee6c940c98mmentovai
12063261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory_ = memory.release();
12073261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
12083261e8b6eac44a41341f112821482bee6c940c98mmentovai
12093261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*memory_)[0];
12103261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12113261e8b6eac44a41341f112821482bee6c940c98mmentovai
12123261e8b6eac44a41341f112821482bee6c940c98mmentovai
12132214cb9bc1872cafae9127778c0cba556c89e43djimblandyu_int64_t MinidumpMemoryRegion::GetBase() const {
1214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
1216af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return static_cast<u_int64_t>(-1);
1217af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1218af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1219af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->start_of_memory_range;
12203261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12213261e8b6eac44a41341f112821482bee6c940c98mmentovai
12223261e8b6eac44a41341f112821482bee6c940c98mmentovai
12232214cb9bc1872cafae9127778c0cba556c89e43djimblandyu_int32_t MinidumpMemoryRegion::GetSize() const {
1224af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1225af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
1226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
1227af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->memory.data_size;
12303261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12313261e8b6eac44a41341f112821482bee6c940c98mmentovai
12323261e8b6eac44a41341f112821482bee6c940c98mmentovai
12333261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::FreeMemory() {
12343261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
12353261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
12363261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12373261e8b6eac44a41341f112821482bee6c940c98mmentovai
12383261e8b6eac44a41341f112821482bee6c940c98mmentovai
12393261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
12403261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddressInternal(u_int64_t address,
12412214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                                      T*        value) const {
1242af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
1243af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                             "requires |value|";
1244af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(value);
1245af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *value = 0;
1246af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1247af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1248af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
1249af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "GetMemoryAtAddressInternal";
12503261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1251af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12523261e8b6eac44a41341f112821482bee6c940c98mmentovai
1253bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Common failure case
12543261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (address < descriptor_->start_of_memory_range ||
1255fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      sizeof(T) > numeric_limits<u_int64_t>::max() - address ||
12563261e8b6eac44a41341f112821482bee6c940c98mmentovai      address + sizeof(T) > descriptor_->start_of_memory_range +
12573261e8b6eac44a41341f112821482bee6c940c98mmentovai                            descriptor_->memory.data_size) {
1258bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com    BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
1259af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(address) << "+" << sizeof(T) << "/" <<
1260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->start_of_memory_range) << "+" <<
1261af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->memory.data_size);
12623261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
12633261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
12643261e8b6eac44a41341f112821482bee6c940c98mmentovai
12653261e8b6eac44a41341f112821482bee6c940c98mmentovai  const u_int8_t* memory = GetMemory();
1266af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!memory) {
1267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // GetMemory already logged a perfectly good message.
12683261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12703261e8b6eac44a41341f112821482bee6c940c98mmentovai
12713261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the CPU requires memory accesses to be aligned, this can crash.
12723261e8b6eac44a41341f112821482bee6c940c98mmentovai  // x86 and ppc are able to cope, though.
12733261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = *reinterpret_cast<const T*>(
12743261e8b6eac44a41341f112821482bee6c940c98mmentovai      &memory[address - descriptor_->start_of_memory_range]);
12753261e8b6eac44a41341f112821482bee6c940c98mmentovai
12763261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
12773261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(value);
12783261e8b6eac44a41341f112821482bee6c940c98mmentovai
12793261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
12803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12813261e8b6eac44a41341f112821482bee6c940c98mmentovai
12823261e8b6eac44a41341f112821482bee6c940c98mmentovai
12833261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
12842214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                              u_int8_t*  value) const {
12853261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
12863261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12873261e8b6eac44a41341f112821482bee6c940c98mmentovai
12883261e8b6eac44a41341f112821482bee6c940c98mmentovai
12893261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
12902214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                              u_int16_t* value) const {
12913261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
12923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12933261e8b6eac44a41341f112821482bee6c940c98mmentovai
12943261e8b6eac44a41341f112821482bee6c940c98mmentovai
12953261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
12962214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                              u_int32_t* value) const {
12973261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
12983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12993261e8b6eac44a41341f112821482bee6c940c98mmentovai
13003261e8b6eac44a41341f112821482bee6c940c98mmentovai
13013261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
13022214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                              u_int64_t* value) const {
13033261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
13043261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13053261e8b6eac44a41341f112821482bee6c940c98mmentovai
13063261e8b6eac44a41341f112821482bee6c940c98mmentovai
13073261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::Print() {
1308af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1309af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
13103261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1311af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13123261e8b6eac44a41341f112821482bee6c940c98mmentovai
13133261e8b6eac44a41341f112821482bee6c940c98mmentovai  const u_int8_t* memory = GetMemory();
13143261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
13153261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("0x");
13163261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int byte_index = 0;
13173261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index < descriptor_->memory.data_size;
13183261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index++) {
13193261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("%02x", memory[byte_index]);
13203261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
13213261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
13223261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
13233261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No memory\n");
13243261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
13253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13263261e8b6eac44a41341f112821482bee6c940c98mmentovai
13273261e8b6eac44a41341f112821482bee6c940c98mmentovai
13283261e8b6eac44a41341f112821482bee6c940c98mmentovai//
13293261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThread
13303261e8b6eac44a41341f112821482bee6c940c98mmentovai//
13313261e8b6eac44a41341f112821482bee6c940c98mmentovai
13323261e8b6eac44a41341f112821482bee6c940c98mmentovai
13333261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::MinidumpThread(Minidump* minidump)
133453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
133553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_(),
133653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL),
133753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
13383261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13393261e8b6eac44a41341f112821482bee6c940c98mmentovai
13403261e8b6eac44a41341f112821482bee6c940c98mmentovai
13413261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::~MinidumpThread() {
13423261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
13433261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
13443261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13453261e8b6eac44a41341f112821482bee6c940c98mmentovai
13463261e8b6eac44a41341f112821482bee6c940c98mmentovai
13473261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThread::Read() {
13483261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
13493261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
13503261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
13513261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
13523261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
13533261e8b6eac44a41341f112821482bee6c940c98mmentovai
13543261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
13553261e8b6eac44a41341f112821482bee6c940c98mmentovai
1356af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
1357af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot read thread";
13583261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1359af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13603261e8b6eac44a41341f112821482bee6c940c98mmentovai
13613261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
13623261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_id);
13633261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.suspend_count);
13643261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority_class);
13653261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority);
13663261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.teb);
13673261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.stack);
13683261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_context);
13693261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
13703261e8b6eac44a41341f112821482bee6c940c98mmentovai
1371fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
13723261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (thread_.stack.memory.data_size == 0 ||
1373fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      thread_.stack.memory.data_size > numeric_limits<u_int64_t>::max() -
1374fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                                       thread_.stack.start_of_memory_range) {
1375e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    // This is ok, but log an error anyway.
1376af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
1377af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(thread_.stack.start_of_memory_range) << "+" <<
1378fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(thread_.stack.memory.data_size);
1379e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  } else {
1380e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_ = new MinidumpMemoryRegion(minidump_);
1381e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_->SetDescriptor(&thread_.stack);
1382af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
13833261e8b6eac44a41341f112821482bee6c940c98mmentovai
13843261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
13853261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
13863261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13873261e8b6eac44a41341f112821482bee6c940c98mmentovai
13883261e8b6eac44a41341f112821482bee6c940c98mmentovai
13893261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpThread::GetMemory() {
1390af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1391af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
1392af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1393af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1394af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1395af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return memory_;
13963261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13973261e8b6eac44a41341f112821482bee6c940c98mmentovai
13983261e8b6eac44a41341f112821482bee6c940c98mmentovai
13993261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpThread::GetContext() {
1400af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1401af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
14023261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1403af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
14043261e8b6eac44a41341f112821482bee6c940c98mmentovai
14053261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
1406af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(thread_.thread_context.rva)) {
1407af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot seek to context";
14083261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1409af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
14103261e8b6eac44a41341f112821482bee6c940c98mmentovai
14112466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
14123261e8b6eac44a41341f112821482bee6c940c98mmentovai
1413af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(thread_.thread_context.data_size)) {
1414af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot read context";
14153261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1416af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
14173261e8b6eac44a41341f112821482bee6c940c98mmentovai
14183261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
14193261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14203261e8b6eac44a41341f112821482bee6c940c98mmentovai
14213261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
14223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14233261e8b6eac44a41341f112821482bee6c940c98mmentovai
14243261e8b6eac44a41341f112821482bee6c940c98mmentovai
142576f052f8fbf8864dee5992b857229d06560a766ammentovaibool MinidumpThread::GetThreadID(u_int32_t *thread_id) const {
1426af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
1427af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
1428af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
1429af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
1430af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1431af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1432af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
143376f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
1434af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
143576f052f8fbf8864dee5992b857229d06560a766ammentovai
143676f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = thread_.thread_id;
143776f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
14383261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14393261e8b6eac44a41341f112821482bee6c940c98mmentovai
14403261e8b6eac44a41341f112821482bee6c940c98mmentovai
14413261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThread::Print() {
1442af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1443af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
14443261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1445af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
14463261e8b6eac44a41341f112821482bee6c940c98mmentovai
14473261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawThread\n");
14483261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
14493261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suspend_count               = %d\n",     thread_.suspend_count);
14503261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority_class              = 0x%x\n",   thread_.priority_class);
14513261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority                    = 0x%x\n",   thread_.priority);
1452c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
1453c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
14543261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.start_of_memory_range);
14553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.data_size      = 0x%x\n",
14563261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.memory.data_size);
14573261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
14583261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size    = 0x%x\n",
14593261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.data_size);
14603261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva          = 0x%x\n",
14613261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.rva);
14623261e8b6eac44a41341f112821482bee6c940c98mmentovai
14633261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
14643261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
14653261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
14663261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
14673261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
14683261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
14693261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
14703261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14713261e8b6eac44a41341f112821482bee6c940c98mmentovai
14723261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryRegion* memory = GetMemory();
14733261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
14743261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("Stack\n");
14753261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory->Print();
14763261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
14773261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No stack\n");
14783261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
14803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14813261e8b6eac44a41341f112821482bee6c940c98mmentovai
14823261e8b6eac44a41341f112821482bee6c940c98mmentovai
14833261e8b6eac44a41341f112821482bee6c940c98mmentovai//
14843261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThreadList
14853261e8b6eac44a41341f112821482bee6c940c98mmentovai//
14863261e8b6eac44a41341f112821482bee6c940c98mmentovai
14873261e8b6eac44a41341f112821482bee6c940c98mmentovai
1488cb33b20f75e240ffb6a621b615bd4f5f20b181dcnealsidu_int32_t MinidumpThreadList::max_threads_ = 4096;
1489e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1490e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
14913261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::MinidumpThreadList(Minidump* minidump)
149253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
149353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      id_to_thread_map_(),
149453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      threads_(NULL),
149553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_count_(0) {
14963261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14973261e8b6eac44a41341f112821482bee6c940c98mmentovai
14983261e8b6eac44a41341f112821482bee6c940c98mmentovai
14993261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::~MinidumpThreadList() {
15003261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
15013261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15023261e8b6eac44a41341f112821482bee6c940c98mmentovai
15033261e8b6eac44a41341f112821482bee6c940c98mmentovai
15043261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThreadList::Read(u_int32_t expected_size) {
15053261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
15063261e8b6eac44a41341f112821482bee6c940c98mmentovai  id_to_thread_map_.clear();
15073261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
15083261e8b6eac44a41341f112821482bee6c940c98mmentovai  threads_ = NULL;
15093261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = 0;
15103261e8b6eac44a41341f112821482bee6c940c98mmentovai
15113261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
15123261e8b6eac44a41341f112821482bee6c940c98mmentovai
15133261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t thread_count;
1514af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(thread_count)) {
1515af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
1516af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(thread_count);
15173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1518af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1519af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
1520af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
15213261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1522af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
15233261e8b6eac44a41341f112821482bee6c940c98mmentovai
15243261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
15253261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_count);
15263261e8b6eac44a41341f112821482bee6c940c98mmentovai
1527fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (thread_count > numeric_limits<u_int32_t>::max() / sizeof(MDRawThread)) {
1528fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
1529fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
1530fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
1531fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
1532fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
15333261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(thread_count) +
15343261e8b6eac44a41341f112821482bee6c940c98mmentovai                       thread_count * sizeof(MDRawThread)) {
1535ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
1536ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(thread_count) + 4 +
1537ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         thread_count * sizeof(MDRawThread)) {
1538ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      u_int32_t useless;
1539ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
1540ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded bytes";
1541ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
1542ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1543ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
1544ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
1545ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    " != " << sizeof(thread_count) +
1546ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    thread_count * sizeof(MDRawThread);
1547ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
1548ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
15493261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
15503261e8b6eac44a41341f112821482bee6c940c98mmentovai
1551bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com
1552e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count > max_threads_) {
1553e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
1554e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_threads_;
1555e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
1556e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
1557e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1558e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count != 0) {
1559373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpThreads> threads(
1560373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
15613261e8b6eac44a41341f112821482bee6c940c98mmentovai
1562373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int thread_index = 0;
1563373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         thread_index < thread_count;
1564373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++thread_index) {
1565373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpThread* thread = &(*threads)[thread_index];
15663261e8b6eac44a41341f112821482bee6c940c98mmentovai
1567373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
1568af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->Read()) {
1569af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
1570af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1571373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1572af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
15733261e8b6eac44a41341f112821482bee6c940c98mmentovai
1574373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int32_t thread_id;
1575af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->GetThreadID(&thread_id)) {
1576af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
1577af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1578373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1579af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
158076f052f8fbf8864dee5992b857229d06560a766ammentovai
1581373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (GetThreadByID(thread_id)) {
1582373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        // Another thread with this ID is already in the list.  Data error.
1583af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
1584af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(thread_id) << " at thread " <<
1585af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1586373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1587373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
1588373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      id_to_thread_map_[thread_id] = thread;
15893261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
1590373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1591373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    threads_ = threads.release();
15923261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
15933261e8b6eac44a41341f112821482bee6c940c98mmentovai
15943261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = thread_count;
15953261e8b6eac44a41341f112821482bee6c940c98mmentovai
15963261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
15973261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
15983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15993261e8b6eac44a41341f112821482bee6c940c98mmentovai
16003261e8b6eac44a41341f112821482bee6c940c98mmentovai
16013261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
16023261e8b6eac44a41341f112821482bee6c940c98mmentovai    const {
1603af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1604af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
1605af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1606af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1607af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1608af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= thread_count_) {
1609af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
1610af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << thread_count_;
16113261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1612af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16133261e8b6eac44a41341f112821482bee6c940c98mmentovai
16143261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*threads_)[index];
16153261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16163261e8b6eac44a41341f112821482bee6c940c98mmentovai
16173261e8b6eac44a41341f112821482bee6c940c98mmentovai
16183261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadByID(u_int32_t thread_id) {
16193261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't check valid_.  Read calls this method before everything is
16203261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validated.  It is safe to not check valid_ here.
16213261e8b6eac44a41341f112821482bee6c940c98mmentovai  return id_to_thread_map_[thread_id];
16223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16233261e8b6eac44a41341f112821482bee6c940c98mmentovai
16243261e8b6eac44a41341f112821482bee6c940c98mmentovai
16253261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThreadList::Print() {
1626af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1627af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
16283261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16303261e8b6eac44a41341f112821482bee6c940c98mmentovai
16313261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpThreadList\n");
16323261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_count = %d\n", thread_count_);
16333261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
16343261e8b6eac44a41341f112821482bee6c940c98mmentovai
16353261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int thread_index = 0;
16363261e8b6eac44a41341f112821482bee6c940c98mmentovai       thread_index < thread_count_;
16373261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++thread_index) {
16383261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("thread[%d]\n", thread_index);
16393261e8b6eac44a41341f112821482bee6c940c98mmentovai
16403261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*threads_)[thread_index].Print();
16413261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16433261e8b6eac44a41341f112821482bee6c940c98mmentovai
16443261e8b6eac44a41341f112821482bee6c940c98mmentovai
16453261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16463261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModule
16473261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16483261e8b6eac44a41341f112821482bee6c940c98mmentovai
16493261e8b6eac44a41341f112821482bee6c940c98mmentovai
1650cb33b20f75e240ffb6a621b615bd4f5f20b181dcnealsidu_int32_t MinidumpModule::max_cv_bytes_ = 32768;
1651cb33b20f75e240ffb6a621b615bd4f5f20b181dcnealsidu_int32_t MinidumpModule::max_misc_bytes_ = 32768;
1652e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1653e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
16543261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::MinidumpModule(Minidump* minidump)
165553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
1656db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_valid_(false),
165711e180cd3e855796aee4239aa4b22dbda5de9c00mmentovai      has_debug_info_(false),
165853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_(),
165953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      name_(NULL),
166053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      cv_record_(NULL),
166148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
1662db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      misc_record_(NULL) {
16633261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16643261e8b6eac44a41341f112821482bee6c940c98mmentovai
16653261e8b6eac44a41341f112821482bee6c940c98mmentovai
16663261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::~MinidumpModule() {
16673261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
16683261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
16693261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
16703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16713261e8b6eac44a41341f112821482bee6c940c98mmentovai
16723261e8b6eac44a41341f112821482bee6c940c98mmentovai
16733261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModule::Read() {
16743261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
16753261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
16763261e8b6eac44a41341f112821482bee6c940c98mmentovai  name_ = NULL;
16773261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
16783261e8b6eac44a41341f112821482bee6c940c98mmentovai  cv_record_ = NULL;
167948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
16803261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
16813261e8b6eac44a41341f112821482bee6c940c98mmentovai  misc_record_ = NULL;
16823261e8b6eac44a41341f112821482bee6c940c98mmentovai
1683db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = false;
1684d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = false;
16853261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
16863261e8b6eac44a41341f112821482bee6c940c98mmentovai
1687af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
1688af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot read module";
16893261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1690af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16913261e8b6eac44a41341f112821482bee6c940c98mmentovai
16923261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
16933261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.base_of_image);
16943261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.size_of_image);
16953261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.checksum);
16963261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.time_date_stamp);
16973261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.module_name_rva);
16983261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.signature);
16993261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.struct_version);
17003261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_hi);
17013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_lo);
17023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_hi);
17033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_lo);
17043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags_mask);
17053261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags);
17063261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_os);
17073261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_type);
17083261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_subtype);
17093261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_hi);
17103261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_lo);
17113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.cv_record);
17123261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.misc_record);
17133261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't swap reserved fields because their contents are unknown (as
17143261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are their proper widths).
17153261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17163261e8b6eac44a41341f112821482bee6c940c98mmentovai
1717fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
1718fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_.size_of_image == 0 ||
1719fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      module_.size_of_image >
1720fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          numeric_limits<u_int64_t>::max() - module_.base_of_image) {
1721af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
1722af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(module_.base_of_image) << "+" <<
1723fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(module_.size_of_image);
17243261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1725af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17263261e8b6eac44a41341f112821482bee6c940c98mmentovai
1727db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = true;
1728db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return true;
1729db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1730db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1731db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1732db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaibool MinidumpModule::ReadAuxiliaryData() {
1733af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
1734af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
1735db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1736af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1737db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1738db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Each module must have a name.
1739db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  name_ = minidump_->ReadString(module_.module_name_rva);
1740af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!name_) {
1741af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule could not read name";
1742db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1743af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1744db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1745d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  // At this point, we have enough info for the module to be valid.
1746d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  valid_ = true;
1747d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1748db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // CodeView and miscellaneous debug records are only required if the
1749db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // module indicates that they exist.
1750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
1751af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
1752af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1753db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1754af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1755db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1756af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
1757af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
1758af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1759db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1760af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1761db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1762d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = true;
17633261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
17643261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17653261e8b6eac44a41341f112821482bee6c940c98mmentovai
17663261e8b6eac44a41341f112821482bee6c940c98mmentovai
1767db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_file() const {
1768af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1769af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
1770db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1771af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1772db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1773db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return *name_;
1774db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
17753261e8b6eac44a41341f112821482bee6c940c98mmentovai
17763261e8b6eac44a41341f112821482bee6c940c98mmentovai
1777db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_identifier() const {
1778af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1779af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
1780db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1781af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1782db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1783d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1784d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1785d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1786db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
1787af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_system_info) {
1788af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires "
1789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "MinidumpSystemInfo";
1790db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1791af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1792db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1793db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
1794af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1795af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
1796db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1797af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1798db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1799db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1800db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1801db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  switch (raw_system_info->platform_id) {
1802db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_NT:
1803db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_WINDOWS: {
1804c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1805c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1806db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
1807c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
1808db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               module_.time_date_stamp, module_.size_of_image);
1809db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
1810db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1811db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1812db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
18130e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_MAC_OS_X:
181463f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
1815ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
18165187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
18170e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_LINUX: {
1818db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // TODO(mmentovai): support uuid extension if present, otherwise fall
1819db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // back to version (from LC_ID_DYLIB?), otherwise fall back to something
1820db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // else.
1821db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = "id";
1822db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1823db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1824db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1825db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    default: {
1826db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // Without knowing what OS generated the dump, we can't generate a good
1827db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // identifier.  Return an empty string, signalling failure.
1828af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
1829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "found " << HexString(raw_system_info->platform_id);
1830db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1831db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1832db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1833db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1834db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
18353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18363261e8b6eac44a41341f112821482bee6c940c98mmentovai
18373261e8b6eac44a41341f112821482bee6c940c98mmentovai
1838db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_file() const {
1839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
1841db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1842af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1843db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1844d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1845d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1846d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1847db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string file;
1848db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Prefer the CodeView record if present.
184928e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
185048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
185148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
185248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
185348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
185448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
185548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1856db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1857db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
185848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
185948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
1860db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
1861db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
186248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1863db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1864db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1865db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
1866db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1867db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1868db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // If there's a CodeView record but it doesn't match a known signature,
186948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // try the miscellaneous record.
1870db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1871db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1872db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (file.empty()) {
1873db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // No usable CodeView record.  Try the miscellaneous debug record.
187428e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai    if (misc_record_) {
187528e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai      const MDImageDebugMisc* misc_record =
187628e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai          reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
1877db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      if (!misc_record->unicode) {
1878db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // If it's not Unicode, just stuff it into the string.  It's unclear
1879db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // if misc_record->data is 0-terminated, so use an explicit size.
1880db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        file = string(
1881db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            reinterpret_cast<const char*>(misc_record->data),
18822e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize);
1883db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      } else {
1884db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // There's a misc_record but it encodes the debug filename in UTF-16.
1885db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // (Actually, because miscellaneous records are so old, it's probably
1886db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
1887db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // that this method (and all other methods in the Minidump family)
1888db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // return.
1889db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1890db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        unsigned int bytes =
18912e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize;
1892db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        if (bytes % 2 == 0) {
1893db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          unsigned int utf16_words = bytes / 2;
1894db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1895db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF16ToUTF8 expects a vector<u_int16_t>, so create a temporary one
1896db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // and copy the UTF-16 data into it.
1897db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          vector<u_int16_t> string_utf16(utf16_words);
1898db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          if (utf16_words)
1899db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            memcpy(&string_utf16[0], &misc_record->data, bytes);
1900db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1901db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // GetMiscRecord already byte-swapped the data[] field if it contains
1902db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF-16, so pass false as the swap argument.
1903db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
1904db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          file = *new_file;
1905db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        }
1906db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      }
1907db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1908db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1909db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1910bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
1911bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
1912bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                  "debug_file for " << *name_;
1913af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1914db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return file;
1915db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1916db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1917db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1918db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_identifier() const {
1919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1920af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
1921db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1922af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1923db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1924d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
1925d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
1926d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
1927db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1928db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1929db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Use the CodeView record if present.
193028e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
193148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
193248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
193348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
193448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
193548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
193648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1937c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1938c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1939db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[41];
1940db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
1941c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
1942db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data1,
1943db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data2,
1944db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data3,
1945db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[0],
1946db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[1],
1947db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[2],
1948db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[3],
1949db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[4],
1950db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[5],
1951db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[6],
1952db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[7],
1953db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->age);
1954db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
195548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
195648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
1957db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
1958db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
195948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1960db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1961c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1962c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1963db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
1964db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
1965c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%x", cv_record_20->signature, cv_record_20->age);
1966db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
1967db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1968db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1969db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
197048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  // TODO(mmentovai): if there's no usable CodeView record, there might be a
1971db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // miscellaneous debug record.  It only carries a filename, though, and no
1972db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // identifier.  I'm not sure what the right thing to do for the identifier
1973db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // is in that case, but I don't expect to find many modules without a
1974e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  // CodeView record (or some other Breakpad extension structure in place of
1975db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a CodeView record).  Treat it as an error (empty identifier) for now.
1976db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1977db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
1978db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1979bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
1980bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
1981bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                        "debug_identifier for " << *name_;
1982af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1983db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
1984db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1985db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1986db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1987db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::version() const {
1988af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1989af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for version";
1990db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1991af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1992db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1993db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string version;
1994db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1995db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
1996db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
1997db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    char version_string[24];
1998db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
1999db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi >> 16,
2000db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi & 0xffff,
2001db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo >> 16,
2002db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo & 0xffff);
2003db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    version = version_string;
2004db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2005db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2006db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): possibly support other struct types in place of
2007db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
2008db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a different structure that better represents versioning facilities on
2009db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Mac OS X and Linux, instead of forcing them to adhere to the dotted
2010db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // quad of 16-bit ints that Windows uses.
2011db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2012af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
2013af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "version for " << *name_;
2014af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2015db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return version;
2016db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2017db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2018db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2019db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModule* MinidumpModule::Copy() const {
2020db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModule(this);
2021db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2022db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2023db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
202448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovaiconst u_int8_t* MinidumpModule::GetCVRecord(u_int32_t* size) {
2025af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2026af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
20273261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2028af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20293261e8b6eac44a41341f112821482bee6c940c98mmentovai
20303261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!cv_record_) {
203148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // This just guards against 0-sized CodeView records; more specific checks
203248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // are used when the signature is checked against various structure types.
2033af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.cv_record.data_size == 0) {
20343261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2035af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
20363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2037af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.cv_record.rva)) {
2038af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
20393261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2040af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
20413261e8b6eac44a41341f112821482bee6c940c98mmentovai
2042e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.cv_record.data_size > max_cv_bytes_) {
2043e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
2044e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.cv_record.data_size << " exceeds maximum " <<
2045e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_cv_bytes_;
2046e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2047e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
20483261e8b6eac44a41341f112821482bee6c940c98mmentovai
20493261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDCVInfoPDB70 or
20503261e8b6eac44a41341f112821482bee6c940c98mmentovai    // MDCVInfoPDB20 but is allocated as u_int8_t[] can cause alignment
20513261e8b6eac44a41341f112821482bee6c940c98mmentovai    // problems.  x86 and ppc are able to cope, though.  This allocation
20523261e8b6eac44a41341f112821482bee6c940c98mmentovai    // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
20533261e8b6eac44a41341f112821482bee6c940c98mmentovai    // variable-sized due to their pdb_file_name fields; these structures
20542e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
20553261e8b6eac44a41341f112821482bee6c940c98mmentovai    // them as such would result in incomplete structures or overruns.
20562466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > cv_record(
20573261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(module_.cv_record.data_size));
20583261e8b6eac44a41341f112821482bee6c940c98mmentovai
2059af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
2060af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
20613261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2062af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
20633261e8b6eac44a41341f112821482bee6c940c98mmentovai
206448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    u_int32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
206548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (module_.cv_record.data_size > sizeof(signature)) {
206648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      MDCVInfoPDB70* cv_record_signature =
206748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
206848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      signature = cv_record_signature->cv_signature;
206948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      if (minidump_->swap())
207048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        Swap(&signature);
207148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    }
20723261e8b6eac44a41341f112821482bee6c940c98mmentovai
20733261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature == MD_CVINFOPDB70_SIGNATURE) {
20743261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Now that the structure type is known, recheck the size.
20752e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
2076af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
20772e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB70_minsize << " > " <<
2078af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
20793261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2080af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
20813261e8b6eac44a41341f112821482bee6c940c98mmentovai
20823261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
208348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        MDCVInfoPDB70* cv_record_70 =
208448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
20853261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->cv_signature);
20863261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->signature);
20873261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->age);
20883261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
208948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        // quantities.  (It's a path, is it UTF-8?)
20903261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
209148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
209248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
209348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2094af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2095af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
2096af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
209748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2098af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
20993261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
210048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // Now that the structure type is known, recheck the size.
21012e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
2102af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
21032e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB20_minsize << " > " <<
2104af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
210548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2106af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21073261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
21083261e8b6eac44a41341f112821482bee6c940c98mmentovai        MDCVInfoPDB20* cv_record_20 =
210948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
21103261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.signature);
21113261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.offset);
21123261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->signature);
21133261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->age);
21143261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
21153261e8b6eac44a41341f112821482bee6c940c98mmentovai        // quantities.  (It's a path, is it UTF-8?)
21163261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
211748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
211848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
211948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2120af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2121af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
2122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
212348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2124af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21253261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
21263261e8b6eac44a41341f112821482bee6c940c98mmentovai
212748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // If the signature doesn't match something above, it's not something
2128e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    // that Breakpad can presently handle directly.  Because some modules in
212948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
213048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // don't bail out here - allow the data to be returned to the user,
213148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // although byte-swapping can't be done.
21323261e8b6eac44a41341f112821482bee6c940c98mmentovai
21333261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
21343261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to u_int8_t*.
21353261e8b6eac44a41341f112821482bee6c940c98mmentovai    cv_record_ = cv_record.release();
213648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    cv_record_signature_ = signature;
21373261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21383261e8b6eac44a41341f112821482bee6c940c98mmentovai
213948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
214048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.cv_record.data_size;
214148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
21423261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*cv_record_)[0];
21433261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21443261e8b6eac44a41341f112821482bee6c940c98mmentovai
21453261e8b6eac44a41341f112821482bee6c940c98mmentovai
214648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovaiconst MDImageDebugMisc* MinidumpModule::GetMiscRecord(u_int32_t* size) {
2147af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2148af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
21493261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2150af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
21513261e8b6eac44a41341f112821482bee6c940c98mmentovai
21523261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!misc_record_) {
2153af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size == 0) {
21543261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2155af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
21563261e8b6eac44a41341f112821482bee6c940c98mmentovai
21572e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
2158af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
21592e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                      "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
2160af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      module_.misc_record.data_size;
21613261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2162af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
2163af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2164af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.misc_record.rva)) {
2165af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
2166af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "debugging record";
2167af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      return NULL;
2168af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
21693261e8b6eac44a41341f112821482bee6c940c98mmentovai
2170e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.misc_record.data_size > max_misc_bytes_) {
2171e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
2172e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.misc_record.data_size << " exceeds maximum " <<
2173e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_misc_bytes_;
2174e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2175e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
21763261e8b6eac44a41341f112821482bee6c940c98mmentovai
21773261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDImageDebugMisc but
21783261e8b6eac44a41341f112821482bee6c940c98mmentovai    // is allocated as u_int8_t[] can cause alignment problems.  x86 and
21793261e8b6eac44a41341f112821482bee6c940c98mmentovai    // ppc are able to cope, though.  This allocation style is needed
21803261e8b6eac44a41341f112821482bee6c940c98mmentovai    // because the MDImageDebugMisc is variable-sized due to its data field;
21812e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // this structure is not MDImageDebugMisc_minsize and treating it as such
21823261e8b6eac44a41341f112821482bee6c940c98mmentovai    // would result in an incomplete structure or an overrun.
21832466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > misc_record_mem(
21843261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(module_.misc_record.data_size));
21853261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDImageDebugMisc* misc_record =
21863261e8b6eac44a41341f112821482bee6c940c98mmentovai        reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
21873261e8b6eac44a41341f112821482bee6c940c98mmentovai
2188af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
2189af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
2190af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "record";
21913261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2192af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
21933261e8b6eac44a41341f112821482bee6c940c98mmentovai
21943261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (minidump_->swap()) {
21953261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->data_type);
21963261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->length);
21973261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap misc_record.unicode because it's an 8-bit quantity.
21983261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap the reserved fields for the same reason, and because
21993261e8b6eac44a41341f112821482bee6c940c98mmentovai      // they don't contain any valid data.
22003261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (misc_record->unicode) {
22013261e8b6eac44a41341f112821482bee6c940c98mmentovai        // There is a potential alignment problem, but shouldn't be a problem
22023261e8b6eac44a41341f112821482bee6c940c98mmentovai        // in practice due to the layout of MDImageDebugMisc.
22033261e8b6eac44a41341f112821482bee6c940c98mmentovai        u_int16_t* data16 = reinterpret_cast<u_int16_t*>(&(misc_record->data));
22043261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataBytes = module_.misc_record.data_size -
22052e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                                 MDImageDebugMisc_minsize;
22063261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataLength = dataBytes / 2;
22073261e8b6eac44a41341f112821482bee6c940c98mmentovai        for (unsigned int characterIndex = 0;
22083261e8b6eac44a41341f112821482bee6c940c98mmentovai             characterIndex < dataLength;
22093261e8b6eac44a41341f112821482bee6c940c98mmentovai             ++characterIndex) {
22103261e8b6eac44a41341f112821482bee6c940c98mmentovai          Swap(&data16[characterIndex]);
22113261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
22123261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
22133261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
22143261e8b6eac44a41341f112821482bee6c940c98mmentovai
2215af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size != misc_record->length) {
2216af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
2217af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << module_.misc_record.data_size <<
2218af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      " != " << misc_record->length;
22193261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
22213261e8b6eac44a41341f112821482bee6c940c98mmentovai
22223261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
22233261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to MDImageDebugMisc*.
22243261e8b6eac44a41341f112821482bee6c940c98mmentovai    misc_record_ = misc_record_mem.release();
22253261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
22263261e8b6eac44a41341f112821482bee6c940c98mmentovai
222748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
222848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.misc_record.data_size;
222948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
22303261e8b6eac44a41341f112821482bee6c940c98mmentovai  return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
22313261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22323261e8b6eac44a41341f112821482bee6c940c98mmentovai
22333261e8b6eac44a41341f112821482bee6c940c98mmentovai
22343261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModule::Print() {
2235af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2236af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
22373261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2238af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22393261e8b6eac44a41341f112821482bee6c940c98mmentovai
22403261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawModule\n");
2241c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  base_of_image                   = 0x%" PRIx64 "\n",
22423261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.base_of_image);
22433261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_image                   = 0x%x\n",
22443261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.size_of_image);
22453261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum                        = 0x%x\n",
22463261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.checksum);
22473261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp                 = 0x%x\n",
22483261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.time_date_stamp);
22493261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_name_rva                 = 0x%x\n",
22503261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.module_name_rva);
22513261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.signature          = 0x%x\n",
22523261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.signature);
22533261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.struct_version     = 0x%x\n",
22543261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.struct_version);
22553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_version       = 0x%x:0x%x\n",
22563261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_hi,
22573261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_lo);
22583261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.product_version    = 0x%x:0x%x\n",
22593261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_hi,
22603261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_lo);
22613261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags_mask    = 0x%x\n",
22623261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags_mask);
22633261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags         = 0x%x\n",
22643261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags);
22653261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_os            = 0x%x\n",
22663261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_os);
22673261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_type          = 0x%x\n",
22683261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_type);
22693261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_subtype       = 0x%x\n",
22703261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_subtype);
22713261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_date          = 0x%x:0x%x\n",
22723261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_hi,
22733261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_lo);
22743261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.data_size             = %d\n",
22753261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.data_size);
22763261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.rva                   = 0x%x\n",
22773261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.rva);
22783261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.data_size           = %d\n",
22793261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.data_size);
22803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.rva                 = 0x%x\n",
22813261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.rva);
22823261e8b6eac44a41341f112821482bee6c940c98mmentovai
2283db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
2284db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_identifier)               = \"%s\"\n",
2285db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         code_identifier().c_str());
22863261e8b6eac44a41341f112821482bee6c940c98mmentovai
228748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  u_int32_t cv_record_size;
228848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const u_int8_t *cv_record = GetCVRecord(&cv_record_size);
22893261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (cv_record) {
229048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
229148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
229248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
229348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
229448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
22953261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_signature        = 0x%x\n",
229648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->cv_signature);
22973261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
229848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data1,
229948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data2,
230048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data3,
230148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[0],
230248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[1]);
23033261e8b6eac44a41341f112821482bee6c940c98mmentovai      for (unsigned int guidIndex = 2;
23043261e8b6eac44a41341f112821482bee6c940c98mmentovai           guidIndex < 8;
23053261e8b6eac44a41341f112821482bee6c940c98mmentovai           ++guidIndex) {
230648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record_70->signature.data4[guidIndex]);
23073261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
23083261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("\n");
23093261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
231048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->age);
23113261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
231248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->pdb_file_name);
231348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
23143261e8b6eac44a41341f112821482bee6c940c98mmentovai      const MDCVInfoPDB20* cv_record_20 =
231548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
231648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
231748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
23183261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.signature = 0x%x\n",
23193261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.signature);
23203261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.offset    = 0x%x\n",
23213261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.offset);
23223261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = 0x%x\n",
23233261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->signature);
23243261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
23253261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->age);
23263261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
23273261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->pdb_file_name);
232848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else {
232948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("  (cv_record)                     = ");
233048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      for (unsigned int cv_byte_index = 0;
233148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           cv_byte_index < cv_record_size;
233248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           ++cv_byte_index) {
233348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record[cv_byte_index]);
233448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      }
233548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("\n");
23363261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
23373261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
23383261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (cv_record)                     = (null)\n");
23393261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23403261e8b6eac44a41341f112821482bee6c940c98mmentovai
234148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
23423261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_record) {
23433261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).data_type         = 0x%x\n",
23443261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->data_type);
23453261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).length            = 0x%x\n",
23463261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->length);
23473261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).unicode           = %d\n",
23483261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->unicode);
23493261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't bother printing the UTF-16, we don't really even expect to ever
23503261e8b6eac44a41341f112821482bee6c940c98mmentovai    // see this misc_record anyway.
23513261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_record->unicode)
23523261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = \"%s\"\n",
23533261e8b6eac44a41341f112821482bee6c940c98mmentovai             misc_record->data);
23543261e8b6eac44a41341f112821482bee6c940c98mmentovai    else
23553261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = (UTF-16)\n");
23563261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
23573261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record)                   = (null)\n");
23583261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23593261e8b6eac44a41341f112821482bee6c940c98mmentovai
2360db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
2361db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_identifier)              = \"%s\"\n",
2362db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         debug_identifier().c_str());
2363db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (version)                       = \"%s\"\n", version().c_str());
23643261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
23653261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23663261e8b6eac44a41341f112821482bee6c940c98mmentovai
23673261e8b6eac44a41341f112821482bee6c940c98mmentovai
23683261e8b6eac44a41341f112821482bee6c940c98mmentovai//
23693261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModuleList
23703261e8b6eac44a41341f112821482bee6c940c98mmentovai//
23713261e8b6eac44a41341f112821482bee6c940c98mmentovai
23723261e8b6eac44a41341f112821482bee6c940c98mmentovai
2373e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiu_int32_t MinidumpModuleList::max_modules_ = 1024;
2374e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2375e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
23763261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::MinidumpModuleList(Minidump* minidump)
237753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
2378fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai      range_map_(new RangeMap<u_int64_t, unsigned int>()),
237953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      modules_(NULL),
238053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_count_(0) {
23813261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23823261e8b6eac44a41341f112821482bee6c940c98mmentovai
23833261e8b6eac44a41341f112821482bee6c940c98mmentovai
23843261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::~MinidumpModuleList() {
2385fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
23863261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
23873261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23883261e8b6eac44a41341f112821482bee6c940c98mmentovai
23893261e8b6eac44a41341f112821482bee6c940c98mmentovai
23903261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModuleList::Read(u_int32_t expected_size) {
23913261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
2392fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
23933261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
23943261e8b6eac44a41341f112821482bee6c940c98mmentovai  modules_ = NULL;
23953261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = 0;
23963261e8b6eac44a41341f112821482bee6c940c98mmentovai
23973261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
23983261e8b6eac44a41341f112821482bee6c940c98mmentovai
23993261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t module_count;
2400af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(module_count)) {
2401af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
2402af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(module_count);
24033261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2404af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2405af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
2406af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList could not read module count";
24073261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2408af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
24093261e8b6eac44a41341f112821482bee6c940c98mmentovai
24103261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
24113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_count);
24123261e8b6eac44a41341f112821482bee6c940c98mmentovai
2413fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_count > numeric_limits<u_int32_t>::max() / MD_MODULE_SIZE) {
2414fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
2415fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2416fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2417fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2418fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
24193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(module_count) +
24203261e8b6eac44a41341f112821482bee6c940c98mmentovai                       module_count * MD_MODULE_SIZE) {
2421ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2422ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(module_count) + 4 +
2423ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         module_count * MD_MODULE_SIZE) {
2424ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      u_int32_t useless;
2425ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2426ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded bytes";
2427ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2428ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2429ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2430ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
2431ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      " != " << sizeof(module_count) +
2432ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      module_count * MD_MODULE_SIZE;
2433ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2434ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
24353261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
24363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2437e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count > max_modules_) {
2438e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
2439e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_modules_;
2440e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2441e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2442e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2443e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count != 0) {
2444373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpModules> modules(
2445373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpModules(module_count, MinidumpModule(minidump_)));
24463261e8b6eac44a41341f112821482bee6c940c98mmentovai
2447373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int module_index = 0;
2448373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         module_index < module_count;
2449373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++module_index) {
2450373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpModule* module = &(*modules)[module_index];
24513261e8b6eac44a41341f112821482bee6c940c98mmentovai
2452373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
2453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->Read()) {
2454af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
2455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
2456373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2457af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2458db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2459db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2460db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // Loop through the module list once more to read additional data and
2461db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // build the range map.  This is done in a second pass because
2462db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
2463db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // included in the loop above, additional seeks would be needed where
2464db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // none are now to read contiguous data.
2465db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    for (unsigned int module_index = 0;
2466db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         module_index < module_count;
2467db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         ++module_index) {
2468db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      MinidumpModule* module = &(*modules)[module_index];
2469db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
247061ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // ReadAuxiliaryData fails if any data that the module indicates should
247161ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // exist is missing, but we treat some such cases as valid anyway.  See
247261ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // issue #222: if a debugging record is of a format that's too large to
247361ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // handle, it shouldn't render the entire dump invalid.  Check module
247461ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // validity before giving up.
247561ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      if (!module->ReadAuxiliaryData() && !module->valid()) {
247661ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read required module "
247761ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        "auxiliary data for module " <<
247861ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        module_index << "/" << module_count;
247961ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        return false;
2480af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2481af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2482af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // It is safe to use module->code_file() after successfully calling
248361ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // module->ReadAuxiliaryData or noting that the module is valid.
24843261e8b6eac44a41341f112821482bee6c940c98mmentovai
2485373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t base_address = module->base_address();
2486373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t module_size = module->size();
2487af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (base_address == static_cast<u_int64_t>(-1)) {
2488af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList found bad base address "
2489af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "for module " << module_index << "/" << module_count <<
2490af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << module->code_file();
2491373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2492af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
24933261e8b6eac44a41341f112821482bee6c940c98mmentovai
2494af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, module_size, module_index)) {
2495af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
2496af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count << ", " <<
2497af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module->code_file() << ", " <<
2498af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
2499af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(module_size);
2500373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2501af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2502373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
2503373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2504373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    modules_ = modules.release();
25053261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
25063261e8b6eac44a41341f112821482bee6c940c98mmentovai
25073261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = module_count;
25083261e8b6eac44a41341f112821482bee6c940c98mmentovai
25093261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
25103261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
25113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25123261e8b6eac44a41341f112821482bee6c940c98mmentovai
25133261e8b6eac44a41341f112821482bee6c940c98mmentovai
2514db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleForAddress(
2515db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    u_int64_t address) const {
2516af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2517af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
25183261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2519af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25203261e8b6eac44a41341f112821482bee6c940c98mmentovai
2521db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  unsigned int module_index;
2522af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
2523af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpModuleList has no module at " <<
2524af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
2525db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2526af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2527db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2528db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtIndex(module_index);
25293261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25303261e8b6eac44a41341f112821482bee6c940c98mmentovai
25313261e8b6eac44a41341f112821482bee6c940c98mmentovai
2532db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetMainModule() const {
2533af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2534af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
25353261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2536af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25373261e8b6eac44a41341f112821482bee6c940c98mmentovai
2538db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // The main code module is the first one present in a minidump file's
2539db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // MDRawModuleList.
2540327783c42fcc2062bfe6c118c54c431ac6b5ffcfmkrebs@chromium.org  return GetModuleAtIndex(0);
2541db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2542db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2543db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2544db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
2545db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int sequence) const {
2546af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2547af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
2548af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2549af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2550af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2551af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sequence >= module_count_) {
2552af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
2553af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sequence << "/" << module_count_;
2554db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2555af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2556db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
25573261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int module_index;
2558af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
2559af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
25603261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25623261e8b6eac44a41341f112821482bee6c940c98mmentovai
25633261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetModuleAtIndex(module_index);
25643261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25653261e8b6eac44a41341f112821482bee6c940c98mmentovai
25663261e8b6eac44a41341f112821482bee6c940c98mmentovai
2567db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
2568db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int index) const {
2569af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2570af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
2571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2572af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2573af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2574af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= module_count_) {
2575af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
2576af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << module_count_;
2577db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2578af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2579db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2580db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return &(*modules_)[index];
2581db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2582db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2583db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2584db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModules* MinidumpModuleList::Copy() const {
2585db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModules(this);
2586db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2587db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2588db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
25893261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModuleList::Print() {
2590af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2591af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
25923261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2593af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25943261e8b6eac44a41341f112821482bee6c940c98mmentovai
25953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpModuleList\n");
25963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_count = %d\n", module_count_);
25973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
25983261e8b6eac44a41341f112821482bee6c940c98mmentovai
25993261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int module_index = 0;
26003261e8b6eac44a41341f112821482bee6c940c98mmentovai       module_index < module_count_;
26013261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++module_index) {
26023261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("module[%d]\n", module_index);
26033261e8b6eac44a41341f112821482bee6c940c98mmentovai
26043261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*modules_)[module_index].Print();
26053261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26063261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26073261e8b6eac44a41341f112821482bee6c940c98mmentovai
26083261e8b6eac44a41341f112821482bee6c940c98mmentovai
26093261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26103261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryList
26113261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26123261e8b6eac44a41341f112821482bee6c940c98mmentovai
26133261e8b6eac44a41341f112821482bee6c940c98mmentovai
2614cb33b20f75e240ffb6a621b615bd4f5f20b181dcnealsidu_int32_t MinidumpMemoryList::max_regions_ = 4096;
2615e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2616e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
26173261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
261853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
2619fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai      range_map_(new RangeMap<u_int64_t, unsigned int>()),
262053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptors_(NULL),
262153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      regions_(NULL),
262253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      region_count_(0) {
26233261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26243261e8b6eac44a41341f112821482bee6c940c98mmentovai
26253261e8b6eac44a41341f112821482bee6c940c98mmentovai
26263261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::~MinidumpMemoryList() {
2627fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
26283261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
26293261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
26303261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26313261e8b6eac44a41341f112821482bee6c940c98mmentovai
26323261e8b6eac44a41341f112821482bee6c940c98mmentovai
26333261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryList::Read(u_int32_t expected_size) {
26343261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
26353261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
26363261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptors_ = NULL;
26373261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
26383261e8b6eac44a41341f112821482bee6c940c98mmentovai  regions_ = NULL;
2639fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
26403261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = 0;
26413261e8b6eac44a41341f112821482bee6c940c98mmentovai
26423261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
26433261e8b6eac44a41341f112821482bee6c940c98mmentovai
26443261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t region_count;
2645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(region_count)) {
2646af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
2647af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(region_count);
26483261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2649af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2650af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
2651af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
26523261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2653af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26543261e8b6eac44a41341f112821482bee6c940c98mmentovai
26553261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
26563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&region_count);
26573261e8b6eac44a41341f112821482bee6c940c98mmentovai
2658fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (region_count >
2659fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          numeric_limits<u_int32_t>::max() / sizeof(MDMemoryDescriptor)) {
2660fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
2661fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2662fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2663fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2664fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
26653261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(region_count) +
26663261e8b6eac44a41341f112821482bee6c940c98mmentovai                       region_count * sizeof(MDMemoryDescriptor)) {
2667ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2668ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(region_count) + 4 +
2669ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         region_count * sizeof(MDMemoryDescriptor)) {
2670ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      u_int32_t useless;
2671ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2672ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded bytes";
2673ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2674ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2675ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2676ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
2677ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      " != " << sizeof(region_count) +
2678ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      region_count * sizeof(MDMemoryDescriptor);
2679ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2680ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
26813261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26823261e8b6eac44a41341f112821482bee6c940c98mmentovai
2683e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count > max_regions_) {
2684e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
2685e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_regions_;
2686e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2687e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2688e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2689e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count != 0) {
2690373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryDescriptors> descriptors(
2691373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryDescriptors(region_count));
26923261e8b6eac44a41341f112821482bee6c940c98mmentovai
2693373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
2694373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
2695373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!minidump_->ReadBytes(&(*descriptors)[0],
2696373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai                              sizeof(MDMemoryDescriptor) * region_count)) {
2697af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
2698373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
2699373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
27003261e8b6eac44a41341f112821482bee6c940c98mmentovai
2701373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryRegions> regions(
2702373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
27033261e8b6eac44a41341f112821482bee6c940c98mmentovai
2704373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int region_index = 0;
2705373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         region_index < region_count;
2706373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++region_index) {
2707373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
27083261e8b6eac44a41341f112821482bee6c940c98mmentovai
2709373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (minidump_->swap())
2710373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(descriptor);
27113261e8b6eac44a41341f112821482bee6c940c98mmentovai
2712373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t base_address = descriptor->start_of_memory_range;
2713373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int32_t region_size = descriptor->memory.data_size;
27143261e8b6eac44a41341f112821482bee6c940c98mmentovai
2715fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      // Check for base + size overflow or undersize.
2716fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      if (region_size == 0 ||
2717fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          region_size > numeric_limits<u_int64_t>::max() - base_address) {
2718af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
2719af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        " region " << region_index << "/" << region_count <<
2720af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << HexString(base_address) << "+" <<
2721fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                        HexString(region_size);
2722373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
27243261e8b6eac44a41341f112821482bee6c940c98mmentovai
2725af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, region_size, region_index)) {
2726af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
2727af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        region_index << "/" << region_count << ", " <<
2728af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
2729af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(region_size);
2730373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2731af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2732373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2733373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      (*regions)[region_index].SetDescriptor(descriptor);
2734373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
27353261e8b6eac44a41341f112821482bee6c940c98mmentovai
2736373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    descriptors_ = descriptors.release();
2737373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    regions_ = regions.release();
27383261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
27393261e8b6eac44a41341f112821482bee6c940c98mmentovai
27403261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = region_count;
27413261e8b6eac44a41341f112821482bee6c940c98mmentovai
27423261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
27433261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
27443261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27453261e8b6eac44a41341f112821482bee6c940c98mmentovai
27463261e8b6eac44a41341f112821482bee6c940c98mmentovai
27473261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
27483261e8b6eac44a41341f112821482bee6c940c98mmentovai      unsigned int index) {
2749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
2751af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2752af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2753af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2754af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= region_count_) {
2755af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
2756af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << region_count_;
27573261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2758af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27593261e8b6eac44a41341f112821482bee6c940c98mmentovai
27603261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*regions_)[index];
27613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27623261e8b6eac44a41341f112821482bee6c940c98mmentovai
27633261e8b6eac44a41341f112821482bee6c940c98mmentovai
27643261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
27653261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int64_t address) {
2766af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2767af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
27683261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2769af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27703261e8b6eac44a41341f112821482bee6c940c98mmentovai
27713261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int region_index;
2772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
2773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
2774af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
27753261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2776af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27773261e8b6eac44a41341f112821482bee6c940c98mmentovai
27783261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryRegionAtIndex(region_index);
27793261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27803261e8b6eac44a41341f112821482bee6c940c98mmentovai
27813261e8b6eac44a41341f112821482bee6c940c98mmentovai
27823261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryList::Print() {
2783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2784af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
27853261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2786af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27873261e8b6eac44a41341f112821482bee6c940c98mmentovai
27883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpMemoryList\n");
27893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  region_count = %d\n", region_count_);
27903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
27913261e8b6eac44a41341f112821482bee6c940c98mmentovai
27923261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int region_index = 0;
27933261e8b6eac44a41341f112821482bee6c940c98mmentovai       region_index < region_count_;
27943261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++region_index) {
27953261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
27963261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("region[%d]\n", region_index);
27973261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDMemoryDescriptor\n");
2798c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  start_of_memory_range = 0x%" PRIx64 "\n",
27993261e8b6eac44a41341f112821482bee6c940c98mmentovai           descriptor->start_of_memory_range);
28003261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
28013261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
28023261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
28033261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (region) {
28043261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("Memory\n");
28053261e8b6eac44a41341f112821482bee6c940c98mmentovai      region->Print();
28063261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
28073261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("No memory\n");
28083261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
28093261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
28103261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28123261e8b6eac44a41341f112821482bee6c940c98mmentovai
28133261e8b6eac44a41341f112821482bee6c940c98mmentovai
28143261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28153261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpException
28163261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28173261e8b6eac44a41341f112821482bee6c940c98mmentovai
28183261e8b6eac44a41341f112821482bee6c940c98mmentovai
28193261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::MinidumpException(Minidump* minidump)
282053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
282153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      exception_(),
282253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
28233261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28243261e8b6eac44a41341f112821482bee6c940c98mmentovai
28253261e8b6eac44a41341f112821482bee6c940c98mmentovai
28263261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::~MinidumpException() {
28273261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
28283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28293261e8b6eac44a41341f112821482bee6c940c98mmentovai
28303261e8b6eac44a41341f112821482bee6c940c98mmentovai
28313261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpException::Read(u_int32_t expected_size) {
28323261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
28333261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
28343261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
28353261e8b6eac44a41341f112821482bee6c940c98mmentovai
28363261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
28373261e8b6eac44a41341f112821482bee6c940c98mmentovai
2838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(exception_)) {
2839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
2840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(exception_);
28413261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2842af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28433261e8b6eac44a41341f112821482bee6c940c98mmentovai
2844af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
2845af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot read exception";
28463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2847af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28483261e8b6eac44a41341f112821482bee6c940c98mmentovai
28493261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
28503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_id);
28513261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.__align is for alignment only and does not need to be
28523261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapped.
28533261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_code);
28543261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_flags);
28553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_record);
28563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_address);
28573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.number_parameters);
28583261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.exception_record.__align is for alignment only and does not
28593261e8b6eac44a41341f112821482bee6c940c98mmentovai    // need to be swapped.
28603261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int parameter_index = 0;
28613261e8b6eac44a41341f112821482bee6c940c98mmentovai         parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
28623261e8b6eac44a41341f112821482bee6c940c98mmentovai         ++parameter_index) {
28633261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&exception_.exception_record.exception_information[parameter_index]);
28643261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
28653261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_context);
28663261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28673261e8b6eac44a41341f112821482bee6c940c98mmentovai
28683261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
28693261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
28703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28713261e8b6eac44a41341f112821482bee6c940c98mmentovai
28723261e8b6eac44a41341f112821482bee6c940c98mmentovai
287376f052f8fbf8864dee5992b857229d06560a766ammentovaibool MinidumpException::GetThreadID(u_int32_t *thread_id) const {
2874af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
2875af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
2876af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
2877af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
2878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2880af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
288176f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
2882af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
288376f052f8fbf8864dee5992b857229d06560a766ammentovai
288476f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = exception_.thread_id;
288576f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
28863261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28873261e8b6eac44a41341f112821482bee6c940c98mmentovai
28883261e8b6eac44a41341f112821482bee6c940c98mmentovai
28893261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpException::GetContext() {
2890af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2891af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
28923261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2893af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28943261e8b6eac44a41341f112821482bee6c940c98mmentovai
28953261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
2896af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(exception_.thread_context.rva)) {
2897af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot seek to context";
28983261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2899af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
29003261e8b6eac44a41341f112821482bee6c940c98mmentovai
29012466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
29023261e8b6eac44a41341f112821482bee6c940c98mmentovai
29039276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // Don't log as an error if we can still fall back on the thread's context
29049276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // (which must be possible if we got this far.)
2905af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(exception_.thread_context.data_size)) {
29065f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org      BPLOG(INFO) << "MinidumpException cannot read context";
29073261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2908af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
29093261e8b6eac44a41341f112821482bee6c940c98mmentovai
29103261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
29113261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29123261e8b6eac44a41341f112821482bee6c940c98mmentovai
29133261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
29143261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29153261e8b6eac44a41341f112821482bee6c940c98mmentovai
29163261e8b6eac44a41341f112821482bee6c940c98mmentovai
29173261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpException::Print() {
2918af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot print invalid data";
29203261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2921af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29223261e8b6eac44a41341f112821482bee6c940c98mmentovai
29233261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDException\n");
29243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                                  = 0x%x\n",
29253261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_id);
29263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_code            = 0x%x\n",
29273261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_code);
29283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_flags           = 0x%x\n",
29293261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_flags);
2930c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
29313261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_record);
2932c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
29333261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_address);
29343261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.number_parameters         = %d\n",
29353261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.number_parameters);
29363261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int parameterIndex = 0;
29373261e8b6eac44a41341f112821482bee6c940c98mmentovai       parameterIndex < exception_.exception_record.number_parameters;
29383261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++parameterIndex) {
2939c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
29403261e8b6eac44a41341f112821482bee6c940c98mmentovai           parameterIndex,
29413261e8b6eac44a41341f112821482bee6c940c98mmentovai           exception_.exception_record.exception_information[parameterIndex]);
29423261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29433261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size                   = %d\n",
29443261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.data_size);
29453261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva                         = 0x%x\n",
29463261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.rva);
29473261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
29483261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
29493261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
29503261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
29513261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
29523261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
29533261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
29543261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29563261e8b6eac44a41341f112821482bee6c940c98mmentovai
29570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
29580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// MinidumpAssertion
29590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
29600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29610314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29620314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::MinidumpAssertion(Minidump* minidump)
29630314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    : MinidumpStream(minidump),
29640314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      assertion_(),
29650314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      expression_(),
29660314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      function_(),
29670314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      file_() {
29680314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
29690314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29700314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29710314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::~MinidumpAssertion() {
29720314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
29730314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29740314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29750314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekbool MinidumpAssertion::Read(u_int32_t expected_size) {
29760314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Invalidate cached data.
29770314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = false;
29780314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29790314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (expected_size != sizeof(assertion_)) {
29800314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
29810314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                    " != " << sizeof(assertion_);
29820314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
29830314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
29840314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29850314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
29860314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
29870314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
29880314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
29890314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
29900314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Each of {expression, function, file} is a UTF-16 string,
29910314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // we'll convert them to UTF-8 for ease of use.
29920314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // expression
29930314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Since we don't have an explicit byte length for each string,
29940314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // we use UTF16codeunits to calculate word length, then derive byte
29950314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // length from that.
29960314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  u_int32_t word_length = UTF16codeunits(assertion_.expression,
29970314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                                         sizeof(assertion_.expression));
29980314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (word_length > 0) {
29990314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    u_int32_t byte_length = word_length * 2;
30000314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    vector<u_int16_t> expression_utf16(word_length);
30010314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    memcpy(&expression_utf16[0], &assertion_.expression[0], byte_length);
30020314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30030314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    scoped_ptr<string> new_expression(UTF16ToUTF8(expression_utf16,
30040314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                                                  minidump_->swap()));
3005de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com    if (new_expression.get())
3006de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com      expression_ = *new_expression;
30070314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30080314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30090314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // assertion
30100314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  word_length = UTF16codeunits(assertion_.function,
30110314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                               sizeof(assertion_.function));
30120314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (word_length) {
30130314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    u_int32_t byte_length = word_length * 2;
30140314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    vector<u_int16_t> function_utf16(word_length);
30150314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    memcpy(&function_utf16[0], &assertion_.function[0], byte_length);
30160314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    scoped_ptr<string> new_function(UTF16ToUTF8(function_utf16,
30170314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                                                minidump_->swap()));
3018de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com    if (new_function.get())
3019de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com      function_ = *new_function;
30200314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30210314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30220314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // file
30230314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  word_length = UTF16codeunits(assertion_.file,
30240314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                               sizeof(assertion_.file));
30250314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (word_length > 0) {
30260314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    u_int32_t byte_length = word_length * 2;
30270314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    vector<u_int16_t> file_utf16(word_length);
30280314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    memcpy(&file_utf16[0], &assertion_.file[0], byte_length);
30290314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    scoped_ptr<string> new_file(UTF16ToUTF8(file_utf16,
30300314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                                            minidump_->swap()));
3031de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com    if (new_file.get())
3032de2c055770751e7ffc42be3f97c5c7a3a99f9056SiyangXie@gmail.com      file_ = *new_file;
30330314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30340314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30350314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (minidump_->swap()) {
30360314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.line);
30370314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.type);
30380314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30390314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30400314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = true;
30410314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return true;
30420314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
30430314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30440314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekvoid MinidumpAssertion::Print() {
30450314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!valid_) {
30460314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
30470314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return;
30480314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
30490314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
30500314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("MDAssertion\n");
30510314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  expression                                 = %s\n",
30520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         expression_.c_str());
30530314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  function                                   = %s\n",
30540314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         function_.c_str());
30550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  file                                       = %s\n",
30560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         file_.c_str());
30570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  line                                       = %u\n",
30580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.line);
30590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  type                                       = %u\n",
30600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.type);
30610314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("\n");
30620314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
30633261e8b6eac44a41341f112821482bee6c940c98mmentovai
30643261e8b6eac44a41341f112821482bee6c940c98mmentovai//
30653261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpSystemInfo
30663261e8b6eac44a41341f112821482bee6c940c98mmentovai//
30673261e8b6eac44a41341f112821482bee6c940c98mmentovai
30683261e8b6eac44a41341f112821482bee6c940c98mmentovai
30693261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
307053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
307153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      system_info_(),
3072e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      csd_version_(NULL),
3073e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      cpu_vendor_(NULL) {
30743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30753261e8b6eac44a41341f112821482bee6c940c98mmentovai
30763261e8b6eac44a41341f112821482bee6c940c98mmentovai
30773261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::~MinidumpSystemInfo() {
30783261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
3079e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
30803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30813261e8b6eac44a41341f112821482bee6c940c98mmentovai
30823261e8b6eac44a41341f112821482bee6c940c98mmentovai
30833261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpSystemInfo::Read(u_int32_t expected_size) {
30843261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
30853261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
30863261e8b6eac44a41341f112821482bee6c940c98mmentovai  csd_version_ = NULL;
3087e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
3088e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  cpu_vendor_ = NULL;
30893261e8b6eac44a41341f112821482bee6c940c98mmentovai
30903261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
30913261e8b6eac44a41341f112821482bee6c940c98mmentovai
3092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(system_info_)) {
3093af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
3094af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(system_info_);
30953261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3096af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30973261e8b6eac44a41341f112821482bee6c940c98mmentovai
3098af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
3099af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
31003261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31023261e8b6eac44a41341f112821482bee6c940c98mmentovai
31033261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
31043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_architecture);
31053261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_level);
31063261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_revision);
31073261e8b6eac44a41341f112821482bee6c940c98mmentovai    // number_of_processors and product_type are 8-bit quantities and need no
31083261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapping.
31093261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.major_version);
31103261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.minor_version);
31113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.build_number);
31123261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.platform_id);
31133261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.csd_version_rva);
31143261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.suite_mask);
31153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    // Don't swap the reserved2 field because its contents are unknown.
31163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
31173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
31183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
31193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 3; ++i)
31203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
31213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.version_information);
31223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.feature_information);
31233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
31243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    } else {
31253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 2; ++i)
31263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
31273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
31283261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
31293261e8b6eac44a41341f112821482bee6c940c98mmentovai
31303261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
31313261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
31323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31333261e8b6eac44a41341f112821482bee6c940c98mmentovai
31343261e8b6eac44a41341f112821482bee6c940c98mmentovai
313597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetOS() {
31364e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com  string os;
31374e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com
3138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3139af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
31404e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com    return os;
3141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
314297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
314397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.platform_id) {
314497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_NT:
314597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_WINDOWS:
314697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "windows";
314797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
314897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
314997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_MAC_OS_X:
315097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "mac";
315197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
315297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
315363f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
315463f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      os = "ios";
315563f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      break;
315663f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org
315797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_LINUX:
315897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "linux";
315997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3160af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3161ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
3162ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      os = "solaris";
31635187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      break;
31645187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org
31655187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
31665187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      os = "android";
3167ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
3168ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
3169af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3170af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
3171af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.platform_id);
3172af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
317397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
317497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
317597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return os;
317697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
317797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
317897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
317997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetCPU() {
3180af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3181af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
318297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return "";
3183af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
318497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
318597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string cpu;
318697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
318797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.processor_architecture) {
318897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86:
318997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86_WIN64:
319097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "x86";
319197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
319297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
31939276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_AMD64:
31949276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "x86-64";
31959276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
31969276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
319797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_PPC:
319897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "ppc";
319997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3200af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3201dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    case MD_CPU_ARCHITECTURE_SPARC:
3202dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      cpu = "sparc";
3203dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      break;
3204dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
32059276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_ARM:
32069276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "arm";
32079276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
32089276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
3209af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3210af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
3211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.processor_architecture);
3212af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
321397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
321497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
321597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return cpu;
321697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
321797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
321897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
32193261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst string* MinidumpSystemInfo::GetCSDVersion() {
3220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
32223261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3223af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32243261e8b6eac44a41341f112821482bee6c940c98mmentovai
32253261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!csd_version_)
32263261e8b6eac44a41341f112821482bee6c940c98mmentovai    csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
32273261e8b6eac44a41341f112821482bee6c940c98mmentovai
3228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
3229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    "CSD version";
3230af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
32313261e8b6eac44a41341f112821482bee6c940c98mmentovai  return csd_version_;
32323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32333261e8b6eac44a41341f112821482bee6c940c98mmentovai
32343261e8b6eac44a41341f112821482bee6c940c98mmentovai
3235e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovaiconst string* MinidumpSystemInfo::GetCPUVendor() {
3236af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3237af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
3238e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    return NULL;
3239af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3240e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3241e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  // CPU vendor information can only be determined from x86 minidumps.
3242e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (!cpu_vendor_ &&
3243e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
3244e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
3245e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    char cpu_vendor_string[13];
3246e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
3247e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             "%c%c%c%c%c%c%c%c%c%c%c%c",
3248e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
3249e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
3250e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
3251e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
3252e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
3253e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
3254e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
3255e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
3256e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
3257e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
3258e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
3259e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
3260e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    cpu_vendor_ = new string(cpu_vendor_string);
3261e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3262e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3263e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  return cpu_vendor_;
3264e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai}
3265e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3266e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
32673261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpSystemInfo::Print() {
3268af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
32703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3271af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32723261e8b6eac44a41341f112821482bee6c940c98mmentovai
32733261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawSystemInfo\n");
32743261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_architecture                     = %d\n",
32753261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_architecture);
32763261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_level                            = %d\n",
32773261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_level);
32780a7e6bf16cad354710df60929c2ac82f647cb54emmentovai  printf("  processor_revision                         = 0x%x\n",
32790a7e6bf16cad354710df60929c2ac82f647cb54emmentovai         system_info_.processor_revision);
32803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  number_of_processors                       = %d\n",
32813261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.number_of_processors);
32823261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  product_type                               = %d\n",
32833261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.product_type);
32843261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  major_version                              = %d\n",
32853261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.major_version);
32863261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  minor_version                              = %d\n",
32873261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.minor_version);
32883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  build_number                               = %d\n",
32893261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.build_number);
32903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  platform_id                                = %d\n",
32913261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.platform_id);
32923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  csd_version_rva                            = 0x%x\n",
32933261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.csd_version_rva);
32943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suite_mask                                 = 0x%x\n",
32953261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.suite_mask);
32963261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int i = 0; i < 3; ++i) {
32973261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
32983261e8b6eac44a41341f112821482bee6c940c98mmentovai           i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
32993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33003261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
33013261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.version_information);
33023261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
33033261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.feature_information);
33043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
33053261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
3306e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* csd_version = GetCSDVersion();
3307e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (csd_version) {
33083261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = \"%s\"\n",
3309e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           csd_version->c_str());
3310e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
33113261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = (null)\n");
3312e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3313e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* cpu_vendor = GetCPUVendor();
3314e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (cpu_vendor) {
3315e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = \"%s\"\n",
3316e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           cpu_vendor->c_str());
3317e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
3318e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = (null)\n");
3319e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
33203261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
33213261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33223261e8b6eac44a41341f112821482bee6c940c98mmentovai
33233261e8b6eac44a41341f112821482bee6c940c98mmentovai
33243261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33253261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMiscInfo
33263261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33273261e8b6eac44a41341f112821482bee6c940c98mmentovai
33283261e8b6eac44a41341f112821482bee6c940c98mmentovai
33293261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
333053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
333153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      misc_info_() {
33323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33333261e8b6eac44a41341f112821482bee6c940c98mmentovai
33343261e8b6eac44a41341f112821482bee6c940c98mmentovai
33353261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMiscInfo::Read(u_int32_t expected_size) {
33363261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
33373261e8b6eac44a41341f112821482bee6c940c98mmentovai
33383261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != MD_MISCINFO_SIZE &&
33393261e8b6eac44a41341f112821482bee6c940c98mmentovai      expected_size != MD_MISCINFO2_SIZE) {
3340af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size <<
3341af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE <<
3342af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ")";
33433261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
33443261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33453261e8b6eac44a41341f112821482bee6c940c98mmentovai
3346af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
3347af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
33483261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3349af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33503261e8b6eac44a41341f112821482bee6c940c98mmentovai
33513261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
33523261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.size_of_info);
33533261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.flags1);
33543261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_id);
33553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_create_time);
33563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_user_time);
33573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_kernel_time);
33583261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
33593261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_mhz);
33603261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_mhz);
33613261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_mhz_limit);
33623261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_idle_state);
33633261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_idle_state);
33643261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
33653261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33663261e8b6eac44a41341f112821482bee6c940c98mmentovai
336765571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai  if (expected_size != misc_info_.size_of_info) {
3368af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
336965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai                    expected_size << " != " << misc_info_.size_of_info;
33703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3371af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33723261e8b6eac44a41341f112821482bee6c940c98mmentovai
33733261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
33743261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
33753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33763261e8b6eac44a41341f112821482bee6c940c98mmentovai
33773261e8b6eac44a41341f112821482bee6c940c98mmentovai
33783261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMiscInfo::Print() {
3379af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3380af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
33813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3382af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
33833261e8b6eac44a41341f112821482bee6c940c98mmentovai
33843261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawMiscInfo\n");
33853261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
33863261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags1                       = 0x%x\n", misc_info_.flags1);
33873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_id                   = 0x%x\n", misc_info_.process_id);
33883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_create_time          = 0x%x\n",
33893261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_create_time);
33903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_user_time            = 0x%x\n",
33913261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_user_time);
33923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_kernel_time          = 0x%x\n",
33933261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_kernel_time);
33943261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
33953261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_mhz            = %d\n",
33963261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_mhz);
33973261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_mhz        = %d\n",
33983261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_mhz);
33993261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_mhz_limit          = %d\n",
34003261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_mhz_limit);
34013261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_idle_state     = 0x%x\n",
34023261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_idle_state);
34033261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_idle_state = 0x%x\n",
34043261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_idle_state);
34053261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
340676f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
340776f052f8fbf8864dee5992b857229d06560a766ammentovai}
340876f052f8fbf8864dee5992b857229d06560a766ammentovai
340976f052f8fbf8864dee5992b857229d06560a766ammentovai
341076f052f8fbf8864dee5992b857229d06560a766ammentovai//
3411e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// MinidumpBreakpadInfo
341276f052f8fbf8864dee5992b857229d06560a766ammentovai//
341376f052f8fbf8864dee5992b857229d06560a766ammentovai
341476f052f8fbf8864dee5992b857229d06560a766ammentovai
3415e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
341676f052f8fbf8864dee5992b857229d06560a766ammentovai    : MinidumpStream(minidump),
3417e5dc60822e5938fea2ae892ccddb906641ba174emmentovai      breakpad_info_() {
341876f052f8fbf8864dee5992b857229d06560a766ammentovai}
341976f052f8fbf8864dee5992b857229d06560a766ammentovai
342076f052f8fbf8864dee5992b857229d06560a766ammentovai
3421e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::Read(u_int32_t expected_size) {
342276f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = false;
342376f052f8fbf8864dee5992b857229d06560a766ammentovai
3424af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(breakpad_info_)) {
3425af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
3426af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(breakpad_info_);
342776f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3428af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
342976f052f8fbf8864dee5992b857229d06560a766ammentovai
3430af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
3431af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
343276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3433af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
343476f052f8fbf8864dee5992b857229d06560a766ammentovai
343576f052f8fbf8864dee5992b857229d06560a766ammentovai  if (minidump_->swap()) {
3436e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.validity);
3437e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.dump_thread_id);
3438e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.requesting_thread_id);
343976f052f8fbf8864dee5992b857229d06560a766ammentovai  }
344076f052f8fbf8864dee5992b857229d06560a766ammentovai
344176f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = true;
344276f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
344376f052f8fbf8864dee5992b857229d06560a766ammentovai}
344476f052f8fbf8864dee5992b857229d06560a766ammentovai
344576f052f8fbf8864dee5992b857229d06560a766ammentovai
3446e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::GetDumpThreadID(u_int32_t *thread_id) const {
3447af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
3448af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3449af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3450af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3451af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3452af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
3454af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3456af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3457af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
3458af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
345976f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
346076f052f8fbf8864dee5992b857229d06560a766ammentovai  }
346176f052f8fbf8864dee5992b857229d06560a766ammentovai
3462e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.dump_thread_id;
346376f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
346476f052f8fbf8864dee5992b857229d06560a766ammentovai}
346576f052f8fbf8864dee5992b857229d06560a766ammentovai
346676f052f8fbf8864dee5992b857229d06560a766ammentovai
3467e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::GetRequestingThreadID(u_int32_t *thread_id)
346876f052f8fbf8864dee5992b857229d06560a766ammentovai    const {
3469af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
3470af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3471af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3472af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3473af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3474af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!thread_id || !valid_) {
3475af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
3476af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3477af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3478af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3479af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity &
3480af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
3481af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
348276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
348376f052f8fbf8864dee5992b857229d06560a766ammentovai  }
348476f052f8fbf8864dee5992b857229d06560a766ammentovai
3485e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.requesting_thread_id;
348676f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
348776f052f8fbf8864dee5992b857229d06560a766ammentovai}
348876f052f8fbf8864dee5992b857229d06560a766ammentovai
348976f052f8fbf8864dee5992b857229d06560a766ammentovai
3490e5dc60822e5938fea2ae892ccddb906641ba174emmentovaivoid MinidumpBreakpadInfo::Print() {
3491af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3492af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
349376f052f8fbf8864dee5992b857229d06560a766ammentovai    return;
3494af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
349576f052f8fbf8864dee5992b857229d06560a766ammentovai
3496e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("MDRawBreakpadInfo\n");
3497e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("  validity             = 0x%x\n", breakpad_info_.validity);
349876f052f8fbf8864dee5992b857229d06560a766ammentovai
3499e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
3500e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    printf("  dump_thread_id       = 0x%x\n", breakpad_info_.dump_thread_id);
350176f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
350276f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  dump_thread_id       = (invalid)\n");
350376f052f8fbf8864dee5992b857229d06560a766ammentovai  }
350476f052f8fbf8864dee5992b857229d06560a766ammentovai
3505e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
350676f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = 0x%x\n",
3507e5dc60822e5938fea2ae892ccddb906641ba174emmentovai           breakpad_info_.requesting_thread_id);
350876f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
350976f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = (invalid)\n");
351076f052f8fbf8864dee5992b857229d06560a766ammentovai  }
351176f052f8fbf8864dee5992b857229d06560a766ammentovai
351276f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
35133261e8b6eac44a41341f112821482bee6c940c98mmentovai}
35143261e8b6eac44a41341f112821482bee6c940c98mmentovai
35153261e8b6eac44a41341f112821482bee6c940c98mmentovai
35163261e8b6eac44a41341f112821482bee6c940c98mmentovai//
35177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfo
35187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
35197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
35227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpObject(minidump),
35237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_() {
35247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
35257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsExecutable() const {
35287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  u_int32_t protection =
35297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
35307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_EXECUTE ||
35317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
35327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
35337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
35347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsWritable() const {
35377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  u_int32_t protection =
35387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
35397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_READWRITE ||
35407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_WRITECOPY ||
35417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
35427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
35437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
35447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::Read() {
35477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
35487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
35507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
35517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
35527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
35537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
35557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.base_address);
35567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_base);
35577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_protection);
35587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.region_size);
35597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.state);
35607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.protection);
35617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.type);
35627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
35637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Check for base + size overflow or undersize.
35657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (memory_info_.region_size == 0 ||
35667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.region_size > numeric_limits<u_int64_t>::max() -
35677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                     memory_info_.base_address) {
35687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
35697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.base_address) << "+" <<
35707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.region_size);
35717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
35727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
35737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
35757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
35767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
35777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfo::Print() {
35807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
35817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
35827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
35837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
35847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MDRawMemoryInfo\n");
35867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  base_address          = 0x%" PRIx64 "\n",
35877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.base_address);
35887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_base       = 0x%" PRIx64 "\n",
35897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_base);
35907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_protection = 0x%x\n",
35917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_protection);
35927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  region_size           = 0x%" PRIx64 "\n", memory_info_.region_size);
35937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  state                 = 0x%x\n", memory_info_.state);
35947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  protection            = 0x%x\n", memory_info_.protection);
35957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  type                  = 0x%x\n", memory_info_.type);
35967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
35977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
35997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
36007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfoList
36017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
36027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
36057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpStream(minidump),
36067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      range_map_(new RangeMap<u_int64_t, unsigned int>()),
36077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      infos_(NULL),
36087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      info_count_(0) {
36097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
36107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
36137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete range_map_;
36147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
36157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
36167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfoList::Read(u_int32_t expected_size) {
36197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Invalidate cached data.
36207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
36217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  infos_ = NULL;
36227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  range_map_->Clear();
36237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  info_count_ = 0;
36247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
36267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MDRawMemoryInfoList header;
36287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size < sizeof(MDRawMemoryInfoList)) {
36297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
36307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    expected_size << " < " << sizeof(MDRawMemoryInfoList);
36317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&header, sizeof(header))) {
36347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
36357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
36397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_header);
36407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_entry);
36417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.number_of_entries);
36427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the header is the expected size.
36457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  //TODO(ted): could possibly handle this more gracefully, assuming
36467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // that future versions of the structs would be backwards-compatible.
36477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
36487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
36497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_header << " != " <<
36507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfoList);
36517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the entries are the expected size.
36557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
36567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
36577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_entry << " != " <<
36587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfo);
36597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries >
36637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek          numeric_limits<u_int32_t>::max() / sizeof(MDRawMemoryInfo)) {
36647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
36657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.number_of_entries <<
36667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " would cause multiplication overflow";
36677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size != sizeof(MDRawMemoryInfoList) +
36717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo)) {
36727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
36737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " != " << sizeof(MDRawMemoryInfoList) +
36747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo);
36757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
36767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
36777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries != 0) {
36797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    scoped_ptr<MinidumpMemoryInfos> infos(
36807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        new MinidumpMemoryInfos(header.number_of_entries,
36817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                MinidumpMemoryInfo(minidump_)));
36827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    for (unsigned int index = 0;
36847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         index < header.number_of_entries;
36857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         ++index) {
36867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      MinidumpMemoryInfo* info = &(*infos)[index];
36877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36887b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      // Assume that the file offset is correct after the last read.
36897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!info->Read()) {
36907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
36917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries;
36927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
36937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
36947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      u_int64_t base_address = info->GetBase();
36967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      u_int32_t region_size = info->GetSize();
36977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
36987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!range_map_->StoreRange(base_address, region_size, index)) {
36997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
37007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        " memory region " <<
37017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries << ", " <<
37027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(base_address) << "+" <<
37037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(region_size);
37047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
37057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
37067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    }
37077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    infos_ = infos.release();
37097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  info_count_ = header.number_of_entries;
37127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
37147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
37157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
37197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      unsigned int index) const {
37207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
37217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
37227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
37237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (index >= info_count_) {
37267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
37277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    index << "/" << info_count_;
37287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
37297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return &(*infos_)[index];
37327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
37367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    u_int64_t address) const {
37377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
37387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
37397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " GetMemoryInfoForAddress";
37407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
37417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  unsigned int info_index;
37447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
37457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
37467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                   HexString(address);
37477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
37487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetMemoryInfoAtIndex(info_index);
37517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfoList::Print() {
37557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
37567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
37577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
37587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MinidumpMemoryInfoList\n");
37617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  info_count = %d\n", info_count_);
37627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("\n");
37637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  for (unsigned int info_index = 0;
37657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       info_index < info_count_;
37667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       ++info_index) {
37677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("info[%d]\n", info_index);
37687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    (*infos_)[info_index].Print();
37697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("\n");
37707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
37717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
37727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
37747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
37753261e8b6eac44a41341f112821482bee6c940c98mmentovai// Minidump
37763261e8b6eac44a41341f112821482bee6c940c98mmentovai//
37773261e8b6eac44a41341f112821482bee6c940c98mmentovai
37783261e8b6eac44a41341f112821482bee6c940c98mmentovai
3779e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiu_int32_t Minidump::max_streams_ = 128;
3780e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiunsigned int Minidump::max_string_length_ = 1024;
3781e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3782e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
37836dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaiMinidump::Minidump(const string& path)
378453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : header_(),
378553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      directory_(NULL),
3786373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      stream_map_(new MinidumpStreamMap()),
37876dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      path_(path),
37880cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(NULL),
378953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      swap_(false),
379053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
37913261e8b6eac44a41341f112821482bee6c940c98mmentovai}
37923261e8b6eac44a41341f112821482bee6c940c98mmentovai
37930cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekMinidump::Minidump(istream& stream)
37940cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    : header_(),
37950cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      directory_(NULL),
37960cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_map_(new MinidumpStreamMap()),
37970cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      path_(),
37980cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(&stream),
37990cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      swap_(false),
38000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      valid_(false) {
38010cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
38023261e8b6eac44a41341f112821482bee6c940c98mmentovai
38033261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidump::~Minidump() {
38040cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_) {
38050cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump closing minidump";
38060cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
38070cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!path_.empty()) {
38080cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    delete stream_;
38090cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
38103261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
38113261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete stream_map_;
38126dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai}
38136dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
38146dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
38156dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaibool Minidump::Open() {
38160cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_ != NULL) {
38170cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump reopening minidump " << path_;
3818af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
38196dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // The file is already open.  Seek to the beginning, which is the position
38206dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // the file would be at if it were opened anew.
38216dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return SeekSet(0);
38226dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  }
38236dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
38240cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
38250cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_ || !stream_->good()) {
3826af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    string error_string;
3827af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    int error_code = ErrnoString(&error_string);
3828af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
3829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ", error " << error_code << ": " << error_string;
38306dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
3831af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
38326dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
38330cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  BPLOG(INFO) << "Minidump opened minidump " << path_;
38346dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  return true;
38353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
38363261e8b6eac44a41341f112821482bee6c940c98mmentovai
3837233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.combool Minidump::GetContextCPUFlagsFromSystemInfo(u_int32_t *context_cpu_flags) {
3838233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Initialize output parameters
3839233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  *context_cpu_flags = 0;
3840233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
3841233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Save the current stream position
3842233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  off_t saved_position = Tell();
3843233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (saved_position == -1) {
3844233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Failed to save the current stream position.
3845233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Returns true because the current position of the stream is preserved.
3846233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    return true;
3847233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
3848233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
3849233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  const MDRawSystemInfo* system_info =
3850233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
3851233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
3852233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (system_info != NULL) {
3853233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    switch (system_info->processor_architecture) {
3854233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86:
3855233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_X86;
3856233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3857233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MIPS:
3858233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_MIPS;
3859233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3860233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA:
3861233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ALPHA;
3862233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3863233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_PPC:
3864233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_PPC;
3865233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3866233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SHX:
3867233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SHX;
3868233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3869233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ARM:
3870233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ARM;
3871233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3872233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_IA64:
3873233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_IA64;
3874233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3875233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA64:
3876233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
3877233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3878233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MSIL:
3879233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
3880233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3881233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_AMD64:
3882233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_AMD64;
3883233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3884233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86_WIN64:
3885233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
3886233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3887233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SPARC:
3888233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SPARC;
3889233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3890233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_UNKNOWN:
3891233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
3892233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3893233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      default:
3894233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
3895233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
3896233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
3897233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
3898233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
3899233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Restore position and return
3900233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  return SeekSet(saved_position);
3901233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com}
3902233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
39033261e8b6eac44a41341f112821482bee6c940c98mmentovai
39043261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::Read() {
39053261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
39063261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
39073261e8b6eac44a41341f112821482bee6c940c98mmentovai  directory_ = NULL;
3908373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  stream_map_->clear();
39093261e8b6eac44a41341f112821482bee6c940c98mmentovai
39103261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
39113261e8b6eac44a41341f112821482bee6c940c98mmentovai
3912af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!Open()) {
3913af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot open minidump";
39146dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
3915af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
39166dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
3917af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
3918af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot read header";
39193261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3920af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
39213261e8b6eac44a41341f112821482bee6c940c98mmentovai
39223261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (header_.signature != MD_HEADER_SIGNATURE) {
39233261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file may be byte-swapped.  Under the present architecture, these
39243261e8b6eac44a41341f112821482bee6c940c98mmentovai    // classes don't know or need to know what CPU (or endianness) the
39253261e8b6eac44a41341f112821482bee6c940c98mmentovai    // minidump was produced on in order to parse it.  Use the signature as
39263261e8b6eac44a41341f112821482bee6c940c98mmentovai    // a byte order marker.
39273261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t signature_swapped = header_.signature;
39283261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&signature_swapped);
39293261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature_swapped != MD_HEADER_SIGNATURE) {
39303261e8b6eac44a41341f112821482bee6c940c98mmentovai      // This isn't a minidump or a byte-swapped minidump.
3931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
3932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(header_.signature) << ", " <<
3933af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(signature_swapped) << ") != " <<
3934af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(MD_HEADER_SIGNATURE);
39353261e8b6eac44a41341f112821482bee6c940c98mmentovai      return false;
39363261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
39373261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = true;
39383261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
39393261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file is not byte-swapped.  Set swap_ false (it may have been true
39403261e8b6eac44a41341f112821482bee6c940c98mmentovai    // if the object is being reused?)
39413261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = false;
39423261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
39433261e8b6eac44a41341f112821482bee6c940c98mmentovai
3944af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
3945af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                 "byte-swapping minidump";
3946af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
39473261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_) {
39483261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.signature);
39493261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.version);
39503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_count);
39513261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_directory_rva);
39523261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.checksum);
39533261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.time_date_stamp);
39543261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.flags);
39553261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
39563261e8b6eac44a41341f112821482bee6c940c98mmentovai
39573261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Version check.  The high 16 bits of header_.version contain something
39583261e8b6eac44a41341f112821482bee6c940c98mmentovai  // else "implementation specific."
39593261e8b6eac44a41341f112821482bee6c940c98mmentovai  if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
3960af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump version mismatch: " <<
3961af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(header_.version & 0x0000ffff) << " != " <<
3962af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(MD_HEADER_VERSION);
39633261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
39643261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
39653261e8b6eac44a41341f112821482bee6c940c98mmentovai
3966af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(header_.stream_directory_rva)) {
3967af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
39683261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3969af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
39703261e8b6eac44a41341f112821482bee6c940c98mmentovai
3971e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count > max_streams_) {
3972e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
3973e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_streams_;
3974e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
3975e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
3976e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3977e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count != 0) {
3978373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpDirectoryEntries> directory(
3979373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpDirectoryEntries(header_.stream_count));
39803261e8b6eac44a41341f112821482bee6c940c98mmentovai
3981373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
3982373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
3983373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&(*directory)[0],
3984af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   sizeof(MDRawDirectory) * header_.stream_count)) {
3985af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump cannot read stream directory";
3986373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
3987af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
39883261e8b6eac44a41341f112821482bee6c940c98mmentovai
3989373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int stream_index = 0;
3990373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         stream_index < header_.stream_count;
3991373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++stream_index) {
3992373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDRawDirectory* directory_entry = &(*directory)[stream_index];
39933261e8b6eac44a41341f112821482bee6c940c98mmentovai
3994373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (swap_) {
3995373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->stream_type);
3996373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->location);
3997373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
39983261e8b6eac44a41341f112821482bee6c940c98mmentovai
3999373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Initialize the stream_map_ map, which speeds locating a stream by
4000373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // type.
4001373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      unsigned int stream_type = directory_entry->stream_type;
4002373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      switch (stream_type) {
4003373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_THREAD_LIST_STREAM:
4004373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MODULE_LIST_STREAM:
4005373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MEMORY_LIST_STREAM:
4006373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_EXCEPTION_STREAM:
4007373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_SYSTEM_INFO_STREAM:
4008373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MISC_INFO_STREAM:
4009e5dc60822e5938fea2ae892ccddb906641ba174emmentovai        case MD_BREAKPAD_INFO_STREAM: {
4010373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          if (stream_map_->find(stream_type) != stream_map_->end()) {
4011373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // Another stream with this type was already found.  A minidump
4012373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // file should contain at most one of each of these stream types.
4013af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            BPLOG(ERROR) << "Minidump found multiple streams of type " <<
4014af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                            stream_type << ", but can only deal with one";
4015373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            return false;
4016373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          }
4017373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Fall through to default
40183261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
40193261e8b6eac44a41341f112821482bee6c940c98mmentovai
4020373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        default: {
4021373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Overwrites for stream types other than those above, but it's
4022373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // expected to be the user's burden in that case.
4023373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          (*stream_map_)[stream_type].stream_index = stream_index;
4024373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        }
40253261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
40263261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
40273261e8b6eac44a41341f112821482bee6c940c98mmentovai
4028373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    directory_ = directory.release();
4029373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
40303261e8b6eac44a41341f112821482bee6c940c98mmentovai
40313261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
40323261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
40333261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40343261e8b6eac44a41341f112821482bee6c940c98mmentovai
40353261e8b6eac44a41341f112821482bee6c940c98mmentovai
40363261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList* Minidump::GetThreadList() {
40373261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpThreadList* thread_list;
40383261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&thread_list);
40393261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40403261e8b6eac44a41341f112821482bee6c940c98mmentovai
40413261e8b6eac44a41341f112821482bee6c940c98mmentovai
40423261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList* Minidump::GetModuleList() {
40433261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpModuleList* module_list;
40443261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&module_list);
40453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40463261e8b6eac44a41341f112821482bee6c940c98mmentovai
40473261e8b6eac44a41341f112821482bee6c940c98mmentovai
40483261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList* Minidump::GetMemoryList() {
40493261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryList* memory_list;
40503261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&memory_list);
40513261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40523261e8b6eac44a41341f112821482bee6c940c98mmentovai
40533261e8b6eac44a41341f112821482bee6c940c98mmentovai
40543261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException* Minidump::GetException() {
40553261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpException* exception;
40563261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&exception);
40573261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40583261e8b6eac44a41341f112821482bee6c940c98mmentovai
40590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion* Minidump::GetAssertion() {
40600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  MinidumpAssertion* assertion;
40610314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return GetStream(&assertion);
40620314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
40630314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
40643261e8b6eac44a41341f112821482bee6c940c98mmentovai
40653261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo* Minidump::GetSystemInfo() {
40663261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpSystemInfo* system_info;
40673261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&system_info);
40683261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40693261e8b6eac44a41341f112821482bee6c940c98mmentovai
40703261e8b6eac44a41341f112821482bee6c940c98mmentovai
40713261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo* Minidump::GetMiscInfo() {
40723261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMiscInfo* misc_info;
40733261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&misc_info);
40743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
40753261e8b6eac44a41341f112821482bee6c940c98mmentovai
40763261e8b6eac44a41341f112821482bee6c940c98mmentovai
4077e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
4078e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  MinidumpBreakpadInfo* breakpad_info;
4079e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  return GetStream(&breakpad_info);
408076f052f8fbf8864dee5992b857229d06560a766ammentovai}
408176f052f8fbf8864dee5992b857229d06560a766ammentovai
40827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
40837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MinidumpMemoryInfoList* memory_info_list;
40847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetStream(&memory_info_list);
40857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
40867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
408776f052f8fbf8864dee5992b857229d06560a766ammentovai
40883261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid Minidump::Print() {
4089af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4090af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot print invalid data";
40913261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
4092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
40933261e8b6eac44a41341f112821482bee6c940c98mmentovai
40943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawHeader\n");
40953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  signature            = 0x%x\n",    header_.signature);
40963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version              = 0x%x\n",    header_.version);
40973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_count         = %d\n",      header_.stream_count);
40983261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
40993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum             = 0x%x\n",    header_.checksum);
4100042ca733d309f48d2987a81151cbf3c59b73e562bryner  struct tm timestruct;
4101c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#ifdef _WIN32
4102c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek  gmtime_s(&timestruct, reinterpret_cast<time_t*>(&header_.time_date_stamp));
4103c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#else
4104042ca733d309f48d2987a81151cbf3c59b73e562bryner  gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
4105c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#endif
41063261e8b6eac44a41341f112821482bee6c940c98mmentovai  char timestr[20];
4107042ca733d309f48d2987a81151cbf3c59b73e562bryner  strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
41083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
41093261e8b6eac44a41341f112821482bee6c940c98mmentovai                                               timestr);
4110c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
41113261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
41123261e8b6eac44a41341f112821482bee6c940c98mmentovai
41133261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int stream_index = 0;
41143261e8b6eac44a41341f112821482bee6c940c98mmentovai       stream_index < header_.stream_count;
41153261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++stream_index) {
41163261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDRawDirectory* directory_entry = &(*directory_)[stream_index];
41173261e8b6eac44a41341f112821482bee6c940c98mmentovai
41183261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("mDirectory[%d]\n", stream_index);
41193261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDRawDirectory\n");
41203261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  stream_type        = %d\n",   directory_entry->stream_type);
41213261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.data_size = %d\n",
41223261e8b6eac44a41341f112821482bee6c940c98mmentovai           directory_entry->location.data_size);
41233261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
41243261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
41253261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
41263261e8b6eac44a41341f112821482bee6c940c98mmentovai
41273261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("Streams:\n");
41283261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
41293261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != stream_map_->end();
41303261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
41313261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t stream_type = iterator->first;
41323261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpStreamInfo info = iterator->second;
413376f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  stream type 0x%x at index %d\n", stream_type, info.stream_index);
41343261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
41353261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
41363261e8b6eac44a41341f112821482bee6c940c98mmentovai}
41373261e8b6eac44a41341f112821482bee6c940c98mmentovai
41383261e8b6eac44a41341f112821482bee6c940c98mmentovai
41393261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
41403261e8b6eac44a41341f112821482bee6c940c98mmentovai      const {
4141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4142af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
41433261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4144af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4145af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4146af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= header_.stream_count) {
4147af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
4148af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << header_.stream_count;
4149af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
4150af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41513261e8b6eac44a41341f112821482bee6c940c98mmentovai
41523261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*directory_)[index];
41533261e8b6eac44a41341f112821482bee6c940c98mmentovai}
41543261e8b6eac44a41341f112821482bee6c940c98mmentovai
41553261e8b6eac44a41341f112821482bee6c940c98mmentovai
41563261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::ReadBytes(void* bytes, size_t count) {
41573261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
41580cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
41590cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
41600cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
41610cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
41620cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->read(static_cast<char*>(bytes), count);
41630cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  size_t bytes_read = stream_->gcount();
41645ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  if (bytes_read != count) {
41655ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy    if (bytes_read == size_t(-1)) {
4166af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      string error_string;
4167af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      int error_code = ErrnoString(&error_string);
4168af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
4169af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    } else {
4170af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "ReadBytes: read " << bytes_read << "/" << count;
4171af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
41723261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4173af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41743261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
41753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
41763261e8b6eac44a41341f112821482bee6c940c98mmentovai
41773261e8b6eac44a41341f112821482bee6c940c98mmentovai
41783261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekSet(off_t offset) {
41793261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
41800cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
41810cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
41820cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
41830cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
41840cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->seekg(offset, std::ios_base::beg);
41850cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_->good()) {
41860cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    string error_string;
41870cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    int error_code = ErrnoString(&error_string);
41880cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
41893261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4190af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
41913261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
41923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
41933261e8b6eac44a41341f112821482bee6c940c98mmentovai
41940cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekoff_t Minidump::Tell() {
41950cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!valid_ || !stream_) {
41960cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return (off_t)-1;
41970cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
41980cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
41990cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  return stream_->tellg();
42000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
42010cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
42023261e8b6eac44a41341f112821482bee6c940c98mmentovai
42033261e8b6eac44a41341f112821482bee6c940c98mmentovaistring* Minidump::ReadString(off_t offset) {
4204af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4205af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for ReadString";
42063261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4207af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4208af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(offset)) {
4209e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
42103261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42123261e8b6eac44a41341f112821482bee6c940c98mmentovai
42133261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t bytes;
4214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&bytes, sizeof(bytes))) {
4215e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not read string size at offset " <<
4216e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    offset;
42173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4218af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_)
42203261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&bytes);
42213261e8b6eac44a41341f112821482bee6c940c98mmentovai
4222af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (bytes % 2 != 0) {
4223e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
4224e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    "-byte string at offset " << offset;
42253261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42273261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int utf16_words = bytes / 2;
42283261e8b6eac44a41341f112821482bee6c940c98mmentovai
4229e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (utf16_words > max_string_length_) {
4230e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString string length " << utf16_words <<
4231e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_string_length_ <<
4232e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " at offset " << offset;
4233e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return NULL;
4234e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4235e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
42363261e8b6eac44a41341f112821482bee6c940c98mmentovai  vector<u_int16_t> string_utf16(utf16_words);
42373261e8b6eac44a41341f112821482bee6c940c98mmentovai
4238373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (utf16_words) {
4239373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&string_utf16[0], bytes)) {
4240e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "ReadString could not read " << bytes <<
4241e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      "-byte string at offset " << offset;
4242373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
4243373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
4244373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
42453261e8b6eac44a41341f112821482bee6c940c98mmentovai
42463261e8b6eac44a41341f112821482bee6c940c98mmentovai  return UTF16ToUTF8(string_utf16, swap_);
42473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42483261e8b6eac44a41341f112821482bee6c940c98mmentovai
42493261e8b6eac44a41341f112821482bee6c940c98mmentovai
42503261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekToStreamType(u_int32_t  stream_type,
42513261e8b6eac44a41341f112821482bee6c940c98mmentovai                                u_int32_t* stream_length) {
4252af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
4253af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "|stream_length|";
4254af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream_length);
4255af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *stream_length = 0;
4256af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
42593261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42613261e8b6eac44a41341f112821482bee6c940c98mmentovai
42623261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
42633261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
42643261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
42663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
42673261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
42683261e8b6eac44a41341f112821482bee6c940c98mmentovai
42693261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo info = iterator->second;
4270af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (info.stream_index >= header_.stream_count) {
4271af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
4272af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " out of range: " <<
4273af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    info.stream_index << "/" << header_.stream_count;
42743261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4275af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42763261e8b6eac44a41341f112821482bee6c940c98mmentovai
42773261e8b6eac44a41341f112821482bee6c940c98mmentovai  MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
4278af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(directory_entry->location.rva)) {
4279af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
4280af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    stream_type;
42813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42833261e8b6eac44a41341f112821482bee6c940c98mmentovai
42843261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream_length = directory_entry->location.data_size;
42853261e8b6eac44a41341f112821482bee6c940c98mmentovai
42863261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
42873261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42883261e8b6eac44a41341f112821482bee6c940c98mmentovai
42893261e8b6eac44a41341f112821482bee6c940c98mmentovai
42903261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
42913261e8b6eac44a41341f112821482bee6c940c98mmentovaiT* Minidump::GetStream(T** stream) {
42923261e8b6eac44a41341f112821482bee6c940c98mmentovai  // stream is a garbage parameter that's present only to account for C++'s
42933261e8b6eac44a41341f112821482bee6c940c98mmentovai  // inability to overload a method based solely on its return type.
42943261e8b6eac44a41341f112821482bee6c940c98mmentovai
4295af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  const u_int32_t stream_type = T::kStreamType;
4296af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4297af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
4298af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                              " requires |stream|";
4299af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream);
43003261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = NULL;
43013261e8b6eac44a41341f112821482bee6c940c98mmentovai
4302af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4303af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
43043261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4305af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43063261e8b6eac44a41341f112821482bee6c940c98mmentovai
43073261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
43083261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
43093261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4310af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
43113261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
43123261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43133261e8b6eac44a41341f112821482bee6c940c98mmentovai
43143261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Get a pointer so that the stored stream field can be altered.
43153261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo* info = &iterator->second;
43163261e8b6eac44a41341f112821482bee6c940c98mmentovai
43173261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (info->stream) {
43183261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This cast is safe because info.stream is only populated by this
43193261e8b6eac44a41341f112821482bee6c940c98mmentovai    // method, and there is a direct correlation between T and stream_type.
43203261e8b6eac44a41341f112821482bee6c940c98mmentovai    *stream = static_cast<T*>(info->stream);
43213261e8b6eac44a41341f112821482bee6c940c98mmentovai    return *stream;
43223261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43233261e8b6eac44a41341f112821482bee6c940c98mmentovai
43243261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t stream_length;
4325af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekToStreamType(stream_type, &stream_length)) {
4326af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
43273261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4328af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43293261e8b6eac44a41341f112821482bee6c940c98mmentovai
43302466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<T> new_stream(new T(this));
43313261e8b6eac44a41341f112821482bee6c940c98mmentovai
4332af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!new_stream->Read(stream_length)) {
4333af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
43343261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4335af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43363261e8b6eac44a41341f112821482bee6c940c98mmentovai
43373261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = new_stream.release();
43383261e8b6eac44a41341f112821482bee6c940c98mmentovai  info->stream = *stream;
43393261e8b6eac44a41341f112821482bee6c940c98mmentovai  return *stream;
43403261e8b6eac44a41341f112821482bee6c940c98mmentovai}
43413261e8b6eac44a41341f112821482bee6c940c98mmentovai
43423261e8b6eac44a41341f112821482bee6c940c98mmentovai
4343e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
4344