minidump.cc revision 5f22d6a7f471f2352d394c188560fd06830e14f3
183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc.
27daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// All rights reserved.
33261e8b6eac44a41341f112821482bee6c940c98mmentovai//
47daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Redistribution and use in source and binary forms, with or without
57daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// modification, are permitted provided that the following conditions are
67daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// met:
73261e8b6eac44a41341f112821482bee6c940c98mmentovai//
87daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions of source code must retain the above copyright
97daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// notice, this list of conditions and the following disclaimer.
107daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions in binary form must reproduce the above
117daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// copyright notice, this list of conditions and the following disclaimer
127daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// in the documentation and/or other materials provided with the
137daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// distribution.
147daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Neither the name of Google Inc. nor the names of its
157daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// contributors may be used to endorse or promote products derived from
167daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// this software without specific prior written permission.
173261e8b6eac44a41341f112821482bee6c940c98mmentovai//
187daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
237daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
247daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
267daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
277daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
287daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293261e8b6eac44a41341f112821482bee6c940c98mmentovai
303261e8b6eac44a41341f112821482bee6c940c98mmentovai// minidump.cc: A minidump reader.
313261e8b6eac44a41341f112821482bee6c940c98mmentovai//
323261e8b6eac44a41341f112821482bee6c940c98mmentovai// See minidump.h for documentation.
333261e8b6eac44a41341f112821482bee6c940c98mmentovai//
343261e8b6eac44a41341f112821482bee6c940c98mmentovai// Author: Mark Mentovai
353261e8b6eac44a41341f112821482bee6c940c98mmentovai
36e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include "google_breakpad/processor/minidump.h"
373261e8b6eac44a41341f112821482bee6c940c98mmentovai
38e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h>
396dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#include <fcntl.h>
40f2e56b1fde88a521971cb6e74d53ce6ac04aa186ted.mielczarek@gmail.com#include <stddef.h>
413261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <stdio.h>
429fcf4db315427032a92078d1212fece2655bf049mmentovai#include <string.h>
433261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <time.h>
44c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek
453261e8b6eac44a41341f112821482bee6c940c98mmentovai#ifdef _WIN32
463261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <io.h>
47c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx64 "llx"
48c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define PRIx32 "lx"
49c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#define snprintf _snprintf
5080e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#else  // _WIN32
51c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#include <unistd.h>
526dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai#define O_BINARY 0
5380e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai#endif  // _WIN32
543261e8b6eac44a41341f112821482bee6c940c98mmentovai
550cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <fstream>
560cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek#include <iostream>
57fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai#include <limits>
583261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <map>
593261e8b6eac44a41341f112821482bee6c940c98mmentovai#include <vector>
603261e8b6eac44a41341f112821482bee6c940c98mmentovai
618c2a4def4ecfbf6293b27eff4359a274e9774b4emmentovai#include "processor/range_map-inl.h"
6280e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai
632cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
64db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_module.h"
65db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "processor/basic_code_modules.h"
66af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai#include "processor/logging.h"
672cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com
68e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
693261e8b6eac44a41341f112821482bee6c940c98mmentovai
703261e8b6eac44a41341f112821482bee6c940c98mmentovai
710cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::istream;
720cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekusing std::ifstream;
73fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovaiusing std::numeric_limits;
743261e8b6eac44a41341f112821482bee6c940c98mmentovaiusing std::vector;
753261e8b6eac44a41341f112821482bee6c940c98mmentovai
763261e8b6eac44a41341f112821482bee6c940c98mmentovai
773261e8b6eac44a41341f112821482bee6c940c98mmentovai//
783261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping routines
793261e8b6eac44a41341f112821482bee6c940c98mmentovai//
803261e8b6eac44a41341f112821482bee6c940c98mmentovai// Inlining these doesn't increase code size significantly, and it saves
813261e8b6eac44a41341f112821482bee6c940c98mmentovai// a whole lot of unnecessary jumping back and forth.
823261e8b6eac44a41341f112821482bee6c940c98mmentovai//
833261e8b6eac44a41341f112821482bee6c940c98mmentovai
843261e8b6eac44a41341f112821482bee6c940c98mmentovai
853261e8b6eac44a41341f112821482bee6c940c98mmentovai// Swapping an 8-bit quantity is a no-op.  This function is only provided
863261e8b6eac44a41341f112821482bee6c940c98mmentovai// to account for certain templatized operations that require swapping for
876162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com// wider types but handle uint8_t too
883261e8b6eac44a41341f112821482bee6c940c98mmentovai// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
896162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint8_t* value) {
903261e8b6eac44a41341f112821482bee6c940c98mmentovai}
913261e8b6eac44a41341f112821482bee6c940c98mmentovai
923261e8b6eac44a41341f112821482bee6c940c98mmentovai
933261e8b6eac44a41341f112821482bee6c940c98mmentovai// Optimization: don't need to AND the furthest right shift, because we're
943261e8b6eac44a41341f112821482bee6c940c98mmentovai// shifting an unsigned quantity.  The standard requires zero-filling in this
953261e8b6eac44a41341f112821482bee6c940c98mmentovai// case.  If the quantities were signed, a bitmask whould be needed for this
963261e8b6eac44a41341f112821482bee6c940c98mmentovai// right shift to avoid an arithmetic shift (which retains the sign bit).
973261e8b6eac44a41341f112821482bee6c940c98mmentovai// The furthest left shift never needs to be ANDed bitmask.
983261e8b6eac44a41341f112821482bee6c940c98mmentovai
993261e8b6eac44a41341f112821482bee6c940c98mmentovai
1006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint16_t* value) {
1013261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = (*value >> 8) |
1023261e8b6eac44a41341f112821482bee6c940c98mmentovai           (*value << 8);
1033261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1043261e8b6eac44a41341f112821482bee6c940c98mmentovai
1053261e8b6eac44a41341f112821482bee6c940c98mmentovai
1066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint32_t* value) {
1073261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value =  (*value >> 24) |
1083261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value >> 8)  & 0x0000ff00) |
1093261e8b6eac44a41341f112821482bee6c940c98mmentovai           ((*value << 8)  & 0x00ff0000) |
1103261e8b6eac44a41341f112821482bee6c940c98mmentovai            (*value << 24);
1113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1123261e8b6eac44a41341f112821482bee6c940c98mmentovai
1133261e8b6eac44a41341f112821482bee6c940c98mmentovai
1146162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic inline void Swap(uint64_t* value) {
1156162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t* value32 = reinterpret_cast<uint32_t*>(value);
1162e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[0]);
1172e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  Swap(&value32[1]);
1186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t temp = value32[0];
1192e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[0] = value32[1];
1202e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai  value32[1] = temp;
1213261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1223261e8b6eac44a41341f112821482bee6c940c98mmentovai
1233261e8b6eac44a41341f112821482bee6c940c98mmentovai
1241d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// Given a pointer to a 128-bit int in the minidump data, set the "low"
1251d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// and "high" fields appropriately.
1266162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Normalize128(uint128_struct* value, bool is_big_endian) {
1271d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // The struct format is [high, low], so if the format is big-endian,
1281d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  // the most significant bytes will already be in the high field.
1291d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  if (!is_big_endian) {
1306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t temp = value->low;
1311d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->low = value->high;
1321d78cad82e3c7aa2315ed7438211a1901a91ed34bryner    value->high = temp;
1331d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  }
1341d78cad82e3c7aa2315ed7438211a1901a91ed34bryner}
1353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1361d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// This just swaps each int64 half of the 128-bit value.
1371d78cad82e3c7aa2315ed7438211a1901a91ed34bryner// The value should also be normalized by calling Normalize128().
1386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic void Swap(uint128_struct* value) {
1391d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->low);
1401d78cad82e3c7aa2315ed7438211a1901a91ed34bryner  Swap(&value->high);
1413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
1423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1433562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com// Swapping signed integers
1443562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int16_t* value) {
1453562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint16_t*>(value));
1463562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1473562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1483562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int32_t* value) {
1493562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint32_t*>(value));
1503562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1513562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1523562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(int64_t* value) {
1533562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(reinterpret_cast<uint64_t*>(value));
1543562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1553562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1573261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDLocationDescriptor* location_descriptor) {
1583261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->data_size);
1593261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&location_descriptor->rva);
1603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1613261e8b6eac44a41341f112821482bee6c940c98mmentovai
1623261e8b6eac44a41341f112821482bee6c940c98mmentovai
1633261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDMemoryDescriptor* memory_descriptor) {
1643261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->start_of_memory_range);
1653261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&memory_descriptor->memory);
1663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1673261e8b6eac44a41341f112821482bee6c940c98mmentovai
1683261e8b6eac44a41341f112821482bee6c940c98mmentovai
1693261e8b6eac44a41341f112821482bee6c940c98mmentovaistatic inline void Swap(MDGUID* guid) {
1703261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data1);
1713261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data2);
1723261e8b6eac44a41341f112821482bee6c940c98mmentovai  Swap(&guid->data3);
1733261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't swap guid->data4[] because it contains 8-bit quantities.
1743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
1753261e8b6eac44a41341f112821482bee6c940c98mmentovai
1763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDSystemTime* system_time) {
1773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->year);
1783562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->month);
1793562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day_of_week);
1803562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->day);
1813562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->hour);
1823562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->minute);
1833562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->second);
1843562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&system_time->milliseconds);
1853562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1863562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
1873562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(uint16_t* data, size_t size_in_bytes) {
1883562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t data_length = size_in_bytes / sizeof(data[0]);
1893562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  for (size_t i = 0; i < data_length; i++) {
1903562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    Swap(&data[i]);
1913562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
1923562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
1933261e8b6eac44a41341f112821482bee6c940c98mmentovai
1943261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1953261e8b6eac44a41341f112821482bee6c940c98mmentovai// Character conversion routines
1963261e8b6eac44a41341f112821482bee6c940c98mmentovai//
1973261e8b6eac44a41341f112821482bee6c940c98mmentovai
1983261e8b6eac44a41341f112821482bee6c940c98mmentovai
1993261e8b6eac44a41341f112821482bee6c940c98mmentovai// Standard wide-character conversion routines depend on the system's own
2003261e8b6eac44a41341f112821482bee6c940c98mmentovai// idea of what width a wide character should be: some use 16 bits, and
2013261e8b6eac44a41341f112821482bee6c940c98mmentovai// some use 32 bits.  For the purposes of a minidump, wide strings are
2023261e8b6eac44a41341f112821482bee6c940c98mmentovai// always represented with 16-bit UTF-16 chracters.  iconv isn't available
2033261e8b6eac44a41341f112821482bee6c940c98mmentovai// everywhere, and its interface varies where it is available.  iconv also
2043261e8b6eac44a41341f112821482bee6c940c98mmentovai// deals purely with char* pointers, so in addition to considering the swap
2053261e8b6eac44a41341f112821482bee6c940c98mmentovai// parameter, a converter that uses iconv would also need to take the host
2063261e8b6eac44a41341f112821482bee6c940c98mmentovai// CPU's endianness into consideration.  It doesn't seems worth the trouble
2073261e8b6eac44a41341f112821482bee6c940c98mmentovai// of making it a dependency when we don't care about anything but UTF-16.
2086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic string* UTF16ToUTF8(const vector<uint16_t>& in,
2093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                           bool swap) {
2102466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<string> out(new string());
2113261e8b6eac44a41341f112821482bee6c940c98mmentovai
2123261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Set the string's initial capacity to the number of UTF-16 characters,
2133261e8b6eac44a41341f112821482bee6c940c98mmentovai  // because the UTF-8 representation will always be at least this long.
2143261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the UTF-8 representation is longer, the string will grow dynamically.
2153261e8b6eac44a41341f112821482bee6c940c98mmentovai  out->reserve(in.size());
2163261e8b6eac44a41341f112821482bee6c940c98mmentovai
2176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  for (vector<uint16_t>::const_iterator iterator = in.begin();
2183261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != in.end();
2193261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
2203261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Get a 16-bit value from the input
2216162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint16_t in_word = *iterator;
2223261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (swap)
2233261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&in_word);
2243261e8b6eac44a41341f112821482bee6c940c98mmentovai
2253261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the input value (in_word) into a Unicode code point (unichar).
2266162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t unichar;
2273261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (in_word >= 0xdc00 && in_word <= 0xdcff) {
228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
229af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(in_word) << " without high";
2303261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2313261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
2323261e8b6eac44a41341f112821482bee6c940c98mmentovai      // High surrogate.
2333261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = (in_word - 0xd7c0) << 10;
2343261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (++iterator == in.end()) {
235af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
236af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word) << " at end of string";
2373261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2383261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t high_word = in_word;
2403261e8b6eac44a41341f112821482bee6c940c98mmentovai      in_word = *iterator;
2413261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (in_word < 0xdc00 || in_word > 0xdcff) {
242af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
243af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(high_word) << " without low " <<
244af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(in_word);
2453261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2463261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
2473261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar |= in_word & 0x03ff;
2483261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
2493261e8b6eac44a41341f112821482bee6c940c98mmentovai      // The ordinary case, a single non-surrogate Unicode character encoded
2503261e8b6eac44a41341f112821482bee6c940c98mmentovai      // as a single 16-bit value.
2513261e8b6eac44a41341f112821482bee6c940c98mmentovai      unichar = in_word;
2523261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2533261e8b6eac44a41341f112821482bee6c940c98mmentovai
2543261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Convert the Unicode code point (unichar) into its UTF-8 representation,
2553261e8b6eac44a41341f112821482bee6c940c98mmentovai    // appending it to the out string.
2563261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (unichar < 0x80) {
257f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += static_cast<char>(unichar);
2583261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x800) {
259f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xc0 | static_cast<char>(unichar >> 6);
260f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2613261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x10000) {
262f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xe0 | static_cast<char>(unichar >> 12);
263f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
264f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2653261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (unichar < 0x200000) {
266f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0xf0 | static_cast<char>(unichar >> 18);
267f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f);
268f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
269f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
2703261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
271af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
272af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(unichar) << " in UTF-8";
2733261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2743261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
2753261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
2763261e8b6eac44a41341f112821482bee6c940c98mmentovai
2773261e8b6eac44a41341f112821482bee6c940c98mmentovai  return out.release();
2783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
2793261e8b6eac44a41341f112821482bee6c940c98mmentovai
2800314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// Return the smaller of the number of code units in the UTF-16 string,
2810314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// not including the terminating null word, or maxlen.
2826162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic size_t UTF16codeunits(const uint16_t *string, size_t maxlen) {
2830314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  size_t count = 0;
2840314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  while (count < maxlen && string[count] != 0)
2850314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    count++;
2860314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return count;
2870314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
2880314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
2893562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic inline void Swap(MDTimeZoneInformation* time_zone) {
2903562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->bias);
2913562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->standard_name.  No need to swap UTF-16 fields.
2923562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
2933562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_date);
2943562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->standard_bias);
2953562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Skip time_zone->daylight_name.  No need to swap UTF-16 fields.
2963562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // The swap will be done as part of the conversion to UTF-8.
2973562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_date);
2983562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  Swap(&time_zone->daylight_bias);
2993562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3003562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
3013562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.comstatic void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data,
3023562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           size_t max_length_in_bytes,
3033562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           string* utf8_result,
3043562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                           bool swap) {
3053562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Since there is no explicit byte length for each string, use
3063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // UTF16codeunits to calculate word length, then derive byte
3073562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // length from that.
3083562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]);
3093562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  size_t word_length = UTF16codeunits(utf16_data, max_word_length);
3103562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (word_length > 0) {
3113562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    size_t byte_length = word_length * sizeof(utf16_data[0]);
3123562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    vector<uint16_t> utf16_vector(word_length);
3133562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    memcpy(&utf16_vector[0], &utf16_data[0], byte_length);
3143562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap));
3153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (temp.get()) {
3163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      utf8_result->assign(*temp);
3173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
3183562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  } else {
3193562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    utf8_result->clear();
3203562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
3213562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com}
3223261e8b6eac44a41341f112821482bee6c940c98mmentovai
3233261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3243261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpObject
3253261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3263261e8b6eac44a41341f112821482bee6c940c98mmentovai
3273261e8b6eac44a41341f112821482bee6c940c98mmentovai
3283261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpObject::MinidumpObject(Minidump* minidump)
32953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : minidump_(minidump),
33053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
3313261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3323261e8b6eac44a41341f112821482bee6c940c98mmentovai
3333261e8b6eac44a41341f112821482bee6c940c98mmentovai
3343261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3353261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpStream
3363261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3373261e8b6eac44a41341f112821482bee6c940c98mmentovai
3383261e8b6eac44a41341f112821482bee6c940c98mmentovai
3393261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpStream::MinidumpStream(Minidump* minidump)
3403261e8b6eac44a41341f112821482bee6c940c98mmentovai    : MinidumpObject(minidump) {
3413261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3423261e8b6eac44a41341f112821482bee6c940c98mmentovai
3433261e8b6eac44a41341f112821482bee6c940c98mmentovai
3443261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3453261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpContext
3463261e8b6eac44a41341f112821482bee6c940c98mmentovai//
3473261e8b6eac44a41341f112821482bee6c940c98mmentovai
3483261e8b6eac44a41341f112821482bee6c940c98mmentovai
3493261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext::MinidumpContext(Minidump* minidump)
35053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
351233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_(),
352233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      context_flags_(0) {
3533261e8b6eac44a41341f112821482bee6c940c98mmentovai}
3543261e8b6eac44a41341f112821482bee6c940c98mmentovai
3553261e8b6eac44a41341f112821482bee6c940c98mmentovai
3563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiMinidumpContext::~MinidumpContext() {
3573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
3583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
3593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3616162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::Read(uint32_t expected_size) {
3623261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
3633261e8b6eac44a41341f112821482bee6c940c98mmentovai
3643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  FreeContext();
3653261e8b6eac44a41341f112821482bee6c940c98mmentovai
3663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // First, figure out what type of CPU this context structure is for.
3678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // For some reason, the AMD64 Context doesn't have context_flags
3688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  // at the beginning of the structure, so special case it here.
3698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (expected_size == sizeof(MDRawContextAMD64)) {
3708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
3718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
3728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
3738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(context_amd64.get(),
3748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                              sizeof(MDRawContextAMD64))) {
3758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
3768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
3778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
3783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
3808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->context_flags);
3813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3826162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
383233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
384233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
385233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_amd64->context_flags |= cpu_type;
386233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
387233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
388233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
389233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
390233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
3913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
3928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (cpu_type != MD_CONTEXT_AMD64) {
393f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // TODO: fall through to switch below?
3948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // need a Tell method to be able to SeekSet back to beginning
3958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // http://code.google.com/p/google-breakpad/issues/detail?id=224
3968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
3978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
3988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
3993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Do this after reading the entire MDRawContext structure because
4018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // GetSystemInfo may seek minidump to a new position.
4028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!CheckAgainstSystemInfo(cpu_type)) {
4038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
4048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
4058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4063261e8b6eac44a41341f112821482bee6c940c98mmentovai
4078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Normalize the 128-bit types in the dump.
4088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Since this is AMD64, by definition, the values are little-endian.
4098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    for (unsigned int vr_index = 0;
4108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         vr_index < MD_CONTEXT_AMD64_VR_COUNT;
4118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek         ++vr_index)
4128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Normalize128(&context_amd64->vector_register[vr_index], false);
4138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
4148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap()) {
4158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p1_home);
4168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p2_home);
4178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p3_home);
4188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p4_home);
4198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p5_home);
4208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->p6_home);
4218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // context_flags is already swapped
4228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->mx_csr);
4238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->cs);
4248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ds);
4258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->es);
4268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->fs);
4278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->ss);
4288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->eflags);
4298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr0);
4308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr1);
4318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr2);
4328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr3);
4338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr6);
4348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->dr7);
4358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rax);
4368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rcx);
4378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdx);
4388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbx);
4398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsp);
4408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rbp);
4418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rsi);
4428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rdi);
4438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r8);
4448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r9);
4458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r10);
4468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r11);
4478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r12);
4488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r13);
4498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r14);
4508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->r15);
4518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->rip);
452f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // FIXME: I'm not sure what actually determines
4538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // which member of the union {flt_save, sse_registers}
4548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // is valid.  We're not currently using either,
4558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      // but it would be good to have them swapped properly.
4563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      for (unsigned int vr_index = 0;
4588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           vr_index < MD_CONTEXT_AMD64_VR_COUNT;
4598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek           ++vr_index)
4608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        Swap(&context_amd64->vector_register[vr_index]);
4618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->vector_control);
4628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->debug_control);
4638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_to_rip);
4648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_branch_from_rip);
4658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_to_rip);
4668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_amd64->last_exception_from_rip);
4678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
4683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_amd64->context_flags;
4703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
4718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_.amd64 = context_amd64.release();
472f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else if (expected_size == sizeof(MDRawContextPPC64)) {
473f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
474f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // in the else case have 32 bits |context_flags|, so special case it here.
475cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint64_t context_flags;
476cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
477cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read context flags";
478cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
479cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
480cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap())
481cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_flags);
482cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
483cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
484cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
485cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
486f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
487cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Set the context_flags member, which has already been read, and
488cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // read the rest of the structure beginning with the first member
489cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // after context_flags.
490cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    context_ppc64->context_flags = context_flags;
491cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
492cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    size_t flags_size = sizeof(context_ppc64->context_flags);
493cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    uint8_t* context_after_flags =
494cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org          reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
495cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!minidump_->ReadBytes(context_after_flags,
496cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org                              sizeof(MDRawContextPPC64) - flags_size)) {
497cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
498cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
499cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
500cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
501cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // Do this after reading the entire MDRawContext structure because
502cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    // GetSystemInfo may seek minidump to a new position.
503cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (!CheckAgainstSystemInfo(cpu_type)) {
504cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
505cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      return false;
506cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
507cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    if (minidump_->swap()) {
508cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // context_ppc64->context_flags was already swapped.
509cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr0);
510cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->srr1);
511cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int gpr_index = 0;
512cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
513cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++gpr_index) {
514cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->gpr[gpr_index]);
515cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
516cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->cr);
517cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->xer);
518cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->lr);
519cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->ctr);
520cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vrsave);
521cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int fpr_index = 0;
522cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
523cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++fpr_index) {
524cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->float_save.fpregs[fpr_index]);
525cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
526cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap context_ppc64->float_save.fpscr_pad because it is only
527cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // used for padding.
528cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->float_save.fpscr);
529cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int vr_index = 0;
530cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
531cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++vr_index) {
532cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
533cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        Swap(&context_ppc64->vector_save.save_vr[vr_index]);
534cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
535cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vscr);
536cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // Don't swap the padding fields in vector_save.
537cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      Swap(&context_ppc64->vector_save.save_vrvalid);
538cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
539cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
540f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    context_flags_ = static_cast<uint32_t>(context_ppc64->context_flags);
541f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
542f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // Check for data loss when converting context flags from uint64_t into
543f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    // uint32_t
544f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    if (static_cast<uint64_t>(context_flags_) !=
545f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        context_ppc64->context_flags) {
546f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
547f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      return false;
548f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    }
549cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
550f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    context_.ppc64 = context_ppc64.release();
551f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
5526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t context_flags;
5538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
5548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      BPLOG(ERROR) << "MinidumpContext could not read context flags";
5558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      return false;
5563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
5578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    if (minidump_->swap())
5588eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      Swap(&context_flags);
5598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
5606162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
5611a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    if (cpu_type == 0) {
5621a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // Unfortunately the flag for MD_CONTEXT_ARM that was taken
5631a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // from a Windows CE SDK header conflicts in practice with
5641a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
5651a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      // but handle dumps with the legacy value gracefully here.
5661a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      if (context_flags & MD_CONTEXT_ARM_OLD) {
5671a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags |= MD_CONTEXT_ARM;
5681a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        context_flags &= ~MD_CONTEXT_ARM_OLD;
5691a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek        cpu_type = MD_CONTEXT_ARM;
5701a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek      }
5711a1890a52aaf8bfbea34a8d918423e6c81f3ea80ted.mielczarek    }
5728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
573233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    if (cpu_type == 0) {
574233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
575233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        context_flags |= cpu_type;
576233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      } else {
577233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        BPLOG(ERROR) << "Failed to preserve the current stream position";
578233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        return false;
579233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      }
580233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
581233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
5828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // Allocate the context structure for the correct CPU and fill it.  The
5838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // casts are slightly unorthodox, but it seems better to do that than to
5848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // maintain a separate pointer for each type of CPU context structure
5858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    // when only one of them will be used.
5868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    switch (cpu_type) {
5878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_X86: {
5888eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextX86)) {
5898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
5908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextX86);
5918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
5928eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
5933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5948eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
5953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
5968eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
5978eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
5988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
5998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_x86->context_flags = context_flags;
6003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_x86->context_flags);
6026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
6036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
6048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
6058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextX86) - flags_size)) {
6068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read x86 context";
6078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
6093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
6118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
6128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
6138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
6148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
6163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
6188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->context_flags was already swapped.
6198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr0);
6208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr1);
6218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr2);
6228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr3);
6238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr6);
6248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->dr7);
6258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.control_word);
6268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.status_word);
6278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.tag_word);
6288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_offset);
6298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.error_selector);
6308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_offset);
6318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.data_selector);
6328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->float_save.register_area[] contains 8-bit quantities
6338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // and does not need to be swapped.
6348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->float_save.cr0_npx_state);
6358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->gs);
6368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->fs);
6378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->es);
6388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ds);
6398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edi);
6408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esi);
6418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebx);
6428eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->edx);
6438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ecx);
6448eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eax);
6458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ebp);
6468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eip);
6478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->cs);
6488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->eflags);
6498eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->esp);
6508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_x86->ss);
6518eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_x86->extended_registers[] contains 8-bit quantities and
6528eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // does not need to be swapped.
6538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
6543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.x86 = context_x86.release();
6568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
6581d78cad82e3c7aa2315ed7438211a1901a91ed34bryner      }
6591d78cad82e3c7aa2315ed7438211a1901a91ed34bryner
6608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_PPC: {
6618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextPPC)) {
6628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
6638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextPPC);
6648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
6668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
6688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
6708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
6718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
6728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_ppc->context_flags = context_flags;
6738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_ppc->context_flags);
6756162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
6766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
6778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
6788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextPPC) - flags_size)) {
6798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read ppc context";
6808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
6828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
6848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
6858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
6868eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
6878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
6883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
6898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
6908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Normalize the 128-bit types in the dump.
6918eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Since this is PowerPC, by definition, the values are big-endian.
6923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        for (unsigned int vr_index = 0;
6933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
6943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             ++vr_index) {
6958eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
6963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        }
6973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
6988eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
6998eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_ppc->context_flags was already swapped.
7008eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr0);
7018eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->srr1);
7028eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
7038eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
7048eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
7058eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->gpr[gpr_index]);
7068eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
7078eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->cr);
7088eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->xer);
7098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->lr);
7108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->ctr);
7118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->mq);
7128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vrsave);
7138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
7148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
7158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
7168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->float_save.fpregs[fpr_index]);
7178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
7188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap context_ppc->float_save.fpscr_pad because it is only
7198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // used for padding.
7208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->float_save.fpscr);
7218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int vr_index = 0;
7228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
7238eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++vr_index) {
7248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_ppc->vector_save.save_vr[vr_index]);
7258eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
7268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vscr);
7278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // Don't swap the padding fields in vector_save.
7288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_ppc->vector_save.save_vrvalid);
7298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
7303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ppc = context_ppc.release();
7323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
7338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
734ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
735ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      case MD_CONTEXT_SPARC: {
7378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (expected_size != sizeof(MDRawContextSPARC)) {
7388eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
7398eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            expected_size << " != " << sizeof(MDRawContextSPARC);
7408eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7418eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
742ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7438eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
744ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7458eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Set the context_flags member, which has already been read, and
7468eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // read the rest of the structure beginning with the first member
7478eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // after context_flags.
7488eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_sparc->context_flags = context_flags;
749ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7508eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        size_t flags_size = sizeof(context_sparc->context_flags);
7516162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
7526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
7538eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
7548eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek                                  sizeof(MDRawContextSPARC) - flags_size)) {
7558eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read sparc context";
7568eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
7578eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        }
758ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // Do this after reading the entire MDRawContext structure because
7608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        // GetSystemInfo may seek minidump to a new position.
7618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
7628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
7638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          return false;
764ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
7658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
7668eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        if (minidump_->swap()) {
7678eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          // context_sparc->context_flags was already swapped.
7688eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int gpr_index = 0;
7698eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
7708eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++gpr_index) {
7718eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->g_r[gpr_index]);
7728eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
7738eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->ccr);
7748eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->pc);
7758eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->npc);
7768eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->y);
7778eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->asi);
7788eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->fprs);
7798eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          for (unsigned int fpr_index = 0;
7808eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
7818eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek               ++fpr_index) {
7828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek            Swap(&context_sparc->float_save.regs[fpr_index]);
7838eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          }
7848eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.filler);
7858eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          Swap(&context_sparc->float_save.fsr);
786ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        }
7878eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        context_.ctx_sparc = context_sparc.release();
788ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7898eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
7908eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
791ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
7929276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      case MD_CONTEXT_ARM: {
7939276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (expected_size != sizeof(MDRawContextARM)) {
7949276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
7959276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            expected_size << " != " << sizeof(MDRawContextARM);
7969276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
7979276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
7989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
7999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
8009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Set the context_flags member, which has already been read, and
8029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // read the rest of the structure beginning with the first member
8039276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // after context_flags.
8049276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_arm->context_flags = context_flags;
8059276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8069276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        size_t flags_size = sizeof(context_arm->context_flags);
8076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint8_t* context_after_flags =
8086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
8099276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!minidump_->ReadBytes(context_after_flags,
8109276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek                                  sizeof(MDRawContextARM) - flags_size)) {
8119276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext could not read arm context";
8129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
8139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
8149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // Do this after reading the entire MDRawContext structure because
8169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        // GetSystemInfo may seek minidump to a new position.
8179276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (!CheckAgainstSystemInfo(cpu_type)) {
8189276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          BPLOG(ERROR) << "MinidumpContext arm does not match system info";
8199276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          return false;
8209276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
8219276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8229276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        if (minidump_->swap()) {
8239276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          // context_arm->context_flags was already swapped.
8249276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int ireg_index = 0;
8259276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
8269276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++ireg_index) {
8279276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->iregs[ireg_index]);
8289276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
8299276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->cpsr);
8309276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          Swap(&context_arm->float_save.fpscr);
8319276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpr_index = 0;
8329276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
8339276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpr_index) {
8349276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.regs[fpr_index]);
8359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
8369276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          for (unsigned int fpe_index = 0;
8379276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
8389276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ++fpe_index) {
8399276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek            Swap(&context_arm->float_save.extra[fpe_index]);
8409276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek          }
8419276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        }
8429276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        context_.arm = context_arm.release();
8439276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8449276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        break;
8459276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
8469276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
8475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      case MD_CONTEXT_MIPS: {
8485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (expected_size != sizeof(MDRawContextMIPS)) {
8495f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
8505f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << expected_size
8515f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << " != "
8525f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                       << sizeof(MDRawContextMIPS);
8535f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
8545f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
8555f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
8565f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
8575f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
8585f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Set the context_flags member, which has already been read, and
8595f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // read the rest of the structure beginning with the first member
8605f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // after context_flags.
8615f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        context_mips->context_flags = context_flags;
8625f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
8635f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        size_t flags_size = sizeof(context_mips->context_flags);
8645f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        uint8_t* context_after_flags =
8655f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
8665f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!minidump_->ReadBytes(context_after_flags,
8675f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com                                  sizeof(MDRawContextMIPS) - flags_size)) {
8685f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
8695f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
8705f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
8715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
8725f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // Do this after reading the entire MDRawContext structure because
8735f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        // GetSystemInfo may seek minidump to a new position.
8745f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (!CheckAgainstSystemInfo(cpu_type)) {
8755f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
8765f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          return false;
8775f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
8785f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
8795f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        if (minidump_->swap()) {
8805f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          // context_mips->context_flags was already swapped.
8815f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int ireg_index = 0;
8825f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
8835f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++ireg_index) {
8845f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->iregs[ireg_index]);
8855f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
8865f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdhi);
8875f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->mdlo);
8885f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int dsp_index = 0;
8895f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
8905f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++dsp_index) {
8915f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->hi[dsp_index]);
8925f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->lo[dsp_index]);
8935f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
8945f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com	  Swap(&context_mips->dsp_control);
8955f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->epc);
8965f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->badvaddr);
8975f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->status);
8985f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->cause);
8995f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          for (int fpr_index = 0;
9005f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
9015f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ++fpr_index) {
9025f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com            Swap(&context_mips->float_save.regs[fpr_index]);
9035f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          }
9045f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fpcsr);
9055f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com          Swap(&context_mips->float_save.fir);
9065f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        }
9075f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        context_.ctx_mips = context_mips.release();
9085f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
9095f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        break;
9105f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
9115f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
9128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      default: {
913bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com        // Unknown context type - Don't log as an error yet. Let the
9145f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        // caller work that out.
9155f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org        BPLOG(INFO) << "MinidumpContext unknown context type " <<
9168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek          HexString(cpu_type);
9178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return false;
9188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        break;
9198eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      }
9203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
9218eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    context_flags_ = context_flags;
9223261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
9233261e8b6eac44a41341f112821482bee6c940c98mmentovai
9243261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
9253261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
9263261e8b6eac44a41341f112821482bee6c940c98mmentovai}
9273261e8b6eac44a41341f112821482bee6c940c98mmentovai
9283261e8b6eac44a41341f112821482bee6c940c98mmentovai
9296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpContext::GetContextCPU() const {
930af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // Don't log a message, GetContextCPU can be legitimately called with
932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // valid_ false by FreeContext, which is called by Read.
933af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
934af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
9368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_flags_ & MD_CONTEXT_CPU_MASK;
9373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
9383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::GetInstructionPointer(uint64_t* ip) const {
940c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  BPLOG_IF(ERROR, !ip) << "MinidumpContext::GetInstructionPointer "
941c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com                          "requires |ip|";
942c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  assert(ip);
943c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  *ip = 0;
944c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
945c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  if (!valid_) {
946c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Invalid MinidumpContext for GetInstructionPointer";
947c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
948c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
949c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
950c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  switch (context_flags_ & MD_CONTEXT_CPU_MASK) {
951c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_AMD64:
952c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.amd64->rip;
953c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
954c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_ARM:
955c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.arm->iregs[MD_CONTEXT_ARM_REG_PC];
956c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
957c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_PPC:
958c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ppc->srr0;
959c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
960cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  case MD_CONTEXT_PPC64:
961cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    *ip = context_.ppc64->srr0;
962cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    break;
963c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_SPARC:
964c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.ctx_sparc->pc;
965c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
966c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  case MD_CONTEXT_X86:
967c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    *ip = context_.x86->eip;
968c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    break;
9695f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  case MD_CONTEXT_MIPS:
9705f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    *ip = context_.ctx_mips->epc;
9715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    break;
972c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  default:
973c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    // This should never happen.
974c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer";
975c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com    return false;
976c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  }
977c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com  return true;
978c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com}
979c551efe9b6129aa5a7911e3469630b52478057fcted.mielczarek@gmail.com
9803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextX86* MinidumpContext::GetContextX86() const {
982af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_X86) {
983af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get x86 context";
984af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
985af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
986af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
987af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.x86;
9883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
9893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
9913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaiconst MDRawContextPPC* MinidumpContext::GetContextPPC() const {
992af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (GetContextCPU() != MD_CONTEXT_PPC) {
993af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get ppc context";
994af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
995af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
996af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
997af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return context_.ppc;
9983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
9993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1000cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.orgconst MDRawContextPPC64* MinidumpContext::GetContextPPC64() const {
1001cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  if (GetContextCPU() != MD_CONTEXT_PPC64) {
1002cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    BPLOG(ERROR) << "MinidumpContext cannot get ppc64 context";
1003cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    return NULL;
1004cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  }
1005cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
1006cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org  return context_.ppc64;
1007cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org}
1008cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
10098eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarekconst MDRawContextAMD64* MinidumpContext::GetContextAMD64() const {
10108eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  if (GetContextCPU() != MD_CONTEXT_AMD64) {
10118eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get amd64 context";
10128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    return NULL;
10138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  }
10148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
10158eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  return context_.amd64;
10168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek}
10178eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1018ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovaiconst MDRawContextSPARC* MinidumpContext::GetContextSPARC() const {
1019ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (GetContextCPU() != MD_CONTEXT_SPARC) {
1020ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    BPLOG(ERROR) << "MinidumpContext cannot get sparc context";
1021ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return NULL;
1022ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  }
1023ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1024ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  return context_.ctx_sparc;
1025ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai}
10263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10279276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarekconst MDRawContextARM* MinidumpContext::GetContextARM() const {
10289276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  if (GetContextCPU() != MD_CONTEXT_ARM) {
10299276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    BPLOG(ERROR) << "MinidumpContext cannot get arm context";
10309276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    return NULL;
10319276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  }
10329276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10339276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek  return context_.arm;
10349276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek}
10359276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10365f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.comconst MDRawContextMIPS* MinidumpContext::GetContextMIPS() const {
10375f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  if (GetContextCPU() != MD_CONTEXT_MIPS) {
10385f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    BPLOG(ERROR) << "MinidumpContext cannot get MIPS context";
10395f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    return NULL;
10405f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  }
10415f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10425f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com  return context_.ctx_mips;
10435f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com}
10445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::FreeContext() {
10463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
10473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
10483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.x86;
10493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
10503261e8b6eac44a41341f112821482bee6c940c98mmentovai
10513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
10523402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      delete context_.ppc;
10533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
10543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1055cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64:
1056cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      delete context_.ppc64;
1057cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1058cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
10598eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
10608eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      delete context_.amd64;
10618eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
10628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1063ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
1064ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      delete context_.ctx_sparc;
1065ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
1066ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
10679276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
10689276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      delete context_.arm;
10699276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
10709276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
10715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS:
10725f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      delete context_.ctx_mips;
10735f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
10745f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
10753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default:
10763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // There is no context record (valid_ is false) or there's a
10773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context record for an unknown CPU (shouldn't happen, only known
10783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // records are stored by Read).
10793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
10803261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
10813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10828eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek  context_flags_ = 0;
10833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  context_.base = NULL;
10843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
10853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10863402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
10876162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
1088e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
10893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // as this function just implements a sanity check.
10903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
1091af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!system_info) {
1092af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1093af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MinidumpSystemInfo";
10943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return true;
1095af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
10963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1097e47047b3835dcbb5da7fe7f5f9b6d78a5307122awaylonis  // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
10983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  const MDRawSystemInfo* raw_system_info = system_info->system_info();
1099af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
1100af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpContext could not be compared against "
1101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   "MDRawSystemInfo";
11023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    return false;
1103af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
11043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
11063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      raw_system_info->processor_architecture);
11073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // Compare the CPU type of the context record to the CPU type in the
11093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  // minidump's system info stream.
1110af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  bool return_value = false;
11113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (context_cpu_type) {
11123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86:
1113af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
1114299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
1115299c816021c5d3e61106d48c1dd2d52fbf4d6cd4luly          system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
1116af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
11173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
11183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
11193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC:
1121af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
1122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        return_value = true;
11233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
1124ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1125cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64:
1126cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64)
1127cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        return_value = true;
1128cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1129cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
11308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64:
11318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
11328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek        return_value = true;
11338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
11348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1135ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC:
1136ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
1137ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return_value = true;
1138ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
11399276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
11409276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM:
11419276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
11429276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        return_value = true;
11439276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
11445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
11455f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS:
11465f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS)
11475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        return_value = true;
11485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
11493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  }
11503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1151af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
1152af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(context_cpu_type) <<
11530344a368deac6abaa280a298bcea9bb00a90df3fted.mielczarek@gmail.com                                    " wrong for MinidumpSystemInfo CPU " <<
1154af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    HexString(system_info_cpu_type);
1155af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1156af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return return_value;
11573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai}
11583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
11603402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovaivoid MinidumpContext::Print() {
1161af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1162af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpContext cannot print invalid data";
1163af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return;
1164af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1165af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
11663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai  switch (GetContextCPU()) {
11673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_X86: {
11683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextX86* context_x86 = GetContextX86();
11693402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextX86\n");
11703402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags                = 0x%x\n",
11713402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->context_flags);
11723402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr0                          = 0x%x\n", context_x86->dr0);
11733402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr1                          = 0x%x\n", context_x86->dr1);
11743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr2                          = 0x%x\n", context_x86->dr2);
11753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr3                          = 0x%x\n", context_x86->dr3);
11763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr6                          = 0x%x\n", context_x86->dr6);
11773402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  dr7                          = 0x%x\n", context_x86->dr7);
11783402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.control_word      = 0x%x\n",
11793402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.control_word);
11803402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.status_word       = 0x%x\n",
11813402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.status_word);
11823402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.tag_word          = 0x%x\n",
11833402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.tag_word);
11843402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_offset      = 0x%x\n",
11853402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_offset);
11863402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.error_selector    = 0x%x\n",
11873402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.error_selector);
11883402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_offset       = 0x%x\n",
11893402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_offset);
11903402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.data_selector     = 0x%x\n",
11913402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.data_selector);
11923402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.register_area[%2d] = 0x",
11933402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
11943402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
11953402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
11963402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
11973402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->float_save.register_area[register_index]);
11983402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
11993402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
12003402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.cr0_npx_state     = 0x%x\n",
12013402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_x86->float_save.cr0_npx_state);
12023402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  gs                           = 0x%x\n", context_x86->gs);
12033402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  fs                           = 0x%x\n", context_x86->fs);
12043402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  es                           = 0x%x\n", context_x86->es);
12053402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ds                           = 0x%x\n", context_x86->ds);
12063402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edi                          = 0x%x\n", context_x86->edi);
12073402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esi                          = 0x%x\n", context_x86->esi);
12083402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebx                          = 0x%x\n", context_x86->ebx);
12093402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  edx                          = 0x%x\n", context_x86->edx);
12103402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ecx                          = 0x%x\n", context_x86->ecx);
12113402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eax                          = 0x%x\n", context_x86->eax);
12123402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ebp                          = 0x%x\n", context_x86->ebp);
12133402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eip                          = 0x%x\n", context_x86->eip);
12143402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cs                           = 0x%x\n", context_x86->cs);
12153402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  eflags                       = 0x%x\n", context_x86->eflags);
12163402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  esp                          = 0x%x\n", context_x86->esp);
12173402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ss                           = 0x%x\n", context_x86->ss);
12183402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  extended_registers[%3d]      = 0x",
12193402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
12203402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int register_index = 0;
12213402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
12223402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++register_index) {
12233402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("%02x", context_x86->extended_registers[register_index]);
12243402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
12253402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n\n");
12263402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
12293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    case MD_CONTEXT_PPC: {
12313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      const MDRawContextPPC* context_ppc = GetContextPPC();
12323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("MDRawContextPPC\n");
12333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  context_flags            = 0x%x\n",
12343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->context_flags);
12353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr0                     = 0x%x\n", context_ppc->srr0);
12363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  srr1                     = 0x%x\n", context_ppc->srr1);
12373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int gpr_index = 0;
12383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
12393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++gpr_index) {
12403402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        printf("  gpr[%2d]                  = 0x%x\n",
12413402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               gpr_index, context_ppc->gpr[gpr_index]);
12423402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
12433402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  cr                       = 0x%x\n", context_ppc->cr);
12443402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  xer                      = 0x%x\n", context_ppc->xer);
12453402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  lr                       = 0x%x\n", context_ppc->lr);
12463402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  ctr                      = 0x%x\n", context_ppc->ctr);
12473402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  mq                       = 0x%x\n", context_ppc->mq);
12483402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vrsave                   = 0x%x\n", context_ppc->vrsave);
12493402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int fpr_index = 0;
12503402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
12513402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai           ++fpr_index) {
1252c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
12533402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai               fpr_index, context_ppc->float_save.fpregs[fpr_index]);
12543402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      }
12553402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  float_save.fpscr         = 0x%x\n",
12563402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->float_save.fpscr);
12573402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // TODO(mmentovai): print the 128-bit quantities in
12583402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // context_ppc->vector_save.  This isn't done yet because printf
12593402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // doesn't support 128-bit quantities, and printing them using
1260c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
12613402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      // byte ordering.
12623402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("  vector_save.save_vrvalid = 0x%x\n",
12633402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai             context_ppc->vector_save.save_vrvalid);
12643402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      printf("\n");
12653402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
12663402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
12673402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
12683402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
1269cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CONTEXT_PPC64: {
1270cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      const MDRawContextPPC64* context_ppc64 = GetContextPPC64();
1271cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("MDRawContextPPC64\n");
127239b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  context_flags            = 0x%" PRIx64 "\n",
1273cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->context_flags);
127439b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  srr0                     = 0x%" PRIx64 "\n",
127539b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->srr0);
127639b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  srr1                     = 0x%" PRIx64 "\n",
127739b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->srr1);
1278cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int gpr_index = 0;
1279cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
1280cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++gpr_index) {
128139b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org        printf("  gpr[%2d]                  = 0x%" PRIx64 "\n",
1282cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org               gpr_index, context_ppc64->gpr[gpr_index]);
1283cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
128439b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  cr                       = 0x%" PRIx64 "\n", context_ppc64->cr);
128539b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  xer                      = 0x%" PRIx64 "\n",
128639b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->xer);
128739b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  lr                       = 0x%" PRIx64 "\n", context_ppc64->lr);
128839b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  ctr                      = 0x%" PRIx64 "\n",
128939b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->ctr);
129039b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org      printf("  vrsave                   = 0x%" PRIx64 "\n",
129139b28d84217c759363de7bb3594cd3da34cb0410thestig@chromium.org             context_ppc64->vrsave);
1292cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      for (unsigned int fpr_index = 0;
1293cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
1294cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org           ++fpr_index) {
1295cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
1296cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org               fpr_index, context_ppc64->float_save.fpregs[fpr_index]);
1297cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      }
1298cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("  float_save.fpscr         = 0x%x\n",
1299cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->float_save.fpscr);
1300cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // TODO(mmentovai): print the 128-bit quantities in
1301cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // context_ppc64->vector_save.  This isn't done yet because printf
1302cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // doesn't support 128-bit quantities, and printing them using
1303cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
1304cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      // byte ordering.
1305cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("  vector_save.save_vrvalid = 0x%x\n",
1306cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org             context_ppc64->vector_save.save_vrvalid);
1307cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      printf("\n");
1308cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
1309cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
1310cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    }
1311cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
13128eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    case MD_CONTEXT_AMD64: {
13138eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      const MDRawContextAMD64* context_amd64 = GetContextAMD64();
13148eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("MDRawContextAMD64\n");
1315c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p1_home       = 0x%" PRIx64 "\n",
13168eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p1_home);
1317c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p2_home       = 0x%" PRIx64 "\n",
13188eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p2_home);
1319c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p3_home       = 0x%" PRIx64 "\n",
13208eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p3_home);
1321c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p4_home       = 0x%" PRIx64 "\n",
13228eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p4_home);
1323c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p5_home       = 0x%" PRIx64 "\n",
13248eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p5_home);
1325c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  p6_home       = 0x%" PRIx64 "\n",
13268eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->p6_home);
13278eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  context_flags = 0x%x\n",
13288eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->context_flags);
13298eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  mx_csr        = 0x%x\n",
13308eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek             context_amd64->mx_csr);
13318eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  cs            = 0x%x\n", context_amd64->cs);
13328eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ds            = 0x%x\n", context_amd64->ds);
13338eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  es            = 0x%x\n", context_amd64->es);
13348eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  fs            = 0x%x\n", context_amd64->fs);
13358eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  gs            = 0x%x\n", context_amd64->gs);
13368eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  ss            = 0x%x\n", context_amd64->ss);
13378eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("  eflags        = 0x%x\n", context_amd64->eflags);
1338c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr0           = 0x%" PRIx64 "\n", context_amd64->dr0);
1339c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr1           = 0x%" PRIx64 "\n", context_amd64->dr1);
1340c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr2           = 0x%" PRIx64 "\n", context_amd64->dr2);
1341c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr3           = 0x%" PRIx64 "\n", context_amd64->dr3);
1342c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr6           = 0x%" PRIx64 "\n", context_amd64->dr6);
1343c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  dr7           = 0x%" PRIx64 "\n", context_amd64->dr7);
1344c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rax           = 0x%" PRIx64 "\n", context_amd64->rax);
1345c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rcx           = 0x%" PRIx64 "\n", context_amd64->rcx);
1346c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdx           = 0x%" PRIx64 "\n", context_amd64->rdx);
1347c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbx           = 0x%" PRIx64 "\n", context_amd64->rbx);
1348c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsp           = 0x%" PRIx64 "\n", context_amd64->rsp);
1349c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rbp           = 0x%" PRIx64 "\n", context_amd64->rbp);
1350c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rsi           = 0x%" PRIx64 "\n", context_amd64->rsi);
1351c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rdi           = 0x%" PRIx64 "\n", context_amd64->rdi);
1352c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r8            = 0x%" PRIx64 "\n", context_amd64->r8);
1353c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r9            = 0x%" PRIx64 "\n", context_amd64->r9);
1354c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r10           = 0x%" PRIx64 "\n", context_amd64->r10);
1355c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r11           = 0x%" PRIx64 "\n", context_amd64->r11);
1356c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r12           = 0x%" PRIx64 "\n", context_amd64->r12);
1357c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r13           = 0x%" PRIx64 "\n", context_amd64->r13);
1358c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r14           = 0x%" PRIx64 "\n", context_amd64->r14);
1359c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  r15           = 0x%" PRIx64 "\n", context_amd64->r15);
1360c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  rip           = 0x%" PRIx64 "\n", context_amd64->rip);
1361f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      // TODO: print xmm, vector, debug registers
13628eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      printf("\n");
13638eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek      break;
13648eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek    }
13658eb7111814953cb64ec0569b91ea99804b2d5b85ted.mielczarek
1366ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_CONTEXT_SPARC: {
1367ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      const MDRawContextSPARC* context_sparc = GetContextSPARC();
1368ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("MDRawContextSPARC\n");
1369ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      printf("  context_flags       = 0x%x\n",
1370ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->context_flags);
1371ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int g_r_index = 0;
1372ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
1373ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++g_r_index) {
1374c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  g_r[%2d]             = 0x%" PRIx64 "\n",
1375ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               g_r_index, context_sparc->g_r[g_r_index]);
1376ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1377c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  ccr                 = 0x%" PRIx64 "\n", context_sparc->ccr);
1378c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  pc                  = 0x%" PRIx64 "\n", context_sparc->pc);
1379c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  npc                 = 0x%" PRIx64 "\n", context_sparc->npc);
1380c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  y                   = 0x%" PRIx64 "\n", context_sparc->y);
1381c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  asi                 = 0x%" PRIx64 "\n", context_sparc->asi);
1382c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  fprs                = 0x%" PRIx64 "\n", context_sparc->fprs);
1383ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
1384ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      for (unsigned int fpr_index = 0;
1385ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
1386ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai           ++fpr_index) {
1387c27cf3e3959189f78fe2de40405987c3f33488cemmentovai        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
1388ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai               fpr_index, context_sparc->float_save.regs[fpr_index]);
1389ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1390c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.filler   = 0x%" PRIx64 "\n",
1391ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.filler);
1392c27cf3e3959189f78fe2de40405987c3f33488cemmentovai      printf("  float_save.fsr      = 0x%" PRIx64 "\n",
1393ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai             context_sparc->float_save.fsr);
1394ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
1395ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
1396ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
13979276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CONTEXT_ARM: {
13989276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      const MDRawContextARM* context_arm = GetContextARM();
13999276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("MDRawContextARM\n");
14009276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  context_flags       = 0x%x\n",
14019276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek             context_arm->context_flags);
14029276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int ireg_index = 0;
14039276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
14049276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++ireg_index) {
14059276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  iregs[%2d]            = 0x%x\n",
14069276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               ireg_index, context_arm->iregs[ireg_index]);
14079276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
14089276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  cpsr                = 0x%x\n", context_arm->cpsr);
14099276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      printf("  float_save.fpscr     = 0x%" PRIx64 "\n",
14101adb184d420c6c5f2304fb945f8477557336f927ted.mielczarek             context_arm->float_save.fpscr);
14119276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpr_index = 0;
14129276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
14139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpr_index) {
14149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
14159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpr_index, context_arm->float_save.regs[fpr_index]);
14169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
14179276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      for (unsigned int fpe_index = 0;
14189276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
14199276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek           ++fpe_index) {
14200441036f9ec45c3bc3037f2b407cf21a8006d66fjimblandy        printf("  float_save.extra[%2d] = 0x%" PRIx32 "\n",
14219276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek               fpe_index, context_arm->float_save.extra[fpe_index]);
14229276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      }
14239276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
14249276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
14259276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    }
14269276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
14275f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    case MD_CONTEXT_MIPS: {
14285f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      const MDRawContextMIPS* context_mips = GetContextMIPS();
14295f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("MDRawContextMIPS\n");
14305f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  context_flags        = 0x%x\n",
14315f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->context_flags);
14325f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int ireg_index = 0;
14335f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
14345f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++ireg_index) {
14355f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  iregs[%2d]           = 0x%" PRIx64 "\n",
14365f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               ireg_index, context_mips->iregs[ireg_index]);
14375f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
14385f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  mdhi                 = 0x%" PRIx64 "\n",
14395f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->mdhi);
14405f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  mdlo                 = 0x%" PRIx64 "\n",
14415f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->mdhi);
14425f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int dsp_index = 0;
14435f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
14445f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++dsp_index) {
14455f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  hi[%1d]              = 0x%" PRIx32 "\n",
14465f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index, context_mips->hi[dsp_index]);
14475f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  lo[%1d]              = 0x%" PRIx32 "\n",
14485f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               dsp_index, context_mips->lo[dsp_index]);
14495f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
14505f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  dsp_control          = 0x%" PRIx32 "\n",
14515f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->dsp_control);
14525f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  epc                  = 0x%" PRIx64 "\n",
14535f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->epc);
14545f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  badvaddr             = 0x%" PRIx64 "\n",
14555f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->badvaddr);
14565f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  status               = 0x%" PRIx32 "\n",
14575f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->status);
14585f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  cause                = 0x%" PRIx32 "\n",
14595f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->cause);
14605f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
14615f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      for (int fpr_index = 0;
14625f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
14635f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com           ++fpr_index) {
14645f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com        printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
14655f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com               fpr_index, context_mips->float_save.regs[fpr_index]);
14665f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      }
14675f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  float_save.fpcsr     = 0x%" PRIx32 "\n",
14685f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->float_save.fpcsr);
14695f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      printf("  float_save.fir       = 0x%" PRIx32 "\n",
14705f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com             context_mips->float_save.fir);
14715f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      break;
14725f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com    }
14735f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com
14743402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    default: {
14753402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      break;
14763402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
14773261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
14783261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14793261e8b6eac44a41341f112821482bee6c940c98mmentovai
14803261e8b6eac44a41341f112821482bee6c940c98mmentovai
14813261e8b6eac44a41341f112821482bee6c940c98mmentovai//
14823261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryRegion
14833261e8b6eac44a41341f112821482bee6c940c98mmentovai//
14843261e8b6eac44a41341f112821482bee6c940c98mmentovai
14853261e8b6eac44a41341f112821482bee6c940c98mmentovai
14866162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
1487e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1488e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
14893261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
149053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
149153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptor_(NULL),
149253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL) {
14933261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14943261e8b6eac44a41341f112821482bee6c940c98mmentovai
14953261e8b6eac44a41341f112821482bee6c940c98mmentovai
14963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion::~MinidumpMemoryRegion() {
14973261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
14983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
14993261e8b6eac44a41341f112821482bee6c940c98mmentovai
15003261e8b6eac44a41341f112821482bee6c940c98mmentovai
15013261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
15023261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptor_ = descriptor;
15033261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = descriptor &&
1504fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai           descriptor_->memory.data_size <=
15056162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com               numeric_limits<uint64_t>::max() -
1506fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai               descriptor_->start_of_memory_range;
15073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15083261e8b6eac44a41341f112821482bee6c940c98mmentovai
15093261e8b6eac44a41341f112821482bee6c940c98mmentovai
15106162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpMemoryRegion::GetMemory() const {
1511af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1512af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
15133261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1514af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
15153261e8b6eac44a41341f112821482bee6c940c98mmentovai
15163261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!memory_) {
1517af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (descriptor_->memory.data_size == 0) {
1518af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
1519373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
1520af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
1521373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1522af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(descriptor_->memory.rva)) {
1523af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
15243261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1525af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
15263261e8b6eac44a41341f112821482bee6c940c98mmentovai
1527e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (descriptor_->memory.data_size > max_bytes_) {
1528e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
1529e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      descriptor_->memory.data_size << " exceeds maximum " <<
1530e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_bytes_;
1531e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
1532e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
1533e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
15346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > memory(
15356162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(descriptor_->memory.data_size));
15363261e8b6eac44a41341f112821482bee6c940c98mmentovai
1537af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
1538af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
15393261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1540af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
15413261e8b6eac44a41341f112821482bee6c940c98mmentovai
15423261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory_ = memory.release();
15433261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
15443261e8b6eac44a41341f112821482bee6c940c98mmentovai
15453261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*memory_)[0];
15463261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15473261e8b6eac44a41341f112821482bee6c940c98mmentovai
15483261e8b6eac44a41341f112821482bee6c940c98mmentovai
15496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint64_t MinidumpMemoryRegion::GetBase() const {
1550af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1551af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
15526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    return static_cast<uint64_t>(-1);
1553af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1554af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1555af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->start_of_memory_range;
15563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15573261e8b6eac44a41341f112821482bee6c940c98mmentovai
15583261e8b6eac44a41341f112821482bee6c940c98mmentovai
15596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryRegion::GetSize() const {
1560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
1562af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return 0;
1563af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1564af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1565af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return descriptor_->memory.data_size;
15663261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15673261e8b6eac44a41341f112821482bee6c940c98mmentovai
15683261e8b6eac44a41341f112821482bee6c940c98mmentovai
15693261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::FreeMemory() {
15703261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
15713261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
15723261e8b6eac44a41341f112821482bee6c940c98mmentovai}
15733261e8b6eac44a41341f112821482bee6c940c98mmentovai
15743261e8b6eac44a41341f112821482bee6c940c98mmentovai
15753261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
15766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address,
15772214cb9bc1872cafae9127778c0cba556c89e43djimblandy                                                      T*        value) const {
1578af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
1579af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                             "requires |value|";
1580af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(value);
1581af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *value = 0;
1582af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1583af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1584af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
1585af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "GetMemoryAtAddressInternal";
15863261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1587af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
15883261e8b6eac44a41341f112821482bee6c940c98mmentovai
1589bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Common failure case
15903261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (address < descriptor_->start_of_memory_range ||
15916162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      sizeof(T) > numeric_limits<uint64_t>::max() - address ||
15923261e8b6eac44a41341f112821482bee6c940c98mmentovai      address + sizeof(T) > descriptor_->start_of_memory_range +
15933261e8b6eac44a41341f112821482bee6c940c98mmentovai                            descriptor_->memory.data_size) {
1594bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com    BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
1595af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(address) << "+" << sizeof(T) << "/" <<
1596af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->start_of_memory_range) << "+" <<
1597af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(descriptor_->memory.data_size);
15983261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
15993261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16003261e8b6eac44a41341f112821482bee6c940c98mmentovai
16016162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
1602af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!memory) {
1603af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    // GetMemory already logged a perfectly good message.
16043261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1605af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16063261e8b6eac44a41341f112821482bee6c940c98mmentovai
16073261e8b6eac44a41341f112821482bee6c940c98mmentovai  // If the CPU requires memory accesses to be aligned, this can crash.
16083261e8b6eac44a41341f112821482bee6c940c98mmentovai  // x86 and ppc are able to cope, though.
16093261e8b6eac44a41341f112821482bee6c940c98mmentovai  *value = *reinterpret_cast<const T*>(
16103261e8b6eac44a41341f112821482bee6c940c98mmentovai      &memory[address - descriptor_->start_of_memory_range]);
16113261e8b6eac44a41341f112821482bee6c940c98mmentovai
16123261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
16133261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(value);
16143261e8b6eac44a41341f112821482bee6c940c98mmentovai
16153261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
16163261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16173261e8b6eac44a41341f112821482bee6c940c98mmentovai
16183261e8b6eac44a41341f112821482bee6c940c98mmentovai
16196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
16206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint8_t*  value) const {
16213261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
16223261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16233261e8b6eac44a41341f112821482bee6c940c98mmentovai
16243261e8b6eac44a41341f112821482bee6c940c98mmentovai
16256162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
16266162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint16_t* value) const {
16273261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
16283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16293261e8b6eac44a41341f112821482bee6c940c98mmentovai
16303261e8b6eac44a41341f112821482bee6c940c98mmentovai
16316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
16326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint32_t* value) const {
16333261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
16343261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16353261e8b6eac44a41341f112821482bee6c940c98mmentovai
16363261e8b6eac44a41341f112821482bee6c940c98mmentovai
16376162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
16386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                              uint64_t* value) const {
16393261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryAtAddressInternal(address, value);
16403261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16413261e8b6eac44a41341f112821482bee6c940c98mmentovai
16423261e8b6eac44a41341f112821482bee6c940c98mmentovai
16433261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryRegion::Print() {
1644af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1645af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
16463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1647af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16483261e8b6eac44a41341f112821482bee6c940c98mmentovai
16496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t* memory = GetMemory();
16503261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
16513261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("0x");
16523261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int byte_index = 0;
16533261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index < descriptor_->memory.data_size;
16543261e8b6eac44a41341f112821482bee6c940c98mmentovai         byte_index++) {
16553261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("%02x", memory[byte_index]);
16563261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
16573261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
16583261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
16593261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No memory\n");
16603261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
16613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16623261e8b6eac44a41341f112821482bee6c940c98mmentovai
16633261e8b6eac44a41341f112821482bee6c940c98mmentovai
16643261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16653261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThread
16663261e8b6eac44a41341f112821482bee6c940c98mmentovai//
16673261e8b6eac44a41341f112821482bee6c940c98mmentovai
16683261e8b6eac44a41341f112821482bee6c940c98mmentovai
16693261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::MinidumpThread(Minidump* minidump)
167053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
167153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_(),
167253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      memory_(NULL),
167353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
16743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16753261e8b6eac44a41341f112821482bee6c940c98mmentovai
16763261e8b6eac44a41341f112821482bee6c940c98mmentovai
16773261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread::~MinidumpThread() {
16783261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
16793261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
16803261e8b6eac44a41341f112821482bee6c940c98mmentovai}
16813261e8b6eac44a41341f112821482bee6c940c98mmentovai
16823261e8b6eac44a41341f112821482bee6c940c98mmentovai
16833261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpThread::Read() {
16843261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
16853261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete memory_;
16863261e8b6eac44a41341f112821482bee6c940c98mmentovai  memory_ = NULL;
16873261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
16883261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
16893261e8b6eac44a41341f112821482bee6c940c98mmentovai
16903261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
16913261e8b6eac44a41341f112821482bee6c940c98mmentovai
1692af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
1693af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot read thread";
16943261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1695af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
16963261e8b6eac44a41341f112821482bee6c940c98mmentovai
16973261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
16983261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_id);
16993261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.suspend_count);
17003261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority_class);
17013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.priority);
17023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.teb);
17033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.stack);
17043261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_.thread_context);
17053261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17063261e8b6eac44a41341f112821482bee6c940c98mmentovai
1707fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
170802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (thread_.stack.memory.rva == 0 ||
170902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      thread_.stack.memory.data_size == 0 ||
17106162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() -
1711fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                                       thread_.stack.start_of_memory_range) {
1712e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    // This is ok, but log an error anyway.
1713af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
1714af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(thread_.stack.start_of_memory_range) << "+" <<
171502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    HexString(thread_.stack.memory.data_size) <<
171602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com                    ", RVA 0x" << HexString(thread_.stack.memory.rva);
1717e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  } else {
1718e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_ = new MinidumpMemoryRegion(minidump_);
1719e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    memory_->SetDescriptor(&thread_.stack);
1720af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17213261e8b6eac44a41341f112821482bee6c940c98mmentovai
17223261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
17233261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
17243261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17253261e8b6eac44a41341f112821482bee6c940c98mmentovai
172602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.comuint64_t MinidumpThread::GetStartOfStackMemoryRange() const {
172702ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  if (!valid_) {
172802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread";
172902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    return 0;
173002ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  }
173102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
173202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  return thread_.stack.start_of_memory_range;
173302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com}
17343261e8b6eac44a41341f112821482bee6c940c98mmentovai
17353261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpThread::GetMemory() {
1736af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1737af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
1738af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1739af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1740af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1741af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  return memory_;
17423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17433261e8b6eac44a41341f112821482bee6c940c98mmentovai
17443261e8b6eac44a41341f112821482bee6c940c98mmentovai
17453261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpThread::GetContext() {
1746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1747af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
17483261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17503261e8b6eac44a41341f112821482bee6c940c98mmentovai
17513261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
1752af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(thread_.thread_context.rva)) {
1753af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot seek to context";
17543261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1755af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
17563261e8b6eac44a41341f112821482bee6c940c98mmentovai
17572466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
17583261e8b6eac44a41341f112821482bee6c940c98mmentovai
1759af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(thread_.thread_context.data_size)) {
1760af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpThread cannot read context";
17613261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
1762af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
17633261e8b6eac44a41341f112821482bee6c940c98mmentovai
17643261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
17653261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
17663261e8b6eac44a41341f112821482bee6c940c98mmentovai
17673261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
17683261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17693261e8b6eac44a41341f112821482bee6c940c98mmentovai
17703261e8b6eac44a41341f112821482bee6c940c98mmentovai
17716162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThread::GetThreadID(uint32_t *thread_id) const {
1772af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
1773af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
1774af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
1775af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
1776af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1777af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1778af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
177976f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
1780af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
178176f052f8fbf8864dee5992b857229d06560a766ammentovai
178276f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = thread_.thread_id;
178376f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
17843261e8b6eac44a41341f112821482bee6c940c98mmentovai}
17853261e8b6eac44a41341f112821482bee6c940c98mmentovai
17863261e8b6eac44a41341f112821482bee6c940c98mmentovai
17873261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThread::Print() {
1788af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1789af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
17903261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1791af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
17923261e8b6eac44a41341f112821482bee6c940c98mmentovai
17933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawThread\n");
17943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
17953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suspend_count               = %d\n",     thread_.suspend_count);
17963261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority_class              = 0x%x\n",   thread_.priority_class);
17973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  priority                    = 0x%x\n",   thread_.priority);
1798c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
1799c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
18003261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.start_of_memory_range);
18013261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.data_size      = 0x%x\n",
18023261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.stack.memory.data_size);
18033261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
18043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size    = 0x%x\n",
18053261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.data_size);
18063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva          = 0x%x\n",
18073261e8b6eac44a41341f112821482bee6c940c98mmentovai         thread_.thread_context.rva);
18083261e8b6eac44a41341f112821482bee6c940c98mmentovai
18093261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
18103261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
18113261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
18123261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
18133261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
18143261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
18153261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
18163261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18173261e8b6eac44a41341f112821482bee6c940c98mmentovai
18183261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryRegion* memory = GetMemory();
18193261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (memory) {
18203261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("Stack\n");
18213261e8b6eac44a41341f112821482bee6c940c98mmentovai    memory->Print();
18223261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
18233261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("No stack\n");
18243261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18253261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
18263261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18273261e8b6eac44a41341f112821482bee6c940c98mmentovai
18283261e8b6eac44a41341f112821482bee6c940c98mmentovai
18293261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18303261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpThreadList
18313261e8b6eac44a41341f112821482bee6c940c98mmentovai//
18323261e8b6eac44a41341f112821482bee6c940c98mmentovai
18333261e8b6eac44a41341f112821482bee6c940c98mmentovai
18346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpThreadList::max_threads_ = 4096;
1835e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1836e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
18373261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::MinidumpThreadList(Minidump* minidump)
183853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
183953d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      id_to_thread_map_(),
184053d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      threads_(NULL),
184153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      thread_count_(0) {
18423261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18433261e8b6eac44a41341f112821482bee6c940c98mmentovai
18443261e8b6eac44a41341f112821482bee6c940c98mmentovai
18453261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList::~MinidumpThreadList() {
18463261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
18473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
18483261e8b6eac44a41341f112821482bee6c940c98mmentovai
18493261e8b6eac44a41341f112821482bee6c940c98mmentovai
18506162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpThreadList::Read(uint32_t expected_size) {
18513261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
18523261e8b6eac44a41341f112821482bee6c940c98mmentovai  id_to_thread_map_.clear();
18533261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete threads_;
18543261e8b6eac44a41341f112821482bee6c940c98mmentovai  threads_ = NULL;
18553261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = 0;
18563261e8b6eac44a41341f112821482bee6c940c98mmentovai
18573261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
18583261e8b6eac44a41341f112821482bee6c940c98mmentovai
18596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t thread_count;
1860af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(thread_count)) {
1861af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
1862af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(thread_count);
18633261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1864af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1865af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
1866af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
18673261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
1868af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
18693261e8b6eac44a41341f112821482bee6c940c98mmentovai
18703261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
18713261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&thread_count);
18723261e8b6eac44a41341f112821482bee6c940c98mmentovai
18736162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) {
1874fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
1875fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
1876fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
1877fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
1878fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
18793261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(thread_count) +
18803261e8b6eac44a41341f112821482bee6c940c98mmentovai                       thread_count * sizeof(MDRawThread)) {
1881ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
1882ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(thread_count) + 4 +
1883ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         thread_count * sizeof(MDRawThread)) {
18846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
1885ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
1886f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded "
1887f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
1888ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
1889ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
1890ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
1891ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
1892ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    " != " << sizeof(thread_count) +
1893ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                    thread_count * sizeof(MDRawThread);
1894ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
1895ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
18963261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
18973261e8b6eac44a41341f112821482bee6c940c98mmentovai
1898bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com
1899e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count > max_threads_) {
1900e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
1901e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_threads_;
1902e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
1903e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
1904e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
1905e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (thread_count != 0) {
1906373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpThreads> threads(
1907373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
19083261e8b6eac44a41341f112821482bee6c940c98mmentovai
1909373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int thread_index = 0;
1910373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         thread_index < thread_count;
1911373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++thread_index) {
1912373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpThread* thread = &(*threads)[thread_index];
19133261e8b6eac44a41341f112821482bee6c940c98mmentovai
1914373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
1915af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->Read()) {
1916af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
1917af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1918373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
19203261e8b6eac44a41341f112821482bee6c940c98mmentovai
19216162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t thread_id;
1922af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!thread->GetThreadID(&thread_id)) {
1923af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
1924af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1925373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1926af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
192776f052f8fbf8864dee5992b857229d06560a766ammentovai
1928373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (GetThreadByID(thread_id)) {
1929373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        // Another thread with this ID is already in the list.  Data error.
1930af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
1931af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(thread_id) << " at thread " <<
1932af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        thread_index << "/" << thread_count;
1933373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
1934373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
1935373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      id_to_thread_map_[thread_id] = thread;
19363261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
1937373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
1938373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    threads_ = threads.release();
19393261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
19403261e8b6eac44a41341f112821482bee6c940c98mmentovai
19413261e8b6eac44a41341f112821482bee6c940c98mmentovai  thread_count_ = thread_count;
19423261e8b6eac44a41341f112821482bee6c940c98mmentovai
19433261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
19443261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
19453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19463261e8b6eac44a41341f112821482bee6c940c98mmentovai
19473261e8b6eac44a41341f112821482bee6c940c98mmentovai
19483261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
19493261e8b6eac44a41341f112821482bee6c940c98mmentovai    const {
1950af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1951af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
1952af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
1953af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
1954af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
1955af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= thread_count_) {
1956af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
1957af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << thread_count_;
19583261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
1959af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19603261e8b6eac44a41341f112821482bee6c940c98mmentovai
19613261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*threads_)[index];
19623261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19633261e8b6eac44a41341f112821482bee6c940c98mmentovai
19643261e8b6eac44a41341f112821482bee6c940c98mmentovai
19656162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comMinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) {
19663261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Don't check valid_.  Read calls this method before everything is
19673261e8b6eac44a41341f112821482bee6c940c98mmentovai  // validated.  It is safe to not check valid_ here.
19683261e8b6eac44a41341f112821482bee6c940c98mmentovai  return id_to_thread_map_[thread_id];
19693261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19703261e8b6eac44a41341f112821482bee6c940c98mmentovai
19713261e8b6eac44a41341f112821482bee6c940c98mmentovai
19723261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpThreadList::Print() {
1973af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
1974af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
19753261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
1976af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
19773261e8b6eac44a41341f112821482bee6c940c98mmentovai
19783261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpThreadList\n");
19793261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_count = %d\n", thread_count_);
19803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
19813261e8b6eac44a41341f112821482bee6c940c98mmentovai
19823261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int thread_index = 0;
19833261e8b6eac44a41341f112821482bee6c940c98mmentovai       thread_index < thread_count_;
19843261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++thread_index) {
19853261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("thread[%d]\n", thread_index);
19863261e8b6eac44a41341f112821482bee6c940c98mmentovai
19873261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*threads_)[thread_index].Print();
19883261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
19893261e8b6eac44a41341f112821482bee6c940c98mmentovai}
19903261e8b6eac44a41341f112821482bee6c940c98mmentovai
19913261e8b6eac44a41341f112821482bee6c940c98mmentovai
19923261e8b6eac44a41341f112821482bee6c940c98mmentovai//
19933261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModule
19943261e8b6eac44a41341f112821482bee6c940c98mmentovai//
19953261e8b6eac44a41341f112821482bee6c940c98mmentovai
19963261e8b6eac44a41341f112821482bee6c940c98mmentovai
19976162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_cv_bytes_ = 32768;
19986162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModule::max_misc_bytes_ = 32768;
1999e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2000e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
20013261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::MinidumpModule(Minidump* minidump)
200253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpObject(minidump),
2003db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_valid_(false),
200411e180cd3e855796aee4239aa4b22dbda5de9c00mmentovai      has_debug_info_(false),
200553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_(),
200653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      name_(NULL),
200753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      cv_record_(NULL),
200848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
2009db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      misc_record_(NULL) {
20103261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20113261e8b6eac44a41341f112821482bee6c940c98mmentovai
20123261e8b6eac44a41341f112821482bee6c940c98mmentovai
20133261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModule::~MinidumpModule() {
20143261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
20153261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
20163261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
20173261e8b6eac44a41341f112821482bee6c940c98mmentovai}
20183261e8b6eac44a41341f112821482bee6c940c98mmentovai
20193261e8b6eac44a41341f112821482bee6c940c98mmentovai
20203261e8b6eac44a41341f112821482bee6c940c98mmentovaibool MinidumpModule::Read() {
20213261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
20223261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete name_;
20233261e8b6eac44a41341f112821482bee6c940c98mmentovai  name_ = NULL;
20243261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete cv_record_;
20253261e8b6eac44a41341f112821482bee6c940c98mmentovai  cv_record_ = NULL;
202648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
20273261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete misc_record_;
20283261e8b6eac44a41341f112821482bee6c940c98mmentovai  misc_record_ = NULL;
20293261e8b6eac44a41341f112821482bee6c940c98mmentovai
2030db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = false;
2031d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = false;
20323261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
20333261e8b6eac44a41341f112821482bee6c940c98mmentovai
2034af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
2035af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot read module";
20363261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2037af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20383261e8b6eac44a41341f112821482bee6c940c98mmentovai
20393261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
20403261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.base_of_image);
20413261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.size_of_image);
20423261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.checksum);
20433261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.time_date_stamp);
20443261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.module_name_rva);
20453261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.signature);
20463261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.struct_version);
20473261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_hi);
20483261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_version_lo);
20493261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_hi);
20503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.product_version_lo);
20513261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags_mask);
20523261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_flags);
20533261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_os);
20543261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_type);
20553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_subtype);
20563261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_hi);
20573261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.version_info.file_date_lo);
20583261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.cv_record);
20593261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_.misc_record);
20603261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't swap reserved fields because their contents are unknown (as
20613261e8b6eac44a41341f112821482bee6c940c98mmentovai    // are their proper widths).
20623261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
20633261e8b6eac44a41341f112821482bee6c940c98mmentovai
2064fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  // Check for base + size overflow or undersize.
2065fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (module_.size_of_image == 0 ||
2066fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      module_.size_of_image >
20676162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint64_t>::max() - module_.base_of_image) {
2068af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
2069af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(module_.base_of_image) << "+" <<
2070fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    HexString(module_.size_of_image);
20713261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2072af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
20733261e8b6eac44a41341f112821482bee6c940c98mmentovai
2074db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  module_valid_ = true;
2075db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return true;
2076db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2077db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2078db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2079db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaibool MinidumpModule::ReadAuxiliaryData() {
2080af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2081af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
2082db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2083af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2084db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2085db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Each module must have a name.
2086db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  name_ = minidump_->ReadString(module_.module_name_rva);
2087af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!name_) {
2088af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule could not read name";
2089db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2090af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2091db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2092d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  // At this point, we have enough info for the module to be valid.
2093d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  valid_ = true;
2094d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2095db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // CodeView and miscellaneous debug records are only required if the
2096db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // module indicates that they exist.
2097af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
2098af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
2099af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
2100db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2102db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2103af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
2104af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
2105af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "but one was expected";
2106db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return false;
2107af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2108db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2109d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  has_debug_info_ = true;
21103261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
21113261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21123261e8b6eac44a41341f112821482bee6c940c98mmentovai
21133261e8b6eac44a41341f112821482bee6c940c98mmentovai
2114db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_file() const {
2115af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2116af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
2117db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2119db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2120db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return *name_;
2121db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
21223261e8b6eac44a41341f112821482bee6c940c98mmentovai
21233261e8b6eac44a41341f112821482bee6c940c98mmentovai
2124db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::code_identifier() const {
2125af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2126af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
2127db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2128af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2129db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2130d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2131d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2132d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2133db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
2134af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_system_info) {
2135af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires "
2136af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    "MinidumpSystemInfo";
2137db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2138af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2139db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2140db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
2141af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!raw_system_info) {
2142af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
2143db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2144af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2145db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2146db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
2147db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2148db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  switch (raw_system_info->platform_id) {
2149db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_NT:
2150db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    case MD_OS_WIN32_WINDOWS: {
2151c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2152c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2153db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
2154c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
2155db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               module_.time_date_stamp, module_.size_of_image);
2156db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
2157db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2158db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2159db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
21600e94332f7c615d2b734e840bef233f3ee1188801ted.mielczarek    case MD_OS_MAC_OS_X:
216163f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
2162ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
21635187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
2164f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    case MD_OS_LINUX:
2165a29f376a8bb9122f29ea1c53c02a188683fd5a72bradnelson@chromium.org    case MD_OS_NACL:
2166d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3: {
2167db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // TODO(mmentovai): support uuid extension if present, otherwise fall
2168db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // back to version (from LC_ID_DYLIB?), otherwise fall back to something
2169db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // else.
2170db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = "id";
2171db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2172db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2173db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2174db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    default: {
2175db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // Without knowing what OS generated the dump, we can't generate a good
2176db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // identifier.  Return an empty string, signalling failure.
2177af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
2178af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "found " << HexString(raw_system_info->platform_id);
2179db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      break;
2180db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2181db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2182db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2183db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
21843261e8b6eac44a41341f112821482bee6c940c98mmentovai}
21853261e8b6eac44a41341f112821482bee6c940c98mmentovai
21863261e8b6eac44a41341f112821482bee6c940c98mmentovai
2187db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_file() const {
2188af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2189af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
2190db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2191af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2192db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2193d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2194d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2195d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2196db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string file;
2197db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Prefer the CodeView record if present.
219828e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
219948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
220048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
220148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
220248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
220348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
220448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
2205db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
2206db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
220748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
220848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
2209db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
2210db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
221148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2212db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2213db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      // GetCVRecord guarantees pdb_file_name is null-terminated.
2214db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
2215db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2216db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2217db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // If there's a CodeView record but it doesn't match a known signature,
221848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // try the miscellaneous record.
2219db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2220db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2221db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (file.empty()) {
2222db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // No usable CodeView record.  Try the miscellaneous debug record.
222328e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai    if (misc_record_) {
222428e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai      const MDImageDebugMisc* misc_record =
222528e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai          reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
2226db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      if (!misc_record->unicode) {
2227db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // If it's not Unicode, just stuff it into the string.  It's unclear
2228db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // if misc_record->data is 0-terminated, so use an explicit size.
2229db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        file = string(
2230db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            reinterpret_cast<const char*>(misc_record->data),
22312e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize);
2232db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      } else {
2233db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // There's a misc_record but it encodes the debug filename in UTF-16.
2234db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // (Actually, because miscellaneous records are so old, it's probably
2235db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
2236db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // that this method (and all other methods in the Minidump family)
2237db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        // return.
2238db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2239db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        unsigned int bytes =
22402e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai            module_.misc_record.data_size - MDImageDebugMisc_minsize;
2241db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        if (bytes % 2 == 0) {
2242db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          unsigned int utf16_words = bytes / 2;
2243db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
22446162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one
2245db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // and copy the UTF-16 data into it.
22466162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          vector<uint16_t> string_utf16(utf16_words);
2247db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          if (utf16_words)
2248db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            memcpy(&string_utf16[0], &misc_record->data, bytes);
2249db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2250db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // GetMiscRecord already byte-swapped the data[] field if it contains
2251db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          // UTF-16, so pass false as the swap argument.
2252db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
2253db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          file = *new_file;
2254db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        }
2255db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      }
2256db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2257db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2258db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2259bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
2260bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
2261bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                  "debug_file for " << *name_;
2262af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2263db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return file;
2264db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2265db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2266db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2267db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::debug_identifier() const {
2268af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2269af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
2270db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2271af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2272db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2273d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek  if (!has_debug_info_)
2274d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek    return "";
2275d732add382b95d1460b281f191f0f0e4397eaf51ted.mielczarek
2276db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string identifier;
2277db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2278db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Use the CodeView record if present.
227928e5990b579f69aaeded6ab4c2b68d841424b4cdmmentovai  if (cv_record_) {
228048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
228148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB70 structure.
228248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
228348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
228448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
228548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
2286c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2287c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2288db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[41];
2289db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
2290c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
2291db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data1,
2292db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data2,
2293db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data3,
2294db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[0],
2295db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[1],
2296db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[2],
2297db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[3],
2298db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[4],
2299db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[5],
2300db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[6],
2301db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->signature.data4[7],
2302db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai               cv_record_70->age);
2303db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
230448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
230548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // It's actually an MDCVInfoPDB20 structure.
2306db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const MDCVInfoPDB20* cv_record_20 =
2307db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai          reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
230848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2309db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2310c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // Use the same format that the MS symbol server uses in filesystem
2311c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai      // hierarchies.
2312db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      char identifier_string[17];
2313db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      snprintf(identifier_string, sizeof(identifier_string),
2314c7b6c11f3287ec4fe52e6ad915ed9c906ed8d301mmentovai               "%08X%x", cv_record_20->signature, cv_record_20->age);
2315db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      identifier = identifier_string;
2316db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2317db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2318db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
231948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  // TODO(mmentovai): if there's no usable CodeView record, there might be a
2320db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // miscellaneous debug record.  It only carries a filename, though, and no
2321db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // identifier.  I'm not sure what the right thing to do for the identifier
2322db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // is in that case, but I don't expect to find many modules without a
2323e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  // CodeView record (or some other Breakpad extension structure in place of
2324db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a CodeView record).  Treat it as an error (empty identifier) for now.
2325db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2326db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
2327db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2328bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  // Relatively common case
2329bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com  BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
2330bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com                                        "debug_identifier for " << *name_;
2331af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2332db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return identifier;
2333db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2334db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2335db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2336db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaistring MinidumpModule::version() const {
2337af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2338af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for version";
2339db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return "";
2340af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2341db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2342db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  string version;
2343db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2344db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
2345db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
2346db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    char version_string[24];
2347db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
2348db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi >> 16,
2349db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_hi & 0xffff,
2350db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo >> 16,
2351db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai             module_.version_info.file_version_lo & 0xffff);
2352db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    version = version_string;
2353db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  }
2354db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2355db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // TODO(mmentovai): possibly support other struct types in place of
2356db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
2357db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // a different structure that better represents versioning facilities on
2358db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // Mac OS X and Linux, instead of forcing them to adhere to the dotted
2359db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // quad of 16-bit ints that Windows uses.
2360db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2361af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
2362af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "version for " << *name_;
2363af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2364db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return version;
2365db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2366db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2367db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2368db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModule* MinidumpModule::Copy() const {
2369db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModule(this);
2370db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2371db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2372db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
23736162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
2374af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2375af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
23763261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2377af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
23783261e8b6eac44a41341f112821482bee6c940c98mmentovai
23793261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!cv_record_) {
238048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // This just guards against 0-sized CodeView records; more specific checks
238148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // are used when the signature is checked against various structure types.
2382af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.cv_record.data_size == 0) {
23833261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2384af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
23853261e8b6eac44a41341f112821482bee6c940c98mmentovai
2386af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.cv_record.rva)) {
2387af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
23883261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2389af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
23903261e8b6eac44a41341f112821482bee6c940c98mmentovai
2391e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.cv_record.data_size > max_cv_bytes_) {
2392e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
2393e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.cv_record.data_size << " exceeds maximum " <<
2394e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_cv_bytes_;
2395e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2396e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
23973261e8b6eac44a41341f112821482bee6c940c98mmentovai
23983261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDCVInfoPDB70 or
23996162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment
24003261e8b6eac44a41341f112821482bee6c940c98mmentovai    // problems.  x86 and ppc are able to cope, though.  This allocation
24013261e8b6eac44a41341f112821482bee6c940c98mmentovai    // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
24023261e8b6eac44a41341f112821482bee6c940c98mmentovai    // variable-sized due to their pdb_file_name fields; these structures
24032e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
24043261e8b6eac44a41341f112821482bee6c940c98mmentovai    // them as such would result in incomplete structures or overruns.
24056162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > cv_record(
24066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.cv_record.data_size));
24073261e8b6eac44a41341f112821482bee6c940c98mmentovai
2408af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
2409af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
24103261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2411af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
24123261e8b6eac44a41341f112821482bee6c940c98mmentovai
24136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
241448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (module_.cv_record.data_size > sizeof(signature)) {
241548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      MDCVInfoPDB70* cv_record_signature =
241648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
241748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      signature = cv_record_signature->cv_signature;
241848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      if (minidump_->swap())
241948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        Swap(&signature);
242048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    }
24213261e8b6eac44a41341f112821482bee6c940c98mmentovai
24223261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature == MD_CVINFOPDB70_SIGNATURE) {
24233261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Now that the structure type is known, recheck the size.
24242e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
2425af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
24262e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB70_minsize << " > " <<
2427af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
24283261e8b6eac44a41341f112821482bee6c940c98mmentovai        return NULL;
2429af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
24303261e8b6eac44a41341f112821482bee6c940c98mmentovai
24313261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
243248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        MDCVInfoPDB70* cv_record_70 =
243348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
24343261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->cv_signature);
24353261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->signature);
24363261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_70->age);
24373261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
243848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        // quantities.  (It's a path, is it UTF-8?)
24393261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
244048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
244148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
244248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2443af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2444af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
2445af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
244648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2447af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
24483261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
244948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // Now that the structure type is known, recheck the size.
24502e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai      if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
2451af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
24522e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                        MDCVInfoPDB20_minsize << " > " <<
2453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_.cv_record.data_size;
245448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2455af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
24563261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (minidump_->swap()) {
24573261e8b6eac44a41341f112821482bee6c940c98mmentovai        MDCVInfoPDB20* cv_record_20 =
245848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai            reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
24593261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.signature);
24603261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->cv_header.offset);
24613261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->signature);
24623261e8b6eac44a41341f112821482bee6c940c98mmentovai        Swap(&cv_record_20->age);
24633261e8b6eac44a41341f112821482bee6c940c98mmentovai        // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
24643261e8b6eac44a41341f112821482bee6c940c98mmentovai        // quantities.  (It's a path, is it UTF-8?)
24653261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
246648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
246748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // The last field of either structure is null-terminated 8-bit character
246848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      // data.  Ensure that it's null-terminated.
2469af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
2470af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
2471af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "0-terminated";
247248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        return NULL;
2473af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
24743261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
24753261e8b6eac44a41341f112821482bee6c940c98mmentovai
247648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // If the signature doesn't match something above, it's not something
2477e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    // that Breakpad can presently handle directly.  Because some modules in
247848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
247948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // don't bail out here - allow the data to be returned to the user,
248048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    // although byte-swapping can't be done.
24813261e8b6eac44a41341f112821482bee6c940c98mmentovai
24823261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
24836162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // return it casted to uint8_t*.
24843261e8b6eac44a41341f112821482bee6c940c98mmentovai    cv_record_ = cv_record.release();
248548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    cv_record_signature_ = signature;
24863261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
24873261e8b6eac44a41341f112821482bee6c940c98mmentovai
248848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
248948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.cv_record.data_size;
249048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
24913261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*cv_record_)[0];
24923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
24933261e8b6eac44a41341f112821482bee6c940c98mmentovai
24943261e8b6eac44a41341f112821482bee6c940c98mmentovai
24956162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) {
2496af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!module_valid_) {
2497af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
24983261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2499af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25003261e8b6eac44a41341f112821482bee6c940c98mmentovai
25013261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!misc_record_) {
2502af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size == 0) {
25033261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2504af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25053261e8b6eac44a41341f112821482bee6c940c98mmentovai
25062e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
2507af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
25082e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                      "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
2509af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      module_.misc_record.data_size;
25103261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2511af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
2512af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2513af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(module_.misc_record.rva)) {
2514af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
2515af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "debugging record";
2516af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      return NULL;
2517af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25183261e8b6eac44a41341f112821482bee6c940c98mmentovai
2519e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    if (module_.misc_record.data_size > max_misc_bytes_) {
2520e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
2521e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      module_.misc_record.data_size << " exceeds maximum " <<
2522e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      max_misc_bytes_;
2523e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      return NULL;
2524e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    }
25253261e8b6eac44a41341f112821482bee6c940c98mmentovai
25263261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Allocating something that will be accessed as MDImageDebugMisc but
25276162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    // is allocated as uint8_t[] can cause alignment problems.  x86 and
25283261e8b6eac44a41341f112821482bee6c940c98mmentovai    // ppc are able to cope, though.  This allocation style is needed
25293261e8b6eac44a41341f112821482bee6c940c98mmentovai    // because the MDImageDebugMisc is variable-sized due to its data field;
25302e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai    // this structure is not MDImageDebugMisc_minsize and treating it as such
25313261e8b6eac44a41341f112821482bee6c940c98mmentovai    // would result in an incomplete structure or an overrun.
25326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    scoped_ptr< vector<uint8_t> > misc_record_mem(
25336162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        new vector<uint8_t>(module_.misc_record.data_size));
25343261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDImageDebugMisc* misc_record =
25353261e8b6eac44a41341f112821482bee6c940c98mmentovai        reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
25363261e8b6eac44a41341f112821482bee6c940c98mmentovai
2537af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
2538af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
2539af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "record";
25403261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2541af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25423261e8b6eac44a41341f112821482bee6c940c98mmentovai
25433261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (minidump_->swap()) {
25443261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->data_type);
25453261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_record->length);
25463261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap misc_record.unicode because it's an 8-bit quantity.
25473261e8b6eac44a41341f112821482bee6c940c98mmentovai      // Don't swap the reserved fields for the same reason, and because
25483261e8b6eac44a41341f112821482bee6c940c98mmentovai      // they don't contain any valid data.
25493261e8b6eac44a41341f112821482bee6c940c98mmentovai      if (misc_record->unicode) {
25503261e8b6eac44a41341f112821482bee6c940c98mmentovai        // There is a potential alignment problem, but shouldn't be a problem
25513261e8b6eac44a41341f112821482bee6c940c98mmentovai        // in practice due to the layout of MDImageDebugMisc.
25526162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com        uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data));
25533261e8b6eac44a41341f112821482bee6c940c98mmentovai        unsigned int dataBytes = module_.misc_record.data_size -
25542e0e2234b9e9d7d82c4c3c20396bdf8f18007e6cmmentovai                                 MDImageDebugMisc_minsize;
25553562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com        Swap(data16, dataBytes);
25563261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
25573261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
25583261e8b6eac44a41341f112821482bee6c940c98mmentovai
2559af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (module_.misc_record.data_size != misc_record->length) {
2560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
2561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      "size mismatch, " << module_.misc_record.data_size <<
2562af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      " != " << misc_record->length;
25633261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
2564af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
25653261e8b6eac44a41341f112821482bee6c940c98mmentovai
25663261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Store the vector type because that's how storage was allocated, but
25673261e8b6eac44a41341f112821482bee6c940c98mmentovai    // return it casted to MDImageDebugMisc*.
25683261e8b6eac44a41341f112821482bee6c940c98mmentovai    misc_record_ = misc_record_mem.release();
25693261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
25703261e8b6eac44a41341f112821482bee6c940c98mmentovai
257148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  if (size)
257248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    *size = module_.misc_record.data_size;
257348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
25743261e8b6eac44a41341f112821482bee6c940c98mmentovai  return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
25753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
25763261e8b6eac44a41341f112821482bee6c940c98mmentovai
25773261e8b6eac44a41341f112821482bee6c940c98mmentovai
25783261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModule::Print() {
2579af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2580af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
25813261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2582af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
25833261e8b6eac44a41341f112821482bee6c940c98mmentovai
25843261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawModule\n");
2585c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  base_of_image                   = 0x%" PRIx64 "\n",
25863261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.base_of_image);
25873261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_image                   = 0x%x\n",
25883261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.size_of_image);
25893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum                        = 0x%x\n",
25903261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.checksum);
25913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp                 = 0x%x\n",
25923261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.time_date_stamp);
25933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_name_rva                 = 0x%x\n",
25943261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.module_name_rva);
25953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.signature          = 0x%x\n",
25963261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.signature);
25973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.struct_version     = 0x%x\n",
25983261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.struct_version);
25993261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_version       = 0x%x:0x%x\n",
26003261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_hi,
26013261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_version_lo);
26023261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.product_version    = 0x%x:0x%x\n",
26033261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_hi,
26043261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.product_version_lo);
26053261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags_mask    = 0x%x\n",
26063261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags_mask);
26073261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_flags         = 0x%x\n",
26083261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_flags);
26093261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_os            = 0x%x\n",
26103261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_os);
26113261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_type          = 0x%x\n",
26123261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_type);
26133261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_subtype       = 0x%x\n",
26143261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_subtype);
26153261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version_info.file_date          = 0x%x:0x%x\n",
26163261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_hi,
26173261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.version_info.file_date_lo);
26183261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.data_size             = %d\n",
26193261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.data_size);
26203261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cv_record.rva                   = 0x%x\n",
26213261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.cv_record.rva);
26223261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.data_size           = %d\n",
26233261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.data_size);
26243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  misc_record.rva                 = 0x%x\n",
26253261e8b6eac44a41341f112821482bee6c940c98mmentovai         module_.misc_record.rva);
26263261e8b6eac44a41341f112821482bee6c940c98mmentovai
2627db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
2628db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (code_identifier)               = \"%s\"\n",
2629db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         code_identifier().c_str());
26303261e8b6eac44a41341f112821482bee6c940c98mmentovai
26316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t cv_record_size;
26326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint8_t *cv_record = GetCVRecord(&cv_record_size);
26333261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (cv_record) {
263448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
263548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      const MDCVInfoPDB70* cv_record_70 =
263648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
263748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
263848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
26393261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_signature        = 0x%x\n",
264048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->cv_signature);
26413261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
264248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data1,
264348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data2,
264448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data3,
264548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[0],
264648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->signature.data4[1]);
26473261e8b6eac44a41341f112821482bee6c940c98mmentovai      for (unsigned int guidIndex = 2;
26483261e8b6eac44a41341f112821482bee6c940c98mmentovai           guidIndex < 8;
26493261e8b6eac44a41341f112821482bee6c940c98mmentovai           ++guidIndex) {
265048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record_70->signature.data4[guidIndex]);
26513261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
26523261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("\n");
26533261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
265448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->age);
26553261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
265648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai             cv_record_70->pdb_file_name);
265748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
26583261e8b6eac44a41341f112821482bee6c940c98mmentovai      const MDCVInfoPDB20* cv_record_20 =
265948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai          reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
266048dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
266148dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai
26623261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.signature = 0x%x\n",
26633261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.signature);
26643261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).cv_header.offset    = 0x%x\n",
26653261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->cv_header.offset);
26663261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).signature           = 0x%x\n",
26673261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->signature);
26683261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).age                 = %d\n",
26693261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->age);
26703261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (cv_record).pdb_file_name       = \"%s\"\n",
26713261e8b6eac44a41341f112821482bee6c940c98mmentovai             cv_record_20->pdb_file_name);
267248dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai    } else {
267348dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("  (cv_record)                     = ");
267448dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      for (unsigned int cv_byte_index = 0;
267548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           cv_byte_index < cv_record_size;
267648dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai           ++cv_byte_index) {
267748dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai        printf("%02x", cv_record[cv_byte_index]);
267848dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      }
267948dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai      printf("\n");
26803261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
26813261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
26823261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (cv_record)                     = (null)\n");
26833261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
26843261e8b6eac44a41341f112821482bee6c940c98mmentovai
268548dab62c2df1621db0e5b57f400e1fc38c1b37eemmentovai  const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
26863261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_record) {
26873261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).data_type         = 0x%x\n",
26883261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->data_type);
26893261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).length            = 0x%x\n",
26903261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->length);
26913261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record).unicode           = %d\n",
26923261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_record->unicode);
26933261e8b6eac44a41341f112821482bee6c940c98mmentovai    // Don't bother printing the UTF-16, we don't really even expect to ever
26943261e8b6eac44a41341f112821482bee6c940c98mmentovai    // see this misc_record anyway.
26953261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_record->unicode)
26963261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = \"%s\"\n",
26973261e8b6eac44a41341f112821482bee6c940c98mmentovai             misc_record->data);
26983261e8b6eac44a41341f112821482bee6c940c98mmentovai    else
26993261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("  (misc_record).data              = (UTF-16)\n");
27003261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
27013261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (misc_record)                   = (null)\n");
27023261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
27033261e8b6eac44a41341f112821482bee6c940c98mmentovai
2704db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
2705db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (debug_identifier)              = \"%s\"\n",
2706db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         debug_identifier().c_str());
2707db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  printf("  (version)                       = \"%s\"\n", version().c_str());
27083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
27093261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27103261e8b6eac44a41341f112821482bee6c940c98mmentovai
27113261e8b6eac44a41341f112821482bee6c940c98mmentovai
27123261e8b6eac44a41341f112821482bee6c940c98mmentovai//
27133261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpModuleList
27143261e8b6eac44a41341f112821482bee6c940c98mmentovai//
27153261e8b6eac44a41341f112821482bee6c940c98mmentovai
27163261e8b6eac44a41341f112821482bee6c940c98mmentovai
27176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpModuleList::max_modules_ = 1024;
2718e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2719e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
27203261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::MinidumpModuleList(Minidump* minidump)
272153d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
27226162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
272353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      modules_(NULL),
272453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      module_count_(0) {
27253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27263261e8b6eac44a41341f112821482bee6c940c98mmentovai
27273261e8b6eac44a41341f112821482bee6c940c98mmentovai
27283261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList::~MinidumpModuleList() {
2729fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
27303261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
27313261e8b6eac44a41341f112821482bee6c940c98mmentovai}
27323261e8b6eac44a41341f112821482bee6c940c98mmentovai
27333261e8b6eac44a41341f112821482bee6c940c98mmentovai
27346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpModuleList::Read(uint32_t expected_size) {
27353261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
2736fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
27373261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete modules_;
27383261e8b6eac44a41341f112821482bee6c940c98mmentovai  modules_ = NULL;
27393261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = 0;
27403261e8b6eac44a41341f112821482bee6c940c98mmentovai
27413261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
27423261e8b6eac44a41341f112821482bee6c940c98mmentovai
27436162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t module_count;
2744af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(module_count)) {
2745af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
2746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(module_count);
27473261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2748af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
2750af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList could not read module count";
27513261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2752af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
27533261e8b6eac44a41341f112821482bee6c940c98mmentovai
27543261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
27553261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&module_count);
27563261e8b6eac44a41341f112821482bee6c940c98mmentovai
27576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) {
2758fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
2759fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
2760fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
2761fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
2762fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
27633261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(module_count) +
27643261e8b6eac44a41341f112821482bee6c940c98mmentovai                       module_count * MD_MODULE_SIZE) {
2765ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
2766ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(module_count) + 4 +
2767ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         module_count * MD_MODULE_SIZE) {
27686162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
2769ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
2770f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded "
2771f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
2772ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
2773ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
2774ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
2775ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
2776ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      " != " << sizeof(module_count) +
2777ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      module_count * MD_MODULE_SIZE;
2778ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
2779ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
27803261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
27813261e8b6eac44a41341f112821482bee6c940c98mmentovai
2782e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count > max_modules_) {
2783e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
2784e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_modules_;
2785e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
2786e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
2787e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2788e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (module_count != 0) {
2789373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpModules> modules(
2790373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpModules(module_count, MinidumpModule(minidump_)));
27913261e8b6eac44a41341f112821482bee6c940c98mmentovai
2792373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int module_index = 0;
2793373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         module_index < module_count;
2794373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++module_index) {
2795373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MinidumpModule* module = &(*modules)[module_index];
27963261e8b6eac44a41341f112821482bee6c940c98mmentovai
2797373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Assume that the file offset is correct after the last read.
2798af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!module->Read()) {
2799af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
2800af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count;
2801373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2802af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2803db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    }
2804db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2805db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // Loop through the module list once more to read additional data and
2806db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // build the range map.  This is done in a second pass because
2807db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
2808db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // included in the loop above, additional seeks would be needed where
2809db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    // none are now to read contiguous data.
2810db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    for (unsigned int module_index = 0;
2811db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         module_index < module_count;
2812db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai         ++module_index) {
2813db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      MinidumpModule* module = &(*modules)[module_index];
2814db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
281561ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // ReadAuxiliaryData fails if any data that the module indicates should
281661ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // exist is missing, but we treat some such cases as valid anyway.  See
281761ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // issue #222: if a debugging record is of a format that's too large to
281861ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // handle, it shouldn't render the entire dump invalid.  Check module
281961ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // validity before giving up.
282061ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      if (!module->ReadAuxiliaryData() && !module->valid()) {
282161ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        BPLOG(ERROR) << "MinidumpModuleList could not read required module "
282261ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        "auxiliary data for module " <<
282361ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai                        module_index << "/" << module_count;
282461ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai        return false;
2825af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2826af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2827af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      // It is safe to use module->code_file() after successfully calling
282861ea8bf0d5c2cf652e8d75605f770d0f9733acfemmentovai      // module->ReadAuxiliaryData or noting that the module is valid.
28293261e8b6eac44a41341f112821482bee6c940c98mmentovai
28306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = module->base_address();
28316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t module_size = module->size();
28326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      if (base_address == static_cast<uint64_t>(-1)) {
2833af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList found bad base address "
2834af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        "for module " << module_index << "/" << module_count <<
2835af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << module->code_file();
2836373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2837af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
28383261e8b6eac44a41341f112821482bee6c940c98mmentovai
2839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, module_size, module_index)) {
2840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
2841af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module_index << "/" << module_count << ", " <<
2842af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        module->code_file() << ", " <<
2843af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
2844af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(module_size);
2845373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
2846af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
2847373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
2848373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
2849373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    modules_ = modules.release();
28503261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
28513261e8b6eac44a41341f112821482bee6c940c98mmentovai
28523261e8b6eac44a41341f112821482bee6c940c98mmentovai  module_count_ = module_count;
28533261e8b6eac44a41341f112821482bee6c940c98mmentovai
28543261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
28553261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
28563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28573261e8b6eac44a41341f112821482bee6c940c98mmentovai
28583261e8b6eac44a41341f112821482bee6c940c98mmentovai
2859db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleForAddress(
28606162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
2861af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2862af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
28633261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2864af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28653261e8b6eac44a41341f112821482bee6c940c98mmentovai
2866db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  unsigned int module_index;
2867af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
2868af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpModuleList has no module at " <<
2869af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
2870db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2871af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2872db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2873db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return GetModuleAtIndex(module_index);
28743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
28753261e8b6eac44a41341f112821482bee6c940c98mmentovai
28763261e8b6eac44a41341f112821482bee6c940c98mmentovai
2877db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetMainModule() const {
2878af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2879af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
28803261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2881af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
28823261e8b6eac44a41341f112821482bee6c940c98mmentovai
2883db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // The main code module is the first one present in a minidump file's
2884db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  // MDRawModuleList.
2885327783c42fcc2062bfe6c118c54c431ac6b5ffcfmkrebs@chromium.org  return GetModuleAtIndex(0);
2886db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2887db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2888db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2889db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
2890db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int sequence) const {
2891af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2892af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
2893af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2894af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2895af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2896af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (sequence >= module_count_) {
2897af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
2898af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    sequence << "/" << module_count_;
2899db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2900af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2901db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
29023261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int module_index;
2903af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
2904af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
29053261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
2906af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29073261e8b6eac44a41341f112821482bee6c940c98mmentovai
29083261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetModuleAtIndex(module_index);
29093261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29103261e8b6eac44a41341f112821482bee6c940c98mmentovai
29113261e8b6eac44a41341f112821482bee6c940c98mmentovai
2912db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
2913db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    unsigned int index) const {
2914af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2915af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
2916af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
2917af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2918af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
2919af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= module_count_) {
2920af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
2921af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << module_count_;
2922db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai    return NULL;
2923af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2924db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2925db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return &(*modules_)[index];
2926db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2927db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2928db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2929db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovaiconst CodeModules* MinidumpModuleList::Copy() const {
2930db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  return new BasicCodeModules(this);
2931db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai}
2932db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
2933db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
29343261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpModuleList::Print() {
2935af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
2936af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
29373261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
2938af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29393261e8b6eac44a41341f112821482bee6c940c98mmentovai
29403261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpModuleList\n");
29413261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  module_count = %d\n", module_count_);
29423261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
29433261e8b6eac44a41341f112821482bee6c940c98mmentovai
29443261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int module_index = 0;
29453261e8b6eac44a41341f112821482bee6c940c98mmentovai       module_index < module_count_;
29463261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++module_index) {
29473261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("module[%d]\n", module_index);
29483261e8b6eac44a41341f112821482bee6c940c98mmentovai
29493261e8b6eac44a41341f112821482bee6c940c98mmentovai    (*modules_)[module_index].Print();
29503261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
29513261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29523261e8b6eac44a41341f112821482bee6c940c98mmentovai
29533261e8b6eac44a41341f112821482bee6c940c98mmentovai
29543261e8b6eac44a41341f112821482bee6c940c98mmentovai//
29553261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMemoryList
29563261e8b6eac44a41341f112821482bee6c940c98mmentovai//
29573261e8b6eac44a41341f112821482bee6c940c98mmentovai
29583261e8b6eac44a41341f112821482bee6c940c98mmentovai
29596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t MinidumpMemoryList::max_regions_ = 4096;
2960e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
2961e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
29623261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
296353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
29646162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
296553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      descriptors_(NULL),
296653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      regions_(NULL),
296753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      region_count_(0) {
29683261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29693261e8b6eac44a41341f112821482bee6c940c98mmentovai
29703261e8b6eac44a41341f112821482bee6c940c98mmentovai
29713261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList::~MinidumpMemoryList() {
2972fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  delete range_map_;
29733261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
29743261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
29753261e8b6eac44a41341f112821482bee6c940c98mmentovai}
29763261e8b6eac44a41341f112821482bee6c940c98mmentovai
29773261e8b6eac44a41341f112821482bee6c940c98mmentovai
29786162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryList::Read(uint32_t expected_size) {
29793261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
29803261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete descriptors_;
29813261e8b6eac44a41341f112821482bee6c940c98mmentovai  descriptors_ = NULL;
29823261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete regions_;
29833261e8b6eac44a41341f112821482bee6c940c98mmentovai  regions_ = NULL;
2984fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai  range_map_->Clear();
29853261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = 0;
29863261e8b6eac44a41341f112821482bee6c940c98mmentovai
29873261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
29883261e8b6eac44a41341f112821482bee6c940c98mmentovai
29896162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t region_count;
2990af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size < sizeof(region_count)) {
2991af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
2992af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    expected_size << " < " << sizeof(region_count);
29933261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2994af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
2995af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
2996af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
29973261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
2998af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
29993261e8b6eac44a41341f112821482bee6c940c98mmentovai
30003261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap())
30013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&region_count);
30023261e8b6eac44a41341f112821482bee6c940c98mmentovai
3003fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  if (region_count >
30046162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) {
3005fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
3006fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                    " would cause multiplication overflow";
3007fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai    return false;
3008fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai  }
3009fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai
30103261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != sizeof(region_count) +
30113261e8b6eac44a41341f112821482bee6c940c98mmentovai                       region_count * sizeof(MDMemoryDescriptor)) {
3012ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    // may be padded with 4 bytes on 64bit ABIs for alignment
3013ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    if (expected_size == sizeof(region_count) + 4 +
3014ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                         region_count * sizeof(MDMemoryDescriptor)) {
30156162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t useless;
3016ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      if (!minidump_->ReadBytes(&useless, 4)) {
3017f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded "
3018f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                        "bytes";
3019ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai        return false;
3020ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      }
3021ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    } else {
3022ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
3023f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                      " != " << sizeof(region_count) +
3024ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                      region_count * sizeof(MDMemoryDescriptor);
3025ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      return false;
3026ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    }
30273261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30283261e8b6eac44a41341f112821482bee6c940c98mmentovai
3029e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count > max_regions_) {
3030e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
3031e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_regions_;
3032e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
3033e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
3034e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
3035e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (region_count != 0) {
3036373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryDescriptors> descriptors(
3037373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryDescriptors(region_count));
30383261e8b6eac44a41341f112821482bee6c940c98mmentovai
3039373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
3040373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
3041373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!minidump_->ReadBytes(&(*descriptors)[0],
3042373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai                              sizeof(MDMemoryDescriptor) * region_count)) {
3043af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
3044373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
3045373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
30463261e8b6eac44a41341f112821482bee6c940c98mmentovai
3047373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MemoryRegions> regions(
3048373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
30493261e8b6eac44a41341f112821482bee6c940c98mmentovai
3050373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int region_index = 0;
3051373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         region_index < region_count;
3052373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++region_index) {
3053373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
30543261e8b6eac44a41341f112821482bee6c940c98mmentovai
3055373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (minidump_->swap())
3056373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(descriptor);
30573261e8b6eac44a41341f112821482bee6c940c98mmentovai
30586162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = descriptor->start_of_memory_range;
30596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint32_t region_size = descriptor->memory.data_size;
30603261e8b6eac44a41341f112821482bee6c940c98mmentovai
3061fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      // Check for base + size overflow or undersize.
3062fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai      if (region_size == 0 ||
30636162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          region_size > numeric_limits<uint64_t>::max() - base_address) {
3064af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
3065af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        " region " << region_index << "/" << region_count <<
3066af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        ", " << HexString(base_address) << "+" <<
3067fabb8714a75b9e857bd216ac49b55a15656d7b8emmentovai                        HexString(region_size);
3068373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3069af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
30703261e8b6eac44a41341f112821482bee6c940c98mmentovai
3071af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      if (!range_map_->StoreRange(base_address, region_size, region_index)) {
3072af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai        BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
3073af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        region_index << "/" << region_count << ", " <<
3074af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(base_address) << "+" <<
3075af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                        HexString(region_size);
3076373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        return false;
3077af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      }
3078373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai
3079373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      (*regions)[region_index].SetDescriptor(descriptor);
3080373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
30813261e8b6eac44a41341f112821482bee6c940c98mmentovai
3082373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    descriptors_ = descriptors.release();
3083373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    regions_ = regions.release();
30843261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
30853261e8b6eac44a41341f112821482bee6c940c98mmentovai
30863261e8b6eac44a41341f112821482bee6c940c98mmentovai  region_count_ = region_count;
30873261e8b6eac44a41341f112821482bee6c940c98mmentovai
30883261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
30893261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
30903261e8b6eac44a41341f112821482bee6c940c98mmentovai}
30913261e8b6eac44a41341f112821482bee6c940c98mmentovai
30923261e8b6eac44a41341f112821482bee6c940c98mmentovai
30933261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
30943261e8b6eac44a41341f112821482bee6c940c98mmentovai      unsigned int index) {
3095af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3096af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
3097af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
3098af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3099af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3100af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= region_count_) {
3101af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
3102af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << region_count_;
31033261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3104af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31053261e8b6eac44a41341f112821482bee6c940c98mmentovai
31063261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*regions_)[index];
31073261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31083261e8b6eac44a41341f112821482bee6c940c98mmentovai
31093261e8b6eac44a41341f112821482bee6c940c98mmentovai
31103261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
31116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) {
3112af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3113af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
31143261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3115af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31163261e8b6eac44a41341f112821482bee6c940c98mmentovai
31173261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int region_index;
3118af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
3119af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
3120af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   HexString(address);
31213261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3122af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31233261e8b6eac44a41341f112821482bee6c940c98mmentovai
31243261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetMemoryRegionAtIndex(region_index);
31253261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31263261e8b6eac44a41341f112821482bee6c940c98mmentovai
31273261e8b6eac44a41341f112821482bee6c940c98mmentovai
31283261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMemoryList::Print() {
3129af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3130af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
31313261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3132af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31333261e8b6eac44a41341f112821482bee6c940c98mmentovai
31343261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MinidumpMemoryList\n");
31353261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  region_count = %d\n", region_count_);
31363261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
31373261e8b6eac44a41341f112821482bee6c940c98mmentovai
31383261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int region_index = 0;
31393261e8b6eac44a41341f112821482bee6c940c98mmentovai       region_index < region_count_;
31403261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++region_index) {
31413261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
31423261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("region[%d]\n", region_index);
31433261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDMemoryDescriptor\n");
3144c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  start_of_memory_range = 0x%" PRIx64 "\n",
31453261e8b6eac44a41341f112821482bee6c940c98mmentovai           descriptor->start_of_memory_range);
31463261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
31473261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
31483261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
31493261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (region) {
31503261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("Memory\n");
31513261e8b6eac44a41341f112821482bee6c940c98mmentovai      region->Print();
31523261e8b6eac44a41341f112821482bee6c940c98mmentovai    } else {
31533261e8b6eac44a41341f112821482bee6c940c98mmentovai      printf("No memory\n");
31543261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
31553261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
31563261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
31573261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31583261e8b6eac44a41341f112821482bee6c940c98mmentovai
31593261e8b6eac44a41341f112821482bee6c940c98mmentovai
31603261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31613261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpException
31623261e8b6eac44a41341f112821482bee6c940c98mmentovai//
31633261e8b6eac44a41341f112821482bee6c940c98mmentovai
31643261e8b6eac44a41341f112821482bee6c940c98mmentovai
31653261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::MinidumpException(Minidump* minidump)
316653d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
316753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      exception_(),
316853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      context_(NULL) {
31693261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31703261e8b6eac44a41341f112821482bee6c940c98mmentovai
31713261e8b6eac44a41341f112821482bee6c940c98mmentovai
31723261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException::~MinidumpException() {
31733261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
31743261e8b6eac44a41341f112821482bee6c940c98mmentovai}
31753261e8b6eac44a41341f112821482bee6c940c98mmentovai
31763261e8b6eac44a41341f112821482bee6c940c98mmentovai
31776162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::Read(uint32_t expected_size) {
31783261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
31793261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete context_;
31803261e8b6eac44a41341f112821482bee6c940c98mmentovai  context_ = NULL;
31813261e8b6eac44a41341f112821482bee6c940c98mmentovai
31823261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
31833261e8b6eac44a41341f112821482bee6c940c98mmentovai
3184af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(exception_)) {
3185af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
3186af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(exception_);
31873261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3188af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31893261e8b6eac44a41341f112821482bee6c940c98mmentovai
3190af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
3191af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot read exception";
31923261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3193af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
31943261e8b6eac44a41341f112821482bee6c940c98mmentovai
31953261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
31963261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_id);
31973261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.__align is for alignment only and does not need to be
31983261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapped.
31993261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_code);
32003261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_flags);
32013261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_record);
32023261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.exception_address);
32033261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.exception_record.number_parameters);
32043261e8b6eac44a41341f112821482bee6c940c98mmentovai    // exception_.exception_record.__align is for alignment only and does not
32053261e8b6eac44a41341f112821482bee6c940c98mmentovai    // need to be swapped.
32063261e8b6eac44a41341f112821482bee6c940c98mmentovai    for (unsigned int parameter_index = 0;
32073261e8b6eac44a41341f112821482bee6c940c98mmentovai         parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
32083261e8b6eac44a41341f112821482bee6c940c98mmentovai         ++parameter_index) {
32093261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&exception_.exception_record.exception_information[parameter_index]);
32103261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
32113261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&exception_.thread_context);
32123261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32133261e8b6eac44a41341f112821482bee6c940c98mmentovai
32143261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
32153261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
32163261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32173261e8b6eac44a41341f112821482bee6c940c98mmentovai
32183261e8b6eac44a41341f112821482bee6c940c98mmentovai
32196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpException::GetThreadID(uint32_t *thread_id) const {
3220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
3221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "|thread_id|";
3222af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3223af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3224af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3225af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3226af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
322776f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3228af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
322976f052f8fbf8864dee5992b857229d06560a766ammentovai
323076f052f8fbf8864dee5992b857229d06560a766ammentovai  *thread_id = exception_.thread_id;
323176f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
32323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32333261e8b6eac44a41341f112821482bee6c940c98mmentovai
32343261e8b6eac44a41341f112821482bee6c940c98mmentovai
32353261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpContext* MinidumpException::GetContext() {
3236af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3237af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
32383261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3239af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32403261e8b6eac44a41341f112821482bee6c940c98mmentovai
32413261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!context_) {
3242af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!minidump_->SeekSet(exception_.thread_context.rva)) {
3243af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpException cannot seek to context";
32443261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
3245af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
32463261e8b6eac44a41341f112821482bee6c940c98mmentovai
32472466d8e993a800a17e00deda2f3a27e0505140e1mmentovai    scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
32483261e8b6eac44a41341f112821482bee6c940c98mmentovai
32499276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // Don't log as an error if we can still fall back on the thread's context
32509276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    // (which must be possible if we got this far.)
3251af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    if (!context->Read(exception_.thread_context.data_size)) {
32525f4fa55598baf92785223debe7d3787c6b29cf3ejschuh@chromium.org      BPLOG(INFO) << "MinidumpException cannot read context";
32533261e8b6eac44a41341f112821482bee6c940c98mmentovai      return NULL;
3254af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
32553261e8b6eac44a41341f112821482bee6c940c98mmentovai
32563261e8b6eac44a41341f112821482bee6c940c98mmentovai    context_ = context.release();
32573261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32583261e8b6eac44a41341f112821482bee6c940c98mmentovai
32593261e8b6eac44a41341f112821482bee6c940c98mmentovai  return context_;
32603261e8b6eac44a41341f112821482bee6c940c98mmentovai}
32613261e8b6eac44a41341f112821482bee6c940c98mmentovai
32623261e8b6eac44a41341f112821482bee6c940c98mmentovai
32633261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpException::Print() {
3264af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3265af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpException cannot print invalid data";
32663261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3267af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
32683261e8b6eac44a41341f112821482bee6c940c98mmentovai
32693261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDException\n");
32703261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_id                                  = 0x%x\n",
32713261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_id);
32723261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_code            = 0x%x\n",
32733261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_code);
32743261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.exception_flags           = 0x%x\n",
32753261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_flags);
3276c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
32773261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_record);
3278c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
32793261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.exception_address);
32803261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  exception_record.number_parameters         = %d\n",
32813261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.exception_record.number_parameters);
32823261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int parameterIndex = 0;
32833261e8b6eac44a41341f112821482bee6c940c98mmentovai       parameterIndex < exception_.exception_record.number_parameters;
32843261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++parameterIndex) {
3285c27cf3e3959189f78fe2de40405987c3f33488cemmentovai    printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
32863261e8b6eac44a41341f112821482bee6c940c98mmentovai           parameterIndex,
32873261e8b6eac44a41341f112821482bee6c940c98mmentovai           exception_.exception_record.exception_information[parameterIndex]);
32883261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
32893261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.data_size                   = %d\n",
32903261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.data_size);
32913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  thread_context.rva                         = 0x%x\n",
32923261e8b6eac44a41341f112821482bee6c940c98mmentovai         exception_.thread_context.rva);
32933261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpContext* context = GetContext();
32943261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (context) {
32953261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
32963261e8b6eac44a41341f112821482bee6c940c98mmentovai    context->Print();
32973261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
32983261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (no context)\n");
32993261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
33003261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
33013261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33023261e8b6eac44a41341f112821482bee6c940c98mmentovai
33030314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
33040314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek// MinidumpAssertion
33050314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek//
33060314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33070314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33080314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::MinidumpAssertion(Minidump* minidump)
33090314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    : MinidumpStream(minidump),
33100314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      assertion_(),
33110314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      expression_(),
33120314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      function_(),
33130314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek      file_() {
33140314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
33150314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33160314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33170314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion::~MinidumpAssertion() {
33180314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
33190314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33200314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33216162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpAssertion::Read(uint32_t expected_size) {
33220314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Invalidate cached data.
33230314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = false;
33240314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33250314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (expected_size != sizeof(assertion_)) {
33260314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
33270314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek                    " != " << sizeof(assertion_);
33280314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
33290314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
33300314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33310314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
33320314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
33330314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return false;
33340314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
33350314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33360314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // Each of {expression, function, file} is a UTF-16 string,
33370314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  // we'll convert them to UTF-8 for ease of use.
33383562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.expression,
33393562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.expression), &expression_,
33403562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
33413562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.function,
33423562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 sizeof(assertion_.function), &function_,
33433562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 minidump_->swap());
33443562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file),
33453562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                 &file_, minidump_->swap());
33460314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33470314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (minidump_->swap()) {
33480314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.line);
33490314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    Swap(&assertion_.type);
33500314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
33510314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33520314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  valid_ = true;
33530314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return true;
33540314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
33550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekvoid MinidumpAssertion::Print() {
33570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  if (!valid_) {
33580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
33590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek    return;
33600314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  }
33610314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
33620314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("MDAssertion\n");
33630314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  expression                                 = %s\n",
33640314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         expression_.c_str());
33650314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  function                                   = %s\n",
33660314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         function_.c_str());
33670314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  file                                       = %s\n",
33680314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         file_.c_str());
33690314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  line                                       = %u\n",
33700314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.line);
33710314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("  type                                       = %u\n",
33720314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek         assertion_.type);
33730314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  printf("\n");
33740314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
33753261e8b6eac44a41341f112821482bee6c940c98mmentovai
33763261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33773261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpSystemInfo
33783261e8b6eac44a41341f112821482bee6c940c98mmentovai//
33793261e8b6eac44a41341f112821482bee6c940c98mmentovai
33803261e8b6eac44a41341f112821482bee6c940c98mmentovai
33813261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
338253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
338353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      system_info_(),
3384e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      csd_version_(NULL),
3385e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      cpu_vendor_(NULL) {
33863261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33873261e8b6eac44a41341f112821482bee6c940c98mmentovai
33883261e8b6eac44a41341f112821482bee6c940c98mmentovai
33893261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo::~MinidumpSystemInfo() {
33903261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
3391e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
33923261e8b6eac44a41341f112821482bee6c940c98mmentovai}
33933261e8b6eac44a41341f112821482bee6c940c98mmentovai
33943261e8b6eac44a41341f112821482bee6c940c98mmentovai
33956162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpSystemInfo::Read(uint32_t expected_size) {
33963261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
33973261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete csd_version_;
33983261e8b6eac44a41341f112821482bee6c940c98mmentovai  csd_version_ = NULL;
3399e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  delete cpu_vendor_;
3400e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  cpu_vendor_ = NULL;
34013261e8b6eac44a41341f112821482bee6c940c98mmentovai
34023261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
34033261e8b6eac44a41341f112821482bee6c940c98mmentovai
3404af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(system_info_)) {
3405af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
3406af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(system_info_);
34073261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3408af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34093261e8b6eac44a41341f112821482bee6c940c98mmentovai
3410af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
3411af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
34123261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3413af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
34143261e8b6eac44a41341f112821482bee6c940c98mmentovai
34153261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
34163261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_architecture);
34173261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_level);
34183261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.processor_revision);
34193261e8b6eac44a41341f112821482bee6c940c98mmentovai    // number_of_processors and product_type are 8-bit quantities and need no
34203261e8b6eac44a41341f112821482bee6c940c98mmentovai    // swapping.
34213261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.major_version);
34223261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.minor_version);
34233261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.build_number);
34243261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.platform_id);
34253261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.csd_version_rva);
34263261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&system_info_.suite_mask);
34273402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    // Don't swap the reserved2 field because its contents are unknown.
34283402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai
34293402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
34303402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
34313402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 3; ++i)
34323402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
34333402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.version_information);
34343402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.feature_information);
34353402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
34363402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    } else {
34373402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai      for (unsigned int i = 0; i < 2; ++i)
34383402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai        Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
34393402cae5e58f7503adc4d9de6d9ea69e725ddcb2mmentovai    }
34403261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
34413261e8b6eac44a41341f112821482bee6c940c98mmentovai
34423261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
34433261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
34443261e8b6eac44a41341f112821482bee6c940c98mmentovai}
34453261e8b6eac44a41341f112821482bee6c940c98mmentovai
34463261e8b6eac44a41341f112821482bee6c940c98mmentovai
344797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetOS() {
34484e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com  string os;
34494e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com
3450af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3451af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
34524e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com    return os;
3453af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
345497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
345597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.platform_id) {
345697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_NT:
345797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_WIN32_WINDOWS:
345897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "windows";
345997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
346097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
346197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_MAC_OS_X:
346297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "mac";
346397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
346497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
346563f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org    case MD_OS_IOS:
346663f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      os = "ios";
346763f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org      break;
346863f97ad134db3fa175c489b50b66a79bf0c95025qsr@chromium.org
346997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_OS_LINUX:
347097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      os = "linux";
347197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3472af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3473ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    case MD_OS_SOLARIS:
3474ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      os = "solaris";
34755187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      break;
34765187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org
34775187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org    case MD_OS_ANDROID:
34785187de1ae5cb7df2343b650416aa805084bdf8dadigit@chromium.org      os = "android";
3479ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai      break;
3480ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
3481d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org    case MD_OS_PS3:
3482d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      os = "ps3";
3483d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org      break;
3484d9b40724ed6a6c243eaef196e617071ec36d4282thestig@chromium.org
348542faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org    case MD_OS_NACL:
348642faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      os = "nacl";
348742faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org      break;
348842faddc9c3be48a8a29236ab866013288d25491emseaborn@chromium.org
3489af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3490af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
3491af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.platform_id);
3492af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
349397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
349497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
349597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return os;
349697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
349797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
349897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
349997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistring MinidumpSystemInfo::GetCPU() {
3500af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3501af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
350297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    return "";
3503af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
350497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
350597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  string cpu;
350697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
350797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  switch (system_info_.processor_architecture) {
350897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86:
350997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_X86_WIN64:
351097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "x86";
351197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
351297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
35139276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_AMD64:
35149276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "x86-64";
35159276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
35169276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
351797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    case MD_CPU_ARCHITECTURE_PPC:
351897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu = "ppc";
351997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      break;
3520af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3521cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org    case MD_CPU_ARCHITECTURE_PPC64:
3522cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      cpu = "ppc64";
3523cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      break;
3524cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org
3525dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    case MD_CPU_ARCHITECTURE_SPARC:
3526dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      cpu = "sparc";
3527dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      break;
3528dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
35299276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek    case MD_CPU_ARCHITECTURE_ARM:
35309276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      cpu = "arm";
35319276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek      break;
35329276b0d3017ad5ca93c8b593cacf317e1eaa114eted.mielczarek
3533af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    default:
3534af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
3535af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(system_info_.processor_architecture);
3536af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      break;
353797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
353897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
353997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  return cpu;
354097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai}
354197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
354297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
35433261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst string* MinidumpSystemInfo::GetCSDVersion() {
3544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3545af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
35463261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
3547af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
35483261e8b6eac44a41341f112821482bee6c940c98mmentovai
35493261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (!csd_version_)
35503261e8b6eac44a41341f112821482bee6c940c98mmentovai    csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
35513261e8b6eac44a41341f112821482bee6c940c98mmentovai
3552af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
3553af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                    "CSD version";
3554af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
35553261e8b6eac44a41341f112821482bee6c940c98mmentovai  return csd_version_;
35563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
35573261e8b6eac44a41341f112821482bee6c940c98mmentovai
35583261e8b6eac44a41341f112821482bee6c940c98mmentovai
3559e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovaiconst string* MinidumpSystemInfo::GetCPUVendor() {
3560af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3561af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
3562e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    return NULL;
3563af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3564e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3565e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  // CPU vendor information can only be determined from x86 minidumps.
3566e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (!cpu_vendor_ &&
3567e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai      (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
3568e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
3569e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    char cpu_vendor_string[13];
3570e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
3571e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             "%c%c%c%c%c%c%c%c%c%c%c%c",
3572e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
3573e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
3574e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
3575e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
3576e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
3577e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
3578e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
3579e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
3580e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai              system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
3581e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
3582e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
3583e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai             (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
3584e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    cpu_vendor_ = new string(cpu_vendor_string);
3585e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3586e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3587e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  return cpu_vendor_;
3588e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai}
3589e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
3590e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai
35913261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpSystemInfo::Print() {
3592af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3593af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
35943261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3595af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
35963261e8b6eac44a41341f112821482bee6c940c98mmentovai
35973261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawSystemInfo\n");
35983261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_architecture                     = %d\n",
35993261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_architecture);
36003261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  processor_level                            = %d\n",
36013261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.processor_level);
36020a7e6bf16cad354710df60929c2ac82f647cb54emmentovai  printf("  processor_revision                         = 0x%x\n",
36030a7e6bf16cad354710df60929c2ac82f647cb54emmentovai         system_info_.processor_revision);
36043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  number_of_processors                       = %d\n",
36053261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.number_of_processors);
36063261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  product_type                               = %d\n",
36073261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.product_type);
36083261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  major_version                              = %d\n",
36093261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.major_version);
36103261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  minor_version                              = %d\n",
36113261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.minor_version);
36123261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  build_number                               = %d\n",
36133261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.build_number);
36143261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  platform_id                                = %d\n",
36153261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.platform_id);
36163261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  csd_version_rva                            = 0x%x\n",
36173261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.csd_version_rva);
36183261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  suite_mask                                 = 0x%x\n",
36193261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.suite_mask);
36203261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int i = 0; i < 3; ++i) {
36213261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
36223261e8b6eac44a41341f112821482bee6c940c98mmentovai           i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
36233261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
36243261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
36253261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.version_information);
36263261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
36273261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.feature_information);
36283261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
36293261e8b6eac44a41341f112821482bee6c940c98mmentovai         system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
3630e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* csd_version = GetCSDVersion();
3631e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (csd_version) {
36323261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = \"%s\"\n",
3633e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           csd_version->c_str());
3634e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
36353261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  (csd_version)                              = (null)\n");
3636e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
3637e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  const string* cpu_vendor = GetCPUVendor();
3638e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  if (cpu_vendor) {
3639e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = \"%s\"\n",
3640e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai           cpu_vendor->c_str());
3641e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  } else {
3642e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai    printf("  (cpu_vendor)                               = (null)\n");
3643e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  }
36443261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
36453261e8b6eac44a41341f112821482bee6c940c98mmentovai}
36463261e8b6eac44a41341f112821482bee6c940c98mmentovai
36473261e8b6eac44a41341f112821482bee6c940c98mmentovai
36483261e8b6eac44a41341f112821482bee6c940c98mmentovai//
36493261e8b6eac44a41341f112821482bee6c940c98mmentovai// MinidumpMiscInfo
36503261e8b6eac44a41341f112821482bee6c940c98mmentovai//
36513261e8b6eac44a41341f112821482bee6c940c98mmentovai
36523261e8b6eac44a41341f112821482bee6c940c98mmentovai
36533261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
365453d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : MinidumpStream(minidump),
365553d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      misc_info_() {
36563261e8b6eac44a41341f112821482bee6c940c98mmentovai}
36573261e8b6eac44a41341f112821482bee6c940c98mmentovai
36583261e8b6eac44a41341f112821482bee6c940c98mmentovai
36596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMiscInfo::Read(uint32_t expected_size) {
36603261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
36613261e8b6eac44a41341f112821482bee6c940c98mmentovai
36623261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (expected_size != MD_MISCINFO_SIZE &&
36633562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO2_SIZE &&
36643562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO3_SIZE &&
36653562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      expected_size != MD_MISCINFO4_SIZE) {
36663562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
36673562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
36683562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
36693562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                 << ")";
36703261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
36713261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
36723261e8b6eac44a41341f112821482bee6c940c98mmentovai
3673af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
3674af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
36753261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3676af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
36773261e8b6eac44a41341f112821482bee6c940c98mmentovai
36783261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (minidump_->swap()) {
36793562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Swap version 1 fields
36803261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.size_of_info);
36813261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.flags1);
36823261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_id);
36833261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_create_time);
36843261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_user_time);
36853261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&misc_info_.process_kernel_time);
36863261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
36873562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 2 fields
36883261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_mhz);
36893261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_mhz);
36903261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_mhz_limit);
36913261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_max_idle_state);
36923261e8b6eac44a41341f112821482bee6c940c98mmentovai      Swap(&misc_info_.processor_current_idle_state);
36933261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
36943562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
36953562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 3 fields
36963562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_integrity_level);
36973562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.process_execute_flags);
36983562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.protected_process);
36993562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone_id);
37003562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      Swap(&misc_info_.time_zone);
37013562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
37023562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
37033562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Swap version 4 fields.
37043562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // Do not swap UTF-16 strings.  The swap is done as part of the
37053562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com      // conversion to UTF-8 (code follows below).
37063562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    }
37073261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
37083261e8b6eac44a41341f112821482bee6c940c98mmentovai
370965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai  if (expected_size != misc_info_.size_of_info) {
3710af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
371165571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai                    expected_size << " != " << misc_info_.size_of_info;
37123261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
3713af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
37143261e8b6eac44a41341f112821482bee6c940c98mmentovai
37153562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Convert UTF-16 strings
37163562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
37173562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 3 fields
37183562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name,
37193562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.standard_name),
37203562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &standard_name_, minidump_->swap());
37213562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name,
37223562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.time_zone.daylight_name),
37233562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &daylight_name_, minidump_->swap());
37243562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
37253562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
37263562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Convert UTF-16 strings in version 4 fields
37273562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.build_string,
37283562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.build_string),
37293562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &build_string_, minidump_->swap());
37303562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str,
37313562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   sizeof(misc_info_.dbg_bld_str),
37323562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com                                   &dbg_bld_str_, minidump_->swap());
37333562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
37343562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com
37353261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
37363261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
37373261e8b6eac44a41341f112821482bee6c940c98mmentovai}
37383261e8b6eac44a41341f112821482bee6c940c98mmentovai
37393261e8b6eac44a41341f112821482bee6c940c98mmentovai
37403261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid MinidumpMiscInfo::Print() {
3741af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3742af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
37433261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
3744af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
37453261e8b6eac44a41341f112821482bee6c940c98mmentovai
37463261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawMiscInfo\n");
37473562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  // Print version 1 fields
37483261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
37493261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  flags1                       = 0x%x\n", misc_info_.flags1);
37503261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_id                   = 0x%x\n", misc_info_.process_id);
37513261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_create_time          = 0x%x\n",
37523261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_create_time);
37533261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_user_time            = 0x%x\n",
37543261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_user_time);
37553261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  process_kernel_time          = 0x%x\n",
37563261e8b6eac44a41341f112821482bee6c940c98mmentovai         misc_info_.process_kernel_time);
37573261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
37583562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 2 fields
37593261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_mhz            = %d\n",
37603261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_mhz);
37613261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_mhz        = %d\n",
37623261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_mhz);
37633261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_mhz_limit          = %d\n",
37643261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_mhz_limit);
37653261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_max_idle_state     = 0x%x\n",
37663261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_max_idle_state);
37673261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  processor_current_idle_state = 0x%x\n",
37683261e8b6eac44a41341f112821482bee6c940c98mmentovai           misc_info_.processor_current_idle_state);
37693261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
37703562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
37713562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 3 fields
37723562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  process_integrity_level      = 0x%x\n",
37733562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.process_integrity_level);
37743562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  process_execute_flags        = 0x%x\n",
37753562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.process_execute_flags);
37763562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  protected_process            = %d\n",
37773562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com           misc_info_.protected_process);
37783562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone_id                 = %d\n", misc_info_.time_zone_id);
37793562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.bias               = %d\n", misc_info_.time_zone.bias);
37803562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.standard_name      = %s\n", standard_name_.c_str());
37813562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  time_zone.daylight_name      = %s\n", daylight_name_.c_str());
37823562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
37833562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
37843562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    // Print version 4 fields
37853562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  build_string                 = %s\n", build_string_.c_str());
37863562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com    printf("  dbg_bld_str                  = %s\n", dbg_bld_str_.c_str());
37873562017ff5a65fff770cd798903ee294db912aa2ivan.penkov@gmail.com  }
378876f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
378976f052f8fbf8864dee5992b857229d06560a766ammentovai}
379076f052f8fbf8864dee5992b857229d06560a766ammentovai
379176f052f8fbf8864dee5992b857229d06560a766ammentovai
379276f052f8fbf8864dee5992b857229d06560a766ammentovai//
3793e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// MinidumpBreakpadInfo
379476f052f8fbf8864dee5992b857229d06560a766ammentovai//
379576f052f8fbf8864dee5992b857229d06560a766ammentovai
379676f052f8fbf8864dee5992b857229d06560a766ammentovai
3797e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
379876f052f8fbf8864dee5992b857229d06560a766ammentovai    : MinidumpStream(minidump),
3799e5dc60822e5938fea2ae892ccddb906641ba174emmentovai      breakpad_info_() {
380076f052f8fbf8864dee5992b857229d06560a766ammentovai}
380176f052f8fbf8864dee5992b857229d06560a766ammentovai
380276f052f8fbf8864dee5992b857229d06560a766ammentovai
38036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::Read(uint32_t expected_size) {
380476f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = false;
380576f052f8fbf8864dee5992b857229d06560a766ammentovai
3806af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (expected_size != sizeof(breakpad_info_)) {
3807af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
3808af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " != " << sizeof(breakpad_info_);
380976f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3810af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
381176f052f8fbf8864dee5992b857229d06560a766ammentovai
3812af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
3813af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
381476f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
3815af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
381676f052f8fbf8864dee5992b857229d06560a766ammentovai
381776f052f8fbf8864dee5992b857229d06560a766ammentovai  if (minidump_->swap()) {
3818e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.validity);
3819e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.dump_thread_id);
3820e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    Swap(&breakpad_info_.requesting_thread_id);
382176f052f8fbf8864dee5992b857229d06560a766ammentovai  }
382276f052f8fbf8864dee5992b857229d06560a766ammentovai
382376f052f8fbf8864dee5992b857229d06560a766ammentovai  valid_ = true;
382476f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
382576f052f8fbf8864dee5992b857229d06560a766ammentovai}
382676f052f8fbf8864dee5992b857229d06560a766ammentovai
382776f052f8fbf8864dee5992b857229d06560a766ammentovai
38286162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const {
3829af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
3830af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3831af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3832af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3833af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3834af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3835af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
3836af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3837af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3838af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3839af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
3840af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
384176f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
384276f052f8fbf8864dee5992b857229d06560a766ammentovai  }
384376f052f8fbf8864dee5992b857229d06560a766ammentovai
3844e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.dump_thread_id;
384576f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
384676f052f8fbf8864dee5992b857229d06560a766ammentovai}
384776f052f8fbf8864dee5992b857229d06560a766ammentovai
384876f052f8fbf8864dee5992b857229d06560a766ammentovai
38496162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id)
385076f052f8fbf8864dee5992b857229d06560a766ammentovai    const {
3851af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
3852af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                 "requires |thread_id|";
3853af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(thread_id);
3854af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *thread_id = 0;
3855af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3856af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!thread_id || !valid_) {
3857af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
3858af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return false;
3859af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
3860af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
3861af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!(breakpad_info_.validity &
3862af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
3863af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
386476f052f8fbf8864dee5992b857229d06560a766ammentovai    return false;
386576f052f8fbf8864dee5992b857229d06560a766ammentovai  }
386676f052f8fbf8864dee5992b857229d06560a766ammentovai
3867e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  *thread_id = breakpad_info_.requesting_thread_id;
386876f052f8fbf8864dee5992b857229d06560a766ammentovai  return true;
386976f052f8fbf8864dee5992b857229d06560a766ammentovai}
387076f052f8fbf8864dee5992b857229d06560a766ammentovai
387176f052f8fbf8864dee5992b857229d06560a766ammentovai
3872e5dc60822e5938fea2ae892ccddb906641ba174emmentovaivoid MinidumpBreakpadInfo::Print() {
3873af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
3874af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
387576f052f8fbf8864dee5992b857229d06560a766ammentovai    return;
3876af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
387776f052f8fbf8864dee5992b857229d06560a766ammentovai
3878e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("MDRawBreakpadInfo\n");
3879e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  printf("  validity             = 0x%x\n", breakpad_info_.validity);
388076f052f8fbf8864dee5992b857229d06560a766ammentovai
3881e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
3882e5dc60822e5938fea2ae892ccddb906641ba174emmentovai    printf("  dump_thread_id       = 0x%x\n", breakpad_info_.dump_thread_id);
388376f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
388476f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  dump_thread_id       = (invalid)\n");
388576f052f8fbf8864dee5992b857229d06560a766ammentovai  }
388676f052f8fbf8864dee5992b857229d06560a766ammentovai
3887e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
388876f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = 0x%x\n",
3889e5dc60822e5938fea2ae892ccddb906641ba174emmentovai           breakpad_info_.requesting_thread_id);
389076f052f8fbf8864dee5992b857229d06560a766ammentovai  } else {
389176f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  requesting_thread_id = (invalid)\n");
389276f052f8fbf8864dee5992b857229d06560a766ammentovai  }
389376f052f8fbf8864dee5992b857229d06560a766ammentovai
389476f052f8fbf8864dee5992b857229d06560a766ammentovai  printf("\n");
38953261e8b6eac44a41341f112821482bee6c940c98mmentovai}
38963261e8b6eac44a41341f112821482bee6c940c98mmentovai
38973261e8b6eac44a41341f112821482bee6c940c98mmentovai
38983261e8b6eac44a41341f112821482bee6c940c98mmentovai//
38997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfo
39007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
39017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
39047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpObject(minidump),
39057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_() {
39067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsExecutable() const {
39106162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
39117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
39127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_EXECUTE ||
39137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
39147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
39157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::IsWritable() const {
39196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t protection =
39207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
39217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return protection == MD_MEMORY_PROTECT_READWRITE ||
39227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_WRITECOPY ||
39237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
39247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
39257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekbool MinidumpMemoryInfo::Read() {
39297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
39307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
39327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
39337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
39347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
39377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.base_address);
39387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_base);
39397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.allocation_protection);
39407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.region_size);
39417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.state);
39427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.protection);
39437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&memory_info_.type);
39447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Check for base + size overflow or undersize.
39477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (memory_info_.region_size == 0 ||
39486162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      memory_info_.region_size > numeric_limits<uint64_t>::max() -
39497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                     memory_info_.base_address) {
39507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
39517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.base_address) << "+" <<
39527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    HexString(memory_info_.region_size);
39537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
39547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
39577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
39587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfo::Print() {
39627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
39637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
39647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
39657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
39667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MDRawMemoryInfo\n");
39687b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  base_address          = 0x%" PRIx64 "\n",
39697b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.base_address);
39707b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_base       = 0x%" PRIx64 "\n",
39717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_base);
39727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  allocation_protection = 0x%x\n",
39737b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         memory_info_.allocation_protection);
39747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  region_size           = 0x%" PRIx64 "\n", memory_info_.region_size);
39757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  state                 = 0x%x\n", memory_info_.state);
39767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  protection            = 0x%x\n", memory_info_.protection);
39777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  type                  = 0x%x\n", memory_info_.type);
39787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
39827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek// MinidumpMemoryInfoList
39837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
39847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
39877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    : MinidumpStream(minidump),
39886162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      range_map_(new RangeMap<uint64_t, unsigned int>()),
39897b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      infos_(NULL),
39907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      info_count_(0) {
39917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
39957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete range_map_;
39967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
39977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
39987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
39997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool MinidumpMemoryInfoList::Read(uint32_t expected_size) {
40017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Invalidate cached data.
40027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  delete infos_;
40037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  infos_ = NULL;
40047b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  range_map_->Clear();
40057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  info_count_ = 0;
40067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = false;
40087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MDRawMemoryInfoList header;
40107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size < sizeof(MDRawMemoryInfoList)) {
40117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
40127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    expected_size << " < " << sizeof(MDRawMemoryInfoList);
40137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!minidump_->ReadBytes(&header, sizeof(header))) {
40167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
40177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (minidump_->swap()) {
40217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_header);
40227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.size_of_entry);
40237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    Swap(&header.number_of_entries);
40247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the header is the expected size.
4027f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // TODO(ted): could possibly handle this more gracefully, assuming
40287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // that future versions of the structs would be backwards-compatible.
40297b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
40307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
40317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_header << " != " <<
40327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfoList);
40337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  // Sanity check that the entries are the expected size.
40377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
40387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
40397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.size_of_entry << " != " <<
40407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    sizeof(MDRawMemoryInfo);
40417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries >
40456162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) {
40467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
40477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    header.number_of_entries <<
40487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " would cause multiplication overflow";
40497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (expected_size != sizeof(MDRawMemoryInfoList) +
40537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo)) {
40547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
40557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " != " << sizeof(MDRawMemoryInfoList) +
40567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        header.number_of_entries * sizeof(MDRawMemoryInfo);
40577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return false;
40587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
40597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
4060f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for data loss when converting header.number_of_entries from
4061f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // uint64_t into MinidumpMemoryInfos::size_type (uint32_t)
4062f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  MinidumpMemoryInfos::size_type header_number_of_entries =
4063f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      static_cast<unsigned int>(header.number_of_entries);
4064f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<uint64_t>(header_number_of_entries) !=
4065f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      header.number_of_entries) {
4066f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected when converting "
4067f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                    "the header's number_of_entries";
4068f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4069f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4070f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
40717b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (header.number_of_entries != 0) {
40727b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    scoped_ptr<MinidumpMemoryInfos> infos(
4073f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com        new MinidumpMemoryInfos(header_number_of_entries,
40747b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                                MinidumpMemoryInfo(minidump_)));
40757b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40767b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    for (unsigned int index = 0;
40777b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         index < header.number_of_entries;
40787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek         ++index) {
40797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      MinidumpMemoryInfo* info = &(*infos)[index];
40807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      // Assume that the file offset is correct after the last read.
40827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!info->Read()) {
40837b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
40847b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries;
40857b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
40867b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
40877b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40886162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      uint64_t base_address = info->GetBase();
4089f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com      uint64_t region_size = info->GetSize();
40907b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
40917b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      if (!range_map_->StoreRange(base_address, region_size, index)) {
40927b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
40937b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        " memory region " <<
40947b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        index << "/" << header.number_of_entries << ", " <<
40957b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(base_address) << "+" <<
40967b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                        HexString(region_size);
40977b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek        return false;
40987b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      }
40997b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    }
41007b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41017b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    infos_ = infos.release();
41027b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41037b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
4104f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  info_count_ = header_number_of_entries;
41057b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41067b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  valid_ = true;
41077b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return true;
41087b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41097b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41107b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41117b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
41127b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek      unsigned int index) const {
41137b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
41147b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
41157b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
41167b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41177b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41187b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (index >= info_count_) {
41197b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
41207b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    index << "/" << info_count_;
41217b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
41227b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41237b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41247b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return &(*infos_)[index];
41257b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41267b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41277b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41287b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekconst MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
41296162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t address) const {
41307b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
41317b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
41327b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                    " GetMemoryInfoForAddress";
41337b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
41347b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41357b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41367b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  unsigned int info_index;
41377b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
41387b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
41397b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek                   HexString(address);
41407b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return NULL;
41417b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41427b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41437b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetMemoryInfoAtIndex(info_index);
41447b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41457b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41467b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41477b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekvoid MinidumpMemoryInfoList::Print() {
41487b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  if (!valid_) {
41497b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
41507b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    return;
41517b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41527b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41537b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("MinidumpMemoryInfoList\n");
41547b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("  info_count = %d\n", info_count_);
41557b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  printf("\n");
41567b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41577b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  for (unsigned int info_index = 0;
41587b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       info_index < info_count_;
41597b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek       ++info_index) {
41607b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("info[%d]\n", info_index);
41617b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    (*infos_)[info_index].Print();
41627b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek    printf("\n");
41637b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  }
41647b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
41657b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41667b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
41677b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek//
41683261e8b6eac44a41341f112821482bee6c940c98mmentovai// Minidump
41693261e8b6eac44a41341f112821482bee6c940c98mmentovai//
41703261e8b6eac44a41341f112821482bee6c940c98mmentovai
41713261e8b6eac44a41341f112821482bee6c940c98mmentovai
41726162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint32_t Minidump::max_streams_ = 128;
4173e96a791d9a0886a24ce08afe13207e8e105542e3mmentovaiunsigned int Minidump::max_string_length_ = 1024;
4174e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
4175e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
41766dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaiMinidump::Minidump(const string& path)
417753d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai    : header_(),
417853d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      directory_(NULL),
4179373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      stream_map_(new MinidumpStreamMap()),
41806dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai      path_(path),
41810cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(NULL),
418253d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      swap_(false),
418353d0f69d35375fe2ffd119ac7e4898083c0e071cmmentovai      valid_(false) {
41843261e8b6eac44a41341f112821482bee6c940c98mmentovai}
41853261e8b6eac44a41341f112821482bee6c940c98mmentovai
41860cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekMinidump::Minidump(istream& stream)
41870cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    : header_(),
41880cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      directory_(NULL),
41890cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_map_(new MinidumpStreamMap()),
41900cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      path_(),
41910cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      stream_(&stream),
41920cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      swap_(false),
41930cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek      valid_(false) {
41940cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
41953261e8b6eac44a41341f112821482bee6c940c98mmentovai
41963261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidump::~Minidump() {
41970cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_) {
41980cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump closing minidump";
41990cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
42000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!path_.empty()) {
42010cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    delete stream_;
42020cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
42033261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
42043261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete stream_map_;
42056dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai}
42066dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
42076dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
42086dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovaibool Minidump::Open() {
42090cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (stream_ != NULL) {
42100cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(INFO) << "Minidump reopening minidump " << path_;
4211af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
42126dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // The file is already open.  Seek to the beginning, which is the position
42136dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    // the file would be at if it were opened anew.
42146dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return SeekSet(0);
42156dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  }
42166dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
42170cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
42180cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_ || !stream_->good()) {
4219af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    string error_string;
4220af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    int error_code = ErrnoString(&error_string);
4221af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
4222af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    ", error " << error_code << ": " << error_string;
42236dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4224af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
42256dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
42260cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  BPLOG(INFO) << "Minidump opened minidump " << path_;
42276dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai  return true;
42283261e8b6eac44a41341f112821482bee6c940c98mmentovai}
42293261e8b6eac44a41341f112821482bee6c940c98mmentovai
42306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) {
4231233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Initialize output parameters
4232233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  *context_cpu_flags = 0;
4233233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4234233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Save the current stream position
4235233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  off_t saved_position = Tell();
4236233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (saved_position == -1) {
4237233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Failed to save the current stream position.
4238233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    // Returns true because the current position of the stream is preserved.
4239233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    return true;
4240233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4241233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4242233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  const MDRawSystemInfo* system_info =
4243233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
4244233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4245233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  if (system_info != NULL) {
4246233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    switch (system_info->processor_architecture) {
4247233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86:
4248233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_X86;
4249233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4250233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MIPS:
4251233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_MIPS;
4252233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4253233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA:
4254233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ALPHA;
4255233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4256233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_PPC:
4257233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_PPC;
4258233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4259cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org      case MD_CPU_ARCHITECTURE_PPC64:
4260cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        *context_cpu_flags = MD_CONTEXT_PPC64;
4261cd1f1a6399d5a73ac2bdf5671f8322ba013e8e21thestig@chromium.org        break;
4262233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SHX:
4263233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SHX;
4264233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4265233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ARM:
4266233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_ARM;
4267233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4268233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_IA64:
4269233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_IA64;
4270233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4271233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_ALPHA64:
4272233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4273233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4274233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_MSIL:
4275233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4276233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4277233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_AMD64:
4278233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_AMD64;
4279233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4280233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_X86_WIN64:
4281233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4282233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4283233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_SPARC:
4284233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = MD_CONTEXT_SPARC;
4285233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4286233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      case MD_CPU_ARCHITECTURE_UNKNOWN:
4287233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4288233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4289233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com      default:
4290233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        *context_cpu_flags = 0;
4291233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com        break;
4292233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com    }
4293233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  }
4294233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
4295233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  // Restore position and return
4296233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com  return SeekSet(saved_position);
4297233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com}
4298233501d467e38955ba38065b7c717486b94c1da9ivan.penkov@gmail.com
42993261e8b6eac44a41341f112821482bee6c940c98mmentovai
43003261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::Read() {
43013261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Invalidate cached data.
43023261e8b6eac44a41341f112821482bee6c940c98mmentovai  delete directory_;
43033261e8b6eac44a41341f112821482bee6c940c98mmentovai  directory_ = NULL;
4304373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  stream_map_->clear();
43053261e8b6eac44a41341f112821482bee6c940c98mmentovai
43063261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = false;
43073261e8b6eac44a41341f112821482bee6c940c98mmentovai
4308af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!Open()) {
4309af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot open minidump";
43106dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai    return false;
4311af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43126dd21d3baf490a34af0b1b1f5a48f8443dcb1ea6mmentovai
4313af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
4314af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot read header";
43153261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4316af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43173261e8b6eac44a41341f112821482bee6c940c98mmentovai
43183261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (header_.signature != MD_HEADER_SIGNATURE) {
43193261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file may be byte-swapped.  Under the present architecture, these
43203261e8b6eac44a41341f112821482bee6c940c98mmentovai    // classes don't know or need to know what CPU (or endianness) the
43213261e8b6eac44a41341f112821482bee6c940c98mmentovai    // minidump was produced on in order to parse it.  Use the signature as
43223261e8b6eac44a41341f112821482bee6c940c98mmentovai    // a byte order marker.
43236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t signature_swapped = header_.signature;
43243261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&signature_swapped);
43253261e8b6eac44a41341f112821482bee6c940c98mmentovai    if (signature_swapped != MD_HEADER_SIGNATURE) {
43263261e8b6eac44a41341f112821482bee6c940c98mmentovai      // This isn't a minidump or a byte-swapped minidump.
4327af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
4328af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(header_.signature) << ", " <<
4329af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(signature_swapped) << ") != " <<
4330af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                      HexString(MD_HEADER_SIGNATURE);
43313261e8b6eac44a41341f112821482bee6c940c98mmentovai      return false;
43323261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
43333261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = true;
43343261e8b6eac44a41341f112821482bee6c940c98mmentovai  } else {
43353261e8b6eac44a41341f112821482bee6c940c98mmentovai    // The file is not byte-swapped.  Set swap_ false (it may have been true
43363261e8b6eac44a41341f112821482bee6c940c98mmentovai    // if the object is being reused?)
43373261e8b6eac44a41341f112821482bee6c940c98mmentovai    swap_ = false;
43383261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43393261e8b6eac44a41341f112821482bee6c940c98mmentovai
4340af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
4341af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                 "byte-swapping minidump";
4342af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
43433261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_) {
43443261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.signature);
43453261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.version);
43463261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_count);
43473261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.stream_directory_rva);
43483261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.checksum);
43493261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.time_date_stamp);
43503261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&header_.flags);
43513261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43523261e8b6eac44a41341f112821482bee6c940c98mmentovai
43533261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Version check.  The high 16 bits of header_.version contain something
43543261e8b6eac44a41341f112821482bee6c940c98mmentovai  // else "implementation specific."
43553261e8b6eac44a41341f112821482bee6c940c98mmentovai  if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
4356af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump version mismatch: " <<
4357af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(header_.version & 0x0000ffff) << " != " <<
4358af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    HexString(MD_HEADER_VERSION);
43593261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
43603261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
43613261e8b6eac44a41341f112821482bee6c940c98mmentovai
4362af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(header_.stream_directory_rva)) {
4363af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
43643261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4365af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
43663261e8b6eac44a41341f112821482bee6c940c98mmentovai
4367e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count > max_streams_) {
4368e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
4369e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_streams_;
4370e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return false;
4371e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4372e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
4373e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (header_.stream_count != 0) {
4374373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    scoped_ptr<MinidumpDirectoryEntries> directory(
4375373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        new MinidumpDirectoryEntries(header_.stream_count));
43763261e8b6eac44a41341f112821482bee6c940c98mmentovai
4377373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // Read the entire array in one fell swoop, instead of reading one entry
4378373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    // at a time in the loop.
4379373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&(*directory)[0],
4380af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                   sizeof(MDRawDirectory) * header_.stream_count)) {
4381af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai      BPLOG(ERROR) << "Minidump cannot read stream directory";
4382373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return false;
4383af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    }
43843261e8b6eac44a41341f112821482bee6c940c98mmentovai
4385373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    for (unsigned int stream_index = 0;
4386373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         stream_index < header_.stream_count;
4387373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai         ++stream_index) {
4388373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      MDRawDirectory* directory_entry = &(*directory)[stream_index];
43893261e8b6eac44a41341f112821482bee6c940c98mmentovai
4390373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      if (swap_) {
4391373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->stream_type);
4392373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        Swap(&directory_entry->location);
4393373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      }
43943261e8b6eac44a41341f112821482bee6c940c98mmentovai
4395373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // Initialize the stream_map_ map, which speeds locating a stream by
4396373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      // type.
4397373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      unsigned int stream_type = directory_entry->stream_type;
4398373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      switch (stream_type) {
4399373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_THREAD_LIST_STREAM:
4400373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MODULE_LIST_STREAM:
4401373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MEMORY_LIST_STREAM:
4402373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_EXCEPTION_STREAM:
4403373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_SYSTEM_INFO_STREAM:
4404373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        case MD_MISC_INFO_STREAM:
4405e5dc60822e5938fea2ae892ccddb906641ba174emmentovai        case MD_BREAKPAD_INFO_STREAM: {
4406373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          if (stream_map_->find(stream_type) != stream_map_->end()) {
4407373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // Another stream with this type was already found.  A minidump
4408373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            // file should contain at most one of each of these stream types.
4409af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai            BPLOG(ERROR) << "Minidump found multiple streams of type " <<
4410af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                            stream_type << ", but can only deal with one";
4411373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai            return false;
4412373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          }
4413373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Fall through to default
44143261e8b6eac44a41341f112821482bee6c940c98mmentovai        }
44153261e8b6eac44a41341f112821482bee6c940c98mmentovai
4416373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        default: {
4417373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // Overwrites for stream types other than those above, but it's
4418373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          // expected to be the user's burden in that case.
4419373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai          (*stream_map_)[stream_type].stream_index = stream_index;
4420373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai        }
44213261e8b6eac44a41341f112821482bee6c940c98mmentovai      }
44223261e8b6eac44a41341f112821482bee6c940c98mmentovai    }
44233261e8b6eac44a41341f112821482bee6c940c98mmentovai
4424373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    directory_ = directory.release();
4425373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
44263261e8b6eac44a41341f112821482bee6c940c98mmentovai
44273261e8b6eac44a41341f112821482bee6c940c98mmentovai  valid_ = true;
44283261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
44293261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44303261e8b6eac44a41341f112821482bee6c940c98mmentovai
44313261e8b6eac44a41341f112821482bee6c940c98mmentovai
44323261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpThreadList* Minidump::GetThreadList() {
44333261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpThreadList* thread_list;
44343261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&thread_list);
44353261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44363261e8b6eac44a41341f112821482bee6c940c98mmentovai
44373261e8b6eac44a41341f112821482bee6c940c98mmentovai
44383261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpModuleList* Minidump::GetModuleList() {
44393261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpModuleList* module_list;
44403261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&module_list);
44413261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44423261e8b6eac44a41341f112821482bee6c940c98mmentovai
44433261e8b6eac44a41341f112821482bee6c940c98mmentovai
44443261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMemoryList* Minidump::GetMemoryList() {
44453261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMemoryList* memory_list;
44463261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&memory_list);
44473261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44483261e8b6eac44a41341f112821482bee6c940c98mmentovai
44493261e8b6eac44a41341f112821482bee6c940c98mmentovai
44503261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpException* Minidump::GetException() {
44513261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpException* exception;
44523261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&exception);
44533261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44543261e8b6eac44a41341f112821482bee6c940c98mmentovai
44550314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarekMinidumpAssertion* Minidump::GetAssertion() {
44560314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  MinidumpAssertion* assertion;
44570314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek  return GetStream(&assertion);
44580314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek}
44590314e487e46a45229e275eb78b09f0538a5a7769ted.mielczarek
44603261e8b6eac44a41341f112821482bee6c940c98mmentovai
44613261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpSystemInfo* Minidump::GetSystemInfo() {
44623261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpSystemInfo* system_info;
44633261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&system_info);
44643261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44653261e8b6eac44a41341f112821482bee6c940c98mmentovai
44663261e8b6eac44a41341f112821482bee6c940c98mmentovai
44673261e8b6eac44a41341f112821482bee6c940c98mmentovaiMinidumpMiscInfo* Minidump::GetMiscInfo() {
44683261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpMiscInfo* misc_info;
44693261e8b6eac44a41341f112821482bee6c940c98mmentovai  return GetStream(&misc_info);
44703261e8b6eac44a41341f112821482bee6c940c98mmentovai}
44713261e8b6eac44a41341f112821482bee6c940c98mmentovai
44723261e8b6eac44a41341f112821482bee6c940c98mmentovai
4473e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiMinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
4474e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  MinidumpBreakpadInfo* breakpad_info;
4475e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  return GetStream(&breakpad_info);
447676f052f8fbf8864dee5992b857229d06560a766ammentovai}
447776f052f8fbf8864dee5992b857229d06560a766ammentovai
44787b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarekMinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
44797b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  MinidumpMemoryInfoList* memory_info_list;
44807b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek  return GetStream(&memory_info_list);
44817b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek}
44827b8e2b7e090b2d1223d0944d1e7da1d4c571bb5dted.mielczarek
448376f052f8fbf8864dee5992b857229d06560a766ammentovai
44843261e8b6eac44a41341f112821482bee6c940c98mmentovaivoid Minidump::Print() {
4485af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4486af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump cannot print invalid data";
44873261e8b6eac44a41341f112821482bee6c940c98mmentovai    return;
4488af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
44893261e8b6eac44a41341f112821482bee6c940c98mmentovai
44903261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("MDRawHeader\n");
44913261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  signature            = 0x%x\n",    header_.signature);
44923261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  version              = 0x%x\n",    header_.version);
44933261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_count         = %d\n",      header_.stream_count);
44943261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
44953261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  checksum             = 0x%x\n",    header_.checksum);
4496042ca733d309f48d2987a81151cbf3c59b73e562bryner  struct tm timestruct;
4497c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#ifdef _WIN32
4498c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek  gmtime_s(&timestruct, reinterpret_cast<time_t*>(&header_.time_date_stamp));
4499c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#else
4500042ca733d309f48d2987a81151cbf3c59b73e562bryner  gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
4501c77fc8a32c8af421c7e0d5fe81eccfb62329dff2ted.mielczarek#endif
45023261e8b6eac44a41341f112821482bee6c940c98mmentovai  char timestr[20];
4503042ca733d309f48d2987a81151cbf3c59b73e562bryner  strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
45043261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
45053261e8b6eac44a41341f112821482bee6c940c98mmentovai                                               timestr);
4506c27cf3e3959189f78fe2de40405987c3f33488cemmentovai  printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
45073261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
45083261e8b6eac44a41341f112821482bee6c940c98mmentovai
45093261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (unsigned int stream_index = 0;
45103261e8b6eac44a41341f112821482bee6c940c98mmentovai       stream_index < header_.stream_count;
45113261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++stream_index) {
45123261e8b6eac44a41341f112821482bee6c940c98mmentovai    MDRawDirectory* directory_entry = &(*directory_)[stream_index];
45133261e8b6eac44a41341f112821482bee6c940c98mmentovai
45143261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("mDirectory[%d]\n", stream_index);
45153261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("MDRawDirectory\n");
45163261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  stream_type        = %d\n",   directory_entry->stream_type);
45173261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.data_size = %d\n",
45183261e8b6eac44a41341f112821482bee6c940c98mmentovai           directory_entry->location.data_size);
45193261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
45203261e8b6eac44a41341f112821482bee6c940c98mmentovai    printf("\n");
45213261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45223261e8b6eac44a41341f112821482bee6c940c98mmentovai
45233261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("Streams:\n");
45243261e8b6eac44a41341f112821482bee6c940c98mmentovai  for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
45253261e8b6eac44a41341f112821482bee6c940c98mmentovai       iterator != stream_map_->end();
45263261e8b6eac44a41341f112821482bee6c940c98mmentovai       ++iterator) {
45276162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint32_t stream_type = iterator->first;
45283261e8b6eac44a41341f112821482bee6c940c98mmentovai    MinidumpStreamInfo info = iterator->second;
452976f052f8fbf8864dee5992b857229d06560a766ammentovai    printf("  stream type 0x%x at index %d\n", stream_type, info.stream_index);
45303261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
45313261e8b6eac44a41341f112821482bee6c940c98mmentovai  printf("\n");
45323261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45333261e8b6eac44a41341f112821482bee6c940c98mmentovai
45343261e8b6eac44a41341f112821482bee6c940c98mmentovai
45353261e8b6eac44a41341f112821482bee6c940c98mmentovaiconst MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
45363261e8b6eac44a41341f112821482bee6c940c98mmentovai      const {
4537af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4538af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
45393261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4540af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4541af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4542af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (index >= header_.stream_count) {
4543af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
4544af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    index << "/" << header_.stream_count;
4545af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    return NULL;
4546af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45473261e8b6eac44a41341f112821482bee6c940c98mmentovai
45483261e8b6eac44a41341f112821482bee6c940c98mmentovai  return &(*directory_)[index];
45493261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45503261e8b6eac44a41341f112821482bee6c940c98mmentovai
45513261e8b6eac44a41341f112821482bee6c940c98mmentovai
45523261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::ReadBytes(void* bytes, size_t count) {
45533261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
45540cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
45550cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
45560cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
45570cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
45580cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->read(static_cast<char*>(bytes), count);
4559f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamsize bytes_read = stream_->gcount();
4560f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read == -1) {
4561f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    string error_string;
4562f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    int error_code = ErrnoString(&error_string);
4563f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
4564f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4565f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4566f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4567f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Convert to size_t and check for data loss
4568f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  size_t bytes_read_converted = static_cast<size_t>(bytes_read);
4569f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) {
4570f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting "
4571f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com                 << bytes_read << " to " << bytes_read_converted;
45723261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4573af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4574f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
4575f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (bytes_read_converted != count) {
4576f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count;
4577f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return false;
4578f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
4579f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com
45803261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
45813261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45823261e8b6eac44a41341f112821482bee6c940c98mmentovai
45833261e8b6eac44a41341f112821482bee6c940c98mmentovai
45843261e8b6eac44a41341f112821482bee6c940c98mmentovaibool Minidump::SeekSet(off_t offset) {
45853261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Can't check valid_ because Read needs to call this method before
45860cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  // validity can be determined.
45870cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_) {
45880cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return false;
45890cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
45900cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  stream_->seekg(offset, std::ios_base::beg);
45910cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!stream_->good()) {
45920cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    string error_string;
45930cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    int error_code = ErrnoString(&error_string);
45940cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
45953261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4596af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
45973261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
45983261e8b6eac44a41341f112821482bee6c940c98mmentovai}
45993261e8b6eac44a41341f112821482bee6c940c98mmentovai
46000cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarekoff_t Minidump::Tell() {
46010cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  if (!valid_ || !stream_) {
46020cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek    return (off_t)-1;
46030cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek  }
46040cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
4605f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // Check for conversion data loss
4606f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  std::streamoff std_streamoff = stream_->tellg();
4607f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  off_t rv = static_cast<off_t>(std_streamoff);
4608f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  if (static_cast<std::streamoff>(rv) == std_streamoff) {
4609f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return rv;
4610f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  } else {
4611f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    BPLOG(ERROR) << "Data loss detected";
4612f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com    return (off_t)-1;
4613f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  }
46140cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek}
46150cbd50c975c1680a6cd0f1ce2760e157e2bfd46fted.mielczarek
46163261e8b6eac44a41341f112821482bee6c940c98mmentovai
46173261e8b6eac44a41341f112821482bee6c940c98mmentovaistring* Minidump::ReadString(off_t offset) {
4618af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4619af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for ReadString";
46203261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4621af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
4622af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(offset)) {
4623e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
46243261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4625af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46263261e8b6eac44a41341f112821482bee6c940c98mmentovai
46276162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t bytes;
4628af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!ReadBytes(&bytes, sizeof(bytes))) {
4629e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString could not read string size at offset " <<
4630e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    offset;
46313261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4632af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46333261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (swap_)
46343261e8b6eac44a41341f112821482bee6c940c98mmentovai    Swap(&bytes);
46353261e8b6eac44a41341f112821482bee6c940c98mmentovai
4636af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (bytes % 2 != 0) {
4637e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
4638e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    "-byte string at offset " << offset;
46393261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4640af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46413261e8b6eac44a41341f112821482bee6c940c98mmentovai  unsigned int utf16_words = bytes / 2;
46423261e8b6eac44a41341f112821482bee6c940c98mmentovai
4643e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  if (utf16_words > max_string_length_) {
4644e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    BPLOG(ERROR) << "ReadString string length " << utf16_words <<
4645e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " exceeds maximum " << max_string_length_ <<
4646e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                    " at offset " << offset;
4647e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai    return NULL;
4648e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai  }
4649e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai
46506162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  vector<uint16_t> string_utf16(utf16_words);
46513261e8b6eac44a41341f112821482bee6c940c98mmentovai
4652373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  if (utf16_words) {
4653373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    if (!ReadBytes(&string_utf16[0], bytes)) {
4654e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai      BPLOG(ERROR) << "ReadString could not read " << bytes <<
4655e96a791d9a0886a24ce08afe13207e8e105542e3mmentovai                      "-byte string at offset " << offset;
4656373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai      return NULL;
4657373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai    }
4658373c49b4167c8a41bfb3adfa613866f0ca516e1cmmentovai  }
46593261e8b6eac44a41341f112821482bee6c940c98mmentovai
46603261e8b6eac44a41341f112821482bee6c940c98mmentovai  return UTF16ToUTF8(string_utf16, swap_);
46613261e8b6eac44a41341f112821482bee6c940c98mmentovai}
46623261e8b6eac44a41341f112821482bee6c940c98mmentovai
46633261e8b6eac44a41341f112821482bee6c940c98mmentovai
46646162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.combool Minidump::SeekToStreamType(uint32_t  stream_type,
46656162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                                uint32_t* stream_length) {
4666af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
4667af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                                     "|stream_length|";
4668af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream_length);
4669af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  *stream_length = 0;
4670af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4671af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4672af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
46733261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4674af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46753261e8b6eac44a41341f112821482bee6c940c98mmentovai
46763261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
46773261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
46783261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4679af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
46803261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
46813261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
46823261e8b6eac44a41341f112821482bee6c940c98mmentovai
46833261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo info = iterator->second;
4684af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (info.stream_index >= header_.stream_count) {
4685af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
4686af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    " out of range: " <<
4687af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    info.stream_index << "/" << header_.stream_count;
46883261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4689af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46903261e8b6eac44a41341f112821482bee6c940c98mmentovai
46913261e8b6eac44a41341f112821482bee6c940c98mmentovai  MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
4692af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekSet(directory_entry->location.rva)) {
4693af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
4694af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                    stream_type;
46953261e8b6eac44a41341f112821482bee6c940c98mmentovai    return false;
4696af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
46973261e8b6eac44a41341f112821482bee6c940c98mmentovai
46983261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream_length = directory_entry->location.data_size;
46993261e8b6eac44a41341f112821482bee6c940c98mmentovai
47003261e8b6eac44a41341f112821482bee6c940c98mmentovai  return true;
47013261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47023261e8b6eac44a41341f112821482bee6c940c98mmentovai
47033261e8b6eac44a41341f112821482bee6c940c98mmentovai
47043261e8b6eac44a41341f112821482bee6c940c98mmentovaitemplate<typename T>
47053261e8b6eac44a41341f112821482bee6c940c98mmentovaiT* Minidump::GetStream(T** stream) {
47063261e8b6eac44a41341f112821482bee6c940c98mmentovai  // stream is a garbage parameter that's present only to account for C++'s
47073261e8b6eac44a41341f112821482bee6c940c98mmentovai  // inability to overload a method based solely on its return type.
47083261e8b6eac44a41341f112821482bee6c940c98mmentovai
47096162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t stream_type = T::kStreamType;
4710af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai
4711af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
4712af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai                              " requires |stream|";
4713af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  assert(stream);
47143261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = NULL;
47153261e8b6eac44a41341f112821482bee6c940c98mmentovai
4716af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!valid_) {
4717af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
47183261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4719af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
47203261e8b6eac44a41341f112821482bee6c940c98mmentovai
47213261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
47223261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (iterator == stream_map_->end()) {
47233261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This stream type didn't exist in the directory.
4724af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
47253261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
47263261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
47273261e8b6eac44a41341f112821482bee6c940c98mmentovai
47283261e8b6eac44a41341f112821482bee6c940c98mmentovai  // Get a pointer so that the stored stream field can be altered.
47293261e8b6eac44a41341f112821482bee6c940c98mmentovai  MinidumpStreamInfo* info = &iterator->second;
47303261e8b6eac44a41341f112821482bee6c940c98mmentovai
47313261e8b6eac44a41341f112821482bee6c940c98mmentovai  if (info->stream) {
47323261e8b6eac44a41341f112821482bee6c940c98mmentovai    // This cast is safe because info.stream is only populated by this
47333261e8b6eac44a41341f112821482bee6c940c98mmentovai    // method, and there is a direct correlation between T and stream_type.
47343261e8b6eac44a41341f112821482bee6c940c98mmentovai    *stream = static_cast<T*>(info->stream);
47353261e8b6eac44a41341f112821482bee6c940c98mmentovai    return *stream;
47363261e8b6eac44a41341f112821482bee6c940c98mmentovai  }
47373261e8b6eac44a41341f112821482bee6c940c98mmentovai
47386162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t stream_length;
4739af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!SeekToStreamType(stream_type, &stream_length)) {
4740af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
47413261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4742af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
47433261e8b6eac44a41341f112821482bee6c940c98mmentovai
47442466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<T> new_stream(new T(this));
47453261e8b6eac44a41341f112821482bee6c940c98mmentovai
4746af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  if (!new_stream->Read(stream_length)) {
4747af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai    BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
47483261e8b6eac44a41341f112821482bee6c940c98mmentovai    return NULL;
4749af3c43f00e98047bc7f80dcf4c16b876e095769fmmentovai  }
47503261e8b6eac44a41341f112821482bee6c940c98mmentovai
47513261e8b6eac44a41341f112821482bee6c940c98mmentovai  *stream = new_stream.release();
47523261e8b6eac44a41341f112821482bee6c940c98mmentovai  info->stream = *stream;
47533261e8b6eac44a41341f112821482bee6c940c98mmentovai  return *stream;
47543261e8b6eac44a41341f112821482bee6c940c98mmentovai}
47553261e8b6eac44a41341f112821482bee6c940c98mmentovai
47563261e8b6eac44a41341f112821482bee6c940c98mmentovai
4757e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
4758