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