Home | History | Annotate | Download | only in processor
      1 // Copyright (c) 2010 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // minidump.cc: A minidump reader.
     31 //
     32 // See minidump.h for documentation.
     33 //
     34 // Author: Mark Mentovai
     35 
     36 #include "google_breakpad/processor/minidump.h"
     37 
     38 #include <assert.h>
     39 #include <fcntl.h>
     40 #include <stddef.h>
     41 #include <stdio.h>
     42 #include <string.h>
     43 #include <time.h>
     44 
     45 #ifdef _WIN32
     46 #include <io.h>
     47 #define PRIx64 "llx"
     48 #define PRIx32 "lx"
     49 #define snprintf _snprintf
     50 #else  // _WIN32
     51 #include <unistd.h>
     52 #endif  // _WIN32
     53 
     54 #include <fstream>
     55 #include <iostream>
     56 #include <limits>
     57 #include <map>
     58 #include <vector>
     59 
     60 #include "processor/range_map-inl.h"
     61 
     62 #include "common/scoped_ptr.h"
     63 #include "google_breakpad/processor/dump_context.h"
     64 #include "processor/basic_code_module.h"
     65 #include "processor/basic_code_modules.h"
     66 #include "processor/logging.h"
     67 
     68 namespace google_breakpad {
     69 
     70 
     71 using std::istream;
     72 using std::ifstream;
     73 using std::numeric_limits;
     74 using std::vector;
     75 
     76 // Returns true iff |context_size| matches exactly one of the sizes of the
     77 // various MDRawContext* types.
     78 // TODO(blundell): This function can be removed once
     79 // http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed.
     80 static bool IsContextSizeUnique(uint32_t context_size) {
     81   int num_matching_contexts = 0;
     82   if (context_size == sizeof(MDRawContextX86))
     83     num_matching_contexts++;
     84   if (context_size == sizeof(MDRawContextPPC))
     85     num_matching_contexts++;
     86   if (context_size == sizeof(MDRawContextPPC64))
     87     num_matching_contexts++;
     88   if (context_size == sizeof(MDRawContextAMD64))
     89     num_matching_contexts++;
     90   if (context_size == sizeof(MDRawContextSPARC))
     91     num_matching_contexts++;
     92   if (context_size == sizeof(MDRawContextARM))
     93     num_matching_contexts++;
     94   if (context_size == sizeof(MDRawContextARM64))
     95     num_matching_contexts++;
     96   if (context_size == sizeof(MDRawContextMIPS))
     97     num_matching_contexts++;
     98   return num_matching_contexts == 1;
     99 }
    100 
    101 //
    102 // Swapping routines
    103 //
    104 // Inlining these doesn't increase code size significantly, and it saves
    105 // a whole lot of unnecessary jumping back and forth.
    106 //
    107 
    108 
    109 // Swapping an 8-bit quantity is a no-op.  This function is only provided
    110 // to account for certain templatized operations that require swapping for
    111 // wider types but handle uint8_t too
    112 // (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
    113 static inline void Swap(uint8_t* value) {
    114 }
    115 
    116 
    117 // Optimization: don't need to AND the furthest right shift, because we're
    118 // shifting an unsigned quantity.  The standard requires zero-filling in this
    119 // case.  If the quantities were signed, a bitmask whould be needed for this
    120 // right shift to avoid an arithmetic shift (which retains the sign bit).
    121 // The furthest left shift never needs to be ANDed bitmask.
    122 
    123 
    124 static inline void Swap(uint16_t* value) {
    125   *value = (*value >> 8) |
    126            (*value << 8);
    127 }
    128 
    129 
    130 static inline void Swap(uint32_t* value) {
    131   *value =  (*value >> 24) |
    132            ((*value >> 8)  & 0x0000ff00) |
    133            ((*value << 8)  & 0x00ff0000) |
    134             (*value << 24);
    135 }
    136 
    137 
    138 static inline void Swap(uint64_t* value) {
    139   uint32_t* value32 = reinterpret_cast<uint32_t*>(value);
    140   Swap(&value32[0]);
    141   Swap(&value32[1]);
    142   uint32_t temp = value32[0];
    143   value32[0] = value32[1];
    144   value32[1] = temp;
    145 }
    146 
    147 
    148 // Given a pointer to a 128-bit int in the minidump data, set the "low"
    149 // and "high" fields appropriately.
    150 static void Normalize128(uint128_struct* value, bool is_big_endian) {
    151   // The struct format is [high, low], so if the format is big-endian,
    152   // the most significant bytes will already be in the high field.
    153   if (!is_big_endian) {
    154     uint64_t temp = value->low;
    155     value->low = value->high;
    156     value->high = temp;
    157   }
    158 }
    159 
    160 // This just swaps each int64 half of the 128-bit value.
    161 // The value should also be normalized by calling Normalize128().
    162 static void Swap(uint128_struct* value) {
    163   Swap(&value->low);
    164   Swap(&value->high);
    165 }
    166 
    167 // Swapping signed integers
    168 static inline void Swap(int16_t* value) {
    169   Swap(reinterpret_cast<uint16_t*>(value));
    170 }
    171 
    172 static inline void Swap(int32_t* value) {
    173   Swap(reinterpret_cast<uint32_t*>(value));
    174 }
    175 
    176 static inline void Swap(int64_t* value) {
    177   Swap(reinterpret_cast<uint64_t*>(value));
    178 }
    179 
    180 
    181 static inline void Swap(MDLocationDescriptor* location_descriptor) {
    182   Swap(&location_descriptor->data_size);
    183   Swap(&location_descriptor->rva);
    184 }
    185 
    186 
    187 static inline void Swap(MDMemoryDescriptor* memory_descriptor) {
    188   Swap(&memory_descriptor->start_of_memory_range);
    189   Swap(&memory_descriptor->memory);
    190 }
    191 
    192 
    193 static inline void Swap(MDGUID* guid) {
    194   Swap(&guid->data1);
    195   Swap(&guid->data2);
    196   Swap(&guid->data3);
    197   // Don't swap guid->data4[] because it contains 8-bit quantities.
    198 }
    199 
    200 static inline void Swap(MDSystemTime* system_time) {
    201   Swap(&system_time->year);
    202   Swap(&system_time->month);
    203   Swap(&system_time->day_of_week);
    204   Swap(&system_time->day);
    205   Swap(&system_time->hour);
    206   Swap(&system_time->minute);
    207   Swap(&system_time->second);
    208   Swap(&system_time->milliseconds);
    209 }
    210 
    211 static inline void Swap(uint16_t* data, size_t size_in_bytes) {
    212   size_t data_length = size_in_bytes / sizeof(data[0]);
    213   for (size_t i = 0; i < data_length; i++) {
    214     Swap(&data[i]);
    215   }
    216 }
    217 
    218 //
    219 // Character conversion routines
    220 //
    221 
    222 
    223 // Standard wide-character conversion routines depend on the system's own
    224 // idea of what width a wide character should be: some use 16 bits, and
    225 // some use 32 bits.  For the purposes of a minidump, wide strings are
    226 // always represented with 16-bit UTF-16 chracters.  iconv isn't available
    227 // everywhere, and its interface varies where it is available.  iconv also
    228 // deals purely with char* pointers, so in addition to considering the swap
    229 // parameter, a converter that uses iconv would also need to take the host
    230 // CPU's endianness into consideration.  It doesn't seems worth the trouble
    231 // of making it a dependency when we don't care about anything but UTF-16.
    232 static string* UTF16ToUTF8(const vector<uint16_t>& in,
    233                            bool swap) {
    234   scoped_ptr<string> out(new string());
    235 
    236   // Set the string's initial capacity to the number of UTF-16 characters,
    237   // because the UTF-8 representation will always be at least this long.
    238   // If the UTF-8 representation is longer, the string will grow dynamically.
    239   out->reserve(in.size());
    240 
    241   for (vector<uint16_t>::const_iterator iterator = in.begin();
    242        iterator != in.end();
    243        ++iterator) {
    244     // Get a 16-bit value from the input
    245     uint16_t in_word = *iterator;
    246     if (swap)
    247       Swap(&in_word);
    248 
    249     // Convert the input value (in_word) into a Unicode code point (unichar).
    250     uint32_t unichar;
    251     if (in_word >= 0xdc00 && in_word <= 0xdcff) {
    252       BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
    253                       HexString(in_word) << " without high";
    254       return NULL;
    255     } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
    256       // High surrogate.
    257       unichar = (in_word - 0xd7c0) << 10;
    258       if (++iterator == in.end()) {
    259         BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
    260                         HexString(in_word) << " at end of string";
    261         return NULL;
    262       }
    263       uint32_t high_word = in_word;
    264       in_word = *iterator;
    265       if (in_word < 0xdc00 || in_word > 0xdcff) {
    266         BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
    267                         HexString(high_word) << " without low " <<
    268                         HexString(in_word);
    269         return NULL;
    270       }
    271       unichar |= in_word & 0x03ff;
    272     } else {
    273       // The ordinary case, a single non-surrogate Unicode character encoded
    274       // as a single 16-bit value.
    275       unichar = in_word;
    276     }
    277 
    278     // Convert the Unicode code point (unichar) into its UTF-8 representation,
    279     // appending it to the out string.
    280     if (unichar < 0x80) {
    281       (*out) += static_cast<char>(unichar);
    282     } else if (unichar < 0x800) {
    283       (*out) += 0xc0 | static_cast<char>(unichar >> 6);
    284       (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
    285     } else if (unichar < 0x10000) {
    286       (*out) += 0xe0 | static_cast<char>(unichar >> 12);
    287       (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
    288       (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
    289     } else if (unichar < 0x200000) {
    290       (*out) += 0xf0 | static_cast<char>(unichar >> 18);
    291       (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f);
    292       (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
    293       (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
    294     } else {
    295       BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
    296                       HexString(unichar) << " in UTF-8";
    297       return NULL;
    298     }
    299   }
    300 
    301   return out.release();
    302 }
    303 
    304 // Return the smaller of the number of code units in the UTF-16 string,
    305 // not including the terminating null word, or maxlen.
    306 static size_t UTF16codeunits(const uint16_t *string, size_t maxlen) {
    307   size_t count = 0;
    308   while (count < maxlen && string[count] != 0)
    309     count++;
    310   return count;
    311 }
    312 
    313 static inline void Swap(MDTimeZoneInformation* time_zone) {
    314   Swap(&time_zone->bias);
    315   // Skip time_zone->standard_name.  No need to swap UTF-16 fields.
    316   // The swap will be done as part of the conversion to UTF-8.
    317   Swap(&time_zone->standard_date);
    318   Swap(&time_zone->standard_bias);
    319   // Skip time_zone->daylight_name.  No need to swap UTF-16 fields.
    320   // The swap will be done as part of the conversion to UTF-8.
    321   Swap(&time_zone->daylight_date);
    322   Swap(&time_zone->daylight_bias);
    323 }
    324 
    325 static void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data,
    326                                            size_t max_length_in_bytes,
    327                                            string* utf8_result,
    328                                            bool swap) {
    329   // Since there is no explicit byte length for each string, use
    330   // UTF16codeunits to calculate word length, then derive byte
    331   // length from that.
    332   size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]);
    333   size_t word_length = UTF16codeunits(utf16_data, max_word_length);
    334   if (word_length > 0) {
    335     size_t byte_length = word_length * sizeof(utf16_data[0]);
    336     vector<uint16_t> utf16_vector(word_length);
    337     memcpy(&utf16_vector[0], &utf16_data[0], byte_length);
    338     scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap));
    339     if (temp.get()) {
    340       utf8_result->assign(*temp);
    341     }
    342   } else {
    343     utf8_result->clear();
    344   }
    345 }
    346 
    347 
    348 // For fields that may or may not be valid, PrintValueOrInvalid will print the
    349 // string "(invalid)" if the field is not valid, and will print the value if
    350 // the field is valid. The value is printed as hexadecimal or decimal.
    351 
    352 enum NumberFormat {
    353   kNumberFormatDecimal,
    354   kNumberFormatHexadecimal,
    355 };
    356 
    357 static void PrintValueOrInvalid(bool valid,
    358                                 NumberFormat number_format,
    359                                 uint32_t value) {
    360   if (!valid) {
    361     printf("(invalid)\n");
    362   } else if (number_format == kNumberFormatDecimal) {
    363     printf("%d\n", value);
    364   } else {
    365     printf("0x%x\n", value);
    366   }
    367 }
    368 
    369 // Converts a time_t to a string showing the time in UTC.
    370 string TimeTToUTCString(time_t tt) {
    371   struct tm timestruct;
    372 #ifdef _WIN32
    373   gmtime_s(&timestruct, &tt);
    374 #else
    375   gmtime_r(&tt, &timestruct);
    376 #endif
    377 
    378   char timestr[20];
    379   int rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
    380   if (rv == 0) {
    381     return string();
    382   }
    383 
    384   return string(timestr);
    385 }
    386 
    387 
    388 //
    389 // MinidumpObject
    390 //
    391 
    392 
    393 MinidumpObject::MinidumpObject(Minidump* minidump)
    394     : DumpObject(),
    395       minidump_(minidump) {
    396 }
    397 
    398 
    399 //
    400 // MinidumpStream
    401 //
    402 
    403 
    404 MinidumpStream::MinidumpStream(Minidump* minidump)
    405     : MinidumpObject(minidump) {
    406 }
    407 
    408 
    409 //
    410 // MinidumpContext
    411 //
    412 
    413 
    414 MinidumpContext::MinidumpContext(Minidump* minidump)
    415     : DumpContext(),
    416       minidump_(minidump) {
    417 }
    418 
    419 MinidumpContext::~MinidumpContext() {
    420 }
    421 
    422 bool MinidumpContext::Read(uint32_t expected_size) {
    423   valid_ = false;
    424 
    425   // Certain raw context types are currently assumed to have unique sizes.
    426   if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) {
    427     BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any "
    428                  << "other raw context";
    429     return false;
    430   }
    431   if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
    432     BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
    433                  << "other raw context";
    434     return false;
    435   }
    436   if (!IsContextSizeUnique(sizeof(MDRawContextARM64))) {
    437     BPLOG(ERROR) << "sizeof(MDRawContextARM64) cannot match the size of any "
    438                  << "other raw context";
    439     return false;
    440   }
    441 
    442   FreeContext();
    443 
    444   // First, figure out what type of CPU this context structure is for.
    445   // For some reason, the AMD64 Context doesn't have context_flags
    446   // at the beginning of the structure, so special case it here.
    447   if (expected_size == sizeof(MDRawContextAMD64)) {
    448     BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
    449 
    450     scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
    451     if (!minidump_->ReadBytes(context_amd64.get(),
    452                               sizeof(MDRawContextAMD64))) {
    453       BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
    454       return false;
    455     }
    456 
    457     if (minidump_->swap())
    458       Swap(&context_amd64->context_flags);
    459 
    460     uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
    461     if (cpu_type == 0) {
    462       if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
    463         context_amd64->context_flags |= cpu_type;
    464       } else {
    465         BPLOG(ERROR) << "Failed to preserve the current stream position";
    466         return false;
    467       }
    468     }
    469 
    470     if (cpu_type != MD_CONTEXT_AMD64) {
    471       // TODO: Fall through to switch below.
    472       // http://code.google.com/p/google-breakpad/issues/detail?id=550
    473       BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
    474       return false;
    475     }
    476 
    477     // Do this after reading the entire MDRawContext structure because
    478     // GetSystemInfo may seek minidump to a new position.
    479     if (!CheckAgainstSystemInfo(cpu_type)) {
    480       BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
    481       return false;
    482     }
    483 
    484     // Normalize the 128-bit types in the dump.
    485     // Since this is AMD64, by definition, the values are little-endian.
    486     for (unsigned int vr_index = 0;
    487          vr_index < MD_CONTEXT_AMD64_VR_COUNT;
    488          ++vr_index)
    489       Normalize128(&context_amd64->vector_register[vr_index], false);
    490 
    491     if (minidump_->swap()) {
    492       Swap(&context_amd64->p1_home);
    493       Swap(&context_amd64->p2_home);
    494       Swap(&context_amd64->p3_home);
    495       Swap(&context_amd64->p4_home);
    496       Swap(&context_amd64->p5_home);
    497       Swap(&context_amd64->p6_home);
    498       // context_flags is already swapped
    499       Swap(&context_amd64->mx_csr);
    500       Swap(&context_amd64->cs);
    501       Swap(&context_amd64->ds);
    502       Swap(&context_amd64->es);
    503       Swap(&context_amd64->fs);
    504       Swap(&context_amd64->ss);
    505       Swap(&context_amd64->eflags);
    506       Swap(&context_amd64->dr0);
    507       Swap(&context_amd64->dr1);
    508       Swap(&context_amd64->dr2);
    509       Swap(&context_amd64->dr3);
    510       Swap(&context_amd64->dr6);
    511       Swap(&context_amd64->dr7);
    512       Swap(&context_amd64->rax);
    513       Swap(&context_amd64->rcx);
    514       Swap(&context_amd64->rdx);
    515       Swap(&context_amd64->rbx);
    516       Swap(&context_amd64->rsp);
    517       Swap(&context_amd64->rbp);
    518       Swap(&context_amd64->rsi);
    519       Swap(&context_amd64->rdi);
    520       Swap(&context_amd64->r8);
    521       Swap(&context_amd64->r9);
    522       Swap(&context_amd64->r10);
    523       Swap(&context_amd64->r11);
    524       Swap(&context_amd64->r12);
    525       Swap(&context_amd64->r13);
    526       Swap(&context_amd64->r14);
    527       Swap(&context_amd64->r15);
    528       Swap(&context_amd64->rip);
    529       // FIXME: I'm not sure what actually determines
    530       // which member of the union {flt_save, sse_registers}
    531       // is valid.  We're not currently using either,
    532       // but it would be good to have them swapped properly.
    533 
    534       for (unsigned int vr_index = 0;
    535            vr_index < MD_CONTEXT_AMD64_VR_COUNT;
    536            ++vr_index)
    537         Swap(&context_amd64->vector_register[vr_index]);
    538       Swap(&context_amd64->vector_control);
    539       Swap(&context_amd64->debug_control);
    540       Swap(&context_amd64->last_branch_to_rip);
    541       Swap(&context_amd64->last_branch_from_rip);
    542       Swap(&context_amd64->last_exception_to_rip);
    543       Swap(&context_amd64->last_exception_from_rip);
    544     }
    545 
    546     SetContextFlags(context_amd64->context_flags);
    547 
    548     SetContextAMD64(context_amd64.release());
    549   } else if (expected_size == sizeof(MDRawContextPPC64)) {
    550     // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
    551     // in the else case have 32 bits |context_flags|, so special case it here.
    552     uint64_t context_flags;
    553     if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
    554       BPLOG(ERROR) << "MinidumpContext could not read context flags";
    555       return false;
    556     }
    557     if (minidump_->swap())
    558       Swap(&context_flags);
    559 
    560     uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
    561     scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
    562 
    563     if (cpu_type == 0) {
    564       if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
    565         context_ppc64->context_flags |= cpu_type;
    566       } else {
    567         BPLOG(ERROR) << "Failed to preserve the current stream position";
    568         return false;
    569       }
    570     }
    571 
    572     if (cpu_type != MD_CONTEXT_PPC64) {
    573       // TODO: Fall through to switch below.
    574       // http://code.google.com/p/google-breakpad/issues/detail?id=550
    575       BPLOG(ERROR) << "MinidumpContext not actually ppc64 context";
    576       return false;
    577     }
    578 
    579     // Set the context_flags member, which has already been read, and
    580     // read the rest of the structure beginning with the first member
    581     // after context_flags.
    582     context_ppc64->context_flags = context_flags;
    583 
    584     size_t flags_size = sizeof(context_ppc64->context_flags);
    585     uint8_t* context_after_flags =
    586           reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
    587     if (!minidump_->ReadBytes(context_after_flags,
    588                               sizeof(MDRawContextPPC64) - flags_size)) {
    589       BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
    590       return false;
    591     }
    592 
    593     // Do this after reading the entire MDRawContext structure because
    594     // GetSystemInfo may seek minidump to a new position.
    595     if (!CheckAgainstSystemInfo(cpu_type)) {
    596       BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
    597       return false;
    598     }
    599     if (minidump_->swap()) {
    600       // context_ppc64->context_flags was already swapped.
    601       Swap(&context_ppc64->srr0);
    602       Swap(&context_ppc64->srr1);
    603       for (unsigned int gpr_index = 0;
    604            gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
    605            ++gpr_index) {
    606         Swap(&context_ppc64->gpr[gpr_index]);
    607       }
    608       Swap(&context_ppc64->cr);
    609       Swap(&context_ppc64->xer);
    610       Swap(&context_ppc64->lr);
    611       Swap(&context_ppc64->ctr);
    612       Swap(&context_ppc64->vrsave);
    613       for (unsigned int fpr_index = 0;
    614            fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
    615            ++fpr_index) {
    616         Swap(&context_ppc64->float_save.fpregs[fpr_index]);
    617       }
    618       // Don't swap context_ppc64->float_save.fpscr_pad because it is only
    619       // used for padding.
    620       Swap(&context_ppc64->float_save.fpscr);
    621       for (unsigned int vr_index = 0;
    622            vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
    623            ++vr_index) {
    624         Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
    625         Swap(&context_ppc64->vector_save.save_vr[vr_index]);
    626       }
    627       Swap(&context_ppc64->vector_save.save_vscr);
    628       // Don't swap the padding fields in vector_save.
    629       Swap(&context_ppc64->vector_save.save_vrvalid);
    630     }
    631 
    632     SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags));
    633 
    634     // Check for data loss when converting context flags from uint64_t into
    635     // uint32_t
    636     if (static_cast<uint64_t>(GetContextFlags()) !=
    637         context_ppc64->context_flags) {
    638       BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
    639       return false;
    640     }
    641 
    642     SetContextPPC64(context_ppc64.release());
    643   } else if (expected_size == sizeof(MDRawContextARM64)) {
    644     // |context_flags| of MDRawContextARM64 is 64 bits, but other MDRawContext
    645     // in the else case have 32 bits |context_flags|, so special case it here.
    646     uint64_t context_flags;
    647 
    648     BPLOG(INFO) << "MinidumpContext: looks like ARM64 context";
    649 
    650     if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
    651       BPLOG(ERROR) << "MinidumpContext could not read context flags";
    652       return false;
    653     }
    654     if (minidump_->swap())
    655       Swap(&context_flags);
    656 
    657     scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64());
    658 
    659     uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
    660     if (cpu_type == 0) {
    661       if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
    662         context_arm64->context_flags |= cpu_type;
    663       } else {
    664         BPLOG(ERROR) << "Failed to preserve the current stream position";
    665         return false;
    666       }
    667     }
    668 
    669     if (cpu_type != MD_CONTEXT_ARM64) {
    670       // TODO: Fall through to switch below.
    671       // http://code.google.com/p/google-breakpad/issues/detail?id=550
    672       BPLOG(ERROR) << "MinidumpContext not actually arm64 context";
    673       return false;
    674     }
    675 
    676     // Set the context_flags member, which has already been read, and
    677     // read the rest of the structure beginning with the first member
    678     // after context_flags.
    679     context_arm64->context_flags = context_flags;
    680 
    681     size_t flags_size = sizeof(context_arm64->context_flags);
    682     uint8_t* context_after_flags =
    683         reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
    684     if (!minidump_->ReadBytes(context_after_flags,
    685                               sizeof(MDRawContextARM64) - flags_size)) {
    686       BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
    687       return false;
    688     }
    689 
    690     // Do this after reading the entire MDRawContext structure because
    691     // GetSystemInfo may seek minidump to a new position.
    692     if (!CheckAgainstSystemInfo(cpu_type)) {
    693       BPLOG(ERROR) << "MinidumpContext arm64 does not match system info";
    694       return false;
    695     }
    696 
    697     if (minidump_->swap()) {
    698       // context_arm64->context_flags was already swapped.
    699       for (unsigned int ireg_index = 0;
    700            ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
    701            ++ireg_index) {
    702         Swap(&context_arm64->iregs[ireg_index]);
    703       }
    704       Swap(&context_arm64->cpsr);
    705       Swap(&context_arm64->float_save.fpsr);
    706       Swap(&context_arm64->float_save.fpcr);
    707       for (unsigned int fpr_index = 0;
    708            fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
    709            ++fpr_index) {
    710         // While ARM64 is bi-endian, iOS (currently the only platform
    711         // for which ARM64 support has been brought up) uses ARM64 exclusively
    712         // in little-endian mode.
    713         Normalize128(&context_arm64->float_save.regs[fpr_index], false);
    714         Swap(&context_arm64->float_save.regs[fpr_index]);
    715       }
    716     }
    717     SetContextFlags(static_cast<uint32_t>(context_arm64->context_flags));
    718 
    719     // Check for data loss when converting context flags from uint64_t into
    720     // uint32_t
    721     if (static_cast<uint64_t>(GetContextFlags()) !=
    722         context_arm64->context_flags) {
    723       BPLOG(ERROR) << "Data loss detected when converting ARM64 context_flags";
    724       return false;
    725     }
    726 
    727     SetContextARM64(context_arm64.release());
    728   } else {
    729     uint32_t context_flags;
    730     if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
    731       BPLOG(ERROR) << "MinidumpContext could not read context flags";
    732       return false;
    733     }
    734     if (minidump_->swap())
    735       Swap(&context_flags);
    736 
    737     uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
    738     if (cpu_type == 0) {
    739       // Unfortunately the flag for MD_CONTEXT_ARM that was taken
    740       // from a Windows CE SDK header conflicts in practice with
    741       // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
    742       // but handle dumps with the legacy value gracefully here.
    743       if (context_flags & MD_CONTEXT_ARM_OLD) {
    744         context_flags |= MD_CONTEXT_ARM;
    745         context_flags &= ~MD_CONTEXT_ARM_OLD;
    746         cpu_type = MD_CONTEXT_ARM;
    747       }
    748     }
    749 
    750     if (cpu_type == 0) {
    751       if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
    752         context_flags |= cpu_type;
    753       } else {
    754         BPLOG(ERROR) << "Failed to preserve the current stream position";
    755         return false;
    756       }
    757     }
    758 
    759     // Allocate the context structure for the correct CPU and fill it.  The
    760     // casts are slightly unorthodox, but it seems better to do that than to
    761     // maintain a separate pointer for each type of CPU context structure
    762     // when only one of them will be used.
    763     switch (cpu_type) {
    764       case MD_CONTEXT_X86: {
    765         if (expected_size != sizeof(MDRawContextX86)) {
    766           BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
    767             expected_size << " != " << sizeof(MDRawContextX86);
    768           return false;
    769         }
    770 
    771         scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
    772 
    773         // Set the context_flags member, which has already been read, and
    774         // read the rest of the structure beginning with the first member
    775         // after context_flags.
    776         context_x86->context_flags = context_flags;
    777 
    778         size_t flags_size = sizeof(context_x86->context_flags);
    779         uint8_t* context_after_flags =
    780           reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
    781         if (!minidump_->ReadBytes(context_after_flags,
    782                                   sizeof(MDRawContextX86) - flags_size)) {
    783           BPLOG(ERROR) << "MinidumpContext could not read x86 context";
    784           return false;
    785         }
    786 
    787         // Do this after reading the entire MDRawContext structure because
    788         // GetSystemInfo may seek minidump to a new position.
    789         if (!CheckAgainstSystemInfo(cpu_type)) {
    790           BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
    791           return false;
    792         }
    793 
    794         if (minidump_->swap()) {
    795           // context_x86->context_flags was already swapped.
    796           Swap(&context_x86->dr0);
    797           Swap(&context_x86->dr1);
    798           Swap(&context_x86->dr2);
    799           Swap(&context_x86->dr3);
    800           Swap(&context_x86->dr6);
    801           Swap(&context_x86->dr7);
    802           Swap(&context_x86->float_save.control_word);
    803           Swap(&context_x86->float_save.status_word);
    804           Swap(&context_x86->float_save.tag_word);
    805           Swap(&context_x86->float_save.error_offset);
    806           Swap(&context_x86->float_save.error_selector);
    807           Swap(&context_x86->float_save.data_offset);
    808           Swap(&context_x86->float_save.data_selector);
    809           // context_x86->float_save.register_area[] contains 8-bit quantities
    810           // and does not need to be swapped.
    811           Swap(&context_x86->float_save.cr0_npx_state);
    812           Swap(&context_x86->gs);
    813           Swap(&context_x86->fs);
    814           Swap(&context_x86->es);
    815           Swap(&context_x86->ds);
    816           Swap(&context_x86->edi);
    817           Swap(&context_x86->esi);
    818           Swap(&context_x86->ebx);
    819           Swap(&context_x86->edx);
    820           Swap(&context_x86->ecx);
    821           Swap(&context_x86->eax);
    822           Swap(&context_x86->ebp);
    823           Swap(&context_x86->eip);
    824           Swap(&context_x86->cs);
    825           Swap(&context_x86->eflags);
    826           Swap(&context_x86->esp);
    827           Swap(&context_x86->ss);
    828           // context_x86->extended_registers[] contains 8-bit quantities and
    829           // does not need to be swapped.
    830         }
    831 
    832         SetContextX86(context_x86.release());
    833 
    834         break;
    835       }
    836 
    837       case MD_CONTEXT_PPC: {
    838         if (expected_size != sizeof(MDRawContextPPC)) {
    839           BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
    840             expected_size << " != " << sizeof(MDRawContextPPC);
    841           return false;
    842         }
    843 
    844         scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
    845 
    846         // Set the context_flags member, which has already been read, and
    847         // read the rest of the structure beginning with the first member
    848         // after context_flags.
    849         context_ppc->context_flags = context_flags;
    850 
    851         size_t flags_size = sizeof(context_ppc->context_flags);
    852         uint8_t* context_after_flags =
    853           reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
    854         if (!minidump_->ReadBytes(context_after_flags,
    855                                   sizeof(MDRawContextPPC) - flags_size)) {
    856           BPLOG(ERROR) << "MinidumpContext could not read ppc context";
    857           return false;
    858         }
    859 
    860         // Do this after reading the entire MDRawContext structure because
    861         // GetSystemInfo may seek minidump to a new position.
    862         if (!CheckAgainstSystemInfo(cpu_type)) {
    863           BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
    864           return false;
    865         }
    866 
    867         // Normalize the 128-bit types in the dump.
    868         // Since this is PowerPC, by definition, the values are big-endian.
    869         for (unsigned int vr_index = 0;
    870              vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
    871              ++vr_index) {
    872           Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
    873         }
    874 
    875         if (minidump_->swap()) {
    876           // context_ppc->context_flags was already swapped.
    877           Swap(&context_ppc->srr0);
    878           Swap(&context_ppc->srr1);
    879           for (unsigned int gpr_index = 0;
    880                gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
    881                ++gpr_index) {
    882             Swap(&context_ppc->gpr[gpr_index]);
    883           }
    884           Swap(&context_ppc->cr);
    885           Swap(&context_ppc->xer);
    886           Swap(&context_ppc->lr);
    887           Swap(&context_ppc->ctr);
    888           Swap(&context_ppc->mq);
    889           Swap(&context_ppc->vrsave);
    890           for (unsigned int fpr_index = 0;
    891                fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
    892                ++fpr_index) {
    893             Swap(&context_ppc->float_save.fpregs[fpr_index]);
    894           }
    895           // Don't swap context_ppc->float_save.fpscr_pad because it is only
    896           // used for padding.
    897           Swap(&context_ppc->float_save.fpscr);
    898           for (unsigned int vr_index = 0;
    899                vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
    900                ++vr_index) {
    901             Swap(&context_ppc->vector_save.save_vr[vr_index]);
    902           }
    903           Swap(&context_ppc->vector_save.save_vscr);
    904           // Don't swap the padding fields in vector_save.
    905           Swap(&context_ppc->vector_save.save_vrvalid);
    906         }
    907 
    908         SetContextPPC(context_ppc.release());
    909 
    910         break;
    911       }
    912 
    913       case MD_CONTEXT_SPARC: {
    914         if (expected_size != sizeof(MDRawContextSPARC)) {
    915           BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
    916             expected_size << " != " << sizeof(MDRawContextSPARC);
    917           return false;
    918         }
    919 
    920         scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
    921 
    922         // Set the context_flags member, which has already been read, and
    923         // read the rest of the structure beginning with the first member
    924         // after context_flags.
    925         context_sparc->context_flags = context_flags;
    926 
    927         size_t flags_size = sizeof(context_sparc->context_flags);
    928         uint8_t* context_after_flags =
    929             reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
    930         if (!minidump_->ReadBytes(context_after_flags,
    931                                   sizeof(MDRawContextSPARC) - flags_size)) {
    932           BPLOG(ERROR) << "MinidumpContext could not read sparc context";
    933           return false;
    934         }
    935 
    936         // Do this after reading the entire MDRawContext structure because
    937         // GetSystemInfo may seek minidump to a new position.
    938         if (!CheckAgainstSystemInfo(cpu_type)) {
    939           BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
    940           return false;
    941         }
    942 
    943         if (minidump_->swap()) {
    944           // context_sparc->context_flags was already swapped.
    945           for (unsigned int gpr_index = 0;
    946                gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
    947                ++gpr_index) {
    948             Swap(&context_sparc->g_r[gpr_index]);
    949           }
    950           Swap(&context_sparc->ccr);
    951           Swap(&context_sparc->pc);
    952           Swap(&context_sparc->npc);
    953           Swap(&context_sparc->y);
    954           Swap(&context_sparc->asi);
    955           Swap(&context_sparc->fprs);
    956           for (unsigned int fpr_index = 0;
    957                fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
    958                ++fpr_index) {
    959             Swap(&context_sparc->float_save.regs[fpr_index]);
    960           }
    961           Swap(&context_sparc->float_save.filler);
    962           Swap(&context_sparc->float_save.fsr);
    963         }
    964         SetContextSPARC(context_sparc.release());
    965 
    966         break;
    967       }
    968 
    969       case MD_CONTEXT_ARM: {
    970         if (expected_size != sizeof(MDRawContextARM)) {
    971           BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
    972             expected_size << " != " << sizeof(MDRawContextARM);
    973           return false;
    974         }
    975 
    976         scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
    977 
    978         // Set the context_flags member, which has already been read, and
    979         // read the rest of the structure beginning with the first member
    980         // after context_flags.
    981         context_arm->context_flags = context_flags;
    982 
    983         size_t flags_size = sizeof(context_arm->context_flags);
    984         uint8_t* context_after_flags =
    985             reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
    986         if (!minidump_->ReadBytes(context_after_flags,
    987                                   sizeof(MDRawContextARM) - flags_size)) {
    988           BPLOG(ERROR) << "MinidumpContext could not read arm context";
    989           return false;
    990         }
    991 
    992         // Do this after reading the entire MDRawContext structure because
    993         // GetSystemInfo may seek minidump to a new position.
    994         if (!CheckAgainstSystemInfo(cpu_type)) {
    995           BPLOG(ERROR) << "MinidumpContext arm does not match system info";
    996           return false;
    997         }
    998 
    999         if (minidump_->swap()) {
   1000           // context_arm->context_flags was already swapped.
   1001           for (unsigned int ireg_index = 0;
   1002                ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
   1003                ++ireg_index) {
   1004             Swap(&context_arm->iregs[ireg_index]);
   1005           }
   1006           Swap(&context_arm->cpsr);
   1007           Swap(&context_arm->float_save.fpscr);
   1008           for (unsigned int fpr_index = 0;
   1009                fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
   1010                ++fpr_index) {
   1011             Swap(&context_arm->float_save.regs[fpr_index]);
   1012           }
   1013           for (unsigned int fpe_index = 0;
   1014                fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
   1015                ++fpe_index) {
   1016             Swap(&context_arm->float_save.extra[fpe_index]);
   1017           }
   1018         }
   1019         SetContextARM(context_arm.release());
   1020 
   1021         break;
   1022       }
   1023 
   1024       case MD_CONTEXT_MIPS: {
   1025         if (expected_size != sizeof(MDRawContextMIPS)) {
   1026           BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
   1027                        << expected_size
   1028                        << " != "
   1029                        << sizeof(MDRawContextMIPS);
   1030           return false;
   1031         }
   1032 
   1033         scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
   1034 
   1035         // Set the context_flags member, which has already been read, and
   1036         // read the rest of the structure beginning with the first member
   1037         // after context_flags.
   1038         context_mips->context_flags = context_flags;
   1039 
   1040         size_t flags_size = sizeof(context_mips->context_flags);
   1041         uint8_t* context_after_flags =
   1042             reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
   1043         if (!minidump_->ReadBytes(context_after_flags,
   1044                                   sizeof(MDRawContextMIPS) - flags_size)) {
   1045           BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
   1046           return false;
   1047         }
   1048 
   1049         // Do this after reading the entire MDRawContext structure because
   1050         // GetSystemInfo may seek minidump to a new position.
   1051         if (!CheckAgainstSystemInfo(cpu_type)) {
   1052           BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
   1053           return false;
   1054         }
   1055 
   1056         if (minidump_->swap()) {
   1057           // context_mips->context_flags was already swapped.
   1058           for (int ireg_index = 0;
   1059                ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
   1060                ++ireg_index) {
   1061             Swap(&context_mips->iregs[ireg_index]);
   1062           }
   1063 	  Swap(&context_mips->mdhi);
   1064 	  Swap(&context_mips->mdlo);
   1065           for (int dsp_index = 0;
   1066                dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
   1067                ++dsp_index) {
   1068             Swap(&context_mips->hi[dsp_index]);
   1069             Swap(&context_mips->lo[dsp_index]);
   1070           }
   1071 	  Swap(&context_mips->dsp_control);
   1072           Swap(&context_mips->epc);
   1073           Swap(&context_mips->badvaddr);
   1074           Swap(&context_mips->status);
   1075           Swap(&context_mips->cause);
   1076           for (int fpr_index = 0;
   1077                fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
   1078                ++fpr_index) {
   1079             Swap(&context_mips->float_save.regs[fpr_index]);
   1080           }
   1081           Swap(&context_mips->float_save.fpcsr);
   1082           Swap(&context_mips->float_save.fir);
   1083         }
   1084         SetContextMIPS(context_mips.release());
   1085 
   1086         break;
   1087       }
   1088 
   1089       default: {
   1090         // Unknown context type - Don't log as an error yet. Let the
   1091         // caller work that out.
   1092         BPLOG(INFO) << "MinidumpContext unknown context type " <<
   1093           HexString(cpu_type);
   1094         return false;
   1095         break;
   1096       }
   1097     }
   1098     SetContextFlags(context_flags);
   1099   }
   1100 
   1101   valid_ = true;
   1102   return true;
   1103 }
   1104 
   1105 bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
   1106   // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
   1107   // as this function just implements a sanity check.
   1108   MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
   1109   if (!system_info) {
   1110     BPLOG(INFO) << "MinidumpContext could not be compared against "
   1111                    "MinidumpSystemInfo";
   1112     return true;
   1113   }
   1114 
   1115   // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
   1116   const MDRawSystemInfo* raw_system_info = system_info->system_info();
   1117   if (!raw_system_info) {
   1118     BPLOG(INFO) << "MinidumpContext could not be compared against "
   1119                    "MDRawSystemInfo";
   1120     return false;
   1121   }
   1122 
   1123   MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
   1124       raw_system_info->processor_architecture);
   1125 
   1126   // Compare the CPU type of the context record to the CPU type in the
   1127   // minidump's system info stream.
   1128   bool return_value = false;
   1129   switch (context_cpu_type) {
   1130     case MD_CONTEXT_X86:
   1131       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
   1132           system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
   1133           system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
   1134         return_value = true;
   1135       }
   1136       break;
   1137 
   1138     case MD_CONTEXT_PPC:
   1139       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
   1140         return_value = true;
   1141       break;
   1142 
   1143     case MD_CONTEXT_PPC64:
   1144       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64)
   1145         return_value = true;
   1146       break;
   1147 
   1148     case MD_CONTEXT_AMD64:
   1149       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
   1150         return_value = true;
   1151       break;
   1152 
   1153     case MD_CONTEXT_SPARC:
   1154       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
   1155         return_value = true;
   1156       break;
   1157 
   1158     case MD_CONTEXT_ARM:
   1159       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
   1160         return_value = true;
   1161       break;
   1162 
   1163     case MD_CONTEXT_ARM64:
   1164       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64)
   1165         return_value = true;
   1166       break;
   1167 
   1168     case MD_CONTEXT_MIPS:
   1169       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS)
   1170         return_value = true;
   1171       break;
   1172   }
   1173 
   1174   BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
   1175                                     HexString(context_cpu_type) <<
   1176                                     " wrong for MinidumpSystemInfo CPU " <<
   1177                                     HexString(system_info_cpu_type);
   1178 
   1179   return return_value;
   1180 }
   1181 
   1182 
   1183 //
   1184 // MinidumpMemoryRegion
   1185 //
   1186 
   1187 
   1188 uint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
   1189 
   1190 
   1191 MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
   1192     : MinidumpObject(minidump),
   1193       descriptor_(NULL),
   1194       memory_(NULL) {
   1195 }
   1196 
   1197 
   1198 MinidumpMemoryRegion::~MinidumpMemoryRegion() {
   1199   delete memory_;
   1200 }
   1201 
   1202 
   1203 void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
   1204   descriptor_ = descriptor;
   1205   valid_ = descriptor &&
   1206            descriptor_->memory.data_size <=
   1207                numeric_limits<uint64_t>::max() -
   1208                descriptor_->start_of_memory_range;
   1209 }
   1210 
   1211 
   1212 const uint8_t* MinidumpMemoryRegion::GetMemory() const {
   1213   if (!valid_) {
   1214     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
   1215     return NULL;
   1216   }
   1217 
   1218   if (!memory_) {
   1219     if (descriptor_->memory.data_size == 0) {
   1220       BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
   1221       return NULL;
   1222     }
   1223 
   1224     if (!minidump_->SeekSet(descriptor_->memory.rva)) {
   1225       BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
   1226       return NULL;
   1227     }
   1228 
   1229     if (descriptor_->memory.data_size > max_bytes_) {
   1230       BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
   1231                       descriptor_->memory.data_size << " exceeds maximum " <<
   1232                       max_bytes_;
   1233       return NULL;
   1234     }
   1235 
   1236     scoped_ptr< vector<uint8_t> > memory(
   1237         new vector<uint8_t>(descriptor_->memory.data_size));
   1238 
   1239     if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
   1240       BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
   1241       return NULL;
   1242     }
   1243 
   1244     memory_ = memory.release();
   1245   }
   1246 
   1247   return &(*memory_)[0];
   1248 }
   1249 
   1250 
   1251 uint64_t MinidumpMemoryRegion::GetBase() const {
   1252   if (!valid_) {
   1253     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
   1254     return static_cast<uint64_t>(-1);
   1255   }
   1256 
   1257   return descriptor_->start_of_memory_range;
   1258 }
   1259 
   1260 
   1261 uint32_t MinidumpMemoryRegion::GetSize() const {
   1262   if (!valid_) {
   1263     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
   1264     return 0;
   1265   }
   1266 
   1267   return descriptor_->memory.data_size;
   1268 }
   1269 
   1270 
   1271 void MinidumpMemoryRegion::FreeMemory() {
   1272   delete memory_;
   1273   memory_ = NULL;
   1274 }
   1275 
   1276 
   1277 template<typename T>
   1278 bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address,
   1279                                                       T*        value) const {
   1280   BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
   1281                              "requires |value|";
   1282   assert(value);
   1283   *value = 0;
   1284 
   1285   if (!valid_) {
   1286     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
   1287                     "GetMemoryAtAddressInternal";
   1288     return false;
   1289   }
   1290 
   1291   // Common failure case
   1292   if (address < descriptor_->start_of_memory_range ||
   1293       sizeof(T) > numeric_limits<uint64_t>::max() - address ||
   1294       address + sizeof(T) > descriptor_->start_of_memory_range +
   1295                             descriptor_->memory.data_size) {
   1296     BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
   1297                     HexString(address) << "+" << sizeof(T) << "/" <<
   1298                     HexString(descriptor_->start_of_memory_range) << "+" <<
   1299                     HexString(descriptor_->memory.data_size);
   1300     return false;
   1301   }
   1302 
   1303   const uint8_t* memory = GetMemory();
   1304   if (!memory) {
   1305     // GetMemory already logged a perfectly good message.
   1306     return false;
   1307   }
   1308 
   1309   // If the CPU requires memory accesses to be aligned, this can crash.
   1310   // x86 and ppc are able to cope, though.
   1311   *value = *reinterpret_cast<const T*>(
   1312       &memory[address - descriptor_->start_of_memory_range]);
   1313 
   1314   if (minidump_->swap())
   1315     Swap(value);
   1316 
   1317   return true;
   1318 }
   1319 
   1320 
   1321 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
   1322                                               uint8_t*  value) const {
   1323   return GetMemoryAtAddressInternal(address, value);
   1324 }
   1325 
   1326 
   1327 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
   1328                                               uint16_t* value) const {
   1329   return GetMemoryAtAddressInternal(address, value);
   1330 }
   1331 
   1332 
   1333 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
   1334                                               uint32_t* value) const {
   1335   return GetMemoryAtAddressInternal(address, value);
   1336 }
   1337 
   1338 
   1339 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t  address,
   1340                                               uint64_t* value) const {
   1341   return GetMemoryAtAddressInternal(address, value);
   1342 }
   1343 
   1344 
   1345 void MinidumpMemoryRegion::Print() const {
   1346   if (!valid_) {
   1347     BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
   1348     return;
   1349   }
   1350 
   1351   const uint8_t* memory = GetMemory();
   1352   if (memory) {
   1353     printf("0x");
   1354     for (unsigned int byte_index = 0;
   1355          byte_index < descriptor_->memory.data_size;
   1356          byte_index++) {
   1357       printf("%02x", memory[byte_index]);
   1358     }
   1359     printf("\n");
   1360   } else {
   1361     printf("No memory\n");
   1362   }
   1363 }
   1364 
   1365 
   1366 //
   1367 // MinidumpThread
   1368 //
   1369 
   1370 
   1371 MinidumpThread::MinidumpThread(Minidump* minidump)
   1372     : MinidumpObject(minidump),
   1373       thread_(),
   1374       memory_(NULL),
   1375       context_(NULL) {
   1376 }
   1377 
   1378 
   1379 MinidumpThread::~MinidumpThread() {
   1380   delete memory_;
   1381   delete context_;
   1382 }
   1383 
   1384 
   1385 bool MinidumpThread::Read() {
   1386   // Invalidate cached data.
   1387   delete memory_;
   1388   memory_ = NULL;
   1389   delete context_;
   1390   context_ = NULL;
   1391 
   1392   valid_ = false;
   1393 
   1394   if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
   1395     BPLOG(ERROR) << "MinidumpThread cannot read thread";
   1396     return false;
   1397   }
   1398 
   1399   if (minidump_->swap()) {
   1400     Swap(&thread_.thread_id);
   1401     Swap(&thread_.suspend_count);
   1402     Swap(&thread_.priority_class);
   1403     Swap(&thread_.priority);
   1404     Swap(&thread_.teb);
   1405     Swap(&thread_.stack);
   1406     Swap(&thread_.thread_context);
   1407   }
   1408 
   1409   // Check for base + size overflow or undersize.
   1410   if (thread_.stack.memory.rva == 0 ||
   1411       thread_.stack.memory.data_size == 0 ||
   1412       thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() -
   1413                                        thread_.stack.start_of_memory_range) {
   1414     // This is ok, but log an error anyway.
   1415     BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
   1416                     HexString(thread_.stack.start_of_memory_range) << "+" <<
   1417                     HexString(thread_.stack.memory.data_size) <<
   1418                     ", RVA 0x" << HexString(thread_.stack.memory.rva);
   1419   } else {
   1420     memory_ = new MinidumpMemoryRegion(minidump_);
   1421     memory_->SetDescriptor(&thread_.stack);
   1422   }
   1423 
   1424   valid_ = true;
   1425   return true;
   1426 }
   1427 
   1428 uint64_t MinidumpThread::GetStartOfStackMemoryRange() const {
   1429   if (!valid_) {
   1430     BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread";
   1431     return 0;
   1432   }
   1433 
   1434   return thread_.stack.start_of_memory_range;
   1435 }
   1436 
   1437 MinidumpMemoryRegion* MinidumpThread::GetMemory() {
   1438   if (!valid_) {
   1439     BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
   1440     return NULL;
   1441   }
   1442 
   1443   return memory_;
   1444 }
   1445 
   1446 
   1447 MinidumpContext* MinidumpThread::GetContext() {
   1448   if (!valid_) {
   1449     BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
   1450     return NULL;
   1451   }
   1452 
   1453   if (!context_) {
   1454     if (!minidump_->SeekSet(thread_.thread_context.rva)) {
   1455       BPLOG(ERROR) << "MinidumpThread cannot seek to context";
   1456       return NULL;
   1457     }
   1458 
   1459     scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
   1460 
   1461     if (!context->Read(thread_.thread_context.data_size)) {
   1462       BPLOG(ERROR) << "MinidumpThread cannot read context";
   1463       return NULL;
   1464     }
   1465 
   1466     context_ = context.release();
   1467   }
   1468 
   1469   return context_;
   1470 }
   1471 
   1472 
   1473 bool MinidumpThread::GetThreadID(uint32_t *thread_id) const {
   1474   BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
   1475                                  "|thread_id|";
   1476   assert(thread_id);
   1477   *thread_id = 0;
   1478 
   1479   if (!valid_) {
   1480     BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
   1481     return false;
   1482   }
   1483 
   1484   *thread_id = thread_.thread_id;
   1485   return true;
   1486 }
   1487 
   1488 
   1489 void MinidumpThread::Print() {
   1490   if (!valid_) {
   1491     BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
   1492     return;
   1493   }
   1494 
   1495   printf("MDRawThread\n");
   1496   printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
   1497   printf("  suspend_count               = %d\n",     thread_.suspend_count);
   1498   printf("  priority_class              = 0x%x\n",   thread_.priority_class);
   1499   printf("  priority                    = 0x%x\n",   thread_.priority);
   1500   printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
   1501   printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
   1502          thread_.stack.start_of_memory_range);
   1503   printf("  stack.memory.data_size      = 0x%x\n",
   1504          thread_.stack.memory.data_size);
   1505   printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
   1506   printf("  thread_context.data_size    = 0x%x\n",
   1507          thread_.thread_context.data_size);
   1508   printf("  thread_context.rva          = 0x%x\n",
   1509          thread_.thread_context.rva);
   1510 
   1511   MinidumpContext* context = GetContext();
   1512   if (context) {
   1513     printf("\n");
   1514     context->Print();
   1515   } else {
   1516     printf("  (no context)\n");
   1517     printf("\n");
   1518   }
   1519 
   1520   MinidumpMemoryRegion* memory = GetMemory();
   1521   if (memory) {
   1522     printf("Stack\n");
   1523     memory->Print();
   1524   } else {
   1525     printf("No stack\n");
   1526   }
   1527   printf("\n");
   1528 }
   1529 
   1530 
   1531 //
   1532 // MinidumpThreadList
   1533 //
   1534 
   1535 
   1536 uint32_t MinidumpThreadList::max_threads_ = 4096;
   1537 
   1538 
   1539 MinidumpThreadList::MinidumpThreadList(Minidump* minidump)
   1540     : MinidumpStream(minidump),
   1541       id_to_thread_map_(),
   1542       threads_(NULL),
   1543       thread_count_(0) {
   1544 }
   1545 
   1546 
   1547 MinidumpThreadList::~MinidumpThreadList() {
   1548   delete threads_;
   1549 }
   1550 
   1551 
   1552 bool MinidumpThreadList::Read(uint32_t expected_size) {
   1553   // Invalidate cached data.
   1554   id_to_thread_map_.clear();
   1555   delete threads_;
   1556   threads_ = NULL;
   1557   thread_count_ = 0;
   1558 
   1559   valid_ = false;
   1560 
   1561   uint32_t thread_count;
   1562   if (expected_size < sizeof(thread_count)) {
   1563     BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
   1564                     expected_size << " < " << sizeof(thread_count);
   1565     return false;
   1566   }
   1567   if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
   1568     BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
   1569     return false;
   1570   }
   1571 
   1572   if (minidump_->swap())
   1573     Swap(&thread_count);
   1574 
   1575   if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) {
   1576     BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
   1577                     " would cause multiplication overflow";
   1578     return false;
   1579   }
   1580 
   1581   if (expected_size != sizeof(thread_count) +
   1582                        thread_count * sizeof(MDRawThread)) {
   1583     // may be padded with 4 bytes on 64bit ABIs for alignment
   1584     if (expected_size == sizeof(thread_count) + 4 +
   1585                          thread_count * sizeof(MDRawThread)) {
   1586       uint32_t useless;
   1587       if (!minidump_->ReadBytes(&useless, 4)) {
   1588         BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded "
   1589                         "bytes";
   1590         return false;
   1591       }
   1592     } else {
   1593       BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
   1594                     " != " << sizeof(thread_count) +
   1595                     thread_count * sizeof(MDRawThread);
   1596       return false;
   1597     }
   1598   }
   1599 
   1600 
   1601   if (thread_count > max_threads_) {
   1602     BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
   1603                     " exceeds maximum " << max_threads_;
   1604     return false;
   1605   }
   1606 
   1607   if (thread_count != 0) {
   1608     scoped_ptr<MinidumpThreads> threads(
   1609         new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
   1610 
   1611     for (unsigned int thread_index = 0;
   1612          thread_index < thread_count;
   1613          ++thread_index) {
   1614       MinidumpThread* thread = &(*threads)[thread_index];
   1615 
   1616       // Assume that the file offset is correct after the last read.
   1617       if (!thread->Read()) {
   1618         BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
   1619                         thread_index << "/" << thread_count;
   1620         return false;
   1621       }
   1622 
   1623       uint32_t thread_id;
   1624       if (!thread->GetThreadID(&thread_id)) {
   1625         BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
   1626                         thread_index << "/" << thread_count;
   1627         return false;
   1628       }
   1629 
   1630       if (GetThreadByID(thread_id)) {
   1631         // Another thread with this ID is already in the list.  Data error.
   1632         BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
   1633                         HexString(thread_id) << " at thread " <<
   1634                         thread_index << "/" << thread_count;
   1635         return false;
   1636       }
   1637       id_to_thread_map_[thread_id] = thread;
   1638     }
   1639 
   1640     threads_ = threads.release();
   1641   }
   1642 
   1643   thread_count_ = thread_count;
   1644 
   1645   valid_ = true;
   1646   return true;
   1647 }
   1648 
   1649 
   1650 MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
   1651     const {
   1652   if (!valid_) {
   1653     BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
   1654     return NULL;
   1655   }
   1656 
   1657   if (index >= thread_count_) {
   1658     BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
   1659                     index << "/" << thread_count_;
   1660     return NULL;
   1661   }
   1662 
   1663   return &(*threads_)[index];
   1664 }
   1665 
   1666 
   1667 MinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) {
   1668   // Don't check valid_.  Read calls this method before everything is
   1669   // validated.  It is safe to not check valid_ here.
   1670   return id_to_thread_map_[thread_id];
   1671 }
   1672 
   1673 
   1674 void MinidumpThreadList::Print() {
   1675   if (!valid_) {
   1676     BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
   1677     return;
   1678   }
   1679 
   1680   printf("MinidumpThreadList\n");
   1681   printf("  thread_count = %d\n", thread_count_);
   1682   printf("\n");
   1683 
   1684   for (unsigned int thread_index = 0;
   1685        thread_index < thread_count_;
   1686        ++thread_index) {
   1687     printf("thread[%d]\n", thread_index);
   1688 
   1689     (*threads_)[thread_index].Print();
   1690   }
   1691 }
   1692 
   1693 
   1694 //
   1695 // MinidumpModule
   1696 //
   1697 
   1698 
   1699 uint32_t MinidumpModule::max_cv_bytes_ = 32768;
   1700 uint32_t MinidumpModule::max_misc_bytes_ = 32768;
   1701 
   1702 
   1703 MinidumpModule::MinidumpModule(Minidump* minidump)
   1704     : MinidumpObject(minidump),
   1705       module_valid_(false),
   1706       has_debug_info_(false),
   1707       module_(),
   1708       name_(NULL),
   1709       cv_record_(NULL),
   1710       cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
   1711       misc_record_(NULL) {
   1712 }
   1713 
   1714 
   1715 MinidumpModule::~MinidumpModule() {
   1716   delete name_;
   1717   delete cv_record_;
   1718   delete misc_record_;
   1719 }
   1720 
   1721 
   1722 bool MinidumpModule::Read() {
   1723   // Invalidate cached data.
   1724   delete name_;
   1725   name_ = NULL;
   1726   delete cv_record_;
   1727   cv_record_ = NULL;
   1728   cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
   1729   delete misc_record_;
   1730   misc_record_ = NULL;
   1731 
   1732   module_valid_ = false;
   1733   has_debug_info_ = false;
   1734   valid_ = false;
   1735 
   1736   if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
   1737     BPLOG(ERROR) << "MinidumpModule cannot read module";
   1738     return false;
   1739   }
   1740 
   1741   if (minidump_->swap()) {
   1742     Swap(&module_.base_of_image);
   1743     Swap(&module_.size_of_image);
   1744     Swap(&module_.checksum);
   1745     Swap(&module_.time_date_stamp);
   1746     Swap(&module_.module_name_rva);
   1747     Swap(&module_.version_info.signature);
   1748     Swap(&module_.version_info.struct_version);
   1749     Swap(&module_.version_info.file_version_hi);
   1750     Swap(&module_.version_info.file_version_lo);
   1751     Swap(&module_.version_info.product_version_hi);
   1752     Swap(&module_.version_info.product_version_lo);
   1753     Swap(&module_.version_info.file_flags_mask);
   1754     Swap(&module_.version_info.file_flags);
   1755     Swap(&module_.version_info.file_os);
   1756     Swap(&module_.version_info.file_type);
   1757     Swap(&module_.version_info.file_subtype);
   1758     Swap(&module_.version_info.file_date_hi);
   1759     Swap(&module_.version_info.file_date_lo);
   1760     Swap(&module_.cv_record);
   1761     Swap(&module_.misc_record);
   1762     // Don't swap reserved fields because their contents are unknown (as
   1763     // are their proper widths).
   1764   }
   1765 
   1766   // Check for base + size overflow or undersize.
   1767   if (module_.size_of_image == 0 ||
   1768       module_.size_of_image >
   1769           numeric_limits<uint64_t>::max() - module_.base_of_image) {
   1770     BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
   1771                     HexString(module_.base_of_image) << "+" <<
   1772                     HexString(module_.size_of_image);
   1773     return false;
   1774   }
   1775 
   1776   module_valid_ = true;
   1777   return true;
   1778 }
   1779 
   1780 
   1781 bool MinidumpModule::ReadAuxiliaryData() {
   1782   if (!module_valid_) {
   1783     BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
   1784     return false;
   1785   }
   1786 
   1787   // Each module must have a name.
   1788   name_ = minidump_->ReadString(module_.module_name_rva);
   1789   if (!name_) {
   1790     BPLOG(ERROR) << "MinidumpModule could not read name";
   1791     return false;
   1792   }
   1793 
   1794   // At this point, we have enough info for the module to be valid.
   1795   valid_ = true;
   1796 
   1797   // CodeView and miscellaneous debug records are only required if the
   1798   // module indicates that they exist.
   1799   if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
   1800     BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
   1801                     "but one was expected";
   1802     return false;
   1803   }
   1804 
   1805   if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
   1806     BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
   1807                     "but one was expected";
   1808     return false;
   1809   }
   1810 
   1811   has_debug_info_ = true;
   1812   return true;
   1813 }
   1814 
   1815 
   1816 string MinidumpModule::code_file() const {
   1817   if (!valid_) {
   1818     BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
   1819     return "";
   1820   }
   1821 
   1822   return *name_;
   1823 }
   1824 
   1825 
   1826 string MinidumpModule::code_identifier() const {
   1827   if (!valid_) {
   1828     BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
   1829     return "";
   1830   }
   1831 
   1832   if (!has_debug_info_)
   1833     return "";
   1834 
   1835   MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
   1836   if (!minidump_system_info) {
   1837     BPLOG(ERROR) << "MinidumpModule code_identifier requires "
   1838                     "MinidumpSystemInfo";
   1839     return "";
   1840   }
   1841 
   1842   const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
   1843   if (!raw_system_info) {
   1844     BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
   1845     return "";
   1846   }
   1847 
   1848   string identifier;
   1849 
   1850   switch (raw_system_info->platform_id) {
   1851     case MD_OS_WIN32_NT:
   1852     case MD_OS_WIN32_WINDOWS: {
   1853       // Use the same format that the MS symbol server uses in filesystem
   1854       // hierarchies.
   1855       char identifier_string[17];
   1856       snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
   1857                module_.time_date_stamp, module_.size_of_image);
   1858       identifier = identifier_string;
   1859       break;
   1860     }
   1861 
   1862     case MD_OS_MAC_OS_X:
   1863     case MD_OS_IOS:
   1864     case MD_OS_SOLARIS:
   1865     case MD_OS_ANDROID:
   1866     case MD_OS_LINUX:
   1867     case MD_OS_NACL:
   1868     case MD_OS_PS3: {
   1869       // TODO(mmentovai): support uuid extension if present, otherwise fall
   1870       // back to version (from LC_ID_DYLIB?), otherwise fall back to something
   1871       // else.
   1872       identifier = "id";
   1873       break;
   1874     }
   1875 
   1876     default: {
   1877       // Without knowing what OS generated the dump, we can't generate a good
   1878       // identifier.  Return an empty string, signalling failure.
   1879       BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
   1880                       "found " << HexString(raw_system_info->platform_id);
   1881       break;
   1882     }
   1883   }
   1884 
   1885   return identifier;
   1886 }
   1887 
   1888 
   1889 string MinidumpModule::debug_file() const {
   1890   if (!valid_) {
   1891     BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
   1892     return "";
   1893   }
   1894 
   1895   if (!has_debug_info_)
   1896     return "";
   1897 
   1898   string file;
   1899   // Prefer the CodeView record if present.
   1900   if (cv_record_) {
   1901     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
   1902       // It's actually an MDCVInfoPDB70 structure.
   1903       const MDCVInfoPDB70* cv_record_70 =
   1904           reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
   1905       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
   1906 
   1907       // GetCVRecord guarantees pdb_file_name is null-terminated.
   1908       file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
   1909     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
   1910       // It's actually an MDCVInfoPDB20 structure.
   1911       const MDCVInfoPDB20* cv_record_20 =
   1912           reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
   1913       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
   1914 
   1915       // GetCVRecord guarantees pdb_file_name is null-terminated.
   1916       file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
   1917     }
   1918 
   1919     // If there's a CodeView record but it doesn't match a known signature,
   1920     // try the miscellaneous record.
   1921   }
   1922 
   1923   if (file.empty()) {
   1924     // No usable CodeView record.  Try the miscellaneous debug record.
   1925     if (misc_record_) {
   1926       const MDImageDebugMisc* misc_record =
   1927           reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
   1928       if (!misc_record->unicode) {
   1929         // If it's not Unicode, just stuff it into the string.  It's unclear
   1930         // if misc_record->data is 0-terminated, so use an explicit size.
   1931         file = string(
   1932             reinterpret_cast<const char*>(misc_record->data),
   1933             module_.misc_record.data_size - MDImageDebugMisc_minsize);
   1934       } else {
   1935         // There's a misc_record but it encodes the debug filename in UTF-16.
   1936         // (Actually, because miscellaneous records are so old, it's probably
   1937         // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
   1938         // that this method (and all other methods in the Minidump family)
   1939         // return.
   1940 
   1941         unsigned int bytes =
   1942             module_.misc_record.data_size - MDImageDebugMisc_minsize;
   1943         if (bytes % 2 == 0) {
   1944           unsigned int utf16_words = bytes / 2;
   1945 
   1946           // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one
   1947           // and copy the UTF-16 data into it.
   1948           vector<uint16_t> string_utf16(utf16_words);
   1949           if (utf16_words)
   1950             memcpy(&string_utf16[0], &misc_record->data, bytes);
   1951 
   1952           // GetMiscRecord already byte-swapped the data[] field if it contains
   1953           // UTF-16, so pass false as the swap argument.
   1954           scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
   1955           file = *new_file;
   1956         }
   1957       }
   1958     }
   1959   }
   1960 
   1961   // Relatively common case
   1962   BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
   1963                                   "debug_file for " << *name_;
   1964 
   1965   return file;
   1966 }
   1967 
   1968 
   1969 string MinidumpModule::debug_identifier() const {
   1970   if (!valid_) {
   1971     BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
   1972     return "";
   1973   }
   1974 
   1975   if (!has_debug_info_)
   1976     return "";
   1977 
   1978   string identifier;
   1979 
   1980   // Use the CodeView record if present.
   1981   if (cv_record_) {
   1982     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
   1983       // It's actually an MDCVInfoPDB70 structure.
   1984       const MDCVInfoPDB70* cv_record_70 =
   1985           reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
   1986       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
   1987 
   1988       // Use the same format that the MS symbol server uses in filesystem
   1989       // hierarchies.
   1990       char identifier_string[41];
   1991       snprintf(identifier_string, sizeof(identifier_string),
   1992                "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
   1993                cv_record_70->signature.data1,
   1994                cv_record_70->signature.data2,
   1995                cv_record_70->signature.data3,
   1996                cv_record_70->signature.data4[0],
   1997                cv_record_70->signature.data4[1],
   1998                cv_record_70->signature.data4[2],
   1999                cv_record_70->signature.data4[3],
   2000                cv_record_70->signature.data4[4],
   2001                cv_record_70->signature.data4[5],
   2002                cv_record_70->signature.data4[6],
   2003                cv_record_70->signature.data4[7],
   2004                cv_record_70->age);
   2005       identifier = identifier_string;
   2006     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
   2007       // It's actually an MDCVInfoPDB20 structure.
   2008       const MDCVInfoPDB20* cv_record_20 =
   2009           reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
   2010       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
   2011 
   2012       // Use the same format that the MS symbol server uses in filesystem
   2013       // hierarchies.
   2014       char identifier_string[17];
   2015       snprintf(identifier_string, sizeof(identifier_string),
   2016                "%08X%x", cv_record_20->signature, cv_record_20->age);
   2017       identifier = identifier_string;
   2018     }
   2019   }
   2020 
   2021   // TODO(mmentovai): if there's no usable CodeView record, there might be a
   2022   // miscellaneous debug record.  It only carries a filename, though, and no
   2023   // identifier.  I'm not sure what the right thing to do for the identifier
   2024   // is in that case, but I don't expect to find many modules without a
   2025   // CodeView record (or some other Breakpad extension structure in place of
   2026   // a CodeView record).  Treat it as an error (empty identifier) for now.
   2027 
   2028   // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
   2029 
   2030   // Relatively common case
   2031   BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
   2032                                         "debug_identifier for " << *name_;
   2033 
   2034   return identifier;
   2035 }
   2036 
   2037 
   2038 string MinidumpModule::version() const {
   2039   if (!valid_) {
   2040     BPLOG(ERROR) << "Invalid MinidumpModule for version";
   2041     return "";
   2042   }
   2043 
   2044   string version;
   2045 
   2046   if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
   2047       module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
   2048     char version_string[24];
   2049     snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
   2050              module_.version_info.file_version_hi >> 16,
   2051              module_.version_info.file_version_hi & 0xffff,
   2052              module_.version_info.file_version_lo >> 16,
   2053              module_.version_info.file_version_lo & 0xffff);
   2054     version = version_string;
   2055   }
   2056 
   2057   // TODO(mmentovai): possibly support other struct types in place of
   2058   // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
   2059   // a different structure that better represents versioning facilities on
   2060   // Mac OS X and Linux, instead of forcing them to adhere to the dotted
   2061   // quad of 16-bit ints that Windows uses.
   2062 
   2063   BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
   2064                                      "version for " << *name_;
   2065 
   2066   return version;
   2067 }
   2068 
   2069 
   2070 const CodeModule* MinidumpModule::Copy() const {
   2071   return new BasicCodeModule(this);
   2072 }
   2073 
   2074 
   2075 const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
   2076   if (!module_valid_) {
   2077     BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
   2078     return NULL;
   2079   }
   2080 
   2081   if (!cv_record_) {
   2082     // This just guards against 0-sized CodeView records; more specific checks
   2083     // are used when the signature is checked against various structure types.
   2084     if (module_.cv_record.data_size == 0) {
   2085       return NULL;
   2086     }
   2087 
   2088     if (!minidump_->SeekSet(module_.cv_record.rva)) {
   2089       BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
   2090       return NULL;
   2091     }
   2092 
   2093     if (module_.cv_record.data_size > max_cv_bytes_) {
   2094       BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
   2095                       module_.cv_record.data_size << " exceeds maximum " <<
   2096                       max_cv_bytes_;
   2097       return NULL;
   2098     }
   2099 
   2100     // Allocating something that will be accessed as MDCVInfoPDB70 or
   2101     // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment
   2102     // problems.  x86 and ppc are able to cope, though.  This allocation
   2103     // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
   2104     // variable-sized due to their pdb_file_name fields; these structures
   2105     // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
   2106     // them as such would result in incomplete structures or overruns.
   2107     scoped_ptr< vector<uint8_t> > cv_record(
   2108         new vector<uint8_t>(module_.cv_record.data_size));
   2109 
   2110     if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
   2111       BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
   2112       return NULL;
   2113     }
   2114 
   2115     uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
   2116     if (module_.cv_record.data_size > sizeof(signature)) {
   2117       MDCVInfoPDB70* cv_record_signature =
   2118           reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
   2119       signature = cv_record_signature->cv_signature;
   2120       if (minidump_->swap())
   2121         Swap(&signature);
   2122     }
   2123 
   2124     if (signature == MD_CVINFOPDB70_SIGNATURE) {
   2125       // Now that the structure type is known, recheck the size.
   2126       if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
   2127         BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
   2128                         MDCVInfoPDB70_minsize << " > " <<
   2129                         module_.cv_record.data_size;
   2130         return NULL;
   2131       }
   2132 
   2133       if (minidump_->swap()) {
   2134         MDCVInfoPDB70* cv_record_70 =
   2135             reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
   2136         Swap(&cv_record_70->cv_signature);
   2137         Swap(&cv_record_70->signature);
   2138         Swap(&cv_record_70->age);
   2139         // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
   2140         // quantities.  (It's a path, is it UTF-8?)
   2141       }
   2142 
   2143       // The last field of either structure is null-terminated 8-bit character
   2144       // data.  Ensure that it's null-terminated.
   2145       if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
   2146         BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
   2147                         "0-terminated";
   2148         return NULL;
   2149       }
   2150     } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
   2151       // Now that the structure type is known, recheck the size.
   2152       if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
   2153         BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
   2154                         MDCVInfoPDB20_minsize << " > " <<
   2155                         module_.cv_record.data_size;
   2156         return NULL;
   2157       }
   2158       if (minidump_->swap()) {
   2159         MDCVInfoPDB20* cv_record_20 =
   2160             reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
   2161         Swap(&cv_record_20->cv_header.signature);
   2162         Swap(&cv_record_20->cv_header.offset);
   2163         Swap(&cv_record_20->signature);
   2164         Swap(&cv_record_20->age);
   2165         // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
   2166         // quantities.  (It's a path, is it UTF-8?)
   2167       }
   2168 
   2169       // The last field of either structure is null-terminated 8-bit character
   2170       // data.  Ensure that it's null-terminated.
   2171       if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
   2172         BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
   2173                         "0-terminated";
   2174         return NULL;
   2175       }
   2176     }
   2177 
   2178     // If the signature doesn't match something above, it's not something
   2179     // that Breakpad can presently handle directly.  Because some modules in
   2180     // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
   2181     // don't bail out here - allow the data to be returned to the user,
   2182     // although byte-swapping can't be done.
   2183 
   2184     // Store the vector type because that's how storage was allocated, but
   2185     // return it casted to uint8_t*.
   2186     cv_record_ = cv_record.release();
   2187     cv_record_signature_ = signature;
   2188   }
   2189 
   2190   if (size)
   2191     *size = module_.cv_record.data_size;
   2192 
   2193   return &(*cv_record_)[0];
   2194 }
   2195 
   2196 
   2197 const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) {
   2198   if (!module_valid_) {
   2199     BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
   2200     return NULL;
   2201   }
   2202 
   2203   if (!misc_record_) {
   2204     if (module_.misc_record.data_size == 0) {
   2205       return NULL;
   2206     }
   2207 
   2208     if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
   2209       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
   2210                       "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
   2211                       module_.misc_record.data_size;
   2212       return NULL;
   2213     }
   2214 
   2215     if (!minidump_->SeekSet(module_.misc_record.rva)) {
   2216       BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
   2217                       "debugging record";
   2218       return NULL;
   2219     }
   2220 
   2221     if (module_.misc_record.data_size > max_misc_bytes_) {
   2222       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
   2223                       module_.misc_record.data_size << " exceeds maximum " <<
   2224                       max_misc_bytes_;
   2225       return NULL;
   2226     }
   2227 
   2228     // Allocating something that will be accessed as MDImageDebugMisc but
   2229     // is allocated as uint8_t[] can cause alignment problems.  x86 and
   2230     // ppc are able to cope, though.  This allocation style is needed
   2231     // because the MDImageDebugMisc is variable-sized due to its data field;
   2232     // this structure is not MDImageDebugMisc_minsize and treating it as such
   2233     // would result in an incomplete structure or an overrun.
   2234     scoped_ptr< vector<uint8_t> > misc_record_mem(
   2235         new vector<uint8_t>(module_.misc_record.data_size));
   2236     MDImageDebugMisc* misc_record =
   2237         reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
   2238 
   2239     if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
   2240       BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
   2241                       "record";
   2242       return NULL;
   2243     }
   2244 
   2245     if (minidump_->swap()) {
   2246       Swap(&misc_record->data_type);
   2247       Swap(&misc_record->length);
   2248       // Don't swap misc_record.unicode because it's an 8-bit quantity.
   2249       // Don't swap the reserved fields for the same reason, and because
   2250       // they don't contain any valid data.
   2251       if (misc_record->unicode) {
   2252         // There is a potential alignment problem, but shouldn't be a problem
   2253         // in practice due to the layout of MDImageDebugMisc.
   2254         uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data));
   2255         unsigned int dataBytes = module_.misc_record.data_size -
   2256                                  MDImageDebugMisc_minsize;
   2257         Swap(data16, dataBytes);
   2258       }
   2259     }
   2260 
   2261     if (module_.misc_record.data_size != misc_record->length) {
   2262       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
   2263                       "size mismatch, " << module_.misc_record.data_size <<
   2264                       " != " << misc_record->length;
   2265       return NULL;
   2266     }
   2267 
   2268     // Store the vector type because that's how storage was allocated, but
   2269     // return it casted to MDImageDebugMisc*.
   2270     misc_record_ = misc_record_mem.release();
   2271   }
   2272 
   2273   if (size)
   2274     *size = module_.misc_record.data_size;
   2275 
   2276   return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
   2277 }
   2278 
   2279 
   2280 void MinidumpModule::Print() {
   2281   if (!valid_) {
   2282     BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
   2283     return;
   2284   }
   2285 
   2286   printf("MDRawModule\n");
   2287   printf("  base_of_image                   = 0x%" PRIx64 "\n",
   2288          module_.base_of_image);
   2289   printf("  size_of_image                   = 0x%x\n",
   2290          module_.size_of_image);
   2291   printf("  checksum                        = 0x%x\n",
   2292          module_.checksum);
   2293   printf("  time_date_stamp                 = 0x%x %s\n",
   2294          module_.time_date_stamp,
   2295          TimeTToUTCString(module_.time_date_stamp).c_str());
   2296   printf("  module_name_rva                 = 0x%x\n",
   2297          module_.module_name_rva);
   2298   printf("  version_info.signature          = 0x%x\n",
   2299          module_.version_info.signature);
   2300   printf("  version_info.struct_version     = 0x%x\n",
   2301          module_.version_info.struct_version);
   2302   printf("  version_info.file_version       = 0x%x:0x%x\n",
   2303          module_.version_info.file_version_hi,
   2304          module_.version_info.file_version_lo);
   2305   printf("  version_info.product_version    = 0x%x:0x%x\n",
   2306          module_.version_info.product_version_hi,
   2307          module_.version_info.product_version_lo);
   2308   printf("  version_info.file_flags_mask    = 0x%x\n",
   2309          module_.version_info.file_flags_mask);
   2310   printf("  version_info.file_flags         = 0x%x\n",
   2311          module_.version_info.file_flags);
   2312   printf("  version_info.file_os            = 0x%x\n",
   2313          module_.version_info.file_os);
   2314   printf("  version_info.file_type          = 0x%x\n",
   2315          module_.version_info.file_type);
   2316   printf("  version_info.file_subtype       = 0x%x\n",
   2317          module_.version_info.file_subtype);
   2318   printf("  version_info.file_date          = 0x%x:0x%x\n",
   2319          module_.version_info.file_date_hi,
   2320          module_.version_info.file_date_lo);
   2321   printf("  cv_record.data_size             = %d\n",
   2322          module_.cv_record.data_size);
   2323   printf("  cv_record.rva                   = 0x%x\n",
   2324          module_.cv_record.rva);
   2325   printf("  misc_record.data_size           = %d\n",
   2326          module_.misc_record.data_size);
   2327   printf("  misc_record.rva                 = 0x%x\n",
   2328          module_.misc_record.rva);
   2329 
   2330   printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
   2331   printf("  (code_identifier)               = \"%s\"\n",
   2332          code_identifier().c_str());
   2333 
   2334   uint32_t cv_record_size;
   2335   const uint8_t *cv_record = GetCVRecord(&cv_record_size);
   2336   if (cv_record) {
   2337     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
   2338       const MDCVInfoPDB70* cv_record_70 =
   2339           reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
   2340       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
   2341 
   2342       printf("  (cv_record).cv_signature        = 0x%x\n",
   2343              cv_record_70->cv_signature);
   2344       printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
   2345              cv_record_70->signature.data1,
   2346              cv_record_70->signature.data2,
   2347              cv_record_70->signature.data3,
   2348              cv_record_70->signature.data4[0],
   2349              cv_record_70->signature.data4[1]);
   2350       for (unsigned int guidIndex = 2;
   2351            guidIndex < 8;
   2352            ++guidIndex) {
   2353         printf("%02x", cv_record_70->signature.data4[guidIndex]);
   2354       }
   2355       printf("\n");
   2356       printf("  (cv_record).age                 = %d\n",
   2357              cv_record_70->age);
   2358       printf("  (cv_record).pdb_file_name       = \"%s\"\n",
   2359              cv_record_70->pdb_file_name);
   2360     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
   2361       const MDCVInfoPDB20* cv_record_20 =
   2362           reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
   2363       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
   2364 
   2365       printf("  (cv_record).cv_header.signature = 0x%x\n",
   2366              cv_record_20->cv_header.signature);
   2367       printf("  (cv_record).cv_header.offset    = 0x%x\n",
   2368              cv_record_20->cv_header.offset);
   2369       printf("  (cv_record).signature           = 0x%x %s\n",
   2370              cv_record_20->signature,
   2371              TimeTToUTCString(cv_record_20->signature).c_str());
   2372       printf("  (cv_record).age                 = %d\n",
   2373              cv_record_20->age);
   2374       printf("  (cv_record).pdb_file_name       = \"%s\"\n",
   2375              cv_record_20->pdb_file_name);
   2376     } else {
   2377       printf("  (cv_record)                     = ");
   2378       for (unsigned int cv_byte_index = 0;
   2379            cv_byte_index < cv_record_size;
   2380            ++cv_byte_index) {
   2381         printf("%02x", cv_record[cv_byte_index]);
   2382       }
   2383       printf("\n");
   2384     }
   2385   } else {
   2386     printf("  (cv_record)                     = (null)\n");
   2387   }
   2388 
   2389   const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
   2390   if (misc_record) {
   2391     printf("  (misc_record).data_type         = 0x%x\n",
   2392            misc_record->data_type);
   2393     printf("  (misc_record).length            = 0x%x\n",
   2394            misc_record->length);
   2395     printf("  (misc_record).unicode           = %d\n",
   2396            misc_record->unicode);
   2397     if (misc_record->unicode) {
   2398       string misc_record_data_utf8;
   2399       ConvertUTF16BufferToUTF8String(
   2400           reinterpret_cast<const uint16_t*>(misc_record->data),
   2401           misc_record->length - offsetof(MDImageDebugMisc, data),
   2402           &misc_record_data_utf8,
   2403           false);  // already swapped
   2404       printf("  (misc_record).data              = \"%s\"\n",
   2405              misc_record_data_utf8.c_str());
   2406     } else {
   2407       printf("  (misc_record).data              = \"%s\"\n",
   2408              misc_record->data);
   2409     }
   2410   } else {
   2411     printf("  (misc_record)                   = (null)\n");
   2412   }
   2413 
   2414   printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
   2415   printf("  (debug_identifier)              = \"%s\"\n",
   2416          debug_identifier().c_str());
   2417   printf("  (version)                       = \"%s\"\n", version().c_str());
   2418   printf("\n");
   2419 }
   2420 
   2421 
   2422 //
   2423 // MinidumpModuleList
   2424 //
   2425 
   2426 
   2427 uint32_t MinidumpModuleList::max_modules_ = 1024;
   2428 
   2429 
   2430 MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
   2431     : MinidumpStream(minidump),
   2432       range_map_(new RangeMap<uint64_t, unsigned int>()),
   2433       modules_(NULL),
   2434       module_count_(0) {
   2435 }
   2436 
   2437 
   2438 MinidumpModuleList::~MinidumpModuleList() {
   2439   delete range_map_;
   2440   delete modules_;
   2441 }
   2442 
   2443 
   2444 bool MinidumpModuleList::Read(uint32_t expected_size) {
   2445   // Invalidate cached data.
   2446   range_map_->Clear();
   2447   delete modules_;
   2448   modules_ = NULL;
   2449   module_count_ = 0;
   2450 
   2451   valid_ = false;
   2452 
   2453   uint32_t module_count;
   2454   if (expected_size < sizeof(module_count)) {
   2455     BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
   2456                     expected_size << " < " << sizeof(module_count);
   2457     return false;
   2458   }
   2459   if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
   2460     BPLOG(ERROR) << "MinidumpModuleList could not read module count";
   2461     return false;
   2462   }
   2463 
   2464   if (minidump_->swap())
   2465     Swap(&module_count);
   2466 
   2467   if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) {
   2468     BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
   2469                     " would cause multiplication overflow";
   2470     return false;
   2471   }
   2472 
   2473   if (expected_size != sizeof(module_count) +
   2474                        module_count * MD_MODULE_SIZE) {
   2475     // may be padded with 4 bytes on 64bit ABIs for alignment
   2476     if (expected_size == sizeof(module_count) + 4 +
   2477                          module_count * MD_MODULE_SIZE) {
   2478       uint32_t useless;
   2479       if (!minidump_->ReadBytes(&useless, 4)) {
   2480         BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded "
   2481                         "bytes";
   2482         return false;
   2483       }
   2484     } else {
   2485       BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
   2486                       " != " << sizeof(module_count) +
   2487                       module_count * MD_MODULE_SIZE;
   2488       return false;
   2489     }
   2490   }
   2491 
   2492   if (module_count > max_modules_) {
   2493     BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
   2494                     " exceeds maximum " << max_modules_;
   2495     return false;
   2496   }
   2497 
   2498   if (module_count != 0) {
   2499     scoped_ptr<MinidumpModules> modules(
   2500         new MinidumpModules(module_count, MinidumpModule(minidump_)));
   2501 
   2502     for (unsigned int module_index = 0;
   2503          module_index < module_count;
   2504          ++module_index) {
   2505       MinidumpModule* module = &(*modules)[module_index];
   2506 
   2507       // Assume that the file offset is correct after the last read.
   2508       if (!module->Read()) {
   2509         BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
   2510                         module_index << "/" << module_count;
   2511         return false;
   2512       }
   2513     }
   2514 
   2515     // Loop through the module list once more to read additional data and
   2516     // build the range map.  This is done in a second pass because
   2517     // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
   2518     // included in the loop above, additional seeks would be needed where
   2519     // none are now to read contiguous data.
   2520     for (unsigned int module_index = 0;
   2521          module_index < module_count;
   2522          ++module_index) {
   2523       MinidumpModule* module = &(*modules)[module_index];
   2524 
   2525       // ReadAuxiliaryData fails if any data that the module indicates should
   2526       // exist is missing, but we treat some such cases as valid anyway.  See
   2527       // issue #222: if a debugging record is of a format that's too large to
   2528       // handle, it shouldn't render the entire dump invalid.  Check module
   2529       // validity before giving up.
   2530       if (!module->ReadAuxiliaryData() && !module->valid()) {
   2531         BPLOG(ERROR) << "MinidumpModuleList could not read required module "
   2532                         "auxiliary data for module " <<
   2533                         module_index << "/" << module_count;
   2534         return false;
   2535       }
   2536 
   2537       // It is safe to use module->code_file() after successfully calling
   2538       // module->ReadAuxiliaryData or noting that the module is valid.
   2539 
   2540       uint64_t base_address = module->base_address();
   2541       uint64_t module_size = module->size();
   2542       if (base_address == static_cast<uint64_t>(-1)) {
   2543         BPLOG(ERROR) << "MinidumpModuleList found bad base address "
   2544                         "for module " << module_index << "/" << module_count <<
   2545                         ", " << module->code_file();
   2546         return false;
   2547       }
   2548 
   2549       if (!range_map_->StoreRange(base_address, module_size, module_index)) {
   2550         // Android's shared memory implementation /dev/ashmem can contain
   2551         // duplicate entries for JITted code, so ignore these.
   2552         // TODO(wfh): Remove this code when Android is fixed.
   2553         // See https://crbug.com/439531
   2554         const string kDevAshmem("/dev/ashmem/");
   2555         if (module->code_file().compare(
   2556             0, kDevAshmem.length(), kDevAshmem) != 0) {
   2557           BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
   2558                           module_index << "/" << module_count << ", " <<
   2559                           module->code_file() << ", " <<
   2560                           HexString(base_address) << "+" <<
   2561                           HexString(module_size);
   2562           return false;
   2563         } else {
   2564           BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module " <<
   2565                           module_index << "/" << module_count << ", " <<
   2566                           module->code_file() << ", " <<
   2567                           HexString(base_address) << "+" <<
   2568                           HexString(module_size);
   2569         }
   2570       }
   2571     }
   2572 
   2573     modules_ = modules.release();
   2574   }
   2575 
   2576   module_count_ = module_count;
   2577 
   2578   valid_ = true;
   2579   return true;
   2580 }
   2581 
   2582 
   2583 const MinidumpModule* MinidumpModuleList::GetModuleForAddress(
   2584     uint64_t address) const {
   2585   if (!valid_) {
   2586     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
   2587     return NULL;
   2588   }
   2589 
   2590   unsigned int module_index;
   2591   if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
   2592     BPLOG(INFO) << "MinidumpModuleList has no module at " <<
   2593                    HexString(address);
   2594     return NULL;
   2595   }
   2596 
   2597   return GetModuleAtIndex(module_index);
   2598 }
   2599 
   2600 
   2601 const MinidumpModule* MinidumpModuleList::GetMainModule() const {
   2602   if (!valid_) {
   2603     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
   2604     return NULL;
   2605   }
   2606 
   2607   // The main code module is the first one present in a minidump file's
   2608   // MDRawModuleList.
   2609   return GetModuleAtIndex(0);
   2610 }
   2611 
   2612 
   2613 const MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
   2614     unsigned int sequence) const {
   2615   if (!valid_) {
   2616     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
   2617     return NULL;
   2618   }
   2619 
   2620   if (sequence >= module_count_) {
   2621     BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
   2622                     sequence << "/" << module_count_;
   2623     return NULL;
   2624   }
   2625 
   2626   unsigned int module_index;
   2627   if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
   2628     BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
   2629     return NULL;
   2630   }
   2631 
   2632   return GetModuleAtIndex(module_index);
   2633 }
   2634 
   2635 
   2636 const MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
   2637     unsigned int index) const {
   2638   if (!valid_) {
   2639     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
   2640     return NULL;
   2641   }
   2642 
   2643   if (index >= module_count_) {
   2644     BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
   2645                     index << "/" << module_count_;
   2646     return NULL;
   2647   }
   2648 
   2649   return &(*modules_)[index];
   2650 }
   2651 
   2652 
   2653 const CodeModules* MinidumpModuleList::Copy() const {
   2654   return new BasicCodeModules(this);
   2655 }
   2656 
   2657 
   2658 void MinidumpModuleList::Print() {
   2659   if (!valid_) {
   2660     BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
   2661     return;
   2662   }
   2663 
   2664   printf("MinidumpModuleList\n");
   2665   printf("  module_count = %d\n", module_count_);
   2666   printf("\n");
   2667 
   2668   for (unsigned int module_index = 0;
   2669        module_index < module_count_;
   2670        ++module_index) {
   2671     printf("module[%d]\n", module_index);
   2672 
   2673     (*modules_)[module_index].Print();
   2674   }
   2675 }
   2676 
   2677 
   2678 //
   2679 // MinidumpMemoryList
   2680 //
   2681 
   2682 
   2683 uint32_t MinidumpMemoryList::max_regions_ = 4096;
   2684 
   2685 
   2686 MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
   2687     : MinidumpStream(minidump),
   2688       range_map_(new RangeMap<uint64_t, unsigned int>()),
   2689       descriptors_(NULL),
   2690       regions_(NULL),
   2691       region_count_(0) {
   2692 }
   2693 
   2694 
   2695 MinidumpMemoryList::~MinidumpMemoryList() {
   2696   delete range_map_;
   2697   delete descriptors_;
   2698   delete regions_;
   2699 }
   2700 
   2701 
   2702 bool MinidumpMemoryList::Read(uint32_t expected_size) {
   2703   // Invalidate cached data.
   2704   delete descriptors_;
   2705   descriptors_ = NULL;
   2706   delete regions_;
   2707   regions_ = NULL;
   2708   range_map_->Clear();
   2709   region_count_ = 0;
   2710 
   2711   valid_ = false;
   2712 
   2713   uint32_t region_count;
   2714   if (expected_size < sizeof(region_count)) {
   2715     BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
   2716                     expected_size << " < " << sizeof(region_count);
   2717     return false;
   2718   }
   2719   if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
   2720     BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
   2721     return false;
   2722   }
   2723 
   2724   if (minidump_->swap())
   2725     Swap(&region_count);
   2726 
   2727   if (region_count >
   2728           numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) {
   2729     BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
   2730                     " would cause multiplication overflow";
   2731     return false;
   2732   }
   2733 
   2734   if (expected_size != sizeof(region_count) +
   2735                        region_count * sizeof(MDMemoryDescriptor)) {
   2736     // may be padded with 4 bytes on 64bit ABIs for alignment
   2737     if (expected_size == sizeof(region_count) + 4 +
   2738                          region_count * sizeof(MDMemoryDescriptor)) {
   2739       uint32_t useless;
   2740       if (!minidump_->ReadBytes(&useless, 4)) {
   2741         BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded "
   2742                         "bytes";
   2743         return false;
   2744       }
   2745     } else {
   2746       BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
   2747                       " != " << sizeof(region_count) +
   2748                       region_count * sizeof(MDMemoryDescriptor);
   2749       return false;
   2750     }
   2751   }
   2752 
   2753   if (region_count > max_regions_) {
   2754     BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
   2755                     " exceeds maximum " << max_regions_;
   2756     return false;
   2757   }
   2758 
   2759   if (region_count != 0) {
   2760     scoped_ptr<MemoryDescriptors> descriptors(
   2761         new MemoryDescriptors(region_count));
   2762 
   2763     // Read the entire array in one fell swoop, instead of reading one entry
   2764     // at a time in the loop.
   2765     if (!minidump_->ReadBytes(&(*descriptors)[0],
   2766                               sizeof(MDMemoryDescriptor) * region_count)) {
   2767       BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
   2768       return false;
   2769     }
   2770 
   2771     scoped_ptr<MemoryRegions> regions(
   2772         new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
   2773 
   2774     for (unsigned int region_index = 0;
   2775          region_index < region_count;
   2776          ++region_index) {
   2777       MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
   2778 
   2779       if (minidump_->swap())
   2780         Swap(descriptor);
   2781 
   2782       uint64_t base_address = descriptor->start_of_memory_range;
   2783       uint32_t region_size = descriptor->memory.data_size;
   2784 
   2785       // Check for base + size overflow or undersize.
   2786       if (region_size == 0 ||
   2787           region_size > numeric_limits<uint64_t>::max() - base_address) {
   2788         BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
   2789                         " region " << region_index << "/" << region_count <<
   2790                         ", " << HexString(base_address) << "+" <<
   2791                         HexString(region_size);
   2792         return false;
   2793       }
   2794 
   2795       if (!range_map_->StoreRange(base_address, region_size, region_index)) {
   2796         BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
   2797                         region_index << "/" << region_count << ", " <<
   2798                         HexString(base_address) << "+" <<
   2799                         HexString(region_size);
   2800         return false;
   2801       }
   2802 
   2803       (*regions)[region_index].SetDescriptor(descriptor);
   2804     }
   2805 
   2806     descriptors_ = descriptors.release();
   2807     regions_ = regions.release();
   2808   }
   2809 
   2810   region_count_ = region_count;
   2811 
   2812   valid_ = true;
   2813   return true;
   2814 }
   2815 
   2816 
   2817 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
   2818       unsigned int index) {
   2819   if (!valid_) {
   2820     BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
   2821     return NULL;
   2822   }
   2823 
   2824   if (index >= region_count_) {
   2825     BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
   2826                     index << "/" << region_count_;
   2827     return NULL;
   2828   }
   2829 
   2830   return &(*regions_)[index];
   2831 }
   2832 
   2833 
   2834 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
   2835     uint64_t address) {
   2836   if (!valid_) {
   2837     BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
   2838     return NULL;
   2839   }
   2840 
   2841   unsigned int region_index;
   2842   if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
   2843     BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
   2844                    HexString(address);
   2845     return NULL;
   2846   }
   2847 
   2848   return GetMemoryRegionAtIndex(region_index);
   2849 }
   2850 
   2851 
   2852 void MinidumpMemoryList::Print() {
   2853   if (!valid_) {
   2854     BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
   2855     return;
   2856   }
   2857 
   2858   printf("MinidumpMemoryList\n");
   2859   printf("  region_count = %d\n", region_count_);
   2860   printf("\n");
   2861 
   2862   for (unsigned int region_index = 0;
   2863        region_index < region_count_;
   2864        ++region_index) {
   2865     MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
   2866     printf("region[%d]\n", region_index);
   2867     printf("MDMemoryDescriptor\n");
   2868     printf("  start_of_memory_range = 0x%" PRIx64 "\n",
   2869            descriptor->start_of_memory_range);
   2870     printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
   2871     printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
   2872     MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
   2873     if (region) {
   2874       printf("Memory\n");
   2875       region->Print();
   2876     } else {
   2877       printf("No memory\n");
   2878     }
   2879     printf("\n");
   2880   }
   2881 }
   2882 
   2883 
   2884 //
   2885 // MinidumpException
   2886 //
   2887 
   2888 
   2889 MinidumpException::MinidumpException(Minidump* minidump)
   2890     : MinidumpStream(minidump),
   2891       exception_(),
   2892       context_(NULL) {
   2893 }
   2894 
   2895 
   2896 MinidumpException::~MinidumpException() {
   2897   delete context_;
   2898 }
   2899 
   2900 
   2901 bool MinidumpException::Read(uint32_t expected_size) {
   2902   // Invalidate cached data.
   2903   delete context_;
   2904   context_ = NULL;
   2905 
   2906   valid_ = false;
   2907 
   2908   if (expected_size != sizeof(exception_)) {
   2909     BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
   2910                     " != " << sizeof(exception_);
   2911     return false;
   2912   }
   2913 
   2914   if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
   2915     BPLOG(ERROR) << "MinidumpException cannot read exception";
   2916     return false;
   2917   }
   2918 
   2919   if (minidump_->swap()) {
   2920     Swap(&exception_.thread_id);
   2921     // exception_.__align is for alignment only and does not need to be
   2922     // swapped.
   2923     Swap(&exception_.exception_record.exception_code);
   2924     Swap(&exception_.exception_record.exception_flags);
   2925     Swap(&exception_.exception_record.exception_record);
   2926     Swap(&exception_.exception_record.exception_address);
   2927     Swap(&exception_.exception_record.number_parameters);
   2928     // exception_.exception_record.__align is for alignment only and does not
   2929     // need to be swapped.
   2930     for (unsigned int parameter_index = 0;
   2931          parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
   2932          ++parameter_index) {
   2933       Swap(&exception_.exception_record.exception_information[parameter_index]);
   2934     }
   2935     Swap(&exception_.thread_context);
   2936   }
   2937 
   2938   valid_ = true;
   2939   return true;
   2940 }
   2941 
   2942 
   2943 bool MinidumpException::GetThreadID(uint32_t *thread_id) const {
   2944   BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
   2945                                  "|thread_id|";
   2946   assert(thread_id);
   2947   *thread_id = 0;
   2948 
   2949   if (!valid_) {
   2950     BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
   2951     return false;
   2952   }
   2953 
   2954   *thread_id = exception_.thread_id;
   2955   return true;
   2956 }
   2957 
   2958 
   2959 MinidumpContext* MinidumpException::GetContext() {
   2960   if (!valid_) {
   2961     BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
   2962     return NULL;
   2963   }
   2964 
   2965   if (!context_) {
   2966     if (!minidump_->SeekSet(exception_.thread_context.rva)) {
   2967       BPLOG(ERROR) << "MinidumpException cannot seek to context";
   2968       return NULL;
   2969     }
   2970 
   2971     scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
   2972 
   2973     // Don't log as an error if we can still fall back on the thread's context
   2974     // (which must be possible if we got this far.)
   2975     if (!context->Read(exception_.thread_context.data_size)) {
   2976       BPLOG(INFO) << "MinidumpException cannot read context";
   2977       return NULL;
   2978     }
   2979 
   2980     context_ = context.release();
   2981   }
   2982 
   2983   return context_;
   2984 }
   2985 
   2986 
   2987 void MinidumpException::Print() {
   2988   if (!valid_) {
   2989     BPLOG(ERROR) << "MinidumpException cannot print invalid data";
   2990     return;
   2991   }
   2992 
   2993   printf("MDException\n");
   2994   printf("  thread_id                                  = 0x%x\n",
   2995          exception_.thread_id);
   2996   printf("  exception_record.exception_code            = 0x%x\n",
   2997          exception_.exception_record.exception_code);
   2998   printf("  exception_record.exception_flags           = 0x%x\n",
   2999          exception_.exception_record.exception_flags);
   3000   printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
   3001          exception_.exception_record.exception_record);
   3002   printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
   3003          exception_.exception_record.exception_address);
   3004   printf("  exception_record.number_parameters         = %d\n",
   3005          exception_.exception_record.number_parameters);
   3006   for (unsigned int parameterIndex = 0;
   3007        parameterIndex < exception_.exception_record.number_parameters;
   3008        ++parameterIndex) {
   3009     printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
   3010            parameterIndex,
   3011            exception_.exception_record.exception_information[parameterIndex]);
   3012   }
   3013   printf("  thread_context.data_size                   = %d\n",
   3014          exception_.thread_context.data_size);
   3015   printf("  thread_context.rva                         = 0x%x\n",
   3016          exception_.thread_context.rva);
   3017   MinidumpContext* context = GetContext();
   3018   if (context) {
   3019     printf("\n");
   3020     context->Print();
   3021   } else {
   3022     printf("  (no context)\n");
   3023     printf("\n");
   3024   }
   3025 }
   3026 
   3027 //
   3028 // MinidumpAssertion
   3029 //
   3030 
   3031 
   3032 MinidumpAssertion::MinidumpAssertion(Minidump* minidump)
   3033     : MinidumpStream(minidump),
   3034       assertion_(),
   3035       expression_(),
   3036       function_(),
   3037       file_() {
   3038 }
   3039 
   3040 
   3041 MinidumpAssertion::~MinidumpAssertion() {
   3042 }
   3043 
   3044 
   3045 bool MinidumpAssertion::Read(uint32_t expected_size) {
   3046   // Invalidate cached data.
   3047   valid_ = false;
   3048 
   3049   if (expected_size != sizeof(assertion_)) {
   3050     BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
   3051                     " != " << sizeof(assertion_);
   3052     return false;
   3053   }
   3054 
   3055   if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
   3056     BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
   3057     return false;
   3058   }
   3059 
   3060   // Each of {expression, function, file} is a UTF-16 string,
   3061   // we'll convert them to UTF-8 for ease of use.
   3062   ConvertUTF16BufferToUTF8String(assertion_.expression,
   3063                                  sizeof(assertion_.expression), &expression_,
   3064                                  minidump_->swap());
   3065   ConvertUTF16BufferToUTF8String(assertion_.function,
   3066                                  sizeof(assertion_.function), &function_,
   3067                                  minidump_->swap());
   3068   ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file),
   3069                                  &file_, minidump_->swap());
   3070 
   3071   if (minidump_->swap()) {
   3072     Swap(&assertion_.line);
   3073     Swap(&assertion_.type);
   3074   }
   3075 
   3076   valid_ = true;
   3077   return true;
   3078 }
   3079 
   3080 void MinidumpAssertion::Print() {
   3081   if (!valid_) {
   3082     BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
   3083     return;
   3084   }
   3085 
   3086   printf("MDAssertion\n");
   3087   printf("  expression                                 = %s\n",
   3088          expression_.c_str());
   3089   printf("  function                                   = %s\n",
   3090          function_.c_str());
   3091   printf("  file                                       = %s\n",
   3092          file_.c_str());
   3093   printf("  line                                       = %u\n",
   3094          assertion_.line);
   3095   printf("  type                                       = %u\n",
   3096          assertion_.type);
   3097   printf("\n");
   3098 }
   3099 
   3100 //
   3101 // MinidumpSystemInfo
   3102 //
   3103 
   3104 
   3105 MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
   3106     : MinidumpStream(minidump),
   3107       system_info_(),
   3108       csd_version_(NULL),
   3109       cpu_vendor_(NULL) {
   3110 }
   3111 
   3112 
   3113 MinidumpSystemInfo::~MinidumpSystemInfo() {
   3114   delete csd_version_;
   3115   delete cpu_vendor_;
   3116 }
   3117 
   3118 
   3119 bool MinidumpSystemInfo::Read(uint32_t expected_size) {
   3120   // Invalidate cached data.
   3121   delete csd_version_;
   3122   csd_version_ = NULL;
   3123   delete cpu_vendor_;
   3124   cpu_vendor_ = NULL;
   3125 
   3126   valid_ = false;
   3127 
   3128   if (expected_size != sizeof(system_info_)) {
   3129     BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
   3130                     " != " << sizeof(system_info_);
   3131     return false;
   3132   }
   3133 
   3134   if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
   3135     BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
   3136     return false;
   3137   }
   3138 
   3139   if (minidump_->swap()) {
   3140     Swap(&system_info_.processor_architecture);
   3141     Swap(&system_info_.processor_level);
   3142     Swap(&system_info_.processor_revision);
   3143     // number_of_processors and product_type are 8-bit quantities and need no
   3144     // swapping.
   3145     Swap(&system_info_.major_version);
   3146     Swap(&system_info_.minor_version);
   3147     Swap(&system_info_.build_number);
   3148     Swap(&system_info_.platform_id);
   3149     Swap(&system_info_.csd_version_rva);
   3150     Swap(&system_info_.suite_mask);
   3151     // Don't swap the reserved2 field because its contents are unknown.
   3152 
   3153     if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
   3154         system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
   3155       for (unsigned int i = 0; i < 3; ++i)
   3156         Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
   3157       Swap(&system_info_.cpu.x86_cpu_info.version_information);
   3158       Swap(&system_info_.cpu.x86_cpu_info.feature_information);
   3159       Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
   3160     } else {
   3161       for (unsigned int i = 0; i < 2; ++i)
   3162         Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
   3163     }
   3164   }
   3165 
   3166   valid_ = true;
   3167   return true;
   3168 }
   3169 
   3170 
   3171 string MinidumpSystemInfo::GetOS() {
   3172   string os;
   3173 
   3174   if (!valid_) {
   3175     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
   3176     return os;
   3177   }
   3178 
   3179   switch (system_info_.platform_id) {
   3180     case MD_OS_WIN32_NT:
   3181     case MD_OS_WIN32_WINDOWS:
   3182       os = "windows";
   3183       break;
   3184 
   3185     case MD_OS_MAC_OS_X:
   3186       os = "mac";
   3187       break;
   3188 
   3189     case MD_OS_IOS:
   3190       os = "ios";
   3191       break;
   3192 
   3193     case MD_OS_LINUX:
   3194       os = "linux";
   3195       break;
   3196 
   3197     case MD_OS_SOLARIS:
   3198       os = "solaris";
   3199       break;
   3200 
   3201     case MD_OS_ANDROID:
   3202       os = "android";
   3203       break;
   3204 
   3205     case MD_OS_PS3:
   3206       os = "ps3";
   3207       break;
   3208 
   3209     case MD_OS_NACL:
   3210       os = "nacl";
   3211       break;
   3212 
   3213     default:
   3214       BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
   3215                       HexString(system_info_.platform_id);
   3216       break;
   3217   }
   3218 
   3219   return os;
   3220 }
   3221 
   3222 
   3223 string MinidumpSystemInfo::GetCPU() {
   3224   if (!valid_) {
   3225     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
   3226     return "";
   3227   }
   3228 
   3229   string cpu;
   3230 
   3231   switch (system_info_.processor_architecture) {
   3232     case MD_CPU_ARCHITECTURE_X86:
   3233     case MD_CPU_ARCHITECTURE_X86_WIN64:
   3234       cpu = "x86";
   3235       break;
   3236 
   3237     case MD_CPU_ARCHITECTURE_AMD64:
   3238       cpu = "x86-64";
   3239       break;
   3240 
   3241     case MD_CPU_ARCHITECTURE_PPC:
   3242       cpu = "ppc";
   3243       break;
   3244 
   3245     case MD_CPU_ARCHITECTURE_PPC64:
   3246       cpu = "ppc64";
   3247       break;
   3248 
   3249     case MD_CPU_ARCHITECTURE_SPARC:
   3250       cpu = "sparc";
   3251       break;
   3252 
   3253     case MD_CPU_ARCHITECTURE_ARM:
   3254       cpu = "arm";
   3255       break;
   3256 
   3257     case MD_CPU_ARCHITECTURE_ARM64:
   3258       cpu = "arm64";
   3259       break;
   3260 
   3261     default:
   3262       BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
   3263                       HexString(system_info_.processor_architecture);
   3264       break;
   3265   }
   3266 
   3267   return cpu;
   3268 }
   3269 
   3270 
   3271 const string* MinidumpSystemInfo::GetCSDVersion() {
   3272   if (!valid_) {
   3273     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
   3274     return NULL;
   3275   }
   3276 
   3277   if (!csd_version_)
   3278     csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
   3279 
   3280   BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
   3281                                     "CSD version";
   3282 
   3283   return csd_version_;
   3284 }
   3285 
   3286 
   3287 const string* MinidumpSystemInfo::GetCPUVendor() {
   3288   if (!valid_) {
   3289     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
   3290     return NULL;
   3291   }
   3292 
   3293   // CPU vendor information can only be determined from x86 minidumps.
   3294   if (!cpu_vendor_ &&
   3295       (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
   3296        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
   3297     char cpu_vendor_string[13];
   3298     snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
   3299              "%c%c%c%c%c%c%c%c%c%c%c%c",
   3300               system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
   3301              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
   3302              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
   3303              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
   3304               system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
   3305              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
   3306              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
   3307              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
   3308               system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
   3309              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
   3310              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
   3311              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
   3312     cpu_vendor_ = new string(cpu_vendor_string);
   3313   }
   3314 
   3315   return cpu_vendor_;
   3316 }
   3317 
   3318 
   3319 void MinidumpSystemInfo::Print() {
   3320   if (!valid_) {
   3321     BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
   3322     return;
   3323   }
   3324 
   3325   printf("MDRawSystemInfo\n");
   3326   printf("  processor_architecture                     = 0x%x\n",
   3327          system_info_.processor_architecture);
   3328   printf("  processor_level                            = %d\n",
   3329          system_info_.processor_level);
   3330   printf("  processor_revision                         = 0x%x\n",
   3331          system_info_.processor_revision);
   3332   printf("  number_of_processors                       = %d\n",
   3333          system_info_.number_of_processors);
   3334   printf("  product_type                               = %d\n",
   3335          system_info_.product_type);
   3336   printf("  major_version                              = %d\n",
   3337          system_info_.major_version);
   3338   printf("  minor_version                              = %d\n",
   3339          system_info_.minor_version);
   3340   printf("  build_number                               = %d\n",
   3341          system_info_.build_number);
   3342   printf("  platform_id                                = 0x%x\n",
   3343          system_info_.platform_id);
   3344   printf("  csd_version_rva                            = 0x%x\n",
   3345          system_info_.csd_version_rva);
   3346   printf("  suite_mask                                 = 0x%x\n",
   3347          system_info_.suite_mask);
   3348   if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
   3349       system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
   3350     printf("  cpu.x86_cpu_info (valid):\n");
   3351   } else {
   3352     printf("  cpu.x86_cpu_info (invalid):\n");
   3353   }
   3354   for (unsigned int i = 0; i < 3; ++i) {
   3355     printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
   3356            i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
   3357   }
   3358   printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
   3359          system_info_.cpu.x86_cpu_info.version_information);
   3360   printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
   3361          system_info_.cpu.x86_cpu_info.feature_information);
   3362   printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
   3363          system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
   3364   if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 &&
   3365       system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) {
   3366     printf("  cpu.other_cpu_info (valid):\n");
   3367     for (unsigned int i = 0; i < 2; ++i) {
   3368       printf("  cpu.other_cpu_info.processor_features[%d]   = 0x%" PRIx64 "\n",
   3369              i, system_info_.cpu.other_cpu_info.processor_features[i]);
   3370     }
   3371   }
   3372   const string* csd_version = GetCSDVersion();
   3373   if (csd_version) {
   3374     printf("  (csd_version)                              = \"%s\"\n",
   3375            csd_version->c_str());
   3376   } else {
   3377     printf("  (csd_version)                              = (null)\n");
   3378   }
   3379   const string* cpu_vendor = GetCPUVendor();
   3380   if (cpu_vendor) {
   3381     printf("  (cpu_vendor)                               = \"%s\"\n",
   3382            cpu_vendor->c_str());
   3383   } else {
   3384     printf("  (cpu_vendor)                               = (null)\n");
   3385   }
   3386   printf("\n");
   3387 }
   3388 
   3389 
   3390 //
   3391 // MinidumpMiscInfo
   3392 //
   3393 
   3394 
   3395 MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
   3396     : MinidumpStream(minidump),
   3397       misc_info_() {
   3398 }
   3399 
   3400 
   3401 bool MinidumpMiscInfo::Read(uint32_t expected_size) {
   3402   valid_ = false;
   3403 
   3404   if (expected_size != MD_MISCINFO_SIZE &&
   3405       expected_size != MD_MISCINFO2_SIZE &&
   3406       expected_size != MD_MISCINFO3_SIZE &&
   3407       expected_size != MD_MISCINFO4_SIZE) {
   3408     BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
   3409                  << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
   3410                  << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
   3411                  << ")";
   3412     return false;
   3413   }
   3414 
   3415   if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
   3416     BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
   3417     return false;
   3418   }
   3419 
   3420   if (minidump_->swap()) {
   3421     // Swap version 1 fields
   3422     Swap(&misc_info_.size_of_info);
   3423     Swap(&misc_info_.flags1);
   3424     Swap(&misc_info_.process_id);
   3425     Swap(&misc_info_.process_create_time);
   3426     Swap(&misc_info_.process_user_time);
   3427     Swap(&misc_info_.process_kernel_time);
   3428     if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
   3429       // Swap version 2 fields
   3430       Swap(&misc_info_.processor_max_mhz);
   3431       Swap(&misc_info_.processor_current_mhz);
   3432       Swap(&misc_info_.processor_mhz_limit);
   3433       Swap(&misc_info_.processor_max_idle_state);
   3434       Swap(&misc_info_.processor_current_idle_state);
   3435     }
   3436     if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
   3437       // Swap version 3 fields
   3438       Swap(&misc_info_.process_integrity_level);
   3439       Swap(&misc_info_.process_execute_flags);
   3440       Swap(&misc_info_.protected_process);
   3441       Swap(&misc_info_.time_zone_id);
   3442       Swap(&misc_info_.time_zone);
   3443     }
   3444     if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
   3445       // Swap version 4 fields.
   3446       // Do not swap UTF-16 strings.  The swap is done as part of the
   3447       // conversion to UTF-8 (code follows below).
   3448     }
   3449   }
   3450 
   3451   if (expected_size != misc_info_.size_of_info) {
   3452     BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
   3453                     expected_size << " != " << misc_info_.size_of_info;
   3454     return false;
   3455   }
   3456 
   3457   // Convert UTF-16 strings
   3458   if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
   3459     // Convert UTF-16 strings in version 3 fields
   3460     ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name,
   3461                                    sizeof(misc_info_.time_zone.standard_name),
   3462                                    &standard_name_, minidump_->swap());
   3463     ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name,
   3464                                    sizeof(misc_info_.time_zone.daylight_name),
   3465                                    &daylight_name_, minidump_->swap());
   3466   }
   3467   if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
   3468     // Convert UTF-16 strings in version 4 fields
   3469     ConvertUTF16BufferToUTF8String(misc_info_.build_string,
   3470                                    sizeof(misc_info_.build_string),
   3471                                    &build_string_, minidump_->swap());
   3472     ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str,
   3473                                    sizeof(misc_info_.dbg_bld_str),
   3474                                    &dbg_bld_str_, minidump_->swap());
   3475   }
   3476 
   3477   valid_ = true;
   3478   return true;
   3479 }
   3480 
   3481 
   3482 void MinidumpMiscInfo::Print() {
   3483   if (!valid_) {
   3484     BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
   3485     return;
   3486   }
   3487 
   3488   printf("MDRawMiscInfo\n");
   3489   // Print version 1 fields
   3490   printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
   3491   printf("  flags1                       = 0x%x\n", misc_info_.flags1);
   3492   printf("  process_id                   = ");
   3493   PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID,
   3494                       kNumberFormatDecimal, misc_info_.process_id);
   3495   if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) {
   3496     printf("  process_create_time          = 0x%x %s\n",
   3497            misc_info_.process_create_time,
   3498            TimeTToUTCString(misc_info_.process_create_time).c_str());
   3499   } else {
   3500     printf("  process_create_time          = (invalid)\n");
   3501   }
   3502   printf("  process_user_time            = ");
   3503   PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
   3504                       kNumberFormatDecimal, misc_info_.process_user_time);
   3505   printf("  process_kernel_time          = ");
   3506   PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
   3507                       kNumberFormatDecimal, misc_info_.process_kernel_time);
   3508   if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
   3509     // Print version 2 fields
   3510     printf("  processor_max_mhz            = ");
   3511     PrintValueOrInvalid(misc_info_.flags1 &
   3512                             MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
   3513                         kNumberFormatDecimal, misc_info_.processor_max_mhz);
   3514     printf("  processor_current_mhz        = ");
   3515     PrintValueOrInvalid(misc_info_.flags1 &
   3516                             MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
   3517                         kNumberFormatDecimal, misc_info_.processor_current_mhz);
   3518     printf("  processor_mhz_limit          = ");
   3519     PrintValueOrInvalid(misc_info_.flags1 &
   3520                             MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
   3521                         kNumberFormatDecimal, misc_info_.processor_mhz_limit);
   3522     printf("  processor_max_idle_state     = ");
   3523     PrintValueOrInvalid(misc_info_.flags1 &
   3524                             MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
   3525                         kNumberFormatDecimal,
   3526                         misc_info_.processor_max_idle_state);
   3527     printf("  processor_current_idle_state = ");
   3528     PrintValueOrInvalid(misc_info_.flags1 &
   3529                             MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
   3530                         kNumberFormatDecimal,
   3531                         misc_info_.processor_current_idle_state);
   3532   }
   3533   if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
   3534     // Print version 3 fields
   3535     printf("  process_integrity_level      = ");
   3536     PrintValueOrInvalid(misc_info_.flags1 &
   3537                             MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY,
   3538                         kNumberFormatHexadecimal,
   3539                         misc_info_.process_integrity_level);
   3540     printf("  process_execute_flags        = ");
   3541     PrintValueOrInvalid(misc_info_.flags1 &
   3542                             MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS,
   3543                         kNumberFormatHexadecimal,
   3544                         misc_info_.process_execute_flags);
   3545     printf("  protected_process            = ");
   3546     PrintValueOrInvalid(misc_info_.flags1 &
   3547                             MD_MISCINFO_FLAGS1_PROTECTED_PROCESS,
   3548                         kNumberFormatDecimal, misc_info_.protected_process);
   3549     printf("  time_zone_id                 = ");
   3550     PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE,
   3551                         kNumberFormatDecimal, misc_info_.time_zone_id);
   3552     if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) {
   3553       printf("  time_zone.bias               = %d\n",
   3554              misc_info_.time_zone.bias);
   3555       printf("  time_zone.standard_name      = %s\n", standard_name_.c_str());
   3556       printf("  time_zone.standard_date      = "
   3557                  "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
   3558              misc_info_.time_zone.standard_date.year,
   3559              misc_info_.time_zone.standard_date.month,
   3560              misc_info_.time_zone.standard_date.day,
   3561              misc_info_.time_zone.standard_date.day_of_week,
   3562              misc_info_.time_zone.standard_date.hour,
   3563              misc_info_.time_zone.standard_date.minute,
   3564              misc_info_.time_zone.standard_date.second,
   3565              misc_info_.time_zone.standard_date.milliseconds);
   3566       printf("  time_zone.standard_bias      = %d\n",
   3567              misc_info_.time_zone.standard_bias);
   3568       printf("  time_zone.daylight_name      = %s\n", daylight_name_.c_str());
   3569       printf("  time_zone.daylight_date      = "
   3570                  "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
   3571              misc_info_.time_zone.daylight_date.year,
   3572              misc_info_.time_zone.daylight_date.month,
   3573              misc_info_.time_zone.daylight_date.day,
   3574              misc_info_.time_zone.daylight_date.day_of_week,
   3575              misc_info_.time_zone.daylight_date.hour,
   3576              misc_info_.time_zone.daylight_date.minute,
   3577              misc_info_.time_zone.daylight_date.second,
   3578              misc_info_.time_zone.daylight_date.milliseconds);
   3579       printf("  time_zone.daylight_bias      = %d\n",
   3580              misc_info_.time_zone.daylight_bias);
   3581     } else {
   3582       printf("  time_zone.bias               = (invalid)\n");
   3583       printf("  time_zone.standard_name      = (invalid)\n");
   3584       printf("  time_zone.standard_date      = (invalid)\n");
   3585       printf("  time_zone.standard_bias      = (invalid)\n");
   3586       printf("  time_zone.daylight_name      = (invalid)\n");
   3587       printf("  time_zone.daylight_date      = (invalid)\n");
   3588       printf("  time_zone.daylight_bias      = (invalid)\n");
   3589     }
   3590   }
   3591   if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
   3592     // Print version 4 fields
   3593     if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) {
   3594       printf("  build_string                 = %s\n", build_string_.c_str());
   3595       printf("  dbg_bld_str                  = %s\n", dbg_bld_str_.c_str());
   3596     } else {
   3597       printf("  build_string                 = (invalid)\n");
   3598       printf("  dbg_bld_str                  = (invalid)\n");
   3599     }
   3600   }
   3601   printf("\n");
   3602 }
   3603 
   3604 
   3605 //
   3606 // MinidumpBreakpadInfo
   3607 //
   3608 
   3609 
   3610 MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
   3611     : MinidumpStream(minidump),
   3612       breakpad_info_() {
   3613 }
   3614 
   3615 
   3616 bool MinidumpBreakpadInfo::Read(uint32_t expected_size) {
   3617   valid_ = false;
   3618 
   3619   if (expected_size != sizeof(breakpad_info_)) {
   3620     BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
   3621                     " != " << sizeof(breakpad_info_);
   3622     return false;
   3623   }
   3624 
   3625   if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
   3626     BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
   3627     return false;
   3628   }
   3629 
   3630   if (minidump_->swap()) {
   3631     Swap(&breakpad_info_.validity);
   3632     Swap(&breakpad_info_.dump_thread_id);
   3633     Swap(&breakpad_info_.requesting_thread_id);
   3634   }
   3635 
   3636   valid_ = true;
   3637   return true;
   3638 }
   3639 
   3640 
   3641 bool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const {
   3642   BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
   3643                                  "requires |thread_id|";
   3644   assert(thread_id);
   3645   *thread_id = 0;
   3646 
   3647   if (!valid_) {
   3648     BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
   3649     return false;
   3650   }
   3651 
   3652   if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
   3653     BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
   3654     return false;
   3655   }
   3656 
   3657   *thread_id = breakpad_info_.dump_thread_id;
   3658   return true;
   3659 }
   3660 
   3661 
   3662 bool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id)
   3663     const {
   3664   BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
   3665                                  "requires |thread_id|";
   3666   assert(thread_id);
   3667   *thread_id = 0;
   3668 
   3669   if (!thread_id || !valid_) {
   3670     BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
   3671     return false;
   3672   }
   3673 
   3674   if (!(breakpad_info_.validity &
   3675             MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
   3676     BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
   3677     return false;
   3678   }
   3679 
   3680   *thread_id = breakpad_info_.requesting_thread_id;
   3681   return true;
   3682 }
   3683 
   3684 
   3685 void MinidumpBreakpadInfo::Print() {
   3686   if (!valid_) {
   3687     BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
   3688     return;
   3689   }
   3690 
   3691   printf("MDRawBreakpadInfo\n");
   3692   printf("  validity             = 0x%x\n", breakpad_info_.validity);
   3693   printf("  dump_thread_id       = ");
   3694   PrintValueOrInvalid(breakpad_info_.validity &
   3695                           MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID,
   3696                       kNumberFormatHexadecimal, breakpad_info_.dump_thread_id);
   3697   printf("  requesting_thread_id = ");
   3698   PrintValueOrInvalid(breakpad_info_.validity &
   3699                           MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID,
   3700                       kNumberFormatHexadecimal,
   3701                       breakpad_info_.requesting_thread_id);
   3702 
   3703   printf("\n");
   3704 }
   3705 
   3706 
   3707 //
   3708 // MinidumpMemoryInfo
   3709 //
   3710 
   3711 
   3712 MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
   3713     : MinidumpObject(minidump),
   3714       memory_info_() {
   3715 }
   3716 
   3717 
   3718 bool MinidumpMemoryInfo::IsExecutable() const {
   3719   uint32_t protection =
   3720       memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
   3721   return protection == MD_MEMORY_PROTECT_EXECUTE ||
   3722       protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
   3723       protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
   3724 }
   3725 
   3726 
   3727 bool MinidumpMemoryInfo::IsWritable() const {
   3728   uint32_t protection =
   3729       memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
   3730   return protection == MD_MEMORY_PROTECT_READWRITE ||
   3731     protection == MD_MEMORY_PROTECT_WRITECOPY ||
   3732     protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
   3733     protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
   3734 }
   3735 
   3736 
   3737 bool MinidumpMemoryInfo::Read() {
   3738   valid_ = false;
   3739 
   3740   if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
   3741     BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
   3742     return false;
   3743   }
   3744 
   3745   if (minidump_->swap()) {
   3746     Swap(&memory_info_.base_address);
   3747     Swap(&memory_info_.allocation_base);
   3748     Swap(&memory_info_.allocation_protection);
   3749     Swap(&memory_info_.region_size);
   3750     Swap(&memory_info_.state);
   3751     Swap(&memory_info_.protection);
   3752     Swap(&memory_info_.type);
   3753   }
   3754 
   3755   // Check for base + size overflow or undersize.
   3756   if (memory_info_.region_size == 0 ||
   3757       memory_info_.region_size > numeric_limits<uint64_t>::max() -
   3758                                      memory_info_.base_address) {
   3759     BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
   3760                     HexString(memory_info_.base_address) << "+" <<
   3761                     HexString(memory_info_.region_size);
   3762     return false;
   3763   }
   3764 
   3765   valid_ = true;
   3766   return true;
   3767 }
   3768 
   3769 
   3770 void MinidumpMemoryInfo::Print() {
   3771   if (!valid_) {
   3772     BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
   3773     return;
   3774   }
   3775 
   3776   printf("MDRawMemoryInfo\n");
   3777   printf("  base_address          = 0x%" PRIx64 "\n",
   3778          memory_info_.base_address);
   3779   printf("  allocation_base       = 0x%" PRIx64 "\n",
   3780          memory_info_.allocation_base);
   3781   printf("  allocation_protection = 0x%x\n",
   3782          memory_info_.allocation_protection);
   3783   printf("  region_size           = 0x%" PRIx64 "\n", memory_info_.region_size);
   3784   printf("  state                 = 0x%x\n", memory_info_.state);
   3785   printf("  protection            = 0x%x\n", memory_info_.protection);
   3786   printf("  type                  = 0x%x\n", memory_info_.type);
   3787 }
   3788 
   3789 
   3790 //
   3791 // MinidumpMemoryInfoList
   3792 //
   3793 
   3794 
   3795 MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
   3796     : MinidumpStream(minidump),
   3797       range_map_(new RangeMap<uint64_t, unsigned int>()),
   3798       infos_(NULL),
   3799       info_count_(0) {
   3800 }
   3801 
   3802 
   3803 MinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
   3804   delete range_map_;
   3805   delete infos_;
   3806 }
   3807 
   3808 
   3809 bool MinidumpMemoryInfoList::Read(uint32_t expected_size) {
   3810   // Invalidate cached data.
   3811   delete infos_;
   3812   infos_ = NULL;
   3813   range_map_->Clear();
   3814   info_count_ = 0;
   3815 
   3816   valid_ = false;
   3817 
   3818   MDRawMemoryInfoList header;
   3819   if (expected_size < sizeof(MDRawMemoryInfoList)) {
   3820     BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
   3821                     expected_size << " < " << sizeof(MDRawMemoryInfoList);
   3822     return false;
   3823   }
   3824   if (!minidump_->ReadBytes(&header, sizeof(header))) {
   3825     BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
   3826     return false;
   3827   }
   3828 
   3829   if (minidump_->swap()) {
   3830     Swap(&header.size_of_header);
   3831     Swap(&header.size_of_entry);
   3832     Swap(&header.number_of_entries);
   3833   }
   3834 
   3835   // Sanity check that the header is the expected size.
   3836   // TODO(ted): could possibly handle this more gracefully, assuming
   3837   // that future versions of the structs would be backwards-compatible.
   3838   if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
   3839     BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
   3840                     header.size_of_header << " != " <<
   3841                     sizeof(MDRawMemoryInfoList);
   3842     return false;
   3843   }
   3844 
   3845   // Sanity check that the entries are the expected size.
   3846   if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
   3847     BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
   3848                     header.size_of_entry << " != " <<
   3849                     sizeof(MDRawMemoryInfo);
   3850     return false;
   3851   }
   3852 
   3853   if (header.number_of_entries >
   3854           numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) {
   3855     BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
   3856                     header.number_of_entries <<
   3857                     " would cause multiplication overflow";
   3858     return false;
   3859   }
   3860 
   3861   if (expected_size != sizeof(MDRawMemoryInfoList) +
   3862                         header.number_of_entries * sizeof(MDRawMemoryInfo)) {
   3863     BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
   3864                     " != " << sizeof(MDRawMemoryInfoList) +
   3865                         header.number_of_entries * sizeof(MDRawMemoryInfo);
   3866     return false;
   3867   }
   3868 
   3869   // Check for data loss when converting header.number_of_entries from
   3870   // uint64_t into MinidumpMemoryInfos::size_type (uint32_t)
   3871   MinidumpMemoryInfos::size_type header_number_of_entries =
   3872       static_cast<unsigned int>(header.number_of_entries);
   3873   if (static_cast<uint64_t>(header_number_of_entries) !=
   3874       header.number_of_entries) {
   3875     BPLOG(ERROR) << "Data loss detected when converting "
   3876                     "the header's number_of_entries";
   3877     return false;
   3878   }
   3879 
   3880   if (header.number_of_entries != 0) {
   3881     scoped_ptr<MinidumpMemoryInfos> infos(
   3882         new MinidumpMemoryInfos(header_number_of_entries,
   3883                                 MinidumpMemoryInfo(minidump_)));
   3884 
   3885     for (unsigned int index = 0;
   3886          index < header.number_of_entries;
   3887          ++index) {
   3888       MinidumpMemoryInfo* info = &(*infos)[index];
   3889 
   3890       // Assume that the file offset is correct after the last read.
   3891       if (!info->Read()) {
   3892         BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
   3893                         index << "/" << header.number_of_entries;
   3894         return false;
   3895       }
   3896 
   3897       uint64_t base_address = info->GetBase();
   3898       uint64_t region_size = info->GetSize();
   3899 
   3900       if (!range_map_->StoreRange(base_address, region_size, index)) {
   3901         BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
   3902                         " memory region " <<
   3903                         index << "/" << header.number_of_entries << ", " <<
   3904                         HexString(base_address) << "+" <<
   3905                         HexString(region_size);
   3906         return false;
   3907       }
   3908     }
   3909 
   3910     infos_ = infos.release();
   3911   }
   3912 
   3913   info_count_ = header_number_of_entries;
   3914 
   3915   valid_ = true;
   3916   return true;
   3917 }
   3918 
   3919 
   3920 const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
   3921       unsigned int index) const {
   3922   if (!valid_) {
   3923     BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
   3924     return NULL;
   3925   }
   3926 
   3927   if (index >= info_count_) {
   3928     BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
   3929                     index << "/" << info_count_;
   3930     return NULL;
   3931   }
   3932 
   3933   return &(*infos_)[index];
   3934 }
   3935 
   3936 
   3937 const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
   3938     uint64_t address) const {
   3939   if (!valid_) {
   3940     BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
   3941                     " GetMemoryInfoForAddress";
   3942     return NULL;
   3943   }
   3944 
   3945   unsigned int info_index;
   3946   if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
   3947     BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
   3948                    HexString(address);
   3949     return NULL;
   3950   }
   3951 
   3952   return GetMemoryInfoAtIndex(info_index);
   3953 }
   3954 
   3955 
   3956 void MinidumpMemoryInfoList::Print() {
   3957   if (!valid_) {
   3958     BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
   3959     return;
   3960   }
   3961 
   3962   printf("MinidumpMemoryInfoList\n");
   3963   printf("  info_count = %d\n", info_count_);
   3964   printf("\n");
   3965 
   3966   for (unsigned int info_index = 0;
   3967        info_index < info_count_;
   3968        ++info_index) {
   3969     printf("info[%d]\n", info_index);
   3970     (*infos_)[info_index].Print();
   3971     printf("\n");
   3972   }
   3973 }
   3974 
   3975 
   3976 //
   3977 // Minidump
   3978 //
   3979 
   3980 
   3981 uint32_t Minidump::max_streams_ = 128;
   3982 unsigned int Minidump::max_string_length_ = 1024;
   3983 
   3984 
   3985 Minidump::Minidump(const string& path)
   3986     : header_(),
   3987       directory_(NULL),
   3988       stream_map_(new MinidumpStreamMap()),
   3989       path_(path),
   3990       stream_(NULL),
   3991       swap_(false),
   3992       valid_(false) {
   3993 }
   3994 
   3995 Minidump::Minidump(istream& stream)
   3996     : header_(),
   3997       directory_(NULL),
   3998       stream_map_(new MinidumpStreamMap()),
   3999       path_(),
   4000       stream_(&stream),
   4001       swap_(false),
   4002       valid_(false) {
   4003 }
   4004 
   4005 Minidump::~Minidump() {
   4006   if (stream_) {
   4007     BPLOG(INFO) << "Minidump closing minidump";
   4008   }
   4009   if (!path_.empty()) {
   4010     delete stream_;
   4011   }
   4012   delete directory_;
   4013   delete stream_map_;
   4014 }
   4015 
   4016 
   4017 bool Minidump::Open() {
   4018   if (stream_ != NULL) {
   4019     BPLOG(INFO) << "Minidump reopening minidump " << path_;
   4020 
   4021     // The file is already open.  Seek to the beginning, which is the position
   4022     // the file would be at if it were opened anew.
   4023     return SeekSet(0);
   4024   }
   4025 
   4026   stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
   4027   if (!stream_ || !stream_->good()) {
   4028     string error_string;
   4029     int error_code = ErrnoString(&error_string);
   4030     BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
   4031                     ", error " << error_code << ": " << error_string;
   4032     return false;
   4033   }
   4034 
   4035   BPLOG(INFO) << "Minidump opened minidump " << path_;
   4036   return true;
   4037 }
   4038 
   4039 bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) {
   4040   // Initialize output parameters
   4041   *context_cpu_flags = 0;
   4042 
   4043   // Save the current stream position
   4044   off_t saved_position = Tell();
   4045   if (saved_position == -1) {
   4046     // Failed to save the current stream position.
   4047     // Returns true because the current position of the stream is preserved.
   4048     return true;
   4049   }
   4050 
   4051   const MDRawSystemInfo* system_info =
   4052     GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
   4053 
   4054   if (system_info != NULL) {
   4055     switch (system_info->processor_architecture) {
   4056       case MD_CPU_ARCHITECTURE_X86:
   4057         *context_cpu_flags = MD_CONTEXT_X86;
   4058         break;
   4059       case MD_CPU_ARCHITECTURE_MIPS:
   4060         *context_cpu_flags = MD_CONTEXT_MIPS;
   4061         break;
   4062       case MD_CPU_ARCHITECTURE_ALPHA:
   4063         *context_cpu_flags = MD_CONTEXT_ALPHA;
   4064         break;
   4065       case MD_CPU_ARCHITECTURE_PPC:
   4066         *context_cpu_flags = MD_CONTEXT_PPC;
   4067         break;
   4068       case MD_CPU_ARCHITECTURE_PPC64:
   4069         *context_cpu_flags = MD_CONTEXT_PPC64;
   4070         break;
   4071       case MD_CPU_ARCHITECTURE_SHX:
   4072         *context_cpu_flags = MD_CONTEXT_SHX;
   4073         break;
   4074       case MD_CPU_ARCHITECTURE_ARM:
   4075         *context_cpu_flags = MD_CONTEXT_ARM;
   4076         break;
   4077       case MD_CPU_ARCHITECTURE_ARM64:
   4078         *context_cpu_flags = MD_CONTEXT_ARM64;
   4079         break;
   4080       case MD_CPU_ARCHITECTURE_IA64:
   4081         *context_cpu_flags = MD_CONTEXT_IA64;
   4082         break;
   4083       case MD_CPU_ARCHITECTURE_ALPHA64:
   4084         *context_cpu_flags = 0;
   4085         break;
   4086       case MD_CPU_ARCHITECTURE_MSIL:
   4087         *context_cpu_flags = 0;
   4088         break;
   4089       case MD_CPU_ARCHITECTURE_AMD64:
   4090         *context_cpu_flags = MD_CONTEXT_AMD64;
   4091         break;
   4092       case MD_CPU_ARCHITECTURE_X86_WIN64:
   4093         *context_cpu_flags = 0;
   4094         break;
   4095       case MD_CPU_ARCHITECTURE_SPARC:
   4096         *context_cpu_flags = MD_CONTEXT_SPARC;
   4097         break;
   4098       case MD_CPU_ARCHITECTURE_UNKNOWN:
   4099         *context_cpu_flags = 0;
   4100         break;
   4101       default:
   4102         *context_cpu_flags = 0;
   4103         break;
   4104     }
   4105   }
   4106 
   4107   // Restore position and return
   4108   return SeekSet(saved_position);
   4109 }
   4110 
   4111 
   4112 bool Minidump::Read() {
   4113   // Invalidate cached data.
   4114   delete directory_;
   4115   directory_ = NULL;
   4116   stream_map_->clear();
   4117 
   4118   valid_ = false;
   4119 
   4120   if (!Open()) {
   4121     BPLOG(ERROR) << "Minidump cannot open minidump";
   4122     return false;
   4123   }
   4124 
   4125   if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
   4126     BPLOG(ERROR) << "Minidump cannot read header";
   4127     return false;
   4128   }
   4129 
   4130   if (header_.signature != MD_HEADER_SIGNATURE) {
   4131     // The file may be byte-swapped.  Under the present architecture, these
   4132     // classes don't know or need to know what CPU (or endianness) the
   4133     // minidump was produced on in order to parse it.  Use the signature as
   4134     // a byte order marker.
   4135     uint32_t signature_swapped = header_.signature;
   4136     Swap(&signature_swapped);
   4137     if (signature_swapped != MD_HEADER_SIGNATURE) {
   4138       // This isn't a minidump or a byte-swapped minidump.
   4139       BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
   4140                       HexString(header_.signature) << ", " <<
   4141                       HexString(signature_swapped) << ") != " <<
   4142                       HexString(MD_HEADER_SIGNATURE);
   4143       return false;
   4144     }
   4145     swap_ = true;
   4146   } else {
   4147     // The file is not byte-swapped.  Set swap_ false (it may have been true
   4148     // if the object is being reused?)
   4149     swap_ = false;
   4150   }
   4151 
   4152   BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
   4153                  "byte-swapping minidump";
   4154 
   4155   if (swap_) {
   4156     Swap(&header_.signature);
   4157     Swap(&header_.version);
   4158     Swap(&header_.stream_count);
   4159     Swap(&header_.stream_directory_rva);
   4160     Swap(&header_.checksum);
   4161     Swap(&header_.time_date_stamp);
   4162     Swap(&header_.flags);
   4163   }
   4164 
   4165   // Version check.  The high 16 bits of header_.version contain something
   4166   // else "implementation specific."
   4167   if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
   4168     BPLOG(ERROR) << "Minidump version mismatch: " <<
   4169                     HexString(header_.version & 0x0000ffff) << " != " <<
   4170                     HexString(MD_HEADER_VERSION);
   4171     return false;
   4172   }
   4173 
   4174   if (!SeekSet(header_.stream_directory_rva)) {
   4175     BPLOG(ERROR) << "Minidump cannot seek to stream directory";
   4176     return false;
   4177   }
   4178 
   4179   if (header_.stream_count > max_streams_) {
   4180     BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
   4181                     " exceeds maximum " << max_streams_;
   4182     return false;
   4183   }
   4184 
   4185   if (header_.stream_count != 0) {
   4186     scoped_ptr<MinidumpDirectoryEntries> directory(
   4187         new MinidumpDirectoryEntries(header_.stream_count));
   4188 
   4189     // Read the entire array in one fell swoop, instead of reading one entry
   4190     // at a time in the loop.
   4191     if (!ReadBytes(&(*directory)[0],
   4192                    sizeof(MDRawDirectory) * header_.stream_count)) {
   4193       BPLOG(ERROR) << "Minidump cannot read stream directory";
   4194       return false;
   4195     }
   4196 
   4197     for (unsigned int stream_index = 0;
   4198          stream_index < header_.stream_count;
   4199          ++stream_index) {
   4200       MDRawDirectory* directory_entry = &(*directory)[stream_index];
   4201 
   4202       if (swap_) {
   4203         Swap(&directory_entry->stream_type);
   4204         Swap(&directory_entry->location);
   4205       }
   4206 
   4207       // Initialize the stream_map_ map, which speeds locating a stream by
   4208       // type.
   4209       unsigned int stream_type = directory_entry->stream_type;
   4210       switch (stream_type) {
   4211         case MD_THREAD_LIST_STREAM:
   4212         case MD_MODULE_LIST_STREAM:
   4213         case MD_MEMORY_LIST_STREAM:
   4214         case MD_EXCEPTION_STREAM:
   4215         case MD_SYSTEM_INFO_STREAM:
   4216         case MD_MISC_INFO_STREAM:
   4217         case MD_BREAKPAD_INFO_STREAM: {
   4218           if (stream_map_->find(stream_type) != stream_map_->end()) {
   4219             // Another stream with this type was already found.  A minidump
   4220             // file should contain at most one of each of these stream types.
   4221             BPLOG(ERROR) << "Minidump found multiple streams of type " <<
   4222                             stream_type << ", but can only deal with one";
   4223             return false;
   4224           }
   4225           // Fall through to default
   4226         }
   4227 
   4228         default: {
   4229           // Overwrites for stream types other than those above, but it's
   4230           // expected to be the user's burden in that case.
   4231           (*stream_map_)[stream_type].stream_index = stream_index;
   4232         }
   4233       }
   4234     }
   4235 
   4236     directory_ = directory.release();
   4237   }
   4238 
   4239   valid_ = true;
   4240   return true;
   4241 }
   4242 
   4243 
   4244 MinidumpThreadList* Minidump::GetThreadList() {
   4245   MinidumpThreadList* thread_list;
   4246   return GetStream(&thread_list);
   4247 }
   4248 
   4249 
   4250 MinidumpModuleList* Minidump::GetModuleList() {
   4251   MinidumpModuleList* module_list;
   4252   return GetStream(&module_list);
   4253 }
   4254 
   4255 
   4256 MinidumpMemoryList* Minidump::GetMemoryList() {
   4257   MinidumpMemoryList* memory_list;
   4258   return GetStream(&memory_list);
   4259 }
   4260 
   4261 
   4262 MinidumpException* Minidump::GetException() {
   4263   MinidumpException* exception;
   4264   return GetStream(&exception);
   4265 }
   4266 
   4267 MinidumpAssertion* Minidump::GetAssertion() {
   4268   MinidumpAssertion* assertion;
   4269   return GetStream(&assertion);
   4270 }
   4271 
   4272 
   4273 MinidumpSystemInfo* Minidump::GetSystemInfo() {
   4274   MinidumpSystemInfo* system_info;
   4275   return GetStream(&system_info);
   4276 }
   4277 
   4278 
   4279 MinidumpMiscInfo* Minidump::GetMiscInfo() {
   4280   MinidumpMiscInfo* misc_info;
   4281   return GetStream(&misc_info);
   4282 }
   4283 
   4284 
   4285 MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
   4286   MinidumpBreakpadInfo* breakpad_info;
   4287   return GetStream(&breakpad_info);
   4288 }
   4289 
   4290 MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
   4291   MinidumpMemoryInfoList* memory_info_list;
   4292   return GetStream(&memory_info_list);
   4293 }
   4294 
   4295 static const char* get_stream_name(uint32_t stream_type) {
   4296   switch (stream_type) {
   4297   case MD_UNUSED_STREAM:
   4298     return "MD_UNUSED_STREAM";
   4299   case MD_RESERVED_STREAM_0:
   4300     return "MD_RESERVED_STREAM_0";
   4301   case MD_RESERVED_STREAM_1:
   4302     return "MD_RESERVED_STREAM_1";
   4303   case MD_THREAD_LIST_STREAM:
   4304     return "MD_THREAD_LIST_STREAM";
   4305   case MD_MODULE_LIST_STREAM:
   4306     return "MD_MODULE_LIST_STREAM";
   4307   case MD_MEMORY_LIST_STREAM:
   4308     return "MD_MEMORY_LIST_STREAM";
   4309   case MD_EXCEPTION_STREAM:
   4310     return "MD_EXCEPTION_STREAM";
   4311   case MD_SYSTEM_INFO_STREAM:
   4312     return "MD_SYSTEM_INFO_STREAM";
   4313   case MD_THREAD_EX_LIST_STREAM:
   4314     return "MD_THREAD_EX_LIST_STREAM";
   4315   case MD_MEMORY_64_LIST_STREAM:
   4316     return "MD_MEMORY_64_LIST_STREAM";
   4317   case MD_COMMENT_STREAM_A:
   4318     return "MD_COMMENT_STREAM_A";
   4319   case MD_COMMENT_STREAM_W:
   4320     return "MD_COMMENT_STREAM_W";
   4321   case MD_HANDLE_DATA_STREAM:
   4322     return "MD_HANDLE_DATA_STREAM";
   4323   case MD_FUNCTION_TABLE_STREAM:
   4324     return "MD_FUNCTION_TABLE_STREAM";
   4325   case MD_UNLOADED_MODULE_LIST_STREAM:
   4326     return "MD_UNLOADED_MODULE_LIST_STREAM";
   4327   case MD_MISC_INFO_STREAM:
   4328     return "MD_MISC_INFO_STREAM";
   4329   case MD_MEMORY_INFO_LIST_STREAM:
   4330     return "MD_MEMORY_INFO_LIST_STREAM";
   4331   case MD_THREAD_INFO_LIST_STREAM:
   4332     return "MD_THREAD_INFO_LIST_STREAM";
   4333   case MD_HANDLE_OPERATION_LIST_STREAM:
   4334     return "MD_HANDLE_OPERATION_LIST_STREAM";
   4335   case MD_LAST_RESERVED_STREAM:
   4336     return "MD_LAST_RESERVED_STREAM";
   4337   case MD_BREAKPAD_INFO_STREAM:
   4338     return "MD_BREAKPAD_INFO_STREAM";
   4339   case MD_ASSERTION_INFO_STREAM:
   4340     return "MD_ASSERTION_INFO_STREAM";
   4341   case MD_LINUX_CPU_INFO:
   4342     return "MD_LINUX_CPU_INFO";
   4343   case MD_LINUX_PROC_STATUS:
   4344     return "MD_LINUX_PROC_STATUS";
   4345   case MD_LINUX_LSB_RELEASE:
   4346     return "MD_LINUX_LSB_RELEASE";
   4347   case MD_LINUX_CMD_LINE:
   4348     return "MD_LINUX_CMD_LINE";
   4349   case MD_LINUX_ENVIRON:
   4350     return "MD_LINUX_ENVIRON";
   4351   case MD_LINUX_AUXV:
   4352     return "MD_LINUX_AUXV";
   4353   case MD_LINUX_MAPS:
   4354     return "MD_LINUX_MAPS";
   4355   case MD_LINUX_DSO_DEBUG:
   4356     return "MD_LINUX_DSO_DEBUG";
   4357   default:
   4358     return "unknown";
   4359   }
   4360 }
   4361 
   4362 void Minidump::Print() {
   4363   if (!valid_) {
   4364     BPLOG(ERROR) << "Minidump cannot print invalid data";
   4365     return;
   4366   }
   4367 
   4368   printf("MDRawHeader\n");
   4369   printf("  signature            = 0x%x\n",    header_.signature);
   4370   printf("  version              = 0x%x\n",    header_.version);
   4371   printf("  stream_count         = %d\n",      header_.stream_count);
   4372   printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
   4373   printf("  checksum             = 0x%x\n",    header_.checksum);
   4374   printf("  time_date_stamp      = 0x%x %s\n",
   4375          header_.time_date_stamp,
   4376          TimeTToUTCString(header_.time_date_stamp).c_str());
   4377   printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
   4378   printf("\n");
   4379 
   4380   for (unsigned int stream_index = 0;
   4381        stream_index < header_.stream_count;
   4382        ++stream_index) {
   4383     MDRawDirectory* directory_entry = &(*directory_)[stream_index];
   4384 
   4385     printf("mDirectory[%d]\n", stream_index);
   4386     printf("MDRawDirectory\n");
   4387     printf("  stream_type        = 0x%x (%s)\n", directory_entry->stream_type,
   4388            get_stream_name(directory_entry->stream_type));
   4389     printf("  location.data_size = %d\n",
   4390            directory_entry->location.data_size);
   4391     printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
   4392     printf("\n");
   4393   }
   4394 
   4395   printf("Streams:\n");
   4396   for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
   4397        iterator != stream_map_->end();
   4398        ++iterator) {
   4399     uint32_t stream_type = iterator->first;
   4400     MinidumpStreamInfo info = iterator->second;
   4401     printf("  stream type 0x%x (%s) at index %d\n", stream_type,
   4402            get_stream_name(stream_type),
   4403            info.stream_index);
   4404   }
   4405   printf("\n");
   4406 }
   4407 
   4408 
   4409 const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
   4410       const {
   4411   if (!valid_) {
   4412     BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
   4413     return NULL;
   4414   }
   4415 
   4416   if (index >= header_.stream_count) {
   4417     BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
   4418                     index << "/" << header_.stream_count;
   4419     return NULL;
   4420   }
   4421 
   4422   return &(*directory_)[index];
   4423 }
   4424 
   4425 
   4426 bool Minidump::ReadBytes(void* bytes, size_t count) {
   4427   // Can't check valid_ because Read needs to call this method before
   4428   // validity can be determined.
   4429   if (!stream_) {
   4430     return false;
   4431   }
   4432   stream_->read(static_cast<char*>(bytes), count);
   4433   std::streamsize bytes_read = stream_->gcount();
   4434   if (bytes_read == -1) {
   4435     string error_string;
   4436     int error_code = ErrnoString(&error_string);
   4437     BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
   4438     return false;
   4439   }
   4440 
   4441   // Convert to size_t and check for data loss
   4442   size_t bytes_read_converted = static_cast<size_t>(bytes_read);
   4443   if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) {
   4444     BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting "
   4445                  << bytes_read << " to " << bytes_read_converted;
   4446     return false;
   4447   }
   4448 
   4449   if (bytes_read_converted != count) {
   4450     BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count;
   4451     return false;
   4452   }
   4453 
   4454   return true;
   4455 }
   4456 
   4457 
   4458 bool Minidump::SeekSet(off_t offset) {
   4459   // Can't check valid_ because Read needs to call this method before
   4460   // validity can be determined.
   4461   if (!stream_) {
   4462     return false;
   4463   }
   4464   stream_->seekg(offset, std::ios_base::beg);
   4465   if (!stream_->good()) {
   4466     string error_string;
   4467     int error_code = ErrnoString(&error_string);
   4468     BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
   4469     return false;
   4470   }
   4471   return true;
   4472 }
   4473 
   4474 off_t Minidump::Tell() {
   4475   if (!valid_ || !stream_) {
   4476     return (off_t)-1;
   4477   }
   4478 
   4479   // Check for conversion data loss
   4480   std::streamoff std_streamoff = stream_->tellg();
   4481   off_t rv = static_cast<off_t>(std_streamoff);
   4482   if (static_cast<std::streamoff>(rv) == std_streamoff) {
   4483     return rv;
   4484   } else {
   4485     BPLOG(ERROR) << "Data loss detected";
   4486     return (off_t)-1;
   4487   }
   4488 }
   4489 
   4490 
   4491 string* Minidump::ReadString(off_t offset) {
   4492   if (!valid_) {
   4493     BPLOG(ERROR) << "Invalid Minidump for ReadString";
   4494     return NULL;
   4495   }
   4496   if (!SeekSet(offset)) {
   4497     BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
   4498     return NULL;
   4499   }
   4500 
   4501   uint32_t bytes;
   4502   if (!ReadBytes(&bytes, sizeof(bytes))) {
   4503     BPLOG(ERROR) << "ReadString could not read string size at offset " <<
   4504                     offset;
   4505     return NULL;
   4506   }
   4507   if (swap_)
   4508     Swap(&bytes);
   4509 
   4510   if (bytes % 2 != 0) {
   4511     BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
   4512                     "-byte string at offset " << offset;
   4513     return NULL;
   4514   }
   4515   unsigned int utf16_words = bytes / 2;
   4516 
   4517   if (utf16_words > max_string_length_) {
   4518     BPLOG(ERROR) << "ReadString string length " << utf16_words <<
   4519                     " exceeds maximum " << max_string_length_ <<
   4520                     " at offset " << offset;
   4521     return NULL;
   4522   }
   4523 
   4524   vector<uint16_t> string_utf16(utf16_words);
   4525 
   4526   if (utf16_words) {
   4527     if (!ReadBytes(&string_utf16[0], bytes)) {
   4528       BPLOG(ERROR) << "ReadString could not read " << bytes <<
   4529                       "-byte string at offset " << offset;
   4530       return NULL;
   4531     }
   4532   }
   4533 
   4534   return UTF16ToUTF8(string_utf16, swap_);
   4535 }
   4536 
   4537 
   4538 bool Minidump::SeekToStreamType(uint32_t  stream_type,
   4539                                 uint32_t* stream_length) {
   4540   BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
   4541                                      "|stream_length|";
   4542   assert(stream_length);
   4543   *stream_length = 0;
   4544 
   4545   if (!valid_) {
   4546     BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
   4547     return false;
   4548   }
   4549 
   4550   MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
   4551   if (iterator == stream_map_->end()) {
   4552     // This stream type didn't exist in the directory.
   4553     BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
   4554     return false;
   4555   }
   4556 
   4557   MinidumpStreamInfo info = iterator->second;
   4558   if (info.stream_index >= header_.stream_count) {
   4559     BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
   4560                     " out of range: " <<
   4561                     info.stream_index << "/" << header_.stream_count;
   4562     return false;
   4563   }
   4564 
   4565   MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
   4566   if (!SeekSet(directory_entry->location.rva)) {
   4567     BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
   4568                     stream_type;
   4569     return false;
   4570   }
   4571 
   4572   *stream_length = directory_entry->location.data_size;
   4573 
   4574   return true;
   4575 }
   4576 
   4577 
   4578 template<typename T>
   4579 T* Minidump::GetStream(T** stream) {
   4580   // stream is a garbage parameter that's present only to account for C++'s
   4581   // inability to overload a method based solely on its return type.
   4582 
   4583   const uint32_t stream_type = T::kStreamType;
   4584 
   4585   BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
   4586                               " requires |stream|";
   4587   assert(stream);
   4588   *stream = NULL;
   4589 
   4590   if (!valid_) {
   4591     BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
   4592     return NULL;
   4593   }
   4594 
   4595   MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
   4596   if (iterator == stream_map_->end()) {
   4597     // This stream type didn't exist in the directory.
   4598     BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
   4599     return NULL;
   4600   }
   4601 
   4602   // Get a pointer so that the stored stream field can be altered.
   4603   MinidumpStreamInfo* info = &iterator->second;
   4604 
   4605   if (info->stream) {
   4606     // This cast is safe because info.stream is only populated by this
   4607     // method, and there is a direct correlation between T and stream_type.
   4608     *stream = static_cast<T*>(info->stream);
   4609     return *stream;
   4610   }
   4611 
   4612   uint32_t stream_length;
   4613   if (!SeekToStreamType(stream_type, &stream_length)) {
   4614     BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
   4615     return NULL;
   4616   }
   4617 
   4618   scoped_ptr<T> new_stream(new T(this));
   4619 
   4620   if (!new_stream->Read(stream_length)) {
   4621     BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
   4622     return NULL;
   4623   }
   4624 
   4625   *stream = new_stream.release();
   4626   info->stream = *stream;
   4627   return *stream;
   4628 }
   4629 
   4630 
   4631 }  // namespace google_breakpad
   4632