minidump.cc revision 0e94332f7c615d2b734e840bef233f3ee1188801
17daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Copyright (c) 2006, 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
363261e8b6eac44a41341f112821482bee6c940c98mmentovai
376dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#include <fcntl.h>
383261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <stdio.h>
393261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <time.h>
403261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <unistd.h>
413261e8b6eac44a41341f112821482bee6c940c98mmentovai#ifdef _WIN32
423261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <io.h>
433261e8b6eac44a41341f112821482bee6c940c98mmentovaitypedef SSIZE_T ssize_t;
446dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#define open _open
453261e8b6eac44a41341f112821482bee6c940c98mmentovai#define read _read
463261e8b6eac44a41341f112821482bee6c940c98mmentovai#define lseek _lseek
4780e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#else  // _WIN32
486dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#define O_BINARY 0
4980e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#endif  // _WIN32
503261e8b6eac44a41341f112821482bee6c940c98mmentovai
5148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai#include <cassert>
52fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai#include <limits>
533261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <map>
543261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <vector>
553261e8b6eac44a41341f112821482bee6c940c98mmentovai
568c2a4def4ecfbf6293b27eff4359a274e9774b4emmentovai#include "processor/range_map-inl.h"
5780e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai
58e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/minidump.h"
59db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_module.h"
60db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_modules.h"
61af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai#include "processor/logging.h"
622466d8e993a800a17e00deda2f3a27e0505140e1mmentovai#include "processor/scoped_ptr.h"
633261e8b6eac44a41341f112821482bee6c940c98mmentovai
643261e8b6eac44a41341f112821482bee6c940c98mmentovai
65e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
663261e8b6eac44a41341f112821482bee6c940c98mmentovai
673261e8b6eac44a41341f112821482bee6c940c98mmentovai
68fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovaiusing std::numeric_limits;
693261e8b6eac44a41341f112821482bee6c940c98mmentovaiusing std::vector;
703261e8b6eac44a41341f112821482bee6c940c98mmentovai
713261e8b6eac44a41341f112821482bee6c940c98mmentovai
723261e8b6eac44a41341f112821482bee6c940c98mmentovai//
733261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping routines
743261e8b6eac44a41341f112821482bee6c940c98mmentovai//
753261e8b6eac44a41341f112821482bee6c940c98mmentovai// Inlining these doesn't increase code size significantly, and it saves
763261e8b6eac44a41341f112821482bee6c940c98mmentovai// a whole lot of unnecessary jumping back and forth.
773261e8b6eac44a41341f112821482bee6c940c98mmentovai//
783261e8b6eac44a41341f112821482bee6c940c98mmentovai
793261e8b6eac44a41341f112821482bee6c940c98mmentovai
803261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping an 8-bit quantity is a no-op.  This function is only provided
813261e8b6eac44a41341f112821482bee6c940c98mmentovai// to account for certain templatized operations that require swapping for
823261e8b6eac44a41341f112821482bee6c940c98mmentovai// wider types but handle u_int8_t too
833261e8b6eac44a41341f112821482bee6c940c98mmentovai// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
843261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int8_t* value) {
853261e8b6eac44a41341f112821482bee6c940c98mmentovai}
863261e8b6eac44a41341f112821482bee6c940c98mmentovai
873261e8b6eac44a41341f112821482bee6c940c98mmentovai
883261e8b6eac44a41341f112821482bee6c940c98mmentovai// Optimization: don't need to AND the furthest right shift, because we're
893261e8b6eac44a41341f112821482bee6c940c98mmentovai// shifting an unsigned quantity.  The standard requires zero-filling in this
903261e8b6eac44a41341f112821482bee6c940c98mmentovai// case.  If the quantities were signed, a bitmask whould be needed for this
913261e8b6eac44a41341f112821482bee6c940c98mmentovai// right shift to avoid an arithmetic shift (which retains the sign bit).
923261e8b6eac44a41341f112821482bee6c940c98mmentovai// The furthest left shift never needs to be ANDed bitmask.
933261e8b6eac44a41341f112821482bee6c940c98mmentovai
943261e8b6eac44a41341f112821482bee6c940c98mmentovai
953261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int16_t* value) {
963261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = (*value >> 8) |
973261e8b6eac44a41341f112821482bee6c940c98mmentovai           (*value << 8);
983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
993261e8b6eac44a41341f112821482bee6c940c98mmentovai
1003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1013261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int32_t* value) {
1023261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 24) |
1033261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x0000ff00) |
1043261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x00ff0000) |
1053261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 24);
1063261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1073261e8b6eac44a41341f112821482bee6c940c98mmentovai
1083261e8b6eac44a41341f112821482bee6c940c98mmentovai
1093261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(u_int64_t* value) {
1103261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 56) |
1113261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 40) & 0x000000000000ff00LL) |
1123261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 24) & 0x0000000000ff0000LL) |
1133261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x00000000ff000000LL) |
1143261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x000000ff00000000LL) |
1153261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 24) & 0x0000ff0000000000LL) |
1163261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 40) & 0x00ff000000000000LL) |
1173261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 56);
1183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1193261e8b6eac44a41341f112821482bee6c940c98mmentovai
1203261e8b6eac44a41341f112821482bee6c940c98mmentovai
1211d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// Given a pointer to a 128-bit int in the minidump data, set the "low"
1221d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// and "high" fields appropriately.
1231d78cad82e3c7aa2315ed7438211a1901a91ed34brynerstatic void Normalize128(u_int128_t* value, bool is_big_endian) {
1241d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // The struct format is [high, low], so if the format is big-endian,
1251d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // the most significant bytes will already be in the high field.
1261d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  if (!is_big_endian) {
1271d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    u_int64_t temp = value->low;
1281d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->low = value->high;
1291d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->high = temp;
1301d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  }
1311d78cad82e3c7aa2315ed7438211a1901a91ed34bryner}
1323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1331d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// This just swaps each int64 half of the 128-bit value.
1341d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// The value should also be normalized by calling Normalize128().
1351d78cad82e3c7aa2315ed7438211a1901a91ed34brynerstatic void Swap(u_int128_t* value) {
1361d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->low);
1371d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->high);
1383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
1393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1413261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDLocationDescriptor* location_descriptor) {
1423261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->data_size);
1433261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->rva);
1443261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1453261e8b6eac44a41341f112821482bee6c940c98mmentovai
1463261e8b6eac44a41341f112821482bee6c940c98mmentovai
1473261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDMemoryDescriptor* memory_descriptor) {
1483261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->start_of_memory_range);
1493261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->memory);
1503261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1513261e8b6eac44a41341f112821482bee6c940c98mmentovai
1523261e8b6eac44a41341f112821482bee6c940c98mmentovai
1533261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDGUID* guid) {
1543261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data1);
1553261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data2);
1563261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data3);
1573261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't swap guid->data4[] because it contains 8-bit quantities.
1583261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1593261e8b6eac44a41341f112821482bee6c940c98mmentovai
1603261e8b6eac44a41341f112821482bee6c940c98mmentovai
1613261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1623261e8b6eac44a41341f112821482bee6c940c98mmentovai// Character conversion routines
1633261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1643261e8b6eac44a41341f112821482bee6c940c98mmentovai
1653261e8b6eac44a41341f112821482bee6c940c98mmentovai
1663261e8b6eac44a41341f112821482bee6c940c98mmentovai// Standard wide-character conversion routines depend on the system's own
1673261e8b6eac44a41341f112821482bee6c940c98mmentovai// idea of what width a wide character should be: some use 16 bits, and
1683261e8b6eac44a41341f112821482bee6c940c98mmentovai// some use 32 bits.  For the purposes of a minidump, wide strings are
1693261e8b6eac44a41341f112821482bee6c940c98mmentovai// always represented with 16-bit UTF-16 chracters.  iconv isn't available
1703261e8b6eac44a41341f112821482bee6c940c98mmentovai// everywhere, and its interface varies where it is available.  iconv also
1713261e8b6eac44a41341f112821482bee6c940c98mmentovai// deals purely with char* pointers, so in addition to considering the swap
1723261e8b6eac44a41341f112821482bee6c940c98mmentovai// parameter, a converter that uses iconv would also need to take the host
1733261e8b6eac44a41341f112821482bee6c940c98mmentovai// CPU's endianness into consideration.  It doesn't seems worth the trouble
1743261e8b6eac44a41341f112821482bee6c940c98mmentovai// of making it a dependency when we don't care about anything but UTF-16.
1753261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic string* UTF16ToUTF8(const vector<u_int16_t>& in,
1763261e8b6eac44a41341f112821482bee6c940c98mmentovai                           bool                     swap) {
1772466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<string> out(new string());
1783261e8b6eac44a41341f112821482bee6c940c98mmentovai
1793261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Set the string's initial capacity to the number of UTF-16 characters,
1803261e8b6eac44a41341f112821482bee6c940c98mmentovai  // because the UTF-8 representation will always be at least this long.
1813261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the UTF-8 representation is longer, the string will grow dynamically.
1823261e8b6eac44a41341f112821482bee6c940c98mmentovai  out->reserve(in.size());
1833261e8b6eac44a41341f112821482bee6c940c98mmentovai
1843261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (vector<u_int16_t>::const_iterator iterator = in.begin();
1853261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != in.end();
1863261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
1873261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Get a 16-bit value from the input
1883261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int16_t in_word = *iterator;
1893261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (swap)
1903261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&in_word);
1913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1923261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the input value (in_word) into a Unicode code point (unichar).
1933261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t unichar;
1943261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (in_word >= 0xdc00 && in_word <= 0xdcff) {
195af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
196af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(in_word) << " without high";
1973261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1983261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
1993261e8b6eac44a41341f112821482bee6c940c98mmentovai      // High surrogate.
2003261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = (in_word - 0xd7c0) << 10;
2013261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (++iterator == in.end()) {
202af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
203af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word) << " at end of string";
2043261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2053261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
206af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      u_int32_t high_word = in_word;
2073261e8b6eac44a41341f112821482bee6c940c98mmentovai      in_word = *iterator;
2083261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (in_word < 0xdc00 || in_word > 0xdcff) {
209af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
210af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(high_word) << " without low " <<
211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word);
2123261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2133261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2143261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar |= in_word & 0x03ff;
2153261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
2163261e8b6eac44a41341f112821482bee6c940c98mmentovai      // The ordinary case, a single non-surrogate Unicode character encoded
2173261e8b6eac44a41341f112821482bee6c940c98mmentovai      // as a single 16-bit value.
2183261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = in_word;
2193261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2203261e8b6eac44a41341f112821482bee6c940c98mmentovai
2213261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the Unicode code point (unichar) into its UTF-8 representation,
2223261e8b6eac44a41341f112821482bee6c940c98mmentovai    // appending it to the out string.
2233261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (unichar < 0x80) {
2243261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += unichar;
2253261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x800) {
2263261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xc0 | (unichar >> 6);
2273261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2283261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x10000) {
2293261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xe0 | (unichar >> 12);
2303261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 6) & 0x3f);
2313261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2323261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x200000) {
2333261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0xf0 | (unichar >> 18);
2343261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 12) & 0x3f);
2353261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | ((unichar >> 6) & 0x3f);
2363261e8b6eac44a41341f112821482bee6c940c98mmentovai      (*out) += 0x80 | (unichar & 0x3f);
2373261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
238af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
239af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(unichar) << " in UTF-8";
2403261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2413261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2423261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
2433261e8b6eac44a41341f112821482bee6c940c98mmentovai
2443261e8b6eac44a41341f112821482bee6c940c98mmentovai  return out.release();
2453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2463261e8b6eac44a41341f112821482bee6c940c98mmentovai
2473261e8b6eac44a41341f112821482bee6c940c98mmentovai
2483261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2493261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpObject
2503261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2513261e8b6eac44a41341f112821482bee6c940c98mmentovai
2523261e8b6eac44a41341f112821482bee6c940c98mmentovai
2533261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpObject::MinidumpObject(Minidump* minidump)
25453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : minidump_(minidump),
25553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
2563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2573261e8b6eac44a41341f112821482bee6c940c98mmentovai
2583261e8b6eac44a41341f112821482bee6c940c98mmentovai
2593261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2603261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpStream
2613261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2623261e8b6eac44a41341f112821482bee6c940c98mmentovai
2633261e8b6eac44a41341f112821482bee6c940c98mmentovai
2643261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpStream::MinidumpStream(Minidump* minidump)
2653261e8b6eac44a41341f112821482bee6c940c98mmentovai    : MinidumpObject(minidump) {
2663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2673261e8b6eac44a41341f112821482bee6c940c98mmentovai
2683261e8b6eac44a41341f112821482bee6c940c98mmentovai
2693261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2703261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpContext
2713261e8b6eac44a41341f112821482bee6c940c98mmentovai//
2723261e8b6eac44a41341f112821482bee6c940c98mmentovai
2733261e8b6eac44a41341f112821482bee6c940c98mmentovai
2743261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext::MinidumpContext(Minidump* minidump)
27553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
27653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_() {
2773261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2783261e8b6eac44a41341f112821482bee6c940c98mmentovai
2793261e8b6eac44a41341f112821482bee6c940c98mmentovai
2803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiMinidumpContext::~MinidumpContext() {
2813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
2823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
2833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
2843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
2853261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpContext::Read(u_int32_t expected_size) {
2863261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
2873261e8b6eac44a41341f112821482bee6c940c98mmentovai
2883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
2893261e8b6eac44a41341f112821482bee6c940c98mmentovai
2903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // First, figure out what type of CPU this context structure is for.
2913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  u_int32_t context_flags;
292af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
293af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext could not read context flags";
2943261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
295af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  if (minidump_->swap())
2973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    Swap(&context_flags);
2983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
2993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
3003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Allocate the context structure for the correct CPU and fill it.  The
3023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // casts are slightly unorthodox, but it seems better to do that than to
3033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // maintain a separate pointer for each type of CPU context structure
3043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // when only one of them will be used.
3053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (cpu_type) {
3063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86: {
307af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (expected_size != sizeof(MDRawContextX86)) {
308af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
309af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        expected_size << " != " << sizeof(MDRawContextX86);
3103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
311af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3132466d8e993a800a17e00deda2f3a27e0505140e1mmentovai      scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
3143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // Set the context_flags member, which has already been read, and
3163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // read the rest of the structure beginning with the first member
3173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // after context_flags.
3183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      context_x86->context_flags = context_flags;
3193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      size_t flags_size = sizeof(context_x86->context_flags);
3213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      u_int8_t* context_after_flags =
3223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai          reinterpret_cast<u_int8_t*>(context_x86.get()) + flags_size;
3233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      if (!minidump_->ReadBytes(context_after_flags,
3243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai                                sizeof(MDRawContextX86) - flags_size)) {
325af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext could not read x86 context";
3263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
3273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
3283261e8b6eac44a41341f112821482bee6c940c98mmentovai
3293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // Do this after reading the entire MDRawContext structure because
3303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // GetSystemInfo may seek minidump to a new position.
331af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!CheckAgainstSystemInfo(cpu_type)) {
332af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
3333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
334af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      if (minidump_->swap()) {
3373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // context_x86->context_flags was already swapped.
3383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr0);
3393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr1);
3403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr2);
3413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr3);
3423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr6);
3433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->dr7);
3443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.control_word);
3453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.status_word);
3463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.tag_word);
3473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.error_offset);
3483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.error_selector);
3493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.data_offset);
3503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.data_selector);
3513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // context_x86->float_save.register_area[] contains 8-bit quantities
3523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // and does not need to be swapped.
3533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->float_save.cr0_npx_state);
3543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->gs);
3553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->fs);
3563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->es);
3573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->ds);
3583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->edi);
3593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->esi);
3603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->ebx);
3613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->edx);
3623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->ecx);
3633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->eax);
3643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->ebp);
3653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->eip);
3663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->cs);
3673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->eflags);
3683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->esp);
3693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_x86->ss);
3703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // context_x86->extended_registers[] contains 8-bit quantities and
3713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // does not need to be swapped.
3723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
3733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      context_.x86 = context_x86.release();
3753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
3773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
3783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC: {
380af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (expected_size != sizeof(MDRawContextPPC)) {
381af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
382af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        expected_size << " != " << sizeof(MDRawContextPPC);
3833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
384af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3862466d8e993a800a17e00deda2f3a27e0505140e1mmentovai      scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
3873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // Set the context_flags member, which has already been read, and
3893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // read the rest of the structure beginning with the first member
3903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // after context_flags.
3913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      context_ppc->context_flags = context_flags;
3923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      size_t flags_size = sizeof(context_ppc->context_flags);
3943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      u_int8_t* context_after_flags =
3953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai          reinterpret_cast<u_int8_t*>(context_ppc.get()) + flags_size;
3963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      if (!minidump_->ReadBytes(context_after_flags,
3973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai                                sizeof(MDRawContextPPC) - flags_size)) {
398af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext could not read ppc context";
3993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
4003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
4013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // Do this after reading the entire MDRawContext structure because
4033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // GetSystemInfo may seek minidump to a new position.
404af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!CheckAgainstSystemInfo(cpu_type)) {
405af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
4063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        return false;
407af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
4083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4091d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      // Normalize the 128-bit types in the dump.
4101d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      // Since this is PowerPC, by definition, the values are big-endian.
4111d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      for (unsigned int vr_index = 0;
4121d78cad82e3c7aa2315ed7438211a1901a91ed34bryner           vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
4131d78cad82e3c7aa2315ed7438211a1901a91ed34bryner           ++vr_index) {
4141d78cad82e3c7aa2315ed7438211a1901a91ed34bryner        Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
4151d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      }
4161d78cad82e3c7aa2315ed7438211a1901a91ed34bryner
4173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      if (minidump_->swap()) {
4183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // context_ppc->context_flags was already swapped.
4193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->srr0);
4203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->srr1);
4213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int gpr_index = 0;
4223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
4233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++gpr_index) {
4243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai          Swap(&context_ppc->gpr[gpr_index]);
4253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
4263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->cr);
4273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->xer);
4283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->lr);
4293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->ctr);
4303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->mq);
4313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->vrsave);
4323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int fpr_index = 0;
4333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
4343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++fpr_index) {
4353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai          Swap(&context_ppc->float_save.fpregs[fpr_index]);
4363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
4373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // Don't swap context_ppc->float_save.fpscr_pad because it is only
4383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // used for padding.
4393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->float_save.fpscr);
4403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int vr_index = 0;
4413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
4423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++vr_index) {
4433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai          Swap(&context_ppc->vector_save.save_vr[vr_index]);
4443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
4453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->vector_save.save_vscr);
4463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        // Don't swap the padding fields in vector_save.
4473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&context_ppc->vector_save.save_vrvalid);
4483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
4493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      context_.ppc = context_ppc.release();
4513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
4533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
4543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default: {
4563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // Unknown context type
457af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpContext unknown context type " <<
458af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(cpu_type);
4593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      return false;
4603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
4613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
4623261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
4633261e8b6eac44a41341f112821482bee6c940c98mmentovai
4643261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
4653261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
4663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
4673261e8b6eac44a41341f112821482bee6c940c98mmentovai
4683261e8b6eac44a41341f112821482bee6c940c98mmentovai
4693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiu_int32_t MinidumpContext::GetContextCPU() const {
470af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
471af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // Don't log a message, GetContextCPU can be legitimately called with
472af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // valid_ false by FreeContext, which is called by Read.
473af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
474af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
475af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
476af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.base->context_flags & MD_CONTEXT_CPU_MASK;
4773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
4783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextX86* MinidumpContext::GetContextX86() const {
481af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_X86) {
482af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get x86 context";
483af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
484af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
485af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
486af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.x86;
4873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
4883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextPPC* MinidumpContext::GetContextPPC() const {
491af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_PPC) {
492af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get ppc context";
493af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
494af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
495af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
496af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.ppc;
4973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
4983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::FreeContext() {
5013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
5023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
5033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.x86;
5043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
5053261e8b6eac44a41341f112821482bee6c940c98mmentovai
5063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
5073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.ppc;
5083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
5093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default:
5113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // There is no context record (valid_ is false) or there's a
5123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context record for an unknown CPU (shouldn't happen, only known
5133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // records are stored by Read).
5143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
5153261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
5163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  context_.base = NULL;
5183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
5193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaibool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) {
522e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
5233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // as this function just implements a sanity check.
5243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
525af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!system_info) {
526af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
527af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MinidumpSystemInfo";
5283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return true;
529af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
5303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
531e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
5323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  const MDRawSystemInfo* raw_system_info = system_info->system_info();
533af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
534af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
535af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MDRawSystemInfo";
5363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return false;
537af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
5383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
5403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      raw_system_info->processor_architecture);
5413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Compare the CPU type of the context record to the CPU type in the
5433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // minidump's system info stream.
544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  bool return_value = false;
5453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (context_cpu_type) {
5463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
547af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
548af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai          system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64) {
549af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
5503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
5513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
5523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
554af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
555af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
5563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
5573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  }
5583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
559af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(context_cpu_type) <<
561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    " wrong for MinidumpSysmtemInfo CPU " <<
562af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(system_info_cpu_type);
563af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
564af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return return_value;
5653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
5663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::Print() {
569af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
570af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot print invalid data";
571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return;
572af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
573af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
5743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
5753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86: {
5763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextX86* context_x86 = GetContextX86();
5773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextX86\n");
5783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags                = 0x%x\n",
5793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->context_flags);
5803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr0                          = 0x%x\n", context_x86->dr0);
5813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr1                          = 0x%x\n", context_x86->dr1);
5823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr2                          = 0x%x\n", context_x86->dr2);
5833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr3                          = 0x%x\n", context_x86->dr3);
5843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr6                          = 0x%x\n", context_x86->dr6);
5853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr7                          = 0x%x\n", context_x86->dr7);
5863402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.control_word      = 0x%x\n",
5873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.control_word);
5883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.status_word       = 0x%x\n",
5893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.status_word);
5903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.tag_word          = 0x%x\n",
5913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.tag_word);
5923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_offset      = 0x%x\n",
5933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_offset);
5943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_selector    = 0x%x\n",
5953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_selector);
5963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_offset       = 0x%x\n",
5973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_offset);
5983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_selector     = 0x%x\n",
5993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_selector);
6003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.register_area[%2d] = 0x",
6013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
6023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
6033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
6043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
6053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->float_save.register_area[register_index]);
6063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
6073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
6083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.cr0_npx_state     = 0x%x\n",
6093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.cr0_npx_state);
6103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  gs                           = 0x%x\n", context_x86->gs);
6113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  fs                           = 0x%x\n", context_x86->fs);
6123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  es                           = 0x%x\n", context_x86->es);
6133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ds                           = 0x%x\n", context_x86->ds);
6143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edi                          = 0x%x\n", context_x86->edi);
6153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esi                          = 0x%x\n", context_x86->esi);
6163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebx                          = 0x%x\n", context_x86->ebx);
6173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edx                          = 0x%x\n", context_x86->edx);
6183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ecx                          = 0x%x\n", context_x86->ecx);
6193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eax                          = 0x%x\n", context_x86->eax);
6203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebp                          = 0x%x\n", context_x86->ebp);
6213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eip                          = 0x%x\n", context_x86->eip);
6223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cs                           = 0x%x\n", context_x86->cs);
6233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eflags                       = 0x%x\n", context_x86->eflags);
6243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esp                          = 0x%x\n", context_x86->esp);
6253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ss                           = 0x%x\n", context_x86->ss);
6263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  extended_registers[%3d]      = 0x",
6273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
6283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
6293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
6303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
6313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->extended_registers[register_index]);
6323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
6333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n\n");
6343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
6363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
6373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC: {
6393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextPPC* context_ppc = GetContextPPC();
6403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextPPC\n");
6413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags            = 0x%x\n",
6423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->context_flags);
6433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr0                     = 0x%x\n", context_ppc->srr0);
6443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr1                     = 0x%x\n", context_ppc->srr1);
6453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int gpr_index = 0;
6463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
6473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++gpr_index) {
6483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("  gpr[%2d]                  = 0x%x\n",
6493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               gpr_index, context_ppc->gpr[gpr_index]);
6503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
6513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cr                       = 0x%x\n", context_ppc->cr);
6523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  xer                      = 0x%x\n", context_ppc->xer);
6533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  lr                       = 0x%x\n", context_ppc->lr);
6543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ctr                      = 0x%x\n", context_ppc->ctr);
6553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  mq                       = 0x%x\n", context_ppc->mq);
6563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vrsave                   = 0x%x\n", context_ppc->vrsave);
6573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int fpr_index = 0;
6583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
6593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++fpr_index) {
660960e5277ee489960c40c50c6222606200419302ammentovai        printf("  float_save.fpregs[%2d]    = 0x%llx\n",
6613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               fpr_index, context_ppc->float_save.fpregs[fpr_index]);
6623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
6633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.fpscr         = 0x%x\n",
6643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->float_save.fpscr);
6653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // TODO(mmentovai): print the 128-bit quantities in
6663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context_ppc->vector_save.  This isn't done yet because printf
6673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // doesn't support 128-bit quantities, and printing them using
6683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // %llx as two 64-bit quantities requires knowledge of the CPU's
6693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // byte ordering.
6703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vector_save.save_vrvalid = 0x%x\n",
6713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->vector_save.save_vrvalid);
6723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
6733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
6753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
6763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default: {
6783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
6793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
6803261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
6813261e8b6eac44a41341f112821482bee6c940c98mmentovai}
6823261e8b6eac44a41341f112821482bee6c940c98mmentovai
6833261e8b6eac44a41341f112821482bee6c940c98mmentovai
6843261e8b6eac44a41341f112821482bee6c940c98mmentovai//
6853261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryRegion
6863261e8b6eac44a41341f112821482bee6c940c98mmentovai//
6873261e8b6eac44a41341f112821482bee6c940c98mmentovai
6883261e8b6eac44a41341f112821482bee6c940c98mmentovai
6893261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
69053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
69153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptor_(NULL),
69253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL) {
6933261e8b6eac44a41341f112821482bee6c940c98mmentovai}
6943261e8b6eac44a41341f112821482bee6c940c98mmentovai
6953261e8b6eac44a41341f112821482bee6c940c98mmentovai
6963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::~MinidumpMemoryRegion() {
6973261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
6983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
6993261e8b6eac44a41341f112821482bee6c940c98mmentovai
7003261e8b6eac44a41341f112821482bee6c940c98mmentovai
7013261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
7023261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptor_ = descriptor;
7033261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = descriptor &&
704fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai           descriptor_->memory.data_size <=
705fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               numeric_limits<uint64_t>::max() -
706fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               descriptor_->start_of_memory_range;
7073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7083261e8b6eac44a41341f112821482bee6c940c98mmentovai
7093261e8b6eac44a41341f112821482bee6c940c98mmentovai
7103261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst u_int8_t* MinidumpMemoryRegion::GetMemory() {
711af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
712af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
7133261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
714af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
7153261e8b6eac44a41341f112821482bee6c940c98mmentovai
7163261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!memory_) {
717af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (descriptor_->memory.data_size == 0) {
718af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
719373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
720af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
721373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
722af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(descriptor_->memory.rva)) {
723af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
7243261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
725af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
7263261e8b6eac44a41341f112821482bee6c940c98mmentovai
7273261e8b6eac44a41341f112821482bee6c940c98mmentovai    // TODO(mmentovai): verify rational size!
7282466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > memory(
7293261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(descriptor_->memory.data_size));
7303261e8b6eac44a41341f112821482bee6c940c98mmentovai
731af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
732af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
7333261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
734af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
7353261e8b6eac44a41341f112821482bee6c940c98mmentovai
7363261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory_ = memory.release();
7373261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
7383261e8b6eac44a41341f112821482bee6c940c98mmentovai
7393261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*memory_)[0];
7403261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7413261e8b6eac44a41341f112821482bee6c940c98mmentovai
7423261e8b6eac44a41341f112821482bee6c940c98mmentovai
7433261e8b6eac44a41341f112821482bee6c940c98mmentovaiu_int64_t MinidumpMemoryRegion::GetBase() {
744af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
745af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return static_cast<u_int64_t>(-1);
747af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
748af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->start_of_memory_range;
7503261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7513261e8b6eac44a41341f112821482bee6c940c98mmentovai
7523261e8b6eac44a41341f112821482bee6c940c98mmentovai
7533261e8b6eac44a41341f112821482bee6c940c98mmentovaiu_int32_t MinidumpMemoryRegion::GetSize() {
754af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
755af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
756af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
757af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
758af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
759af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->memory.data_size;
7603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7613261e8b6eac44a41341f112821482bee6c940c98mmentovai
7623261e8b6eac44a41341f112821482bee6c940c98mmentovai
7633261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::FreeMemory() {
7643261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
7653261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
7663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
7673261e8b6eac44a41341f112821482bee6c940c98mmentovai
7683261e8b6eac44a41341f112821482bee6c940c98mmentovai
7693261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
7703261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddressInternal(u_int64_t address,
7713261e8b6eac44a41341f112821482bee6c940c98mmentovai                                                      T*        value) {
772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                             "requires |value|";
774af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(value);
775af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *value = 0;
776af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
777af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
778af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
779af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "GetMemoryAtAddressInternal";
7803261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
781af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
7823261e8b6eac44a41341f112821482bee6c940c98mmentovai
7833261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (address < descriptor_->start_of_memory_range ||
784fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      sizeof(T) > numeric_limits<u_int64_t>::max() - address ||
7853261e8b6eac44a41341f112821482bee6c940c98mmentovai      address + sizeof(T) > descriptor_->start_of_memory_range +
7863261e8b6eac44a41341f112821482bee6c940c98mmentovai                            descriptor_->memory.data_size) {
787af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion request out of range: " <<
788af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(address) << "+" << sizeof(T) << "/" <<
789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->start_of_memory_range) << "+" <<
790af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->memory.data_size);
7913261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
7923261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
7933261e8b6eac44a41341f112821482bee6c940c98mmentovai
7943261e8b6eac44a41341f112821482bee6c940c98mmentovai  const u_int8_t* memory = GetMemory();
795af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!memory) {
796af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // GetMemory already logged a perfectly good message.
7973261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
798af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
7993261e8b6eac44a41341f112821482bee6c940c98mmentovai
8003261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the CPU requires memory accesses to be aligned, this can crash.
8013261e8b6eac44a41341f112821482bee6c940c98mmentovai  // x86 and ppc are able to cope, though.
8023261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = *reinterpret_cast<const T*>(
8033261e8b6eac44a41341f112821482bee6c940c98mmentovai      &memory[address - descriptor_->start_of_memory_range]);
8043261e8b6eac44a41341f112821482bee6c940c98mmentovai
8053261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
8063261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(value);
8073261e8b6eac44a41341f112821482bee6c940c98mmentovai
8083261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
8093261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8103261e8b6eac44a41341f112821482bee6c940c98mmentovai
8113261e8b6eac44a41341f112821482bee6c940c98mmentovai
8123261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
8133261e8b6eac44a41341f112821482bee6c940c98mmentovai                                              u_int8_t*  value) {
8143261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
8153261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8163261e8b6eac44a41341f112821482bee6c940c98mmentovai
8173261e8b6eac44a41341f112821482bee6c940c98mmentovai
8183261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
8193261e8b6eac44a41341f112821482bee6c940c98mmentovai                                              u_int16_t* value) {
8203261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
8213261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8223261e8b6eac44a41341f112821482bee6c940c98mmentovai
8233261e8b6eac44a41341f112821482bee6c940c98mmentovai
8243261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
8253261e8b6eac44a41341f112821482bee6c940c98mmentovai                                              u_int32_t* value) {
8263261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
8273261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8283261e8b6eac44a41341f112821482bee6c940c98mmentovai
8293261e8b6eac44a41341f112821482bee6c940c98mmentovai
8303261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
8313261e8b6eac44a41341f112821482bee6c940c98mmentovai                                              u_int64_t* value) {
8323261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
8333261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8343261e8b6eac44a41341f112821482bee6c940c98mmentovai
8353261e8b6eac44a41341f112821482bee6c940c98mmentovai
8363261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::Print() {
837af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
8393261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
8413261e8b6eac44a41341f112821482bee6c940c98mmentovai
8423261e8b6eac44a41341f112821482bee6c940c98mmentovai  const u_int8_t* memory = GetMemory();
8433261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
8443261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("0x");
8453261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int byte_index = 0;
8463261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index < descriptor_->memory.data_size;
8473261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index++) {
8483261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("%02x", memory[byte_index]);
8493261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
8503261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
8513261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
8523261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No memory\n");
8533261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
8543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8553261e8b6eac44a41341f112821482bee6c940c98mmentovai
8563261e8b6eac44a41341f112821482bee6c940c98mmentovai
8573261e8b6eac44a41341f112821482bee6c940c98mmentovai//
8583261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThread
8593261e8b6eac44a41341f112821482bee6c940c98mmentovai//
8603261e8b6eac44a41341f112821482bee6c940c98mmentovai
8613261e8b6eac44a41341f112821482bee6c940c98mmentovai
8623261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::MinidumpThread(Minidump* minidump)
86353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
86453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_(),
86553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL),
86653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
8673261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8683261e8b6eac44a41341f112821482bee6c940c98mmentovai
8693261e8b6eac44a41341f112821482bee6c940c98mmentovai
8703261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::~MinidumpThread() {
8713261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
8723261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
8733261e8b6eac44a41341f112821482bee6c940c98mmentovai}
8743261e8b6eac44a41341f112821482bee6c940c98mmentovai
8753261e8b6eac44a41341f112821482bee6c940c98mmentovai
8763261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThread::Read() {
8773261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
8783261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
8793261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
8803261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
8813261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
8823261e8b6eac44a41341f112821482bee6c940c98mmentovai
8833261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
8843261e8b6eac44a41341f112821482bee6c940c98mmentovai
885af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
886af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot read thread";
8873261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
888af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
8893261e8b6eac44a41341f112821482bee6c940c98mmentovai
8903261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
8913261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_id);
8923261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.suspend_count);
8933261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority_class);
8943261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority);
8953261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.teb);
8963261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.stack);
8973261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_context);
8983261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
8993261e8b6eac44a41341f112821482bee6c940c98mmentovai
900fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
9013261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (thread_.stack.memory.data_size == 0 ||
902fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      thread_.stack.memory.data_size > numeric_limits<u_int64_t>::max() -
903fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                                       thread_.stack.start_of_memory_range) {
904af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
905af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(thread_.stack.start_of_memory_range) << "+" <<
906fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(thread_.stack.memory.data_size);
9073261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
908af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
9093261e8b6eac44a41341f112821482bee6c940c98mmentovai
9103261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = new MinidumpMemoryRegion(minidump_);
9113261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_->SetDescriptor(&thread_.stack);
9123261e8b6eac44a41341f112821482bee6c940c98mmentovai
9133261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
9143261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
9153261e8b6eac44a41341f112821482bee6c940c98mmentovai}
9163261e8b6eac44a41341f112821482bee6c940c98mmentovai
9173261e8b6eac44a41341f112821482bee6c940c98mmentovai
9183261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpThread::GetMemory() {
919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
920af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
921af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
922af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
923af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
924af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return memory_;
9253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
9263261e8b6eac44a41341f112821482bee6c940c98mmentovai
9273261e8b6eac44a41341f112821482bee6c940c98mmentovai
9283261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpThread::GetContext() {
929af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
930af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
9313261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
9333261e8b6eac44a41341f112821482bee6c940c98mmentovai
9343261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(thread_.thread_context.rva)) {
936af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot seek to context";
9373261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
938af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
9393261e8b6eac44a41341f112821482bee6c940c98mmentovai
9402466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
9413261e8b6eac44a41341f112821482bee6c940c98mmentovai
942af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(thread_.thread_context.data_size)) {
943af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot read context";
9443261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
945af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
9463261e8b6eac44a41341f112821482bee6c940c98mmentovai
9473261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
9483261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
9493261e8b6eac44a41341f112821482bee6c940c98mmentovai
9503261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
9513261e8b6eac44a41341f112821482bee6c940c98mmentovai}
9523261e8b6eac44a41341f112821482bee6c940c98mmentovai
9533261e8b6eac44a41341f112821482bee6c940c98mmentovai
95476f052f8fbf8864dee5992b857229d06560a766ammentovaibool MinidumpThread::GetThreadID(u_int32_t *thread_id) const {
955af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
956af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
957af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
958af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
959af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
960af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
961af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
96276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
963af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
96476f052f8fbf8864dee5992b857229d06560a766ammentovai
96576f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = thread_.thread_id;
96676f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
9673261e8b6eac44a41341f112821482bee6c940c98mmentovai}
9683261e8b6eac44a41341f112821482bee6c940c98mmentovai
9693261e8b6eac44a41341f112821482bee6c940c98mmentovai
9703261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThread::Print() {
971af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
972af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
9733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
974af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
9753261e8b6eac44a41341f112821482bee6c940c98mmentovai
9763261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawThread\n");
9773261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
9783261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suspend_count               = %d\n",     thread_.suspend_count);
9793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority_class              = 0x%x\n",   thread_.priority_class);
9803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority                    = 0x%x\n",   thread_.priority);
9813261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  teb                         = 0x%llx\n", thread_.teb);
9823261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.start_of_memory_range = 0x%llx\n",
9833261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.start_of_memory_range);
9843261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.data_size      = 0x%x\n",
9853261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.memory.data_size);
9863261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
9873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size    = 0x%x\n",
9883261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.data_size);
9893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva          = 0x%x\n",
9903261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.rva);
9913261e8b6eac44a41341f112821482bee6c940c98mmentovai
9923261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
9933261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
9943261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
9953261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
9963261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
9973261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
9983261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
9993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
10003261e8b6eac44a41341f112821482bee6c940c98mmentovai
10013261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryRegion* memory = GetMemory();
10023261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
10033261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("Stack\n");
10043261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory->Print();
10053261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
10063261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No stack\n");
10073261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
10083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
10093261e8b6eac44a41341f112821482bee6c940c98mmentovai}
10103261e8b6eac44a41341f112821482bee6c940c98mmentovai
10113261e8b6eac44a41341f112821482bee6c940c98mmentovai
10123261e8b6eac44a41341f112821482bee6c940c98mmentovai//
10133261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThreadList
10143261e8b6eac44a41341f112821482bee6c940c98mmentovai//
10153261e8b6eac44a41341f112821482bee6c940c98mmentovai
10163261e8b6eac44a41341f112821482bee6c940c98mmentovai
10173261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::MinidumpThreadList(Minidump* minidump)
101853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
101953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      id_to_thread_map_(),
102053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      threads_(NULL),
102153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_count_(0) {
10223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
10233261e8b6eac44a41341f112821482bee6c940c98mmentovai
10243261e8b6eac44a41341f112821482bee6c940c98mmentovai
10253261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::~MinidumpThreadList() {
10263261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
10273261e8b6eac44a41341f112821482bee6c940c98mmentovai}
10283261e8b6eac44a41341f112821482bee6c940c98mmentovai
10293261e8b6eac44a41341f112821482bee6c940c98mmentovai
10303261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThreadList::Read(u_int32_t expected_size) {
10313261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
10323261e8b6eac44a41341f112821482bee6c940c98mmentovai  id_to_thread_map_.clear();
10333261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
10343261e8b6eac44a41341f112821482bee6c940c98mmentovai  threads_ = NULL;
10353261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = 0;
10363261e8b6eac44a41341f112821482bee6c940c98mmentovai
10373261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
10383261e8b6eac44a41341f112821482bee6c940c98mmentovai
10393261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t thread_count;
1040af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(thread_count)) {
1041af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
1042af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(thread_count);
10433261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1044af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1045af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
1046af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
10473261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1048af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
10493261e8b6eac44a41341f112821482bee6c940c98mmentovai
10503261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
10513261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_count);
10523261e8b6eac44a41341f112821482bee6c940c98mmentovai
1053fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (thread_count > numeric_limits<u_int32_t>::max() / sizeof(MDRawThread)) {
1054fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
1055fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
1056fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
1057fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
1058fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
10593261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(thread_count) +
10603261e8b6eac44a41341f112821482bee6c940c98mmentovai                       thread_count * sizeof(MDRawThread)) {
1061af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
1062af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " <<
1063af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sizeof(thread_count) + thread_count * sizeof(MDRawThread);
10643261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
10653261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
10663261e8b6eac44a41341f112821482bee6c940c98mmentovai
1067373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (thread_count) {
1068373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // TODO(mmentovai): verify rational size!
1069373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpThreads> threads(
1070373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
10713261e8b6eac44a41341f112821482bee6c940c98mmentovai
1072373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int thread_index = 0;
1073373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         thread_index < thread_count;
1074373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++thread_index) {
1075373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpThread* thread = &(*threads)[thread_index];
10763261e8b6eac44a41341f112821482bee6c940c98mmentovai
1077373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
1078af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->Read()) {
1079af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
1080af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1081373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1082af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
10833261e8b6eac44a41341f112821482bee6c940c98mmentovai
1084373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int32_t thread_id;
1085af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->GetThreadID(&thread_id)) {
1086af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
1087af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1088373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1089af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
109076f052f8fbf8864dee5992b857229d06560a766ammentovai
1091373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (GetThreadByID(thread_id)) {
1092373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        // Another thread with this ID is already in the list.  Data error.
1093af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
1094af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(thread_id) << " at thread " <<
1095af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1096373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1097373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
1098373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      id_to_thread_map_[thread_id] = thread;
10993261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
1100373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1101373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    threads_ = threads.release();
11023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
11033261e8b6eac44a41341f112821482bee6c940c98mmentovai
11043261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = thread_count;
11053261e8b6eac44a41341f112821482bee6c940c98mmentovai
11063261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
11073261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
11083261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11093261e8b6eac44a41341f112821482bee6c940c98mmentovai
11103261e8b6eac44a41341f112821482bee6c940c98mmentovai
11113261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
11123261e8b6eac44a41341f112821482bee6c940c98mmentovai    const {
1113af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1114af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
1115af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1116af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1117af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= thread_count_) {
1119af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
1120af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << thread_count_;
11213261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11233261e8b6eac44a41341f112821482bee6c940c98mmentovai
11243261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*threads_)[index];
11253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11263261e8b6eac44a41341f112821482bee6c940c98mmentovai
11273261e8b6eac44a41341f112821482bee6c940c98mmentovai
11283261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadByID(u_int32_t thread_id) {
11293261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't check valid_.  Read calls this method before everything is
11303261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validated.  It is safe to not check valid_ here.
11313261e8b6eac44a41341f112821482bee6c940c98mmentovai  return id_to_thread_map_[thread_id];
11323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11333261e8b6eac44a41341f112821482bee6c940c98mmentovai
11343261e8b6eac44a41341f112821482bee6c940c98mmentovai
11353261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThreadList::Print() {
1136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1137af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
11383261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1139af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11403261e8b6eac44a41341f112821482bee6c940c98mmentovai
11413261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpThreadList\n");
11423261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_count = %d\n", thread_count_);
11433261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
11443261e8b6eac44a41341f112821482bee6c940c98mmentovai
11453261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int thread_index = 0;
11463261e8b6eac44a41341f112821482bee6c940c98mmentovai       thread_index < thread_count_;
11473261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++thread_index) {
11483261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("thread[%d]\n", thread_index);
11493261e8b6eac44a41341f112821482bee6c940c98mmentovai
11503261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*threads_)[thread_index].Print();
11513261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
11523261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11533261e8b6eac44a41341f112821482bee6c940c98mmentovai
11543261e8b6eac44a41341f112821482bee6c940c98mmentovai
11553261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11563261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModule
11573261e8b6eac44a41341f112821482bee6c940c98mmentovai//
11583261e8b6eac44a41341f112821482bee6c940c98mmentovai
11593261e8b6eac44a41341f112821482bee6c940c98mmentovai
11603261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::MinidumpModule(Minidump* minidump)
116153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
1162db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_valid_(false),
116353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_(),
116453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      name_(NULL),
116553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      cv_record_(NULL),
116648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
1167db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      misc_record_(NULL) {
11683261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11693261e8b6eac44a41341f112821482bee6c940c98mmentovai
11703261e8b6eac44a41341f112821482bee6c940c98mmentovai
11713261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::~MinidumpModule() {
11723261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
11733261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
11743261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
11753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
11763261e8b6eac44a41341f112821482bee6c940c98mmentovai
11773261e8b6eac44a41341f112821482bee6c940c98mmentovai
11783261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModule::Read() {
11793261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
11803261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
11813261e8b6eac44a41341f112821482bee6c940c98mmentovai  name_ = NULL;
11823261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
11833261e8b6eac44a41341f112821482bee6c940c98mmentovai  cv_record_ = NULL;
118448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
11853261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
11863261e8b6eac44a41341f112821482bee6c940c98mmentovai  misc_record_ = NULL;
11873261e8b6eac44a41341f112821482bee6c940c98mmentovai
1188db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = false;
11893261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
11903261e8b6eac44a41341f112821482bee6c940c98mmentovai
1191af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
1192af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot read module";
11933261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1194af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11953261e8b6eac44a41341f112821482bee6c940c98mmentovai
11963261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
11973261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.base_of_image);
11983261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.size_of_image);
11993261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.checksum);
12003261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.time_date_stamp);
12013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.module_name_rva);
12023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.signature);
12033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.struct_version);
12043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_hi);
12053261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_lo);
12063261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_hi);
12073261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_lo);
12083261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags_mask);
12093261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags);
12103261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_os);
12113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_type);
12123261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_subtype);
12133261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_hi);
12143261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_lo);
12153261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.cv_record);
12163261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.misc_record);
12173261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't swap reserved fields because their contents are unknown (as
12183261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are their proper widths).
12193261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
12203261e8b6eac44a41341f112821482bee6c940c98mmentovai
1221fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
1222fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_.size_of_image == 0 ||
1223fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      module_.size_of_image >
1224fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          numeric_limits<u_int64_t>::max() - module_.base_of_image) {
1225af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
1226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(module_.base_of_image) << "+" <<
1227fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(module_.size_of_image);
12283261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
12303261e8b6eac44a41341f112821482bee6c940c98mmentovai
1231db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = true;
1232db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return true;
1233db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1234db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1235db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1236db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaibool MinidumpModule::ReadAuxiliaryData() {
1237af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
1238af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
1239db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1240af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1241db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1242db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Each module must have a name.
1243db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  name_ = minidump_->ReadString(module_.module_name_rva);
1244af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!name_) {
1245af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule could not read name";
1246db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1247af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1248db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1249db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // CodeView and miscellaneous debug records are only required if the
1250db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // module indicates that they exist.
1251af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
1252af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
1253af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1254db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1255af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1256db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
1258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
1259af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
1260db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
1261af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1262db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
12633261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
12643261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
12653261e8b6eac44a41341f112821482bee6c940c98mmentovai}
12663261e8b6eac44a41341f112821482bee6c940c98mmentovai
12673261e8b6eac44a41341f112821482bee6c940c98mmentovai
1268db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_file() const {
1269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1270af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
1271db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1272af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1273db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1274db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return *name_;
1275db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
12763261e8b6eac44a41341f112821482bee6c940c98mmentovai
12773261e8b6eac44a41341f112821482bee6c940c98mmentovai
1278db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_identifier() const {
1279af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1280af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
1281db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1283db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1284db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
1285af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_system_info) {
1286af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires "
1287af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "MinidumpSystemInfo";
1288db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1289af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1290db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1291db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
1292af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1293af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
1294db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1295af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1296db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1297db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1298db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1299db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  switch (raw_system_info->platform_id) {
1300db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_NT:
1301db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_WINDOWS: {
1302c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1303c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1304db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
1305c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
1306db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               module_.time_date_stamp, module_.size_of_image);
1307db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
1308db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1309db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1310db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
13110e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_MAC_OS_X:
13120e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_LINUX: {
1313db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // TODO(mmentovai): support uuid extension if present, otherwise fall
1314db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // back to version (from LC_ID_DYLIB?), otherwise fall back to something
1315db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // else.
1316db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = "id";
1317db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1318db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1319db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1320db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    default: {
1321db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // Without knowing what OS generated the dump, we can't generate a good
1322db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // identifier.  Return an empty string, signalling failure.
1323af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
1324af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "found " << HexString(raw_system_info->platform_id);
1325db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
1326db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1327db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1328db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1329db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
13303261e8b6eac44a41341f112821482bee6c940c98mmentovai}
13313261e8b6eac44a41341f112821482bee6c940c98mmentovai
13323261e8b6eac44a41341f112821482bee6c940c98mmentovai
1333db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_file() const {
1334af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1335af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
1336db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1337af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1338db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1339db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string file;
1340db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Prefer the CodeView record if present.
134128e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
134248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
134348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
134448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
134548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
134648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
134748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1348db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1349db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
135048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
135148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
1352db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
1353db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
135448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1355db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1356db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
1357db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
1358db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1359db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1360db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // If there's a CodeView record but it doesn't match a known signature,
136148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // try the miscellaneous record.
1362db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1363db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1364db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (file.empty()) {
1365db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // No usable CodeView record.  Try the miscellaneous debug record.
136628e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai    if (misc_record_) {
136728e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai      const MDImageDebugMisc* misc_record =
136828e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai          reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
1369db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      if (!misc_record->unicode) {
1370db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // If it's not Unicode, just stuff it into the string.  It's unclear
1371db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // if misc_record->data is 0-terminated, so use an explicit size.
1372db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        file = string(
1373db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            reinterpret_cast<const char*>(misc_record->data),
1374db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            module_.misc_record.data_size - sizeof(MDImageDebugMisc));
1375db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      } else {
1376db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // There's a misc_record but it encodes the debug filename in UTF-16.
1377db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // (Actually, because miscellaneous records are so old, it's probably
1378db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
1379db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // that this method (and all other methods in the Minidump family)
1380db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // return.
1381db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1382db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        unsigned int bytes =
1383db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            module_.misc_record.data_size - sizeof(MDImageDebugMisc);
1384db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        if (bytes % 2 == 0) {
1385db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          unsigned int utf16_words = bytes / 2;
1386db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1387db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF16ToUTF8 expects a vector<u_int16_t>, so create a temporary one
1388db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // and copy the UTF-16 data into it.
1389db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          vector<u_int16_t> string_utf16(utf16_words);
1390db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          if (utf16_words)
1391db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            memcpy(&string_utf16[0], &misc_record->data, bytes);
1392db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1393db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // GetMiscRecord already byte-swapped the data[] field if it contains
1394db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF-16, so pass false as the swap argument.
1395db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
1396db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          file = *new_file;
1397db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        }
1398db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      }
1399db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1400db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1401db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1402af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, file.empty()) << "MinidumpModule could not determine "
1403af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                   "debug_file for " << *name_;
1404af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1405db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return file;
1406db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1407db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1408db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1409db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_identifier() const {
1410af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1411af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
1412db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1413af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1414db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1415db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
1416db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1417db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Use the CodeView record if present.
141828e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
141948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
142048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
142148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
142248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
142348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
142448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
1425c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1426c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1427db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[41];
1428db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
1429c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
1430db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data1,
1431db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data2,
1432db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data3,
1433db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[0],
1434db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[1],
1435db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[2],
1436db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[3],
1437db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[4],
1438db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[5],
1439db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[6],
1440db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[7],
1441db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->age);
1442db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
144348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
144448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
1445db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
1446db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
144748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1448db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1449c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
1450c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
1451db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
1452db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
1453c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%x", cv_record_20->signature, cv_record_20->age);
1454db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
1455db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1456db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1457db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
145848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  // TODO(mmentovai): if there's no usable CodeView record, there might be a
1459db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // miscellaneous debug record.  It only carries a filename, though, and no
1460db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // identifier.  I'm not sure what the right thing to do for the identifier
1461db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // is in that case, but I don't expect to find many modules without a
1462e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  // CodeView record (or some other Breakpad extension structure in place of
1463db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a CodeView record).  Treat it as an error (empty identifier) for now.
1464db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1465db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
1466db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1467af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, identifier.empty()) << "MinidumpModule could not determine "
1468af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                         "debug_identifier for " << *name_;
1469af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1470db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
1471db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1472db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1473db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1474db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::version() const {
1475af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1476af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for version";
1477db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
1478af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1479db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1480db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string version;
1481db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1482db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
1483db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
1484db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    char version_string[24];
1485db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
1486db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi >> 16,
1487db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi & 0xffff,
1488db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo >> 16,
1489db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo & 0xffff);
1490db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    version = version_string;
1491db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
1492db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1493db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): possibly support other struct types in place of
1494db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
1495db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a different structure that better represents versioning facilities on
1496db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Mac OS X and Linux, instead of forcing them to adhere to the dotted
1497db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // quad of 16-bit ints that Windows uses.
1498db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1499af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
1500af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "version for " << *name_;
1501af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1502db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return version;
1503db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1504db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1505db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1506db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModule* MinidumpModule::Copy() const {
1507db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModule(this);
1508db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1509db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1510db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
151148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovaiconst u_int8_t* MinidumpModule::GetCVRecord(u_int32_t* size) {
1512af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
1513af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
15143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1515af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
15163261e8b6eac44a41341f112821482bee6c940c98mmentovai
15173261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!cv_record_) {
151848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // This just guards against 0-sized CodeView records; more specific checks
151948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // are used when the signature is checked against various structure types.
1520af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.cv_record.data_size == 0) {
15213261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1522af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
15233261e8b6eac44a41341f112821482bee6c940c98mmentovai
1524af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.cv_record.rva)) {
1525af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
15263261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1527af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
15283261e8b6eac44a41341f112821482bee6c940c98mmentovai
15293261e8b6eac44a41341f112821482bee6c940c98mmentovai    // TODO(mmentovai): verify rational size!
15303261e8b6eac44a41341f112821482bee6c940c98mmentovai
15313261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDCVInfoPDB70 or
15323261e8b6eac44a41341f112821482bee6c940c98mmentovai    // MDCVInfoPDB20 but is allocated as u_int8_t[] can cause alignment
15333261e8b6eac44a41341f112821482bee6c940c98mmentovai    // problems.  x86 and ppc are able to cope, though.  This allocation
15343261e8b6eac44a41341f112821482bee6c940c98mmentovai    // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
15353261e8b6eac44a41341f112821482bee6c940c98mmentovai    // variable-sized due to their pdb_file_name fields; these structures
15363261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are not sizeof(MDCVInfoPDB70) or sizeof(MDCVInfoPDB20) and treating
15373261e8b6eac44a41341f112821482bee6c940c98mmentovai    // them as such would result in incomplete structures or overruns.
15382466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > cv_record(
15393261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(module_.cv_record.data_size));
15403261e8b6eac44a41341f112821482bee6c940c98mmentovai
1541af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
1542af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
15433261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
15453261e8b6eac44a41341f112821482bee6c940c98mmentovai
154648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    u_int32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
154748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (module_.cv_record.data_size > sizeof(signature)) {
154848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      MDCVInfoPDB70* cv_record_signature =
154948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
155048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      signature = cv_record_signature->cv_signature;
155148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      if (minidump_->swap())
155248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        Swap(&signature);
155348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    }
15543261e8b6eac44a41341f112821482bee6c940c98mmentovai
15553261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature == MD_CVINFOPDB70_SIGNATURE) {
15563261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Now that the structure type is known, recheck the size.
1557af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (sizeof(MDCVInfoPDB70) > module_.cv_record.data_size) {
1558af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
1559af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        sizeof(MDCVInfoPDB70) << " > " <<
1560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
15613261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
1562af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
15633261e8b6eac44a41341f112821482bee6c940c98mmentovai
15643261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
156548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        MDCVInfoPDB70* cv_record_70 =
156648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
15673261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->cv_signature);
15683261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->signature);
15693261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->age);
15703261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
157148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        // quantities.  (It's a path, is it UTF-8?)
15723261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
157348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
157448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
157548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
1576af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
1577af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
1578af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
157948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
1580af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
15813261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
158248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // Now that the structure type is known, recheck the size.
1583af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (sizeof(MDCVInfoPDB20) > module_.cv_record.data_size) {
1584af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
1585af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        sizeof(MDCVInfoPDB20) << " > " <<
1586af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
158748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
1588af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
15893261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
15903261e8b6eac44a41341f112821482bee6c940c98mmentovai        MDCVInfoPDB20* cv_record_20 =
159148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
15923261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.signature);
15933261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.offset);
15943261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->signature);
15953261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->age);
15963261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
15973261e8b6eac44a41341f112821482bee6c940c98mmentovai        // quantities.  (It's a path, is it UTF-8?)
15983261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
159948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
160048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
160148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
1602af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
1603af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
1604af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
160548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
1606af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
16073261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
16083261e8b6eac44a41341f112821482bee6c940c98mmentovai
160948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // If the signature doesn't match something above, it's not something
1610e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    // that Breakpad can presently handle directly.  Because some modules in
161148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
161248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // don't bail out here - allow the data to be returned to the user,
161348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // although byte-swapping can't be done.
16143261e8b6eac44a41341f112821482bee6c940c98mmentovai
16153261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
16163261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to u_int8_t*.
16173261e8b6eac44a41341f112821482bee6c940c98mmentovai    cv_record_ = cv_record.release();
161848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    cv_record_signature_ = signature;
16193261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16203261e8b6eac44a41341f112821482bee6c940c98mmentovai
162148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
162248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.cv_record.data_size;
162348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
16243261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*cv_record_)[0];
16253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16263261e8b6eac44a41341f112821482bee6c940c98mmentovai
16273261e8b6eac44a41341f112821482bee6c940c98mmentovai
162848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovaiconst MDImageDebugMisc* MinidumpModule::GetMiscRecord(u_int32_t* size) {
1629af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
1630af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
16313261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1632af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16333261e8b6eac44a41341f112821482bee6c940c98mmentovai
16343261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!misc_record_) {
1635af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size == 0) {
16363261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1637af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
16383261e8b6eac44a41341f112821482bee6c940c98mmentovai
1639af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (sizeof(MDImageDebugMisc) > module_.misc_record.data_size) {
1640af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
1641af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << sizeof(MDImageDebugMisc) << " > " <<
1642af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      module_.misc_record.data_size;
16433261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1644af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
1645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1646af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.misc_record.rva)) {
1647af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
1648af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "debugging record";
1649af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      return NULL;
1650af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
16513261e8b6eac44a41341f112821482bee6c940c98mmentovai
16523261e8b6eac44a41341f112821482bee6c940c98mmentovai    // TODO(mmentovai): verify rational size!
16533261e8b6eac44a41341f112821482bee6c940c98mmentovai
16543261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDImageDebugMisc but
16553261e8b6eac44a41341f112821482bee6c940c98mmentovai    // is allocated as u_int8_t[] can cause alignment problems.  x86 and
16563261e8b6eac44a41341f112821482bee6c940c98mmentovai    // ppc are able to cope, though.  This allocation style is needed
16573261e8b6eac44a41341f112821482bee6c940c98mmentovai    // because the MDImageDebugMisc is variable-sized due to its data field;
16583261e8b6eac44a41341f112821482bee6c940c98mmentovai    // this structure is not sizeof(MDImageDebugMisc) and treating it as such
16593261e8b6eac44a41341f112821482bee6c940c98mmentovai    // would result in an incomplete structure or an overrun.
16602466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr< vector<u_int8_t> > misc_record_mem(
16613261e8b6eac44a41341f112821482bee6c940c98mmentovai        new vector<u_int8_t>(module_.misc_record.data_size));
16623261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDImageDebugMisc* misc_record =
16633261e8b6eac44a41341f112821482bee6c940c98mmentovai        reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
16643261e8b6eac44a41341f112821482bee6c940c98mmentovai
1665af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
1666af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
1667af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "record";
16683261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1669af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
16703261e8b6eac44a41341f112821482bee6c940c98mmentovai
16713261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (minidump_->swap()) {
16723261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->data_type);
16733261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->length);
16743261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap misc_record.unicode because it's an 8-bit quantity.
16753261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap the reserved fields for the same reason, and because
16763261e8b6eac44a41341f112821482bee6c940c98mmentovai      // they don't contain any valid data.
16773261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (misc_record->unicode) {
16783261e8b6eac44a41341f112821482bee6c940c98mmentovai        // There is a potential alignment problem, but shouldn't be a problem
16793261e8b6eac44a41341f112821482bee6c940c98mmentovai        // in practice due to the layout of MDImageDebugMisc.
16803261e8b6eac44a41341f112821482bee6c940c98mmentovai        u_int16_t* data16 = reinterpret_cast<u_int16_t*>(&(misc_record->data));
16813261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataBytes = module_.misc_record.data_size -
16823261e8b6eac44a41341f112821482bee6c940c98mmentovai                                 sizeof(MDImageDebugMisc);
16833261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataLength = dataBytes / 2;
16843261e8b6eac44a41341f112821482bee6c940c98mmentovai        for (unsigned int characterIndex = 0;
16853261e8b6eac44a41341f112821482bee6c940c98mmentovai             characterIndex < dataLength;
16863261e8b6eac44a41341f112821482bee6c940c98mmentovai             ++characterIndex) {
16873261e8b6eac44a41341f112821482bee6c940c98mmentovai          Swap(&data16[characterIndex]);
16883261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
16893261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
16903261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
16913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1692af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size != misc_record->length) {
1693af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
1694af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << module_.misc_record.data_size <<
1695af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      " != " << misc_record->length;
16963261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1697af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
16983261e8b6eac44a41341f112821482bee6c940c98mmentovai
16993261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
17003261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to MDImageDebugMisc*.
17013261e8b6eac44a41341f112821482bee6c940c98mmentovai    misc_record_ = misc_record_mem.release();
17023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17033261e8b6eac44a41341f112821482bee6c940c98mmentovai
170448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
170548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.misc_record.data_size;
170648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
17073261e8b6eac44a41341f112821482bee6c940c98mmentovai  return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
17083261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17093261e8b6eac44a41341f112821482bee6c940c98mmentovai
17103261e8b6eac44a41341f112821482bee6c940c98mmentovai
17113261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModule::Print() {
1712af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1713af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
17143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1715af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17163261e8b6eac44a41341f112821482bee6c940c98mmentovai
17173261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawModule\n");
17183261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  base_of_image                   = 0x%llx\n",
17193261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.base_of_image);
17203261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_image                   = 0x%x\n",
17213261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.size_of_image);
17223261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum                        = 0x%x\n",
17233261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.checksum);
17243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp                 = 0x%x\n",
17253261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.time_date_stamp);
17263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_name_rva                 = 0x%x\n",
17273261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.module_name_rva);
17283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.signature          = 0x%x\n",
17293261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.signature);
17303261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.struct_version     = 0x%x\n",
17313261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.struct_version);
17323261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_version       = 0x%x:0x%x\n",
17333261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_hi,
17343261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_lo);
17353261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.product_version    = 0x%x:0x%x\n",
17363261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_hi,
17373261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_lo);
17383261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags_mask    = 0x%x\n",
17393261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags_mask);
17403261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags         = 0x%x\n",
17413261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags);
17423261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_os            = 0x%x\n",
17433261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_os);
17443261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_type          = 0x%x\n",
17453261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_type);
17463261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_subtype       = 0x%x\n",
17473261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_subtype);
17483261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_date          = 0x%x:0x%x\n",
17493261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_hi,
17503261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_lo);
17513261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.data_size             = %d\n",
17523261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.data_size);
17533261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.rva                   = 0x%x\n",
17543261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.rva);
17553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.data_size           = %d\n",
17563261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.data_size);
17573261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.rva                 = 0x%x\n",
17583261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.rva);
17593261e8b6eac44a41341f112821482bee6c940c98mmentovai
1760db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
1761db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_identifier)               = \"%s\"\n",
1762db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         code_identifier().c_str());
17633261e8b6eac44a41341f112821482bee6c940c98mmentovai
176448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  u_int32_t cv_record_size;
176548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const u_int8_t *cv_record = GetCVRecord(&cv_record_size);
17663261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (cv_record) {
176748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
176848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
176948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
177048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
177148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
17723261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_signature        = 0x%x\n",
177348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->cv_signature);
17743261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
177548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data1,
177648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data2,
177748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data3,
177848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[0],
177948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[1]);
17803261e8b6eac44a41341f112821482bee6c940c98mmentovai      for (unsigned int guidIndex = 2;
17813261e8b6eac44a41341f112821482bee6c940c98mmentovai           guidIndex < 8;
17823261e8b6eac44a41341f112821482bee6c940c98mmentovai           ++guidIndex) {
178348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record_70->signature.data4[guidIndex]);
17843261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
17853261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("\n");
17863261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
178748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->age);
17883261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
178948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->pdb_file_name);
179048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
17913261e8b6eac44a41341f112821482bee6c940c98mmentovai      const MDCVInfoPDB20* cv_record_20 =
179248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
179348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
179448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
17953261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.signature = 0x%x\n",
17963261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.signature);
17973261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.offset    = 0x%x\n",
17983261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.offset);
17993261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = 0x%x\n",
18003261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->signature);
18013261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
18023261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->age);
18033261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
18043261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->pdb_file_name);
180548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else {
180648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("  (cv_record)                     = ");
180748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      for (unsigned int cv_byte_index = 0;
180848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           cv_byte_index < cv_record_size;
180948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           ++cv_byte_index) {
181048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record[cv_byte_index]);
181148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      }
181248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("\n");
18133261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
18143261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
18153261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (cv_record)                     = (null)\n");
18163261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18173261e8b6eac44a41341f112821482bee6c940c98mmentovai
181848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
18193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_record) {
18203261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).data_type         = 0x%x\n",
18213261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->data_type);
18223261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).length            = 0x%x\n",
18233261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->length);
18243261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).unicode           = %d\n",
18253261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->unicode);
18263261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't bother printing the UTF-16, we don't really even expect to ever
18273261e8b6eac44a41341f112821482bee6c940c98mmentovai    // see this misc_record anyway.
18283261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_record->unicode)
18293261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = \"%s\"\n",
18303261e8b6eac44a41341f112821482bee6c940c98mmentovai             misc_record->data);
18313261e8b6eac44a41341f112821482bee6c940c98mmentovai    else
18323261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = (UTF-16)\n");
18333261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
18343261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record)                   = (null)\n");
18353261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18363261e8b6eac44a41341f112821482bee6c940c98mmentovai
1837db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
1838db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_identifier)              = \"%s\"\n",
1839db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         debug_identifier().c_str());
1840db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (version)                       = \"%s\"\n", version().c_str());
18413261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
18423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18433261e8b6eac44a41341f112821482bee6c940c98mmentovai
18443261e8b6eac44a41341f112821482bee6c940c98mmentovai
18453261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18463261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModuleList
18473261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18483261e8b6eac44a41341f112821482bee6c940c98mmentovai
18493261e8b6eac44a41341f112821482bee6c940c98mmentovai
18503261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::MinidumpModuleList(Minidump* minidump)
185153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
1852fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai      range_map_(new RangeMap<u_int64_t, unsigned int>()),
185353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      modules_(NULL),
185453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_count_(0) {
18553261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18563261e8b6eac44a41341f112821482bee6c940c98mmentovai
18573261e8b6eac44a41341f112821482bee6c940c98mmentovai
18583261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::~MinidumpModuleList() {
1859fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
18603261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
18613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18623261e8b6eac44a41341f112821482bee6c940c98mmentovai
18633261e8b6eac44a41341f112821482bee6c940c98mmentovai
18643261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModuleList::Read(u_int32_t expected_size) {
18653261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
1866fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
18673261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
18683261e8b6eac44a41341f112821482bee6c940c98mmentovai  modules_ = NULL;
18693261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = 0;
18703261e8b6eac44a41341f112821482bee6c940c98mmentovai
18713261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
18723261e8b6eac44a41341f112821482bee6c940c98mmentovai
18733261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t module_count;
1874af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(module_count)) {
1875af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
1876af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(module_count);
18773261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
1880af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList could not read module count";
18813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1882af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
18833261e8b6eac44a41341f112821482bee6c940c98mmentovai
18843261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
18853261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_count);
18863261e8b6eac44a41341f112821482bee6c940c98mmentovai
1887fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_count > numeric_limits<u_int32_t>::max() / MD_MODULE_SIZE) {
1888fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
1889fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
1890fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
1891fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
1892fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
18933261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(module_count) +
18943261e8b6eac44a41341f112821482bee6c940c98mmentovai                       module_count * MD_MODULE_SIZE) {
1895af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
1896af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " <<
1897af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sizeof(module_count) + module_count * MD_MODULE_SIZE;
18983261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
18993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
19003261e8b6eac44a41341f112821482bee6c940c98mmentovai
1901373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (module_count) {
1902373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // TODO(mmentovai): verify rational size!
1903373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpModules> modules(
1904373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpModules(module_count, MinidumpModule(minidump_)));
19053261e8b6eac44a41341f112821482bee6c940c98mmentovai
1906373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int module_index = 0;
1907373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         module_index < module_count;
1908373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++module_index) {
1909373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpModule* module = &(*modules)[module_index];
19103261e8b6eac44a41341f112821482bee6c940c98mmentovai
1911373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
1912af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->Read()) {
1913af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
1914af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
1915373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1916af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
1917db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
1918db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1919db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // Loop through the module list once more to read additional data and
1920db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // build the range map.  This is done in a second pass because
1921db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
1922db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // included in the loop above, additional seeks would be needed where
1923db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // none are now to read contiguous data.
1924db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    for (unsigned int module_index = 0;
1925db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         module_index < module_count;
1926db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         ++module_index) {
1927db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      MinidumpModule* module = &(*modules)[module_index];
1928db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1929af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->ReadAuxiliaryData()) {
1930af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module auxiliary "
1931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "data for module " <<
1932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
1933db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        return false;
1934af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
1935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1936af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // It is safe to use module->code_file() after successfully calling
1937af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // module->ReadAuxiliaryData.
19383261e8b6eac44a41341f112821482bee6c940c98mmentovai
1939373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t base_address = module->base_address();
1940373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t module_size = module->size();
1941af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (base_address == static_cast<u_int64_t>(-1)) {
1942af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList found bad base address "
1943af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "for module " << module_index << "/" << module_count <<
1944af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << module->code_file();
1945373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1946af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
19473261e8b6eac44a41341f112821482bee6c940c98mmentovai
1948af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, module_size, module_index)) {
1949af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
1950af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count << ", " <<
1951af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module->code_file() << ", " <<
1952af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
1953af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(module_size);
1954373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1955af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
1956373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
1957373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1958373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    modules_ = modules.release();
19593261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
19603261e8b6eac44a41341f112821482bee6c940c98mmentovai
19613261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = module_count;
19623261e8b6eac44a41341f112821482bee6c940c98mmentovai
19633261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
19643261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
19653261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19663261e8b6eac44a41341f112821482bee6c940c98mmentovai
19673261e8b6eac44a41341f112821482bee6c940c98mmentovai
1968db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleForAddress(
1969db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    u_int64_t address) const {
1970af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1971af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
19723261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1973af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19743261e8b6eac44a41341f112821482bee6c940c98mmentovai
1975db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  unsigned int module_index;
1976af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
1977af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpModuleList has no module at " <<
1978af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
1979db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
1980af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1981db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1982db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtIndex(module_index);
19833261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19843261e8b6eac44a41341f112821482bee6c940c98mmentovai
19853261e8b6eac44a41341f112821482bee6c940c98mmentovai
1986db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetMainModule() const {
1987af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1988af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
19893261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1990af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1992db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // The main code module is the first one present in a minidump file's
1993db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // MDRawModuleList.
1994db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtSequence(0);
1995db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
1996db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1997db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
1998db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
1999db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int sequence) const {
2000af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2001af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
2002af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2003af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2004af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2005af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sequence >= module_count_) {
2006af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
2007af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sequence << "/" << module_count_;
2008db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2009af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2010db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
20113261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int module_index;
2012af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
2013af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
20143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2015af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20163261e8b6eac44a41341f112821482bee6c940c98mmentovai
20173261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetModuleAtIndex(module_index);
20183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20193261e8b6eac44a41341f112821482bee6c940c98mmentovai
20203261e8b6eac44a41341f112821482bee6c940c98mmentovai
2021db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
2022db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int index) const {
2023af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2024af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
2025af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2026af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2027af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2028af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= module_count_) {
2029af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
2030af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << module_count_;
2031db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2032af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2033db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2034db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return &(*modules_)[index];
2035db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2036db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2037db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2038db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModules* MinidumpModuleList::Copy() const {
2039db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModules(this);
2040db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2041db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2042db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
20433261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModuleList::Print() {
2044af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2045af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
20463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2047af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20483261e8b6eac44a41341f112821482bee6c940c98mmentovai
20493261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpModuleList\n");
20503261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_count = %d\n", module_count_);
20513261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
20523261e8b6eac44a41341f112821482bee6c940c98mmentovai
20533261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int module_index = 0;
20543261e8b6eac44a41341f112821482bee6c940c98mmentovai       module_index < module_count_;
20553261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++module_index) {
20563261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("module[%d]\n", module_index);
20573261e8b6eac44a41341f112821482bee6c940c98mmentovai
20583261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*modules_)[module_index].Print();
20593261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
20603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20613261e8b6eac44a41341f112821482bee6c940c98mmentovai
20623261e8b6eac44a41341f112821482bee6c940c98mmentovai
20633261e8b6eac44a41341f112821482bee6c940c98mmentovai//
20643261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryList
20653261e8b6eac44a41341f112821482bee6c940c98mmentovai//
20663261e8b6eac44a41341f112821482bee6c940c98mmentovai
20673261e8b6eac44a41341f112821482bee6c940c98mmentovai
20683261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
206953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
2070fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai      range_map_(new RangeMap<u_int64_t, unsigned int>()),
207153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptors_(NULL),
207253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      regions_(NULL),
207353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      region_count_(0) {
20743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20753261e8b6eac44a41341f112821482bee6c940c98mmentovai
20763261e8b6eac44a41341f112821482bee6c940c98mmentovai
20773261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::~MinidumpMemoryList() {
2078fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
20793261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
20803261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
20813261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20823261e8b6eac44a41341f112821482bee6c940c98mmentovai
20833261e8b6eac44a41341f112821482bee6c940c98mmentovai
20843261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMemoryList::Read(u_int32_t expected_size) {
20853261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
20863261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
20873261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptors_ = NULL;
20883261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
20893261e8b6eac44a41341f112821482bee6c940c98mmentovai  regions_ = NULL;
2090fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
20913261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = 0;
20923261e8b6eac44a41341f112821482bee6c940c98mmentovai
20933261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
20943261e8b6eac44a41341f112821482bee6c940c98mmentovai
20953261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t region_count;
2096af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(region_count)) {
2097af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
2098af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(region_count);
20993261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2100af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
2102af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
21033261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2104af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
21053261e8b6eac44a41341f112821482bee6c940c98mmentovai
21063261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
21073261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&region_count);
21083261e8b6eac44a41341f112821482bee6c940c98mmentovai
2109fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (region_count >
2110fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          numeric_limits<u_int32_t>::max() / sizeof(MDMemoryDescriptor)) {
2111fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
2112fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2113fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2114fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2115fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
21163261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(region_count) +
21173261e8b6eac44a41341f112821482bee6c940c98mmentovai                       region_count * sizeof(MDMemoryDescriptor)) {
2118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
2119af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << region_count * sizeof(MDMemoryDescriptor);
21203261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
21213261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21223261e8b6eac44a41341f112821482bee6c940c98mmentovai
2123373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (region_count) {
2124373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // TODO(mmentovai): verify rational size!
2125373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryDescriptors> descriptors(
2126373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryDescriptors(region_count));
21273261e8b6eac44a41341f112821482bee6c940c98mmentovai
2128373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
2129373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
2130373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!minidump_->ReadBytes(&(*descriptors)[0],
2131373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai                              sizeof(MDMemoryDescriptor) * region_count)) {
2132af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
2133373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
2134373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
21353261e8b6eac44a41341f112821482bee6c940c98mmentovai
2136373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryRegions> regions(
2137373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
21383261e8b6eac44a41341f112821482bee6c940c98mmentovai
2139373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int region_index = 0;
2140373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         region_index < region_count;
2141373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++region_index) {
2142373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
21433261e8b6eac44a41341f112821482bee6c940c98mmentovai
2144373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (minidump_->swap())
2145373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(descriptor);
21463261e8b6eac44a41341f112821482bee6c940c98mmentovai
2147373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int64_t base_address = descriptor->start_of_memory_range;
2148373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      u_int32_t region_size = descriptor->memory.data_size;
21493261e8b6eac44a41341f112821482bee6c940c98mmentovai
2150fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      // Check for base + size overflow or undersize.
2151fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      if (region_size == 0 ||
2152fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai          region_size > numeric_limits<u_int64_t>::max() - base_address) {
2153af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
2154af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        " region " << region_index << "/" << region_count <<
2155af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << HexString(base_address) << "+" <<
2156fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                        HexString(region_size);
2157373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2158af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
21593261e8b6eac44a41341f112821482bee6c940c98mmentovai
2160af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, region_size, region_index)) {
2161af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
2162af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        region_index << "/" << region_count << ", " <<
2163af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
2164af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(region_size);
2165373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2166af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2167373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2168373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      (*regions)[region_index].SetDescriptor(descriptor);
2169373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
21703261e8b6eac44a41341f112821482bee6c940c98mmentovai
2171373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    descriptors_ = descriptors.release();
2172373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    regions_ = regions.release();
21733261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
21743261e8b6eac44a41341f112821482bee6c940c98mmentovai
21753261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = region_count;
21763261e8b6eac44a41341f112821482bee6c940c98mmentovai
21773261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
21783261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
21793261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21803261e8b6eac44a41341f112821482bee6c940c98mmentovai
21813261e8b6eac44a41341f112821482bee6c940c98mmentovai
21823261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
21833261e8b6eac44a41341f112821482bee6c940c98mmentovai      unsigned int index) {
2184af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2185af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
2186af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2187af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2188af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2189af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= region_count_) {
2190af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
2191af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << region_count_;
21923261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2193af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
21943261e8b6eac44a41341f112821482bee6c940c98mmentovai
21953261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*regions_)[index];
21963261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21973261e8b6eac44a41341f112821482bee6c940c98mmentovai
21983261e8b6eac44a41341f112821482bee6c940c98mmentovai
21993261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
22003261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int64_t address) {
2201af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2202af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
22033261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2204af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22053261e8b6eac44a41341f112821482bee6c940c98mmentovai
22063261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int region_index;
2207af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
2208af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
2209af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
22103261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22123261e8b6eac44a41341f112821482bee6c940c98mmentovai
22133261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryRegionAtIndex(region_index);
22143261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22153261e8b6eac44a41341f112821482bee6c940c98mmentovai
22163261e8b6eac44a41341f112821482bee6c940c98mmentovai
22173261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryList::Print() {
2218af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2219af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
22203261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22223261e8b6eac44a41341f112821482bee6c940c98mmentovai
22233261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpMemoryList\n");
22243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  region_count = %d\n", region_count_);
22253261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
22263261e8b6eac44a41341f112821482bee6c940c98mmentovai
22273261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int region_index = 0;
22283261e8b6eac44a41341f112821482bee6c940c98mmentovai       region_index < region_count_;
22293261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++region_index) {
22303261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
22313261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("region[%d]\n", region_index);
22323261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDMemoryDescriptor\n");
22333261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  start_of_memory_range = 0x%llx\n",
22343261e8b6eac44a41341f112821482bee6c940c98mmentovai           descriptor->start_of_memory_range);
22353261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
22363261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
22373261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
22383261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (region) {
22393261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("Memory\n");
22403261e8b6eac44a41341f112821482bee6c940c98mmentovai      region->Print();
22413261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
22423261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("No memory\n");
22433261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
22443261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
22453261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
22463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22473261e8b6eac44a41341f112821482bee6c940c98mmentovai
22483261e8b6eac44a41341f112821482bee6c940c98mmentovai
22493261e8b6eac44a41341f112821482bee6c940c98mmentovai//
22503261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpException
22513261e8b6eac44a41341f112821482bee6c940c98mmentovai//
22523261e8b6eac44a41341f112821482bee6c940c98mmentovai
22533261e8b6eac44a41341f112821482bee6c940c98mmentovai
22543261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::MinidumpException(Minidump* minidump)
225553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
225653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      exception_(),
225753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
22583261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22593261e8b6eac44a41341f112821482bee6c940c98mmentovai
22603261e8b6eac44a41341f112821482bee6c940c98mmentovai
22613261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::~MinidumpException() {
22623261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
22633261e8b6eac44a41341f112821482bee6c940c98mmentovai}
22643261e8b6eac44a41341f112821482bee6c940c98mmentovai
22653261e8b6eac44a41341f112821482bee6c940c98mmentovai
22663261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpException::Read(u_int32_t expected_size) {
22673261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
22683261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
22693261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
22703261e8b6eac44a41341f112821482bee6c940c98mmentovai
22713261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
22723261e8b6eac44a41341f112821482bee6c940c98mmentovai
2273af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(exception_)) {
2274af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
2275af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(exception_);
22763261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2277af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22783261e8b6eac44a41341f112821482bee6c940c98mmentovai
2279af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
2280af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot read exception";
22813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2282af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
22833261e8b6eac44a41341f112821482bee6c940c98mmentovai
22843261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
22853261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_id);
22863261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.__align is for alignment only and does not need to be
22873261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapped.
22883261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_code);
22893261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_flags);
22903261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_record);
22913261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_address);
22923261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.number_parameters);
22933261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.exception_record.__align is for alignment only and does not
22943261e8b6eac44a41341f112821482bee6c940c98mmentovai    // need to be swapped.
22953261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int parameter_index = 0;
22963261e8b6eac44a41341f112821482bee6c940c98mmentovai         parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
22973261e8b6eac44a41341f112821482bee6c940c98mmentovai         ++parameter_index) {
22983261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&exception_.exception_record.exception_information[parameter_index]);
22993261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
23003261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_context);
23013261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23023261e8b6eac44a41341f112821482bee6c940c98mmentovai
23033261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
23043261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
23053261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23063261e8b6eac44a41341f112821482bee6c940c98mmentovai
23073261e8b6eac44a41341f112821482bee6c940c98mmentovai
230876f052f8fbf8864dee5992b857229d06560a766ammentovaibool MinidumpException::GetThreadID(u_int32_t *thread_id) const {
2309af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
2310af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
2311af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
2312af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
2313af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2314af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2315af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
231676f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
2317af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
231876f052f8fbf8864dee5992b857229d06560a766ammentovai
231976f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = exception_.thread_id;
232076f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
23213261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23223261e8b6eac44a41341f112821482bee6c940c98mmentovai
23233261e8b6eac44a41341f112821482bee6c940c98mmentovai
23243261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpException::GetContext() {
2325af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2326af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
23273261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2328af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
23293261e8b6eac44a41341f112821482bee6c940c98mmentovai
23303261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
2331af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(exception_.thread_context.rva)) {
2332af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot seek to context";
23333261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2334af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
23353261e8b6eac44a41341f112821482bee6c940c98mmentovai
23362466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
23373261e8b6eac44a41341f112821482bee6c940c98mmentovai
2338af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(exception_.thread_context.data_size)) {
2339af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot read context";
23403261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2341af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
23423261e8b6eac44a41341f112821482bee6c940c98mmentovai
23433261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
23443261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23453261e8b6eac44a41341f112821482bee6c940c98mmentovai
23463261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
23473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23483261e8b6eac44a41341f112821482bee6c940c98mmentovai
23493261e8b6eac44a41341f112821482bee6c940c98mmentovai
23503261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpException::Print() {
2351af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2352af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot print invalid data";
23533261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2354af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
23553261e8b6eac44a41341f112821482bee6c940c98mmentovai
23563261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDException\n");
23573261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                                  = 0x%x\n",
23583261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_id);
23593261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_code            = 0x%x\n",
23603261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_code);
23613261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_flags           = 0x%x\n",
23623261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_flags);
23633261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_record          = 0x%llx\n",
23643261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_record);
23653261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_address         = 0x%llx\n",
23663261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_address);
23673261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.number_parameters         = %d\n",
23683261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.number_parameters);
23693261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int parameterIndex = 0;
23703261e8b6eac44a41341f112821482bee6c940c98mmentovai       parameterIndex < exception_.exception_record.number_parameters;
23713261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++parameterIndex) {
23723261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  exception_record.exception_information[%2d] = 0x%llx\n",
23733261e8b6eac44a41341f112821482bee6c940c98mmentovai           parameterIndex,
23743261e8b6eac44a41341f112821482bee6c940c98mmentovai           exception_.exception_record.exception_information[parameterIndex]);
23753261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23763261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size                   = %d\n",
23773261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.data_size);
23783261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva                         = 0x%x\n",
23793261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.rva);
23803261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
23813261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
23823261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
23833261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
23843261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
23853261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
23863261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
23873261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
23883261e8b6eac44a41341f112821482bee6c940c98mmentovai}
23893261e8b6eac44a41341f112821482bee6c940c98mmentovai
23903261e8b6eac44a41341f112821482bee6c940c98mmentovai
23913261e8b6eac44a41341f112821482bee6c940c98mmentovai//
23923261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpSystemInfo
23933261e8b6eac44a41341f112821482bee6c940c98mmentovai//
23943261e8b6eac44a41341f112821482bee6c940c98mmentovai
23953261e8b6eac44a41341f112821482bee6c940c98mmentovai
23963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
239753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
239853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      system_info_(),
2399e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      csd_version_(NULL),
2400e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      cpu_vendor_(NULL) {
24013261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24023261e8b6eac44a41341f112821482bee6c940c98mmentovai
24033261e8b6eac44a41341f112821482bee6c940c98mmentovai
24043261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::~MinidumpSystemInfo() {
24053261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
2406e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
24073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24083261e8b6eac44a41341f112821482bee6c940c98mmentovai
24093261e8b6eac44a41341f112821482bee6c940c98mmentovai
24103261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpSystemInfo::Read(u_int32_t expected_size) {
24113261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
24123261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
24133261e8b6eac44a41341f112821482bee6c940c98mmentovai  csd_version_ = NULL;
2414e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
2415e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  cpu_vendor_ = NULL;
24163261e8b6eac44a41341f112821482bee6c940c98mmentovai
24173261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
24183261e8b6eac44a41341f112821482bee6c940c98mmentovai
2419af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(system_info_)) {
2420af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
2421af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(system_info_);
24223261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2423af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
24243261e8b6eac44a41341f112821482bee6c940c98mmentovai
2425af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
2426af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
24273261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2428af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
24293261e8b6eac44a41341f112821482bee6c940c98mmentovai
24303261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
24313261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_architecture);
24323261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_level);
24333261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_revision);
24343261e8b6eac44a41341f112821482bee6c940c98mmentovai    // number_of_processors and product_type are 8-bit quantities and need no
24353261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapping.
24363261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.major_version);
24373261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.minor_version);
24383261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.build_number);
24393261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.platform_id);
24403261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.csd_version_rva);
24413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.suite_mask);
24423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    // Don't swap the reserved2 field because its contents are unknown.
24433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
24443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
24453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
24463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 3; ++i)
24473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
24483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.version_information);
24493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.feature_information);
24503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
24513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    } else {
24523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 2; ++i)
24533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
24543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
24553261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
24563261e8b6eac44a41341f112821482bee6c940c98mmentovai
24573261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
24583261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
24593261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24603261e8b6eac44a41341f112821482bee6c940c98mmentovai
24613261e8b6eac44a41341f112821482bee6c940c98mmentovai
246297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetOS() {
2463af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2464af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
246597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return NULL;
2466af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
246797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
246897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string os;
246997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
247097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.platform_id) {
247197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_NT:
247297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_WINDOWS:
247397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "windows";
247497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
247597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
247697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_MAC_OS_X:
247797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "mac";
247897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
247997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
248097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_LINUX:
248197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "linux";
248297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
2483af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2484af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
2485af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
2486af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.platform_id);
2487af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
248897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
248997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
249097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return os;
249197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
249297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
249397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
249497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetCPU() {
2495af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2496af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
249797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return "";
2498af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
249997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
250097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string cpu;
250197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
250297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.processor_architecture) {
250397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86:
250497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86_WIN64:
250597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "x86";
250697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
250797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
250897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_PPC:
250997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "ppc";
251097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
2511af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2512af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
2513af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
2514af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.processor_architecture);
2515af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
251697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
251797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
251897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return cpu;
251997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
252097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
252197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
25223261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst string* MinidumpSystemInfo::GetCSDVersion() {
2523af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2524af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
25253261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2526af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25273261e8b6eac44a41341f112821482bee6c940c98mmentovai
25283261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!csd_version_)
25293261e8b6eac44a41341f112821482bee6c940c98mmentovai    csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
25303261e8b6eac44a41341f112821482bee6c940c98mmentovai
2531af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
2532af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    "CSD version";
2533af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
25343261e8b6eac44a41341f112821482bee6c940c98mmentovai  return csd_version_;
25353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25363261e8b6eac44a41341f112821482bee6c940c98mmentovai
25373261e8b6eac44a41341f112821482bee6c940c98mmentovai
2538e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovaiconst string* MinidumpSystemInfo::GetCPUVendor() {
2539af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2540af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
2541e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    return NULL;
2542af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2543e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
2544e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  // CPU vendor information can only be determined from x86 minidumps.
2545e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (!cpu_vendor_ &&
2546e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
2547e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
2548e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    char cpu_vendor_string[13];
2549e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
2550e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             "%c%c%c%c%c%c%c%c%c%c%c%c",
2551e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
2552e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
2553e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
2554e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
2555e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
2556e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
2557e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
2558e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
2559e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
2560e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
2561e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
2562e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
2563e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    cpu_vendor_ = new string(cpu_vendor_string);
2564e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
2565e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
2566e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  return cpu_vendor_;
2567e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai}
2568e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
2569e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
25703261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpSystemInfo::Print() {
2571af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2572af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
25733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2574af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25753261e8b6eac44a41341f112821482bee6c940c98mmentovai
25763261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawSystemInfo\n");
25773261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_architecture                     = %d\n",
25783261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_architecture);
25793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_level                            = %d\n",
25803261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_level);
25810a7e6bf16cad354710df60929c2ac82f647cb54emmentovai  printf("  processor_revision                         = 0x%x\n",
25820a7e6bf16cad354710df60929c2ac82f647cb54emmentovai         system_info_.processor_revision);
25833261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  number_of_processors                       = %d\n",
25843261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.number_of_processors);
25853261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  product_type                               = %d\n",
25863261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.product_type);
25873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  major_version                              = %d\n",
25883261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.major_version);
25893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  minor_version                              = %d\n",
25903261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.minor_version);
25913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  build_number                               = %d\n",
25923261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.build_number);
25933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  platform_id                                = %d\n",
25943261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.platform_id);
25953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  csd_version_rva                            = 0x%x\n",
25963261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.csd_version_rva);
25973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suite_mask                                 = 0x%x\n",
25983261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.suite_mask);
25993261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int i = 0; i < 3; ++i) {
26003261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
26013261e8b6eac44a41341f112821482bee6c940c98mmentovai           i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
26023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26033261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
26043261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.version_information);
26053261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
26063261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.feature_information);
26073261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
26083261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
2609e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* csd_version = GetCSDVersion();
2610e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (csd_version) {
26113261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = \"%s\"\n",
2612e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           csd_version->c_str());
2613e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
26143261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = (null)\n");
2615e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
2616e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* cpu_vendor = GetCPUVendor();
2617e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (cpu_vendor) {
2618e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = \"%s\"\n",
2619e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           cpu_vendor->c_str());
2620e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
2621e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = (null)\n");
2622e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
26233261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
26243261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26253261e8b6eac44a41341f112821482bee6c940c98mmentovai
26263261e8b6eac44a41341f112821482bee6c940c98mmentovai
26273261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26283261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMiscInfo
26293261e8b6eac44a41341f112821482bee6c940c98mmentovai//
26303261e8b6eac44a41341f112821482bee6c940c98mmentovai
26313261e8b6eac44a41341f112821482bee6c940c98mmentovai
26323261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
263353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
263453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      misc_info_() {
26353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26363261e8b6eac44a41341f112821482bee6c940c98mmentovai
26373261e8b6eac44a41341f112821482bee6c940c98mmentovai
26383261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpMiscInfo::Read(u_int32_t expected_size) {
26393261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
26403261e8b6eac44a41341f112821482bee6c940c98mmentovai
26413261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != MD_MISCINFO_SIZE &&
26423261e8b6eac44a41341f112821482bee6c940c98mmentovai      expected_size != MD_MISCINFO2_SIZE) {
2643af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size <<
2644af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE <<
2645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ")";
26463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
26473261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26483261e8b6eac44a41341f112821482bee6c940c98mmentovai
2649af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
2650af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
26513261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2652af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26533261e8b6eac44a41341f112821482bee6c940c98mmentovai
26543261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
26553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.size_of_info);
26563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.flags1);
26573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_id);
26583261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_create_time);
26593261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_user_time);
26603261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_kernel_time);
26613261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
26623261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_mhz);
26633261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_mhz);
26643261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_mhz_limit);
26653261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_idle_state);
26663261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_idle_state);
26673261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
26683261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26693261e8b6eac44a41341f112821482bee6c940c98mmentovai
267065571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai  if (expected_size != misc_info_.size_of_info) {
2671af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
267265571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai                    expected_size << " != " << misc_info_.size_of_info;
26733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2674af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26753261e8b6eac44a41341f112821482bee6c940c98mmentovai
26763261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
26773261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
26783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
26793261e8b6eac44a41341f112821482bee6c940c98mmentovai
26803261e8b6eac44a41341f112821482bee6c940c98mmentovai
26813261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMiscInfo::Print() {
2682af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2683af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
26843261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2685af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
26863261e8b6eac44a41341f112821482bee6c940c98mmentovai
26873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawMiscInfo\n");
26883261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
26893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags1                       = 0x%x\n", misc_info_.flags1);
26903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_id                   = 0x%x\n", misc_info_.process_id);
26913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_create_time          = 0x%x\n",
26923261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_create_time);
26933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_user_time            = 0x%x\n",
26943261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_user_time);
26953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_kernel_time          = 0x%x\n",
26963261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_kernel_time);
26973261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
26983261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_mhz            = %d\n",
26993261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_mhz);
27003261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_mhz        = %d\n",
27013261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_mhz);
27023261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_mhz_limit          = %d\n",
27033261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_mhz_limit);
27043261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_idle_state     = 0x%x\n",
27053261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_idle_state);
27063261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_idle_state = 0x%x\n",
27073261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_idle_state);
27083261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
270976f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
271076f052f8fbf8864dee5992b857229d06560a766ammentovai}
271176f052f8fbf8864dee5992b857229d06560a766ammentovai
271276f052f8fbf8864dee5992b857229d06560a766ammentovai
271376f052f8fbf8864dee5992b857229d06560a766ammentovai//
2714e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// MinidumpBreakpadInfo
271576f052f8fbf8864dee5992b857229d06560a766ammentovai//
271676f052f8fbf8864dee5992b857229d06560a766ammentovai
271776f052f8fbf8864dee5992b857229d06560a766ammentovai
2718e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
271976f052f8fbf8864dee5992b857229d06560a766ammentovai    : MinidumpStream(minidump),
2720e5dc60822e5938fea2ae892ccddb906641ba174emmentovai      breakpad_info_() {
272176f052f8fbf8864dee5992b857229d06560a766ammentovai}
272276f052f8fbf8864dee5992b857229d06560a766ammentovai
272376f052f8fbf8864dee5992b857229d06560a766ammentovai
2724e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::Read(u_int32_t expected_size) {
272576f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = false;
272676f052f8fbf8864dee5992b857229d06560a766ammentovai
2727af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(breakpad_info_)) {
2728af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
2729af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(breakpad_info_);
273076f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
2731af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
273276f052f8fbf8864dee5992b857229d06560a766ammentovai
2733af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
2734af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
273576f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
2736af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
273776f052f8fbf8864dee5992b857229d06560a766ammentovai
273876f052f8fbf8864dee5992b857229d06560a766ammentovai  if (minidump_->swap()) {
2739e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.validity);
2740e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.dump_thread_id);
2741e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.requesting_thread_id);
274276f052f8fbf8864dee5992b857229d06560a766ammentovai  }
274376f052f8fbf8864dee5992b857229d06560a766ammentovai
274476f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = true;
274576f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
274676f052f8fbf8864dee5992b857229d06560a766ammentovai}
274776f052f8fbf8864dee5992b857229d06560a766ammentovai
274876f052f8fbf8864dee5992b857229d06560a766ammentovai
2749e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::GetDumpThreadID(u_int32_t *thread_id) const {
2750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
2751af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
2752af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
2753af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
2754af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2755af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2756af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
2757af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
2758af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2759af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2760af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
2761af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
276276f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
276376f052f8fbf8864dee5992b857229d06560a766ammentovai  }
276476f052f8fbf8864dee5992b857229d06560a766ammentovai
2765e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.dump_thread_id;
276676f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
276776f052f8fbf8864dee5992b857229d06560a766ammentovai}
276876f052f8fbf8864dee5992b857229d06560a766ammentovai
276976f052f8fbf8864dee5992b857229d06560a766ammentovai
2770e5dc60822e5938fea2ae892ccddb906641ba174emmentovaibool MinidumpBreakpadInfo::GetRequestingThreadID(u_int32_t *thread_id)
277176f052f8fbf8864dee5992b857229d06560a766ammentovai    const {
2772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
2773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
2774af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
2775af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
2776af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2777af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!thread_id || !valid_) {
2778af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
2779af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
2780af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2781af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2782af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity &
2783af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
2784af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
278576f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
278676f052f8fbf8864dee5992b857229d06560a766ammentovai  }
278776f052f8fbf8864dee5992b857229d06560a766ammentovai
2788e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.requesting_thread_id;
278976f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
279076f052f8fbf8864dee5992b857229d06560a766ammentovai}
279176f052f8fbf8864dee5992b857229d06560a766ammentovai
279276f052f8fbf8864dee5992b857229d06560a766ammentovai
2793e5dc60822e5938fea2ae892ccddb906641ba174emmentovaivoid MinidumpBreakpadInfo::Print() {
2794af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2795af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
279676f052f8fbf8864dee5992b857229d06560a766ammentovai    return;
2797af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
279876f052f8fbf8864dee5992b857229d06560a766ammentovai
2799e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("MDRawBreakpadInfo\n");
2800e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("  validity             = 0x%x\n", breakpad_info_.validity);
280176f052f8fbf8864dee5992b857229d06560a766ammentovai
2802e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
2803e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    printf("  dump_thread_id       = 0x%x\n", breakpad_info_.dump_thread_id);
280476f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
280576f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  dump_thread_id       = (invalid)\n");
280676f052f8fbf8864dee5992b857229d06560a766ammentovai  }
280776f052f8fbf8864dee5992b857229d06560a766ammentovai
2808e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
280976f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = 0x%x\n",
2810e5dc60822e5938fea2ae892ccddb906641ba174emmentovai           breakpad_info_.requesting_thread_id);
281176f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
281276f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = (invalid)\n");
281376f052f8fbf8864dee5992b857229d06560a766ammentovai  }
281476f052f8fbf8864dee5992b857229d06560a766ammentovai
281576f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
28163261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28173261e8b6eac44a41341f112821482bee6c940c98mmentovai
28183261e8b6eac44a41341f112821482bee6c940c98mmentovai
28193261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28203261e8b6eac44a41341f112821482bee6c940c98mmentovai// Minidump
28213261e8b6eac44a41341f112821482bee6c940c98mmentovai//
28223261e8b6eac44a41341f112821482bee6c940c98mmentovai
28233261e8b6eac44a41341f112821482bee6c940c98mmentovai
28246dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaiMinidump::Minidump(const string& path)
282553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : header_(),
282653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      directory_(NULL),
2827373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      stream_map_(new MinidumpStreamMap()),
28286dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      path_(path),
28296dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      fd_(-1),
283053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      swap_(false),
283153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
28323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28333261e8b6eac44a41341f112821482bee6c940c98mmentovai
28343261e8b6eac44a41341f112821482bee6c940c98mmentovai
28353261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidump::~Minidump() {
28363261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
28373261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete stream_map_;
2838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (fd_ != -1) {
2839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "Minidump closing minidump on fd " << fd_;
28406dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    close(fd_);
2841af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28426dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai}
28436dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
28446dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
28456dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaibool Minidump::Open() {
28466dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  if (fd_ != -1) {
2847af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "Minidump reopening minidump " << path_ << " on fd " << fd_;
2848af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
28496dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // The file is already open.  Seek to the beginning, which is the position
28506dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // the file would be at if it were opened anew.
28516dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return SeekSet(0);
28526dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  }
28536dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
28546dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  // O_BINARY is useful (and defined) on Windows.  On other platforms, it's
28556dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  // useless, and because it's defined as 0 above, harmless.
28566dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  fd_ = open(path_.c_str(), O_RDONLY | O_BINARY);
2857af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (fd_ == -1) {
2858af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    string error_string;
2859af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    int error_code = ErrnoString(&error_string);
2860af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
2861af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ", error " << error_code << ": " << error_string;
28626dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
2863af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28646dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
2865af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump opened minidump " << path_ << " on fd " << fd_;
28666dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  return true;
28673261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28683261e8b6eac44a41341f112821482bee6c940c98mmentovai
28693261e8b6eac44a41341f112821482bee6c940c98mmentovai
28703261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::Read() {
28713261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
28723261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
28733261e8b6eac44a41341f112821482bee6c940c98mmentovai  directory_ = NULL;
2874373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  stream_map_->clear();
28753261e8b6eac44a41341f112821482bee6c940c98mmentovai
28763261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
28773261e8b6eac44a41341f112821482bee6c940c98mmentovai
2878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!Open()) {
2879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot open minidump";
28806dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
2881af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28826dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
2883af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
2884af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot read header";
28853261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2886af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28873261e8b6eac44a41341f112821482bee6c940c98mmentovai
28883261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (header_.signature != MD_HEADER_SIGNATURE) {
28893261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file may be byte-swapped.  Under the present architecture, these
28903261e8b6eac44a41341f112821482bee6c940c98mmentovai    // classes don't know or need to know what CPU (or endianness) the
28913261e8b6eac44a41341f112821482bee6c940c98mmentovai    // minidump was produced on in order to parse it.  Use the signature as
28923261e8b6eac44a41341f112821482bee6c940c98mmentovai    // a byte order marker.
28933261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t signature_swapped = header_.signature;
28943261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&signature_swapped);
28953261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature_swapped != MD_HEADER_SIGNATURE) {
28963261e8b6eac44a41341f112821482bee6c940c98mmentovai      // This isn't a minidump or a byte-swapped minidump.
2897af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
2898af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(header_.signature) << ", " <<
2899af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(signature_swapped) << ") != " <<
2900af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(MD_HEADER_SIGNATURE);
29013261e8b6eac44a41341f112821482bee6c940c98mmentovai      return false;
29023261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
29033261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = true;
29043261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
29053261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file is not byte-swapped.  Set swap_ false (it may have been true
29063261e8b6eac44a41341f112821482bee6c940c98mmentovai    // if the object is being reused?)
29073261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = false;
29083261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29093261e8b6eac44a41341f112821482bee6c940c98mmentovai
2910af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
2911af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                 "byte-swapping minidump";
2912af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
29133261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_) {
29143261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.signature);
29153261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.version);
29163261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_count);
29173261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_directory_rva);
29183261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.checksum);
29193261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.time_date_stamp);
29203261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.flags);
29213261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29223261e8b6eac44a41341f112821482bee6c940c98mmentovai
29233261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Version check.  The high 16 bits of header_.version contain something
29243261e8b6eac44a41341f112821482bee6c940c98mmentovai  // else "implementation specific."
29253261e8b6eac44a41341f112821482bee6c940c98mmentovai  if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
2926af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump version mismatch: " <<
2927af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(header_.version & 0x0000ffff) << " != " <<
2928af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(MD_HEADER_VERSION);
29293261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
29303261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29313261e8b6eac44a41341f112821482bee6c940c98mmentovai
2932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(header_.stream_directory_rva)) {
2933af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
29343261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2937373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (header_.stream_count) {
2938373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // TODO(mmentovai): verify rational size!
2939373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpDirectoryEntries> directory(
2940373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpDirectoryEntries(header_.stream_count));
29413261e8b6eac44a41341f112821482bee6c940c98mmentovai
2942373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
2943373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
2944373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&(*directory)[0],
2945af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   sizeof(MDRawDirectory) * header_.stream_count)) {
2946af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump cannot read stream directory";
2947373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
2948af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
29493261e8b6eac44a41341f112821482bee6c940c98mmentovai
2950373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int stream_index = 0;
2951373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         stream_index < header_.stream_count;
2952373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++stream_index) {
2953373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDRawDirectory* directory_entry = &(*directory)[stream_index];
29543261e8b6eac44a41341f112821482bee6c940c98mmentovai
2955373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (swap_) {
2956373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->stream_type);
2957373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->location);
2958373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
29593261e8b6eac44a41341f112821482bee6c940c98mmentovai
2960373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Initialize the stream_map_ map, which speeds locating a stream by
2961373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // type.
2962373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      unsigned int stream_type = directory_entry->stream_type;
2963373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      switch (stream_type) {
2964373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_THREAD_LIST_STREAM:
2965373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MODULE_LIST_STREAM:
2966373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MEMORY_LIST_STREAM:
2967373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_EXCEPTION_STREAM:
2968373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_SYSTEM_INFO_STREAM:
2969373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MISC_INFO_STREAM:
2970e5dc60822e5938fea2ae892ccddb906641ba174emmentovai        case MD_BREAKPAD_INFO_STREAM: {
2971373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          if (stream_map_->find(stream_type) != stream_map_->end()) {
2972373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // Another stream with this type was already found.  A minidump
2973373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // file should contain at most one of each of these stream types.
2974af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            BPLOG(ERROR) << "Minidump found multiple streams of type " <<
2975af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                            stream_type << ", but can only deal with one";
2976373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            return false;
2977373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          }
2978373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Fall through to default
29793261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
29803261e8b6eac44a41341f112821482bee6c940c98mmentovai
2981373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        default: {
2982373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Overwrites for stream types other than those above, but it's
2983373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // expected to be the user's burden in that case.
2984373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          (*stream_map_)[stream_type].stream_index = stream_index;
2985373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        }
29863261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
29873261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
29883261e8b6eac44a41341f112821482bee6c940c98mmentovai
2989373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    directory_ = directory.release();
2990373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
29913261e8b6eac44a41341f112821482bee6c940c98mmentovai
29923261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
29933261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
29943261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29953261e8b6eac44a41341f112821482bee6c940c98mmentovai
29963261e8b6eac44a41341f112821482bee6c940c98mmentovai
29973261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList* Minidump::GetThreadList() {
29983261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpThreadList* thread_list;
29993261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&thread_list);
30003261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30013261e8b6eac44a41341f112821482bee6c940c98mmentovai
30023261e8b6eac44a41341f112821482bee6c940c98mmentovai
30033261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList* Minidump::GetModuleList() {
30043261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpModuleList* module_list;
30053261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&module_list);
30063261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30073261e8b6eac44a41341f112821482bee6c940c98mmentovai
30083261e8b6eac44a41341f112821482bee6c940c98mmentovai
30093261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList* Minidump::GetMemoryList() {
30103261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryList* memory_list;
30113261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&memory_list);
30123261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30133261e8b6eac44a41341f112821482bee6c940c98mmentovai
30143261e8b6eac44a41341f112821482bee6c940c98mmentovai
30153261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException* Minidump::GetException() {
30163261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpException* exception;
30173261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&exception);
30183261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30193261e8b6eac44a41341f112821482bee6c940c98mmentovai
30203261e8b6eac44a41341f112821482bee6c940c98mmentovai
30213261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo* Minidump::GetSystemInfo() {
30223261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpSystemInfo* system_info;
30233261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&system_info);
30243261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30253261e8b6eac44a41341f112821482bee6c940c98mmentovai
30263261e8b6eac44a41341f112821482bee6c940c98mmentovai
30273261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo* Minidump::GetMiscInfo() {
30283261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMiscInfo* misc_info;
30293261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&misc_info);
30303261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30313261e8b6eac44a41341f112821482bee6c940c98mmentovai
30323261e8b6eac44a41341f112821482bee6c940c98mmentovai
3033e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
3034e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  MinidumpBreakpadInfo* breakpad_info;
3035e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  return GetStream(&breakpad_info);
303676f052f8fbf8864dee5992b857229d06560a766ammentovai}
303776f052f8fbf8864dee5992b857229d06560a766ammentovai
303876f052f8fbf8864dee5992b857229d06560a766ammentovai
30393261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid Minidump::Print() {
3040af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3041af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot print invalid data";
30423261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3043af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30443261e8b6eac44a41341f112821482bee6c940c98mmentovai
30453261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawHeader\n");
30463261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  signature            = 0x%x\n",    header_.signature);
30473261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version              = 0x%x\n",    header_.version);
30483261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_count         = %d\n",      header_.stream_count);
30493261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
30503261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum             = 0x%x\n",    header_.checksum);
3051042ca733d309f48d2987a81151cbf3c59b73e562bryner  struct tm timestruct;
3052042ca733d309f48d2987a81151cbf3c59b73e562bryner  gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
30533261e8b6eac44a41341f112821482bee6c940c98mmentovai  char timestr[20];
3054042ca733d309f48d2987a81151cbf3c59b73e562bryner  strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
30553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
30563261e8b6eac44a41341f112821482bee6c940c98mmentovai                                               timestr);
30573261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags                = 0x%llx\n",  header_.flags);
30583261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
30593261e8b6eac44a41341f112821482bee6c940c98mmentovai
30603261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int stream_index = 0;
30613261e8b6eac44a41341f112821482bee6c940c98mmentovai       stream_index < header_.stream_count;
30623261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++stream_index) {
30633261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDRawDirectory* directory_entry = &(*directory_)[stream_index];
30643261e8b6eac44a41341f112821482bee6c940c98mmentovai
30653261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("mDirectory[%d]\n", stream_index);
30663261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDRawDirectory\n");
30673261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  stream_type        = %d\n",   directory_entry->stream_type);
30683261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.data_size = %d\n",
30693261e8b6eac44a41341f112821482bee6c940c98mmentovai           directory_entry->location.data_size);
30703261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
30713261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
30723261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30733261e8b6eac44a41341f112821482bee6c940c98mmentovai
30743261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("Streams:\n");
30753261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
30763261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != stream_map_->end();
30773261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
30783261e8b6eac44a41341f112821482bee6c940c98mmentovai    u_int32_t stream_type = iterator->first;
30793261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpStreamInfo info = iterator->second;
308076f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  stream type 0x%x at index %d\n", stream_type, info.stream_index);
30813261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30823261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
30833261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30843261e8b6eac44a41341f112821482bee6c940c98mmentovai
30853261e8b6eac44a41341f112821482bee6c940c98mmentovai
30863261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
30873261e8b6eac44a41341f112821482bee6c940c98mmentovai      const {
3088af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3089af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
30903261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3091af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3093af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= header_.stream_count) {
3094af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
3095af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << header_.stream_count;
3096af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
3097af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
30983261e8b6eac44a41341f112821482bee6c940c98mmentovai
30993261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*directory_)[index];
31003261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31013261e8b6eac44a41341f112821482bee6c940c98mmentovai
31023261e8b6eac44a41341f112821482bee6c940c98mmentovai
31033261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::ReadBytes(void* bytes, size_t count) {
31043261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
31053261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validity can be determined.  The only member that this method
31063261e8b6eac44a41341f112821482bee6c940c98mmentovai  // depends on is mFD, and an unset or invalid fd may generate an
31073261e8b6eac44a41341f112821482bee6c940c98mmentovai  // error but should not cause a crash.
31083261e8b6eac44a41341f112821482bee6c940c98mmentovai  ssize_t bytes_read = read(fd_, bytes, count);
3109af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (static_cast<size_t>(bytes_read) != count) {
3110af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (bytes_read == -1) {
3111af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      string error_string;
3112af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      int error_code = ErrnoString(&error_string);
3113af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
3114af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    } else {
3115af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "ReadBytes: read " << bytes_read << "/" << count;
3116af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
31173261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31193261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
31203261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31213261e8b6eac44a41341f112821482bee6c940c98mmentovai
31223261e8b6eac44a41341f112821482bee6c940c98mmentovai
31233261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekSet(off_t offset) {
31243261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
31253261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validity can be determined.  The only member that this method
31263261e8b6eac44a41341f112821482bee6c940c98mmentovai  // depends on is mFD, and an unset or invalid fd may generate an
31273261e8b6eac44a41341f112821482bee6c940c98mmentovai  // error but should not cause a crash.
31283261e8b6eac44a41341f112821482bee6c940c98mmentovai  off_t sought = lseek(fd_, offset, SEEK_SET);
3129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sought != offset) {
3130af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (sought == -1) {
3131af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      string error_string;
3132af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      int error_code = ErrnoString(&error_string);
3133af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
3134af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    } else {
3135af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "SeekSet: sought " << sought << "/" << offset;
3136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
31373261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31393261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
31403261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31413261e8b6eac44a41341f112821482bee6c940c98mmentovai
31423261e8b6eac44a41341f112821482bee6c940c98mmentovai
31433261e8b6eac44a41341f112821482bee6c940c98mmentovaistring* Minidump::ReadString(off_t offset) {
3144af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3145af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for ReadString";
31463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3147af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3148af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(offset)) {
3149af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "ReadString could not seek to string";
31503261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3151af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31523261e8b6eac44a41341f112821482bee6c940c98mmentovai
31533261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t bytes;
3154af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&bytes, sizeof(bytes))) {
3155af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "ReadString could not read string size";
31563261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3157af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31583261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_)
31593261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&bytes);
31603261e8b6eac44a41341f112821482bee6c940c98mmentovai
3161af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (bytes % 2 != 0) {
3162af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "ReadString found odd-sized string of " << bytes <<
3163af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " bytes at offset " << offset;
31643261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3165af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31663261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int utf16_words = bytes / 2;
31673261e8b6eac44a41341f112821482bee6c940c98mmentovai
31683261e8b6eac44a41341f112821482bee6c940c98mmentovai  // TODO(mmentovai): verify rational size!
31693261e8b6eac44a41341f112821482bee6c940c98mmentovai  vector<u_int16_t> string_utf16(utf16_words);
31703261e8b6eac44a41341f112821482bee6c940c98mmentovai
3171373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (utf16_words) {
3172373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&string_utf16[0], bytes)) {
3173af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "ReadString could not read string";
3174373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
3175373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
3176373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
31773261e8b6eac44a41341f112821482bee6c940c98mmentovai
31783261e8b6eac44a41341f112821482bee6c940c98mmentovai  return UTF16ToUTF8(string_utf16, swap_);
31793261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31803261e8b6eac44a41341f112821482bee6c940c98mmentovai
31813261e8b6eac44a41341f112821482bee6c940c98mmentovai
31823261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekToStreamType(u_int32_t  stream_type,
31833261e8b6eac44a41341f112821482bee6c940c98mmentovai                                u_int32_t* stream_length) {
3184af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
3185af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "|stream_length|";
3186af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream_length);
3187af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *stream_length = 0;
3188af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3189af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3190af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
31913261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3192af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31933261e8b6eac44a41341f112821482bee6c940c98mmentovai
31943261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
31953261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
31963261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
3197af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
31983261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
31993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32003261e8b6eac44a41341f112821482bee6c940c98mmentovai
32013261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo info = iterator->second;
3202af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (info.stream_index >= header_.stream_count) {
3203af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
3204af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " out of range: " <<
3205af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    info.stream_index << "/" << header_.stream_count;
32063261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3207af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32083261e8b6eac44a41341f112821482bee6c940c98mmentovai
32093261e8b6eac44a41341f112821482bee6c940c98mmentovai  MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
3210af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(directory_entry->location.rva)) {
3211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
3212af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    stream_type;
32133261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3214af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32153261e8b6eac44a41341f112821482bee6c940c98mmentovai
32163261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream_length = directory_entry->location.data_size;
32173261e8b6eac44a41341f112821482bee6c940c98mmentovai
32183261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
32193261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32203261e8b6eac44a41341f112821482bee6c940c98mmentovai
32213261e8b6eac44a41341f112821482bee6c940c98mmentovai
32223261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
32233261e8b6eac44a41341f112821482bee6c940c98mmentovaiT* Minidump::GetStream(T** stream) {
32243261e8b6eac44a41341f112821482bee6c940c98mmentovai  // stream is a garbage parameter that's present only to account for C++'s
32253261e8b6eac44a41341f112821482bee6c940c98mmentovai  // inability to overload a method based solely on its return type.
32263261e8b6eac44a41341f112821482bee6c940c98mmentovai
3227af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  const u_int32_t stream_type = T::kStreamType;
3228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
3230af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                              " requires |stream|";
3231af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream);
32323261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = NULL;
32333261e8b6eac44a41341f112821482bee6c940c98mmentovai
3234af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3235af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
32363261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3237af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32383261e8b6eac44a41341f112821482bee6c940c98mmentovai
32393261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
32403261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
32413261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
3242af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
32433261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
32443261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32453261e8b6eac44a41341f112821482bee6c940c98mmentovai
32463261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Get a pointer so that the stored stream field can be altered.
32473261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo* info = &iterator->second;
32483261e8b6eac44a41341f112821482bee6c940c98mmentovai
32493261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (info->stream) {
32503261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This cast is safe because info.stream is only populated by this
32513261e8b6eac44a41341f112821482bee6c940c98mmentovai    // method, and there is a direct correlation between T and stream_type.
32523261e8b6eac44a41341f112821482bee6c940c98mmentovai    *stream = static_cast<T*>(info->stream);
32533261e8b6eac44a41341f112821482bee6c940c98mmentovai    return *stream;
32543261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32553261e8b6eac44a41341f112821482bee6c940c98mmentovai
32563261e8b6eac44a41341f112821482bee6c940c98mmentovai  u_int32_t stream_length;
3257af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekToStreamType(stream_type, &stream_length)) {
3258af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
32593261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3260af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32613261e8b6eac44a41341f112821482bee6c940c98mmentovai
32622466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<T> new_stream(new T(this));
32633261e8b6eac44a41341f112821482bee6c940c98mmentovai
3264af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!new_stream->Read(stream_length)) {
3265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
32663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32683261e8b6eac44a41341f112821482bee6c940c98mmentovai
32693261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = new_stream.release();
32703261e8b6eac44a41341f112821482bee6c940c98mmentovai  info->stream = *stream;
32713261e8b6eac44a41341f112821482bee6c940c98mmentovai  return *stream;
32723261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32733261e8b6eac44a41341f112821482bee6c940c98mmentovai
32743261e8b6eac44a41341f112821482bee6c940c98mmentovai
3275e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
3276