minidump.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // minidump.cc: A minidump reader. 30 // 31 // See minidump.h for documentation. 32 // 33 // Author: Mark Mentovai 34 35 #ifdef HAVE_CONFIG_H 36 #include <config.h> // Must come first 37 #endif 38 39 #include "google_breakpad/processor/minidump.h" 40 41 #include <assert.h> 42 #include <fcntl.h> 43 #include <inttypes.h> 44 #include <stddef.h> 45 #include <string.h> 46 #include <time.h> 47 48 #ifdef _WIN32 49 #include <io.h> 50 #else // _WIN32 51 #include <unistd.h> 52 #endif // _WIN32 53 54 #include <algorithm> 55 #include <fstream> 56 #include <limits> 57 #include <utility> 58 59 #include "processor/range_map-inl.h" 60 61 #include "common/macros.h" 62 #include "common/scoped_ptr.h" 63 #include "common/stdio_wrapper.h" 64 #include "google_breakpad/processor/dump_context.h" 65 #include "processor/basic_code_module.h" 66 #include "processor/basic_code_modules.h" 67 #include "processor/convert_old_arm64_context.h" 68 #include "processor/logging.h" 69 70 namespace google_breakpad { 71 72 using std::istream; 73 using std::ifstream; 74 using std::numeric_limits; 75 using std::vector; 76 77 namespace { 78 79 // Limit arrived at by adding up possible states in Intel Ch. 13.5 X-SAVE 80 // MANAGED STATE 81 // (~ 3680 bytes) plus some extra for the future. 82 const uint32_t kMaxXSaveAreaSize = 16384; 83 84 // Returns true iff |context_size| matches exactly one of the sizes of the 85 // various MDRawContext* types. 86 // TODO(blundell): This function can be removed once 87 // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 is fixed. 88 bool IsContextSizeUnique(uint32_t context_size) { 89 int num_matching_contexts = 0; 90 if (context_size == sizeof(MDRawContextX86)) 91 num_matching_contexts++; 92 if (context_size == sizeof(MDRawContextPPC)) 93 num_matching_contexts++; 94 if (context_size == sizeof(MDRawContextPPC64)) 95 num_matching_contexts++; 96 if (context_size == sizeof(MDRawContextAMD64)) 97 num_matching_contexts++; 98 if (context_size == sizeof(MDRawContextSPARC)) 99 num_matching_contexts++; 100 if (context_size == sizeof(MDRawContextARM)) 101 num_matching_contexts++; 102 if (context_size == sizeof(MDRawContextARM64)) 103 num_matching_contexts++; 104 if (context_size == sizeof(MDRawContextARM64_Old)) 105 num_matching_contexts++; 106 if (context_size == sizeof(MDRawContextMIPS)) 107 num_matching_contexts++; 108 if (context_size == sizeof(MDRawContextRISCV)) 109 num_matching_contexts++; 110 if (context_size == sizeof(MDRawContextRISCV64)) 111 num_matching_contexts++; 112 return num_matching_contexts == 1; 113 } 114 115 // 116 // Swapping routines 117 // 118 // Inlining these doesn't increase code size significantly, and it saves 119 // a whole lot of unnecessary jumping back and forth. 120 // 121 122 123 // Swapping an 8-bit quantity is a no-op. This function is only provided 124 // to account for certain templatized operations that require swapping for 125 // wider types but handle uint8_t too 126 // (MinidumpMemoryRegion::GetMemoryAtAddressInternal). 127 inline void Swap(uint8_t* value) {} 128 129 // Optimization: don't need to AND the furthest right shift, because we're 130 // shifting an unsigned quantity. The standard requires zero-filling in this 131 // case. If the quantities were signed, a bitmask whould be needed for this 132 // right shift to avoid an arithmetic shift (which retains the sign bit). 133 // The furthest left shift never needs to be ANDed bitmask. 134 135 inline void Swap(uint16_t* value) { 136 *value = (*value >> 8) | (*value << 8); 137 } 138 139 inline void Swap(uint32_t* value) { 140 *value = (*value >> 24) | 141 ((*value >> 8) & 0x0000ff00) | 142 ((*value << 8) & 0x00ff0000) | 143 (*value << 24); 144 } 145 146 inline void Swap(uint64_t* value) { 147 uint32_t* value32 = reinterpret_cast<uint32_t*>(value); 148 Swap(&value32[0]); 149 Swap(&value32[1]); 150 uint32_t temp = value32[0]; 151 value32[0] = value32[1]; 152 value32[1] = temp; 153 } 154 155 156 // Given a pointer to a 128-bit int in the minidump data, set the "low" 157 // and "high" fields appropriately. 158 void Normalize128(uint128_struct* value, bool is_big_endian) { 159 // The struct format is [high, low], so if the format is big-endian, 160 // the most significant bytes will already be in the high field. 161 if (!is_big_endian) { 162 uint64_t temp = value->low; 163 value->low = value->high; 164 value->high = temp; 165 } 166 } 167 168 // This just swaps each int64 half of the 128-bit value. 169 // The value should also be normalized by calling Normalize128(). 170 void Swap(uint128_struct* value) { 171 Swap(&value->low); 172 Swap(&value->high); 173 } 174 175 // Swapping signed integers 176 inline void Swap(int32_t* value) { 177 Swap(reinterpret_cast<uint32_t*>(value)); 178 } 179 180 inline void Swap(MDLocationDescriptor* location_descriptor) { 181 Swap(&location_descriptor->data_size); 182 Swap(&location_descriptor->rva); 183 } 184 185 inline void Swap(MDMemoryDescriptor* memory_descriptor) { 186 Swap(&memory_descriptor->start_of_memory_range); 187 Swap(&memory_descriptor->memory); 188 } 189 190 inline void Swap(MDGUID* guid) { 191 Swap(&guid->data1); 192 Swap(&guid->data2); 193 Swap(&guid->data3); 194 // Don't swap guid->data4[] because it contains 8-bit quantities. 195 } 196 197 inline void Swap(MDSystemTime* system_time) { 198 Swap(&system_time->year); 199 Swap(&system_time->month); 200 Swap(&system_time->day_of_week); 201 Swap(&system_time->day); 202 Swap(&system_time->hour); 203 Swap(&system_time->minute); 204 Swap(&system_time->second); 205 Swap(&system_time->milliseconds); 206 } 207 208 inline void Swap(MDXStateFeature* xstate_feature) { 209 Swap(&xstate_feature->offset); 210 Swap(&xstate_feature->size); 211 } 212 213 inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) { 214 Swap(&xstate_feature_info->size_of_info); 215 Swap(&xstate_feature_info->context_size); 216 Swap(&xstate_feature_info->enabled_features); 217 218 for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) { 219 Swap(&xstate_feature_info->features[i]); 220 } 221 } 222 223 inline void Swap(MDRawSimpleStringDictionaryEntry* entry) { 224 Swap(&entry->key); 225 Swap(&entry->value); 226 } 227 228 inline void Swap(MDRawCrashpadAnnotation* annotation) { 229 Swap(&annotation->name); 230 Swap(&annotation->type); 231 Swap(&annotation->value); 232 } 233 234 inline void Swap(uint16_t* data, size_t size_in_bytes) { 235 size_t data_length = size_in_bytes / sizeof(data[0]); 236 for (size_t i = 0; i < data_length; i++) { 237 Swap(&data[i]); 238 } 239 } 240 241 // 242 // Character conversion routines 243 // 244 245 246 // Standard wide-character conversion routines depend on the system's own 247 // idea of what width a wide character should be: some use 16 bits, and 248 // some use 32 bits. For the purposes of a minidump, wide strings are 249 // always represented with 16-bit UTF-16 chracters. iconv isn't available 250 // everywhere, and its interface varies where it is available. iconv also 251 // deals purely with char* pointers, so in addition to considering the swap 252 // parameter, a converter that uses iconv would also need to take the host 253 // CPU's endianness into consideration. It doesn't seems worth the trouble 254 // of making it a dependency when we don't care about anything but UTF-16. 255 string* UTF16ToUTF8(const vector<uint16_t>& in, bool swap) { 256 scoped_ptr<string> out(new string()); 257 258 // Set the string's initial capacity to the number of UTF-16 characters, 259 // because the UTF-8 representation will always be at least this long. 260 // If the UTF-8 representation is longer, the string will grow dynamically. 261 out->reserve(in.size()); 262 263 for (vector<uint16_t>::const_iterator iterator = in.begin(); 264 iterator != in.end(); 265 ++iterator) { 266 // Get a 16-bit value from the input 267 uint16_t in_word = *iterator; 268 if (swap) 269 Swap(&in_word); 270 271 // Convert the input value (in_word) into a Unicode code point (unichar). 272 uint32_t unichar; 273 if (in_word >= 0xdc00 && in_word <= 0xdcff) { 274 BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " << 275 HexString(in_word) << " without high"; 276 return NULL; 277 } else if (in_word >= 0xd800 && in_word <= 0xdbff) { 278 // High surrogate. 279 unichar = (in_word - 0xd7c0) << 10; 280 if (++iterator == in.end()) { 281 BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << 282 HexString(in_word) << " at end of string"; 283 return NULL; 284 } 285 uint32_t high_word = in_word; 286 in_word = *iterator; 287 if (in_word < 0xdc00 || in_word > 0xdcff) { 288 BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << 289 HexString(high_word) << " without low " << 290 HexString(in_word); 291 return NULL; 292 } 293 unichar |= in_word & 0x03ff; 294 } else { 295 // The ordinary case, a single non-surrogate Unicode character encoded 296 // as a single 16-bit value. 297 unichar = in_word; 298 } 299 300 // Convert the Unicode code point (unichar) into its UTF-8 representation, 301 // appending it to the out string. 302 if (unichar < 0x80) { 303 (*out) += static_cast<char>(unichar); 304 } else if (unichar < 0x800) { 305 (*out) += 0xc0 | static_cast<char>(unichar >> 6); 306 (*out) += 0x80 | static_cast<char>(unichar & 0x3f); 307 } else if (unichar < 0x10000) { 308 (*out) += 0xe0 | static_cast<char>(unichar >> 12); 309 (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); 310 (*out) += 0x80 | static_cast<char>(unichar & 0x3f); 311 } else if (unichar < 0x200000) { 312 (*out) += 0xf0 | static_cast<char>(unichar >> 18); 313 (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f); 314 (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); 315 (*out) += 0x80 | static_cast<char>(unichar & 0x3f); 316 } else { 317 BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " << 318 HexString(unichar) << " in UTF-8"; 319 return NULL; 320 } 321 } 322 323 return out.release(); 324 } 325 326 // Return the smaller of the number of code units in the UTF-16 string, 327 // not including the terminating null word, or maxlen. 328 size_t UTF16codeunits(const uint16_t* string, size_t maxlen) { 329 size_t count = 0; 330 while (count < maxlen && string[count] != 0) 331 count++; 332 return count; 333 } 334 335 inline void Swap(MDTimeZoneInformation* time_zone) { 336 Swap(&time_zone->bias); 337 // Skip time_zone->standard_name. No need to swap UTF-16 fields. 338 // The swap will be done as part of the conversion to UTF-8. 339 Swap(&time_zone->standard_date); 340 Swap(&time_zone->standard_bias); 341 // Skip time_zone->daylight_name. No need to swap UTF-16 fields. 342 // The swap will be done as part of the conversion to UTF-8. 343 Swap(&time_zone->daylight_date); 344 Swap(&time_zone->daylight_bias); 345 } 346 347 void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data, 348 size_t max_length_in_bytes, 349 string* utf8_result, 350 bool swap) { 351 // Since there is no explicit byte length for each string, use 352 // UTF16codeunits to calculate word length, then derive byte 353 // length from that. 354 size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]); 355 size_t word_length = UTF16codeunits(utf16_data, max_word_length); 356 if (word_length > 0) { 357 size_t byte_length = word_length * sizeof(utf16_data[0]); 358 vector<uint16_t> utf16_vector(word_length); 359 memcpy(&utf16_vector[0], &utf16_data[0], byte_length); 360 scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap)); 361 if (temp.get()) { 362 utf8_result->assign(*temp); 363 } 364 } else { 365 utf8_result->clear(); 366 } 367 } 368 369 370 // For fields that may or may not be valid, PrintValueOrInvalid will print the 371 // string "(invalid)" if the field is not valid, and will print the value if 372 // the field is valid. The value is printed as hexadecimal or decimal. 373 374 enum NumberFormat { 375 kNumberFormatDecimal, 376 kNumberFormatHexadecimal, 377 }; 378 379 void PrintValueOrInvalid(bool valid, 380 NumberFormat number_format, 381 uint32_t value) { 382 if (!valid) { 383 printf("(invalid)\n"); 384 } else if (number_format == kNumberFormatDecimal) { 385 printf("%d\n", value); 386 } else { 387 printf("0x%x\n", value); 388 } 389 } 390 391 // Converts a time_t to a string showing the time in UTC. 392 string TimeTToUTCString(time_t tt) { 393 struct tm timestruct; 394 #ifdef _WIN32 395 gmtime_s(×truct, &tt); 396 #else 397 gmtime_r(&tt, ×truct); 398 #endif 399 400 char timestr[20]; 401 size_t rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); 402 if (rv == 0) { 403 return string(); 404 } 405 406 return string(timestr); 407 } 408 409 string MDGUIDToString(const MDGUID& uuid) { 410 char buf[37]; 411 snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 412 uuid.data1, 413 uuid.data2, 414 uuid.data3, 415 uuid.data4[0], 416 uuid.data4[1], 417 uuid.data4[2], 418 uuid.data4[3], 419 uuid.data4[4], 420 uuid.data4[5], 421 uuid.data4[6], 422 uuid.data4[7]); 423 return std::string(buf); 424 } 425 426 bool IsDevAshmem(const string& filename) { 427 const string kDevAshmem("/dev/ashmem/"); 428 return filename.compare(0, kDevAshmem.length(), kDevAshmem) == 0; 429 } 430 431 } // namespace 432 433 // 434 // MinidumpObject 435 // 436 437 438 MinidumpObject::MinidumpObject(Minidump* minidump) 439 : DumpObject(), 440 minidump_(minidump) { 441 } 442 443 444 // 445 // MinidumpStream 446 // 447 448 449 MinidumpStream::MinidumpStream(Minidump* minidump) 450 : MinidumpObject(minidump) { 451 } 452 453 454 // 455 // MinidumpContext 456 // 457 458 459 MinidumpContext::MinidumpContext(Minidump* minidump) 460 : DumpContext(), 461 minidump_(minidump) { 462 } 463 464 MinidumpContext::~MinidumpContext() { 465 } 466 467 bool MinidumpContext::Read(uint32_t expected_size) { 468 valid_ = false; 469 470 // Certain raw context types are currently assumed to have unique sizes. 471 if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) { 472 BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any " 473 << "other raw context"; 474 return false; 475 } 476 if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) { 477 BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any " 478 << "other raw context"; 479 return false; 480 } 481 if (!IsContextSizeUnique(sizeof(MDRawContextARM64_Old))) { 482 BPLOG(ERROR) << "sizeof(MDRawContextARM64_Old) cannot match the size of any " 483 << "other raw context"; 484 return false; 485 } 486 487 FreeContext(); 488 489 // First, figure out what type of CPU this context structure is for. 490 // For some reason, the AMD64 Context doesn't have context_flags 491 // at the beginning of the structure, so special case it here. 492 493 uint32_t sysinfo_cpu_type = 0; 494 if (!minidump_->GetContextCPUFlagsFromSystemInfo(&sysinfo_cpu_type)) { 495 BPLOG(ERROR) << "Failed to preserve the current stream position"; 496 return false; 497 } 498 499 if (expected_size == sizeof(MDRawContextAMD64) || 500 (sysinfo_cpu_type == MD_CONTEXT_AMD64 && 501 expected_size >= sizeof(MDRawContextAMD64))) { 502 BPLOG(INFO) << "MinidumpContext: looks like AMD64 context"; 503 504 scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64()); 505 if (!minidump_->ReadBytes(context_amd64.get(), 506 sizeof(MDRawContextAMD64))) { 507 BPLOG(ERROR) << "MinidumpContext could not read amd64 context"; 508 return false; 509 } 510 511 // Context may include xsave registers and so be larger than 512 // sizeof(MDRawContextAMD64). For now we skip this extended data. 513 if (expected_size > sizeof(MDRawContextAMD64)) { 514 size_t bytes_left = expected_size - sizeof(MDRawContextAMD64); 515 if (bytes_left > kMaxXSaveAreaSize) { 516 BPLOG(ERROR) << "MinidumpContext oversized xstate area"; 517 return false; 518 } 519 std::vector<uint8_t> xstate(bytes_left); 520 if (!minidump_->ReadBytes(xstate.data(), 521 bytes_left)) { 522 BPLOG(ERROR) << "MinidumpContext could not skip amd64 xstate"; 523 return false; 524 } 525 } 526 527 if (minidump_->swap()) 528 Swap(&context_amd64->context_flags); 529 530 uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK; 531 if (cpu_type == 0) { 532 context_amd64->context_flags |= sysinfo_cpu_type; 533 } 534 535 if (cpu_type != MD_CONTEXT_AMD64) { 536 // TODO: Fall through to switch below. 537 // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 538 BPLOG(ERROR) << "MinidumpContext not actually amd64 context"; 539 return false; 540 } 541 542 // Do this after reading the entire MDRawContext structure because 543 // GetSystemInfo may seek minidump to a new position. 544 if (!CheckAgainstSystemInfo(cpu_type)) { 545 BPLOG(ERROR) << "MinidumpContext amd64 does not match system info"; 546 return false; 547 } 548 549 // Normalize the 128-bit types in the dump. 550 // Since this is AMD64, by definition, the values are little-endian. 551 for (unsigned int vr_index = 0; 552 vr_index < MD_CONTEXT_AMD64_VR_COUNT; 553 ++vr_index) 554 Normalize128(&context_amd64->vector_register[vr_index], false); 555 556 if (minidump_->swap()) { 557 Swap(&context_amd64->p1_home); 558 Swap(&context_amd64->p2_home); 559 Swap(&context_amd64->p3_home); 560 Swap(&context_amd64->p4_home); 561 Swap(&context_amd64->p5_home); 562 Swap(&context_amd64->p6_home); 563 // context_flags is already swapped 564 Swap(&context_amd64->mx_csr); 565 Swap(&context_amd64->cs); 566 Swap(&context_amd64->ds); 567 Swap(&context_amd64->es); 568 Swap(&context_amd64->fs); 569 Swap(&context_amd64->ss); 570 Swap(&context_amd64->eflags); 571 Swap(&context_amd64->dr0); 572 Swap(&context_amd64->dr1); 573 Swap(&context_amd64->dr2); 574 Swap(&context_amd64->dr3); 575 Swap(&context_amd64->dr6); 576 Swap(&context_amd64->dr7); 577 Swap(&context_amd64->rax); 578 Swap(&context_amd64->rcx); 579 Swap(&context_amd64->rdx); 580 Swap(&context_amd64->rbx); 581 Swap(&context_amd64->rsp); 582 Swap(&context_amd64->rbp); 583 Swap(&context_amd64->rsi); 584 Swap(&context_amd64->rdi); 585 Swap(&context_amd64->r8); 586 Swap(&context_amd64->r9); 587 Swap(&context_amd64->r10); 588 Swap(&context_amd64->r11); 589 Swap(&context_amd64->r12); 590 Swap(&context_amd64->r13); 591 Swap(&context_amd64->r14); 592 Swap(&context_amd64->r15); 593 Swap(&context_amd64->rip); 594 // FIXME: I'm not sure what actually determines 595 // which member of the union {flt_save, sse_registers} 596 // is valid. We're not currently using either, 597 // but it would be good to have them swapped properly. 598 599 for (unsigned int vr_index = 0; 600 vr_index < MD_CONTEXT_AMD64_VR_COUNT; 601 ++vr_index) 602 Swap(&context_amd64->vector_register[vr_index]); 603 Swap(&context_amd64->vector_control); 604 Swap(&context_amd64->debug_control); 605 Swap(&context_amd64->last_branch_to_rip); 606 Swap(&context_amd64->last_branch_from_rip); 607 Swap(&context_amd64->last_exception_to_rip); 608 Swap(&context_amd64->last_exception_from_rip); 609 } 610 611 SetContextFlags(context_amd64->context_flags); 612 613 SetContextAMD64(context_amd64.release()); 614 } else if (expected_size == sizeof(MDRawContextPPC64)) { 615 // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext 616 // in the else case have 32 bits |context_flags|, so special case it here. 617 uint64_t context_flags; 618 if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { 619 BPLOG(ERROR) << "MinidumpContext could not read context flags"; 620 return false; 621 } 622 if (minidump_->swap()) 623 Swap(&context_flags); 624 625 uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; 626 scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64()); 627 628 if (cpu_type == 0) { 629 if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { 630 context_ppc64->context_flags |= cpu_type; 631 } else { 632 BPLOG(ERROR) << "Failed to preserve the current stream position"; 633 return false; 634 } 635 } 636 637 if (cpu_type != MD_CONTEXT_PPC64) { 638 // TODO: Fall through to switch below. 639 // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 640 BPLOG(ERROR) << "MinidumpContext not actually ppc64 context"; 641 return false; 642 } 643 644 // Set the context_flags member, which has already been read, and 645 // read the rest of the structure beginning with the first member 646 // after context_flags. 647 context_ppc64->context_flags = context_flags; 648 649 size_t flags_size = sizeof(context_ppc64->context_flags); 650 uint8_t* context_after_flags = 651 reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size; 652 if (!minidump_->ReadBytes(context_after_flags, 653 sizeof(MDRawContextPPC64) - flags_size)) { 654 BPLOG(ERROR) << "MinidumpContext could not read ppc64 context"; 655 return false; 656 } 657 658 // Do this after reading the entire MDRawContext structure because 659 // GetSystemInfo may seek minidump to a new position. 660 if (!CheckAgainstSystemInfo(cpu_type)) { 661 BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info"; 662 return false; 663 } 664 if (minidump_->swap()) { 665 // context_ppc64->context_flags was already swapped. 666 Swap(&context_ppc64->srr0); 667 Swap(&context_ppc64->srr1); 668 for (unsigned int gpr_index = 0; 669 gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; 670 ++gpr_index) { 671 Swap(&context_ppc64->gpr[gpr_index]); 672 } 673 Swap(&context_ppc64->cr); 674 Swap(&context_ppc64->xer); 675 Swap(&context_ppc64->lr); 676 Swap(&context_ppc64->ctr); 677 Swap(&context_ppc64->vrsave); 678 for (unsigned int fpr_index = 0; 679 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 680 ++fpr_index) { 681 Swap(&context_ppc64->float_save.fpregs[fpr_index]); 682 } 683 // Don't swap context_ppc64->float_save.fpscr_pad because it is only 684 // used for padding. 685 Swap(&context_ppc64->float_save.fpscr); 686 for (unsigned int vr_index = 0; 687 vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; 688 ++vr_index) { 689 Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true); 690 Swap(&context_ppc64->vector_save.save_vr[vr_index]); 691 } 692 Swap(&context_ppc64->vector_save.save_vscr); 693 // Don't swap the padding fields in vector_save. 694 Swap(&context_ppc64->vector_save.save_vrvalid); 695 } 696 697 SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags)); 698 699 // Check for data loss when converting context flags from uint64_t into 700 // uint32_t 701 if (static_cast<uint64_t>(GetContextFlags()) != 702 context_ppc64->context_flags) { 703 BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags"; 704 return false; 705 } 706 707 SetContextPPC64(context_ppc64.release()); 708 } else if (expected_size == sizeof(MDRawContextARM64_Old)) { 709 // |context_flags| of MDRawContextARM64_Old is 64 bits, but other MDRawContext 710 // in the else case have 32 bits |context_flags|, so special case it here. 711 uint64_t context_flags; 712 713 BPLOG(INFO) << "MinidumpContext: looks like ARM64 context"; 714 715 if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { 716 BPLOG(ERROR) << "MinidumpContext could not read context flags"; 717 return false; 718 } 719 if (minidump_->swap()) 720 Swap(&context_flags); 721 722 scoped_ptr<MDRawContextARM64_Old> context_arm64(new MDRawContextARM64_Old()); 723 724 uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; 725 if (cpu_type == 0) { 726 if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { 727 context_arm64->context_flags |= cpu_type; 728 } else { 729 BPLOG(ERROR) << "Failed to preserve the current stream position"; 730 return false; 731 } 732 } 733 734 if (cpu_type != MD_CONTEXT_ARM64_OLD) { 735 // TODO: Fall through to switch below. 736 // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 737 BPLOG(ERROR) << "MinidumpContext not actually arm64 context"; 738 return false; 739 } 740 741 // Set the context_flags member, which has already been read, and 742 // read the rest of the structure beginning with the first member 743 // after context_flags. 744 context_arm64->context_flags = context_flags; 745 746 size_t flags_size = sizeof(context_arm64->context_flags); 747 uint8_t* context_after_flags = 748 reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size; 749 if (!minidump_->ReadBytes(context_after_flags, 750 sizeof(MDRawContextARM64_Old) - flags_size)) { 751 BPLOG(ERROR) << "MinidumpContext could not read arm64 context"; 752 return false; 753 } 754 755 // Do this after reading the entire MDRawContext structure because 756 // GetSystemInfo may seek minidump to a new position. 757 if (!CheckAgainstSystemInfo(cpu_type)) { 758 BPLOG(ERROR) << "MinidumpContext arm64 does not match system info"; 759 return false; 760 } 761 762 if (minidump_->swap()) { 763 // context_arm64->context_flags was already swapped. 764 for (unsigned int ireg_index = 0; 765 ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; 766 ++ireg_index) { 767 Swap(&context_arm64->iregs[ireg_index]); 768 } 769 Swap(&context_arm64->cpsr); 770 Swap(&context_arm64->float_save.fpsr); 771 Swap(&context_arm64->float_save.fpcr); 772 for (unsigned int fpr_index = 0; 773 fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; 774 ++fpr_index) { 775 Normalize128(&context_arm64->float_save.regs[fpr_index], 776 minidump_->is_big_endian()); 777 Swap(&context_arm64->float_save.regs[fpr_index]); 778 } 779 } 780 781 scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64()); 782 ConvertOldARM64Context(*context_arm64.get(), new_context.get()); 783 SetContextFlags(new_context->context_flags); 784 SetContextARM64(new_context.release()); 785 } else { 786 uint32_t context_flags; 787 if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { 788 BPLOG(ERROR) << "MinidumpContext could not read context flags"; 789 return false; 790 } 791 if (minidump_->swap()) 792 Swap(&context_flags); 793 794 uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; 795 if (cpu_type == 0) { 796 // Unfortunately the flag for MD_CONTEXT_ARM that was taken 797 // from a Windows CE SDK header conflicts in practice with 798 // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered, 799 // but handle dumps with the legacy value gracefully here. 800 if (context_flags & MD_CONTEXT_ARM_OLD) { 801 context_flags |= MD_CONTEXT_ARM; 802 context_flags &= ~MD_CONTEXT_ARM_OLD; 803 cpu_type = MD_CONTEXT_ARM; 804 } 805 } 806 807 // Fixup if we were not provided a cpu type. 808 if (cpu_type == 0) { 809 cpu_type = sysinfo_cpu_type; 810 context_flags |= cpu_type; 811 } 812 813 // Allocate the context structure for the correct CPU and fill it. The 814 // casts are slightly unorthodox, but it seems better to do that than to 815 // maintain a separate pointer for each type of CPU context structure 816 // when only one of them will be used. 817 switch (cpu_type) { 818 case MD_CONTEXT_X86: { 819 if (expected_size != sizeof(MDRawContextX86)) { 820 BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " << 821 expected_size << " != " << sizeof(MDRawContextX86); 822 return false; 823 } 824 825 scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86()); 826 827 // Set the context_flags member, which has already been read, and 828 // read the rest of the structure beginning with the first member 829 // after context_flags. 830 context_x86->context_flags = context_flags; 831 832 size_t flags_size = sizeof(context_x86->context_flags); 833 uint8_t* context_after_flags = 834 reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size; 835 if (!minidump_->ReadBytes(context_after_flags, 836 sizeof(MDRawContextX86) - flags_size)) { 837 BPLOG(ERROR) << "MinidumpContext could not read x86 context"; 838 return false; 839 } 840 841 // Do this after reading the entire MDRawContext structure because 842 // GetSystemInfo may seek minidump to a new position. 843 if (!CheckAgainstSystemInfo(cpu_type)) { 844 BPLOG(ERROR) << "MinidumpContext x86 does not match system info"; 845 return false; 846 } 847 848 if (minidump_->swap()) { 849 // context_x86->context_flags was already swapped. 850 Swap(&context_x86->dr0); 851 Swap(&context_x86->dr1); 852 Swap(&context_x86->dr2); 853 Swap(&context_x86->dr3); 854 Swap(&context_x86->dr6); 855 Swap(&context_x86->dr7); 856 Swap(&context_x86->float_save.control_word); 857 Swap(&context_x86->float_save.status_word); 858 Swap(&context_x86->float_save.tag_word); 859 Swap(&context_x86->float_save.error_offset); 860 Swap(&context_x86->float_save.error_selector); 861 Swap(&context_x86->float_save.data_offset); 862 Swap(&context_x86->float_save.data_selector); 863 // context_x86->float_save.register_area[] contains 8-bit quantities 864 // and does not need to be swapped. 865 Swap(&context_x86->float_save.cr0_npx_state); 866 Swap(&context_x86->gs); 867 Swap(&context_x86->fs); 868 Swap(&context_x86->es); 869 Swap(&context_x86->ds); 870 Swap(&context_x86->edi); 871 Swap(&context_x86->esi); 872 Swap(&context_x86->ebx); 873 Swap(&context_x86->edx); 874 Swap(&context_x86->ecx); 875 Swap(&context_x86->eax); 876 Swap(&context_x86->ebp); 877 Swap(&context_x86->eip); 878 Swap(&context_x86->cs); 879 Swap(&context_x86->eflags); 880 Swap(&context_x86->esp); 881 Swap(&context_x86->ss); 882 // context_x86->extended_registers[] contains 8-bit quantities and 883 // does not need to be swapped. 884 } 885 886 SetContextX86(context_x86.release()); 887 888 break; 889 } 890 891 case MD_CONTEXT_PPC: { 892 if (expected_size != sizeof(MDRawContextPPC)) { 893 BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " << 894 expected_size << " != " << sizeof(MDRawContextPPC); 895 return false; 896 } 897 898 scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC()); 899 900 // Set the context_flags member, which has already been read, and 901 // read the rest of the structure beginning with the first member 902 // after context_flags. 903 context_ppc->context_flags = context_flags; 904 905 size_t flags_size = sizeof(context_ppc->context_flags); 906 uint8_t* context_after_flags = 907 reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size; 908 if (!minidump_->ReadBytes(context_after_flags, 909 sizeof(MDRawContextPPC) - flags_size)) { 910 BPLOG(ERROR) << "MinidumpContext could not read ppc context"; 911 return false; 912 } 913 914 // Do this after reading the entire MDRawContext structure because 915 // GetSystemInfo may seek minidump to a new position. 916 if (!CheckAgainstSystemInfo(cpu_type)) { 917 BPLOG(ERROR) << "MinidumpContext ppc does not match system info"; 918 return false; 919 } 920 921 // Normalize the 128-bit types in the dump. 922 // Since this is PowerPC, by definition, the values are big-endian. 923 for (unsigned int vr_index = 0; 924 vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; 925 ++vr_index) { 926 Normalize128(&context_ppc->vector_save.save_vr[vr_index], true); 927 } 928 929 if (minidump_->swap()) { 930 // context_ppc->context_flags was already swapped. 931 Swap(&context_ppc->srr0); 932 Swap(&context_ppc->srr1); 933 for (unsigned int gpr_index = 0; 934 gpr_index < MD_CONTEXT_PPC_GPR_COUNT; 935 ++gpr_index) { 936 Swap(&context_ppc->gpr[gpr_index]); 937 } 938 Swap(&context_ppc->cr); 939 Swap(&context_ppc->xer); 940 Swap(&context_ppc->lr); 941 Swap(&context_ppc->ctr); 942 Swap(&context_ppc->mq); 943 Swap(&context_ppc->vrsave); 944 for (unsigned int fpr_index = 0; 945 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 946 ++fpr_index) { 947 Swap(&context_ppc->float_save.fpregs[fpr_index]); 948 } 949 // Don't swap context_ppc->float_save.fpscr_pad because it is only 950 // used for padding. 951 Swap(&context_ppc->float_save.fpscr); 952 for (unsigned int vr_index = 0; 953 vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; 954 ++vr_index) { 955 Swap(&context_ppc->vector_save.save_vr[vr_index]); 956 } 957 Swap(&context_ppc->vector_save.save_vscr); 958 // Don't swap the padding fields in vector_save. 959 Swap(&context_ppc->vector_save.save_vrvalid); 960 } 961 962 SetContextPPC(context_ppc.release()); 963 964 break; 965 } 966 967 case MD_CONTEXT_SPARC: { 968 if (expected_size != sizeof(MDRawContextSPARC)) { 969 BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " << 970 expected_size << " != " << sizeof(MDRawContextSPARC); 971 return false; 972 } 973 974 scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC()); 975 976 // Set the context_flags member, which has already been read, and 977 // read the rest of the structure beginning with the first member 978 // after context_flags. 979 context_sparc->context_flags = context_flags; 980 981 size_t flags_size = sizeof(context_sparc->context_flags); 982 uint8_t* context_after_flags = 983 reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size; 984 if (!minidump_->ReadBytes(context_after_flags, 985 sizeof(MDRawContextSPARC) - flags_size)) { 986 BPLOG(ERROR) << "MinidumpContext could not read sparc context"; 987 return false; 988 } 989 990 // Do this after reading the entire MDRawContext structure because 991 // GetSystemInfo may seek minidump to a new position. 992 if (!CheckAgainstSystemInfo(cpu_type)) { 993 BPLOG(ERROR) << "MinidumpContext sparc does not match system info"; 994 return false; 995 } 996 997 if (minidump_->swap()) { 998 // context_sparc->context_flags was already swapped. 999 for (unsigned int gpr_index = 0; 1000 gpr_index < MD_CONTEXT_SPARC_GPR_COUNT; 1001 ++gpr_index) { 1002 Swap(&context_sparc->g_r[gpr_index]); 1003 } 1004 Swap(&context_sparc->ccr); 1005 Swap(&context_sparc->pc); 1006 Swap(&context_sparc->npc); 1007 Swap(&context_sparc->y); 1008 Swap(&context_sparc->asi); 1009 Swap(&context_sparc->fprs); 1010 for (unsigned int fpr_index = 0; 1011 fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; 1012 ++fpr_index) { 1013 Swap(&context_sparc->float_save.regs[fpr_index]); 1014 } 1015 Swap(&context_sparc->float_save.filler); 1016 Swap(&context_sparc->float_save.fsr); 1017 } 1018 SetContextSPARC(context_sparc.release()); 1019 1020 break; 1021 } 1022 1023 case MD_CONTEXT_ARM: { 1024 if (expected_size != sizeof(MDRawContextARM)) { 1025 BPLOG(ERROR) << "MinidumpContext arm size mismatch, " << 1026 expected_size << " != " << sizeof(MDRawContextARM); 1027 return false; 1028 } 1029 1030 scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM()); 1031 1032 // Set the context_flags member, which has already been read, and 1033 // read the rest of the structure beginning with the first member 1034 // after context_flags. 1035 context_arm->context_flags = context_flags; 1036 1037 size_t flags_size = sizeof(context_arm->context_flags); 1038 uint8_t* context_after_flags = 1039 reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size; 1040 if (!minidump_->ReadBytes(context_after_flags, 1041 sizeof(MDRawContextARM) - flags_size)) { 1042 BPLOG(ERROR) << "MinidumpContext could not read arm context"; 1043 return false; 1044 } 1045 1046 // Do this after reading the entire MDRawContext structure because 1047 // GetSystemInfo may seek minidump to a new position. 1048 if (!CheckAgainstSystemInfo(cpu_type)) { 1049 BPLOG(ERROR) << "MinidumpContext arm does not match system info"; 1050 return false; 1051 } 1052 1053 if (minidump_->swap()) { 1054 // context_arm->context_flags was already swapped. 1055 for (unsigned int ireg_index = 0; 1056 ireg_index < MD_CONTEXT_ARM_GPR_COUNT; 1057 ++ireg_index) { 1058 Swap(&context_arm->iregs[ireg_index]); 1059 } 1060 Swap(&context_arm->cpsr); 1061 Swap(&context_arm->float_save.fpscr); 1062 for (unsigned int fpr_index = 0; 1063 fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; 1064 ++fpr_index) { 1065 Swap(&context_arm->float_save.regs[fpr_index]); 1066 } 1067 for (unsigned int fpe_index = 0; 1068 fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; 1069 ++fpe_index) { 1070 Swap(&context_arm->float_save.extra[fpe_index]); 1071 } 1072 } 1073 SetContextARM(context_arm.release()); 1074 1075 break; 1076 } 1077 1078 case MD_CONTEXT_ARM64: { 1079 if (expected_size != sizeof(MDRawContextARM64)) { 1080 BPLOG(ERROR) << "MinidumpContext arm64 size mismatch, " << 1081 expected_size << " != " << sizeof(MDRawContextARM64); 1082 return false; 1083 } 1084 1085 scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64()); 1086 1087 // Set the context_flags member, which has already been read, and 1088 // read the rest of the structure beginning with the first member 1089 // after context_flags. 1090 context_arm64->context_flags = context_flags; 1091 1092 size_t flags_size = sizeof(context_arm64->context_flags); 1093 uint8_t* context_after_flags = 1094 reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size; 1095 if (!minidump_->ReadBytes(context_after_flags, 1096 sizeof(*context_arm64) - flags_size)) { 1097 BPLOG(ERROR) << "MinidumpContext could not read arm64 context"; 1098 return false; 1099 } 1100 1101 // Do this after reading the entire MDRawContext structure because 1102 // GetSystemInfo may seek minidump to a new position. 1103 if (!CheckAgainstSystemInfo(cpu_type)) { 1104 BPLOG(ERROR) << "MinidumpContext arm does not match system info"; 1105 return false; 1106 } 1107 1108 if (minidump_->swap()) { 1109 // context_arm64->context_flags was already swapped. 1110 for (unsigned int ireg_index = 0; 1111 ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; 1112 ++ireg_index) { 1113 Swap(&context_arm64->iregs[ireg_index]); 1114 } 1115 Swap(&context_arm64->cpsr); 1116 Swap(&context_arm64->float_save.fpsr); 1117 Swap(&context_arm64->float_save.fpcr); 1118 for (unsigned int fpr_index = 0; 1119 fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; 1120 ++fpr_index) { 1121 Normalize128(&context_arm64->float_save.regs[fpr_index], 1122 minidump_->is_big_endian()); 1123 Swap(&context_arm64->float_save.regs[fpr_index]); 1124 } 1125 } 1126 SetContextARM64(context_arm64.release()); 1127 break; 1128 } 1129 1130 case MD_CONTEXT_MIPS: 1131 case MD_CONTEXT_MIPS64: { 1132 if (expected_size != sizeof(MDRawContextMIPS)) { 1133 BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, " 1134 << expected_size 1135 << " != " 1136 << sizeof(MDRawContextMIPS); 1137 return false; 1138 } 1139 1140 scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS()); 1141 1142 // Set the context_flags member, which has already been read, and 1143 // read the rest of the structure beginning with the first member 1144 // after context_flags. 1145 context_mips->context_flags = context_flags; 1146 1147 size_t flags_size = sizeof(context_mips->context_flags); 1148 uint8_t* context_after_flags = 1149 reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size; 1150 if (!minidump_->ReadBytes(context_after_flags, 1151 sizeof(MDRawContextMIPS) - flags_size)) { 1152 BPLOG(ERROR) << "MinidumpContext could not read MIPS context"; 1153 return false; 1154 } 1155 1156 // Do this after reading the entire MDRawContext structure because 1157 // GetSystemInfo may seek minidump to a new position. 1158 if (!CheckAgainstSystemInfo(cpu_type)) { 1159 BPLOG(ERROR) << "MinidumpContext MIPS does not match system info"; 1160 return false; 1161 } 1162 1163 if (minidump_->swap()) { 1164 // context_mips->context_flags was already swapped. 1165 for (int ireg_index = 0; 1166 ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; 1167 ++ireg_index) { 1168 Swap(&context_mips->iregs[ireg_index]); 1169 } 1170 Swap(&context_mips->mdhi); 1171 Swap(&context_mips->mdlo); 1172 for (int dsp_index = 0; 1173 dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; 1174 ++dsp_index) { 1175 Swap(&context_mips->hi[dsp_index]); 1176 Swap(&context_mips->lo[dsp_index]); 1177 } 1178 Swap(&context_mips->dsp_control); 1179 Swap(&context_mips->epc); 1180 Swap(&context_mips->badvaddr); 1181 Swap(&context_mips->status); 1182 Swap(&context_mips->cause); 1183 for (int fpr_index = 0; 1184 fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; 1185 ++fpr_index) { 1186 Swap(&context_mips->float_save.regs[fpr_index]); 1187 } 1188 Swap(&context_mips->float_save.fpcsr); 1189 Swap(&context_mips->float_save.fir); 1190 } 1191 SetContextMIPS(context_mips.release()); 1192 1193 break; 1194 } 1195 1196 case MD_CONTEXT_RISCV: { 1197 if (expected_size != sizeof(MDRawContextRISCV)) { 1198 BPLOG(ERROR) << "MinidumpContext RISCV size mismatch, " 1199 << expected_size 1200 << " != " 1201 << sizeof(MDRawContextRISCV); 1202 return false; 1203 } 1204 1205 scoped_ptr<MDRawContextRISCV> context_riscv(new MDRawContextRISCV()); 1206 1207 // Set the context_flags member, which has already been read, and 1208 // read the rest of the structure beginning with the first member 1209 // after context_flags. 1210 context_riscv->context_flags = context_flags; 1211 1212 size_t flags_size = sizeof(context_riscv->context_flags); 1213 uint8_t* context_after_flags = 1214 reinterpret_cast<uint8_t*>(context_riscv.get()) + flags_size; 1215 if (!minidump_->ReadBytes(context_after_flags, 1216 sizeof(MDRawContextRISCV) - flags_size)) { 1217 BPLOG(ERROR) << "MinidumpContext could not read RISCV context"; 1218 return false; 1219 } 1220 1221 // Do this after reading the entire MDRawContext structure because 1222 // GetSystemInfo may seek minidump to a new position. 1223 if (!CheckAgainstSystemInfo(cpu_type)) { 1224 BPLOG(ERROR) << "MinidumpContext RISCV does not match system info"; 1225 return false; 1226 } 1227 1228 if (minidump_->swap()) { 1229 Swap(&context_riscv->pc); 1230 Swap(&context_riscv->ra); 1231 Swap(&context_riscv->sp); 1232 Swap(&context_riscv->gp); 1233 Swap(&context_riscv->tp); 1234 Swap(&context_riscv->t0); 1235 Swap(&context_riscv->t1); 1236 Swap(&context_riscv->t2); 1237 Swap(&context_riscv->s0); 1238 Swap(&context_riscv->s1); 1239 Swap(&context_riscv->a0); 1240 Swap(&context_riscv->a1); 1241 Swap(&context_riscv->a2); 1242 Swap(&context_riscv->a3); 1243 Swap(&context_riscv->a4); 1244 Swap(&context_riscv->a5); 1245 Swap(&context_riscv->a6); 1246 Swap(&context_riscv->a7); 1247 Swap(&context_riscv->s2); 1248 Swap(&context_riscv->s3); 1249 Swap(&context_riscv->s4); 1250 Swap(&context_riscv->s5); 1251 Swap(&context_riscv->s6); 1252 Swap(&context_riscv->s7); 1253 Swap(&context_riscv->s8); 1254 Swap(&context_riscv->s9); 1255 Swap(&context_riscv->s10); 1256 Swap(&context_riscv->s11); 1257 Swap(&context_riscv->t3); 1258 Swap(&context_riscv->t4); 1259 Swap(&context_riscv->t5); 1260 Swap(&context_riscv->t6); 1261 1262 for (int fpr_index = 0; fpr_index < MD_CONTEXT_RISCV_FPR_COUNT; 1263 ++fpr_index) { 1264 Swap(&context_riscv->fpregs[fpr_index]); 1265 } 1266 Swap(&context_riscv->fcsr); 1267 } 1268 SetContextRISCV(context_riscv.release()); 1269 1270 break; 1271 } 1272 1273 case MD_CONTEXT_RISCV64: { 1274 if (expected_size != sizeof(MDRawContextRISCV64)) { 1275 BPLOG(ERROR) << "MinidumpContext RISCV64 size mismatch, " 1276 << expected_size 1277 << " != " 1278 << sizeof(MDRawContextRISCV64); 1279 return false; 1280 } 1281 1282 scoped_ptr<MDRawContextRISCV64> context_riscv64( 1283 new MDRawContextRISCV64()); 1284 1285 // Set the context_flags member, which has already been read, and 1286 // read the rest of the structure beginning with the first member 1287 // after context_flags. 1288 context_riscv64->context_flags = context_flags; 1289 1290 size_t flags_size = sizeof(context_riscv64->context_flags); 1291 uint8_t* context_after_flags = 1292 reinterpret_cast<uint8_t*>(context_riscv64.get()) + flags_size; 1293 if (!minidump_->ReadBytes(context_after_flags, 1294 sizeof(MDRawContextRISCV64) - flags_size)) { 1295 BPLOG(ERROR) << "MinidumpContext could not read RISCV context"; 1296 return false; 1297 } 1298 1299 // Do this after reading the entire MDRawContext structure because 1300 // GetSystemInfo may seek minidump to a new position. 1301 if (!CheckAgainstSystemInfo(cpu_type)) { 1302 BPLOG(ERROR) << "MinidumpContext RISCV does not match system info"; 1303 return false; 1304 } 1305 1306 if (minidump_->swap()) { 1307 Swap(&context_riscv64->pc); 1308 Swap(&context_riscv64->ra); 1309 Swap(&context_riscv64->sp); 1310 Swap(&context_riscv64->gp); 1311 Swap(&context_riscv64->tp); 1312 Swap(&context_riscv64->t0); 1313 Swap(&context_riscv64->t1); 1314 Swap(&context_riscv64->t2); 1315 Swap(&context_riscv64->s0); 1316 Swap(&context_riscv64->s1); 1317 Swap(&context_riscv64->a0); 1318 Swap(&context_riscv64->a1); 1319 Swap(&context_riscv64->a2); 1320 Swap(&context_riscv64->a3); 1321 Swap(&context_riscv64->a4); 1322 Swap(&context_riscv64->a5); 1323 Swap(&context_riscv64->a6); 1324 Swap(&context_riscv64->a7); 1325 Swap(&context_riscv64->s2); 1326 Swap(&context_riscv64->s3); 1327 Swap(&context_riscv64->s4); 1328 Swap(&context_riscv64->s5); 1329 Swap(&context_riscv64->s6); 1330 Swap(&context_riscv64->s7); 1331 Swap(&context_riscv64->s8); 1332 Swap(&context_riscv64->s9); 1333 Swap(&context_riscv64->s10); 1334 Swap(&context_riscv64->s11); 1335 Swap(&context_riscv64->t3); 1336 Swap(&context_riscv64->t4); 1337 Swap(&context_riscv64->t5); 1338 Swap(&context_riscv64->t6); 1339 1340 for (int fpr_index = 0; fpr_index < MD_CONTEXT_RISCV_FPR_COUNT; 1341 ++fpr_index) { 1342 Swap(&context_riscv64->fpregs[fpr_index]); 1343 } 1344 Swap(&context_riscv64->fcsr); 1345 } 1346 SetContextRISCV64(context_riscv64.release()); 1347 1348 break; 1349 } 1350 1351 default: { 1352 // Unknown context type - Don't log as an error yet. Let the 1353 // caller work that out. 1354 BPLOG(INFO) << "MinidumpContext unknown context type " << 1355 HexString(cpu_type); 1356 return false; 1357 } 1358 } 1359 SetContextFlags(context_flags); 1360 } 1361 1362 valid_ = true; 1363 return true; 1364 } 1365 1366 bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { 1367 // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM, 1368 // as this function just implements a sanity check. 1369 MinidumpSystemInfo* system_info = minidump_->GetSystemInfo(); 1370 if (!system_info) { 1371 BPLOG(INFO) << "MinidumpContext could not be compared against " 1372 "MinidumpSystemInfo"; 1373 return true; 1374 } 1375 1376 // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info. 1377 const MDRawSystemInfo* raw_system_info = system_info->system_info(); 1378 if (!raw_system_info) { 1379 BPLOG(INFO) << "MinidumpContext could not be compared against " 1380 "MDRawSystemInfo"; 1381 return false; 1382 } 1383 1384 MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>( 1385 raw_system_info->processor_architecture); 1386 1387 // Compare the CPU type of the context record to the CPU type in the 1388 // minidump's system info stream. 1389 bool return_value = false; 1390 switch (context_cpu_type) { 1391 case MD_CONTEXT_X86: 1392 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 || 1393 system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 || 1394 system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) { 1395 return_value = true; 1396 } 1397 break; 1398 1399 case MD_CONTEXT_PPC: 1400 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC) 1401 return_value = true; 1402 break; 1403 1404 case MD_CONTEXT_PPC64: 1405 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64) 1406 return_value = true; 1407 break; 1408 1409 case MD_CONTEXT_AMD64: 1410 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) 1411 return_value = true; 1412 break; 1413 1414 case MD_CONTEXT_SPARC: 1415 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) 1416 return_value = true; 1417 break; 1418 1419 case MD_CONTEXT_ARM: 1420 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM) 1421 return_value = true; 1422 break; 1423 1424 case MD_CONTEXT_ARM64: 1425 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64) 1426 return_value = true; 1427 break; 1428 1429 case MD_CONTEXT_ARM64_OLD: 1430 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64_OLD) 1431 return_value = true; 1432 break; 1433 1434 case MD_CONTEXT_MIPS: 1435 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS) 1436 return_value = true; 1437 break; 1438 1439 case MD_CONTEXT_MIPS64: 1440 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS64) 1441 return_value = true; 1442 break; 1443 1444 case MD_CONTEXT_RISCV: 1445 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_RISCV) 1446 return_value = true; 1447 break; 1448 1449 case MD_CONTEXT_RISCV64: 1450 if (system_info_cpu_type == MD_CPU_ARCHITECTURE_RISCV64) 1451 return_value = true; 1452 break; 1453 } 1454 1455 BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << 1456 HexString(context_cpu_type) << 1457 " wrong for MinidumpSystemInfo CPU " << 1458 HexString(system_info_cpu_type); 1459 1460 return return_value; 1461 } 1462 1463 1464 // 1465 // MinidumpMemoryRegion 1466 // 1467 1468 1469 uint32_t MinidumpMemoryRegion::max_bytes_ = 64 * 1024 * 1024; // 64MB 1470 1471 1472 MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) 1473 : MinidumpObject(minidump), 1474 descriptor_(NULL), 1475 memory_(NULL) { 1476 hexdump_width_ = minidump_ ? minidump_->HexdumpMode() : 0; 1477 hexdump_ = hexdump_width_ != 0; 1478 } 1479 1480 1481 MinidumpMemoryRegion::~MinidumpMemoryRegion() { 1482 delete memory_; 1483 } 1484 1485 1486 void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { 1487 descriptor_ = descriptor; 1488 valid_ = descriptor && 1489 descriptor_->memory.data_size <= 1490 numeric_limits<uint64_t>::max() - 1491 descriptor_->start_of_memory_range; 1492 } 1493 1494 1495 const uint8_t* MinidumpMemoryRegion::GetMemory() const { 1496 if (!valid_) { 1497 BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory"; 1498 return NULL; 1499 } 1500 1501 if (!memory_) { 1502 if (descriptor_->memory.data_size == 0) { 1503 BPLOG(ERROR) << "MinidumpMemoryRegion is empty"; 1504 return NULL; 1505 } 1506 1507 if (!minidump_->SeekSet(descriptor_->memory.rva)) { 1508 BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region"; 1509 return NULL; 1510 } 1511 1512 if (descriptor_->memory.data_size > max_bytes_) { 1513 BPLOG(ERROR) << "MinidumpMemoryRegion size " << 1514 descriptor_->memory.data_size << " exceeds maximum " << 1515 max_bytes_; 1516 return NULL; 1517 } 1518 1519 scoped_ptr< vector<uint8_t> > memory( 1520 new vector<uint8_t>(descriptor_->memory.data_size)); 1521 1522 if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) { 1523 BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region"; 1524 return NULL; 1525 } 1526 1527 memory_ = memory.release(); 1528 } 1529 1530 return &(*memory_)[0]; 1531 } 1532 1533 1534 uint64_t MinidumpMemoryRegion::GetBase() const { 1535 if (!valid_) { 1536 BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase"; 1537 return static_cast<uint64_t>(-1); 1538 } 1539 1540 return descriptor_->start_of_memory_range; 1541 } 1542 1543 1544 uint32_t MinidumpMemoryRegion::GetSize() const { 1545 if (!valid_) { 1546 BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize"; 1547 return 0; 1548 } 1549 1550 return descriptor_->memory.data_size; 1551 } 1552 1553 1554 void MinidumpMemoryRegion::FreeMemory() { 1555 delete memory_; 1556 memory_ = NULL; 1557 } 1558 1559 1560 template<typename T> 1561 bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address, 1562 T* value) const { 1563 BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal " 1564 "requires |value|"; 1565 assert(value); 1566 *value = 0; 1567 1568 if (!valid_) { 1569 BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for " 1570 "GetMemoryAtAddressInternal"; 1571 return false; 1572 } 1573 1574 // Common failure case 1575 if (address < descriptor_->start_of_memory_range || 1576 sizeof(T) > numeric_limits<uint64_t>::max() - address || 1577 address + sizeof(T) > descriptor_->start_of_memory_range + 1578 descriptor_->memory.data_size) { 1579 BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " << 1580 HexString(address) << "+" << sizeof(T) << "/" << 1581 HexString(descriptor_->start_of_memory_range) << "+" << 1582 HexString(descriptor_->memory.data_size); 1583 return false; 1584 } 1585 1586 const uint8_t* memory = GetMemory(); 1587 if (!memory) { 1588 // GetMemory already logged a perfectly good message. 1589 return false; 1590 } 1591 1592 // If the CPU requires memory accesses to be aligned, this can crash. 1593 // x86 and ppc are able to cope, though. 1594 *value = *reinterpret_cast<const T*>( 1595 &memory[address - descriptor_->start_of_memory_range]); 1596 1597 if (minidump_->swap()) 1598 Swap(value); 1599 1600 return true; 1601 } 1602 1603 1604 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, 1605 uint8_t* value) const { 1606 return GetMemoryAtAddressInternal(address, value); 1607 } 1608 1609 1610 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, 1611 uint16_t* value) const { 1612 return GetMemoryAtAddressInternal(address, value); 1613 } 1614 1615 1616 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, 1617 uint32_t* value) const { 1618 return GetMemoryAtAddressInternal(address, value); 1619 } 1620 1621 1622 bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, 1623 uint64_t* value) const { 1624 return GetMemoryAtAddressInternal(address, value); 1625 } 1626 1627 1628 void MinidumpMemoryRegion::Print() const { 1629 if (!valid_) { 1630 BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data"; 1631 return; 1632 } 1633 1634 const uint8_t* memory = GetMemory(); 1635 if (memory) { 1636 if (hexdump_) { 1637 // Pretty hexdump view. 1638 for (unsigned int byte_index = 0; 1639 byte_index < descriptor_->memory.data_size; 1640 byte_index += hexdump_width_) { 1641 // In case the memory won't fill a whole line. 1642 unsigned int num_bytes = std::min( 1643 descriptor_->memory.data_size - byte_index, hexdump_width_); 1644 1645 // Display the leading address. 1646 printf("%08x ", byte_index); 1647 1648 // Show the bytes in hex. 1649 for (unsigned int i = 0; i < hexdump_width_; ++i) { 1650 if (i < num_bytes) { 1651 // Show the single byte of memory in hex. 1652 printf("%02x ", memory[byte_index + i]); 1653 } else { 1654 // If this line doesn't fill up, pad it out. 1655 printf(" "); 1656 } 1657 1658 // Insert a space every 8 bytes to make it more readable. 1659 if (((i + 1) % 8) == 0) { 1660 printf(" "); 1661 } 1662 } 1663 1664 // Decode the line as ASCII. 1665 printf("|"); 1666 for (unsigned int i = 0; i < hexdump_width_; ++i) { 1667 if (i < num_bytes) { 1668 uint8_t byte = memory[byte_index + i]; 1669 printf("%c", isprint(byte) ? byte : '.'); 1670 } else { 1671 // If this line doesn't fill up, pad it out. 1672 printf(" "); 1673 } 1674 } 1675 printf("|\n"); 1676 } 1677 } else { 1678 // Ugly raw string view. 1679 printf("0x"); 1680 for (unsigned int i = 0; 1681 i < descriptor_->memory.data_size; 1682 i++) { 1683 printf("%02x", memory[i]); 1684 } 1685 printf("\n"); 1686 } 1687 } else { 1688 printf("No memory\n"); 1689 } 1690 } 1691 1692 1693 void MinidumpMemoryRegion::SetPrintMode(bool hexdump, 1694 unsigned int hexdump_width) { 1695 // Require the width to be a multiple of 8 bytes. 1696 if (hexdump_width == 0 || (hexdump_width % 8) != 0) { 1697 BPLOG(ERROR) << "MinidumpMemoryRegion print hexdump_width must be " 1698 "multiple of 8, not " << hexdump_width; 1699 return; 1700 } 1701 1702 hexdump_ = hexdump; 1703 hexdump_width_ = hexdump_width; 1704 } 1705 1706 1707 // 1708 // MinidumpThread 1709 // 1710 1711 1712 MinidumpThread::MinidumpThread(Minidump* minidump) 1713 : MinidumpObject(minidump), 1714 thread_(), 1715 memory_(NULL), 1716 context_(NULL) { 1717 } 1718 1719 1720 MinidumpThread::~MinidumpThread() { 1721 delete memory_; 1722 delete context_; 1723 } 1724 1725 1726 bool MinidumpThread::Read() { 1727 // Invalidate cached data. 1728 delete memory_; 1729 memory_ = NULL; 1730 delete context_; 1731 context_ = NULL; 1732 1733 valid_ = false; 1734 1735 if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) { 1736 BPLOG(ERROR) << "MinidumpThread cannot read thread"; 1737 return false; 1738 } 1739 1740 if (minidump_->swap()) { 1741 Swap(&thread_.thread_id); 1742 Swap(&thread_.suspend_count); 1743 Swap(&thread_.priority_class); 1744 Swap(&thread_.priority); 1745 Swap(&thread_.teb); 1746 Swap(&thread_.stack); 1747 Swap(&thread_.thread_context); 1748 } 1749 1750 // Check for base + size overflow or undersize. 1751 if (thread_.stack.memory.rva == 0 || 1752 thread_.stack.memory.data_size == 0 || 1753 thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() - 1754 thread_.stack.start_of_memory_range) { 1755 // This is ok, but log an error anyway. 1756 BPLOG(ERROR) << "MinidumpThread has a memory region problem, " << 1757 HexString(thread_.stack.start_of_memory_range) << "+" << 1758 HexString(thread_.stack.memory.data_size) << 1759 ", RVA 0x" << HexString(thread_.stack.memory.rva); 1760 } else { 1761 memory_ = new MinidumpMemoryRegion(minidump_); 1762 memory_->SetDescriptor(&thread_.stack); 1763 } 1764 1765 valid_ = true; 1766 return true; 1767 } 1768 1769 uint64_t MinidumpThread::GetStartOfStackMemoryRange() const { 1770 if (!valid_) { 1771 BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread"; 1772 return 0; 1773 } 1774 1775 return thread_.stack.start_of_memory_range; 1776 } 1777 1778 MinidumpMemoryRegion* MinidumpThread::GetMemory() { 1779 if (!valid_) { 1780 BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory"; 1781 return NULL; 1782 } 1783 1784 return memory_; 1785 } 1786 1787 1788 MinidumpContext* MinidumpThread::GetContext() { 1789 if (!valid_) { 1790 BPLOG(ERROR) << "Invalid MinidumpThread for GetContext"; 1791 return NULL; 1792 } 1793 1794 if (!context_) { 1795 if (!minidump_->SeekSet(thread_.thread_context.rva)) { 1796 BPLOG(ERROR) << "MinidumpThread cannot seek to context"; 1797 return NULL; 1798 } 1799 1800 scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); 1801 1802 if (!context->Read(thread_.thread_context.data_size)) { 1803 BPLOG(ERROR) << "MinidumpThread cannot read context"; 1804 return NULL; 1805 } 1806 1807 context_ = context.release(); 1808 } 1809 1810 return context_; 1811 } 1812 1813 1814 bool MinidumpThread::GetThreadID(uint32_t* thread_id) const { 1815 BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires " 1816 "|thread_id|"; 1817 assert(thread_id); 1818 *thread_id = 0; 1819 1820 if (!valid_) { 1821 BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID"; 1822 return false; 1823 } 1824 1825 *thread_id = thread_.thread_id; 1826 return true; 1827 } 1828 1829 1830 void MinidumpThread::Print() { 1831 if (!valid_) { 1832 BPLOG(ERROR) << "MinidumpThread cannot print invalid data"; 1833 return; 1834 } 1835 1836 printf("MDRawThread\n"); 1837 printf(" thread_id = 0x%x\n", thread_.thread_id); 1838 printf(" suspend_count = %d\n", thread_.suspend_count); 1839 printf(" priority_class = 0x%x\n", thread_.priority_class); 1840 printf(" priority = 0x%x\n", thread_.priority); 1841 printf(" teb = 0x%" PRIx64 "\n", thread_.teb); 1842 printf(" stack.start_of_memory_range = 0x%" PRIx64 "\n", 1843 thread_.stack.start_of_memory_range); 1844 printf(" stack.memory.data_size = 0x%x\n", 1845 thread_.stack.memory.data_size); 1846 printf(" stack.memory.rva = 0x%x\n", thread_.stack.memory.rva); 1847 printf(" thread_context.data_size = 0x%x\n", 1848 thread_.thread_context.data_size); 1849 printf(" thread_context.rva = 0x%x\n", 1850 thread_.thread_context.rva); 1851 1852 MinidumpContext* context = GetContext(); 1853 if (context) { 1854 printf("\n"); 1855 context->Print(); 1856 } else { 1857 printf(" (no context)\n"); 1858 printf("\n"); 1859 } 1860 1861 MinidumpMemoryRegion* memory = GetMemory(); 1862 if (memory) { 1863 printf("Stack\n"); 1864 memory->Print(); 1865 } else { 1866 printf("No stack\n"); 1867 } 1868 printf("\n"); 1869 } 1870 1871 1872 // 1873 // MinidumpThreadList 1874 // 1875 1876 1877 uint32_t MinidumpThreadList::max_threads_ = 4096; 1878 1879 1880 MinidumpThreadList::MinidumpThreadList(Minidump* minidump) 1881 : MinidumpStream(minidump), 1882 id_to_thread_map_(), 1883 threads_(NULL), 1884 thread_count_(0) { 1885 } 1886 1887 1888 MinidumpThreadList::~MinidumpThreadList() { 1889 delete threads_; 1890 } 1891 1892 1893 bool MinidumpThreadList::Read(uint32_t expected_size) { 1894 // Invalidate cached data. 1895 id_to_thread_map_.clear(); 1896 delete threads_; 1897 threads_ = NULL; 1898 thread_count_ = 0; 1899 1900 valid_ = false; 1901 1902 uint32_t thread_count; 1903 if (expected_size < sizeof(thread_count)) { 1904 BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " << 1905 expected_size << " < " << sizeof(thread_count); 1906 return false; 1907 } 1908 if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) { 1909 BPLOG(ERROR) << "MinidumpThreadList cannot read thread count"; 1910 return false; 1911 } 1912 1913 if (minidump_->swap()) 1914 Swap(&thread_count); 1915 1916 if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) { 1917 BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count << 1918 " would cause multiplication overflow"; 1919 return false; 1920 } 1921 1922 if (expected_size != sizeof(thread_count) + 1923 thread_count * sizeof(MDRawThread)) { 1924 // may be padded with 4 bytes on 64bit ABIs for alignment 1925 if (expected_size == sizeof(thread_count) + 4 + 1926 thread_count * sizeof(MDRawThread)) { 1927 uint32_t useless; 1928 if (!minidump_->ReadBytes(&useless, 4)) { 1929 BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded " 1930 "bytes"; 1931 return false; 1932 } 1933 } else { 1934 BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << 1935 " != " << sizeof(thread_count) + 1936 thread_count * sizeof(MDRawThread); 1937 return false; 1938 } 1939 } 1940 1941 1942 if (thread_count > max_threads_) { 1943 BPLOG(ERROR) << "MinidumpThreadList count " << thread_count << 1944 " exceeds maximum " << max_threads_; 1945 return false; 1946 } 1947 1948 if (thread_count != 0) { 1949 scoped_ptr<MinidumpThreads> threads( 1950 new MinidumpThreads(thread_count, MinidumpThread(minidump_))); 1951 1952 for (unsigned int thread_index = 0; 1953 thread_index < thread_count; 1954 ++thread_index) { 1955 MinidumpThread* thread = &(*threads)[thread_index]; 1956 1957 // Assume that the file offset is correct after the last read. 1958 if (!thread->Read()) { 1959 BPLOG(ERROR) << "MinidumpThreadList cannot read thread " << 1960 thread_index << "/" << thread_count; 1961 return false; 1962 } 1963 1964 uint32_t thread_id; 1965 if (!thread->GetThreadID(&thread_id)) { 1966 BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " << 1967 thread_index << "/" << thread_count; 1968 return false; 1969 } 1970 1971 if (GetThreadByID(thread_id)) { 1972 // Another thread with this ID is already in the list. Data error. 1973 BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " << 1974 HexString(thread_id) << " at thread " << 1975 thread_index << "/" << thread_count; 1976 return false; 1977 } 1978 id_to_thread_map_[thread_id] = thread; 1979 } 1980 1981 threads_ = threads.release(); 1982 } 1983 1984 thread_count_ = thread_count; 1985 1986 valid_ = true; 1987 return true; 1988 } 1989 1990 1991 MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index) 1992 const { 1993 if (!valid_) { 1994 BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex"; 1995 return NULL; 1996 } 1997 1998 if (index >= thread_count_) { 1999 BPLOG(ERROR) << "MinidumpThreadList index out of range: " << 2000 index << "/" << thread_count_; 2001 return NULL; 2002 } 2003 2004 return &(*threads_)[index]; 2005 } 2006 2007 2008 MinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) { 2009 // Don't check valid_. Read calls this method before everything is 2010 // validated. It is safe to not check valid_ here. 2011 return id_to_thread_map_[thread_id]; 2012 } 2013 2014 2015 void MinidumpThreadList::Print() { 2016 if (!valid_) { 2017 BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data"; 2018 return; 2019 } 2020 2021 printf("MinidumpThreadList\n"); 2022 printf(" thread_count = %d\n", thread_count_); 2023 printf("\n"); 2024 2025 for (unsigned int thread_index = 0; 2026 thread_index < thread_count_; 2027 ++thread_index) { 2028 printf("thread[%d]\n", thread_index); 2029 2030 (*threads_)[thread_index].Print(); 2031 } 2032 } 2033 2034 // 2035 // MinidumpThreadName 2036 // 2037 2038 MinidumpThreadName::MinidumpThreadName(Minidump* minidump) 2039 : MinidumpObject(minidump), 2040 thread_name_valid_(false), 2041 thread_name_(), 2042 name_(NULL) {} 2043 2044 MinidumpThreadName::~MinidumpThreadName() { 2045 delete name_; 2046 } 2047 2048 bool MinidumpThreadName::Read() { 2049 // Invalidate cached data. 2050 delete name_; 2051 name_ = NULL; 2052 2053 valid_ = false; 2054 2055 if (!minidump_->ReadBytes(&thread_name_, sizeof(thread_name_))) { 2056 BPLOG(ERROR) << "MinidumpThreadName cannot read thread name"; 2057 return false; 2058 } 2059 2060 if (minidump_->swap()) { 2061 Swap(&thread_name_.thread_id); 2062 Swap(&thread_name_.thread_name_rva); 2063 } 2064 2065 thread_name_valid_ = true; 2066 return true; 2067 } 2068 2069 bool MinidumpThreadName::ReadAuxiliaryData() { 2070 if (!thread_name_valid_) { 2071 BPLOG(ERROR) << "Invalid MinidumpThreadName for ReadAuxiliaryData"; 2072 return false; 2073 } 2074 2075 // On 32-bit systems, check that the RVA64 is within range (off_t is 32 bits). 2076 if (thread_name_.thread_name_rva > numeric_limits<off_t>::max()) { 2077 BPLOG(ERROR) << "MinidumpThreadName RVA64 out of range"; 2078 return false; 2079 } 2080 2081 // Read the thread name. 2082 const off_t thread_name_rva_offset = 2083 static_cast<off_t>(thread_name_.thread_name_rva); 2084 name_ = minidump_->ReadString(thread_name_rva_offset); 2085 if (!name_) { 2086 BPLOG(ERROR) << "MinidumpThreadName could not read name"; 2087 return false; 2088 } 2089 2090 // At this point, we have enough info for the thread name to be valid. 2091 valid_ = true; 2092 return true; 2093 } 2094 2095 bool MinidumpThreadName::GetThreadID(uint32_t* thread_id) const { 2096 BPLOG_IF(ERROR, !thread_id) << "MinidumpThreadName::GetThreadID requires " 2097 "|thread_id|"; 2098 assert(thread_id); 2099 *thread_id = 0; 2100 2101 if (!valid_) { 2102 BPLOG(ERROR) << "Invalid MinidumpThreadName for GetThreadID"; 2103 return false; 2104 } 2105 2106 *thread_id = thread_name_.thread_id; 2107 return true; 2108 } 2109 2110 string MinidumpThreadName::GetThreadName() const { 2111 if (!valid_) { 2112 BPLOG(ERROR) << "Invalid MinidumpThreadName for GetThreadName"; 2113 return ""; 2114 } 2115 2116 return *name_; 2117 } 2118 2119 void MinidumpThreadName::Print() { 2120 if (!valid_) { 2121 BPLOG(ERROR) << "MinidumpThreadName cannot print invalid data"; 2122 return; 2123 } 2124 2125 printf("MDRawThreadName\n"); 2126 printf(" thread_id = 0x%x\n", thread_name_.thread_id); 2127 printf(" thread_name_rva = 0x%" PRIx64 "\n", 2128 thread_name_.thread_name_rva); 2129 printf(" thread_name = \"%s\"\n", GetThreadName().c_str()); 2130 printf("\n"); 2131 } 2132 2133 // 2134 // MinidumpThreadNameList 2135 // 2136 2137 MinidumpThreadNameList::MinidumpThreadNameList(Minidump* minidump) 2138 : MinidumpStream(minidump), thread_names_(NULL), thread_name_count_(0) {} 2139 2140 MinidumpThreadNameList::~MinidumpThreadNameList() { 2141 delete thread_names_; 2142 } 2143 2144 bool MinidumpThreadNameList::Read(uint32_t expected_size) { 2145 // Invalidate cached data. 2146 delete thread_names_; 2147 thread_names_ = NULL; 2148 thread_name_count_ = 0; 2149 2150 valid_ = false; 2151 2152 uint32_t thread_name_count; 2153 if (expected_size < sizeof(thread_name_count)) { 2154 BPLOG(ERROR) << "MinidumpThreadNameList count size mismatch, " 2155 << expected_size << " < " << sizeof(thread_name_count); 2156 return false; 2157 } 2158 if (!minidump_->ReadBytes(&thread_name_count, sizeof(thread_name_count))) { 2159 BPLOG(ERROR) << "MinidumpThreadNameList cannot read thread name count"; 2160 return false; 2161 } 2162 2163 if (minidump_->swap()) 2164 Swap(&thread_name_count); 2165 2166 if (thread_name_count > 2167 numeric_limits<uint32_t>::max() / sizeof(MDRawThreadName)) { 2168 BPLOG(ERROR) << "MinidumpThreadNameList thread name count " 2169 << thread_name_count << " would cause multiplication overflow"; 2170 return false; 2171 } 2172 2173 if (expected_size != 2174 sizeof(thread_name_count) + thread_name_count * sizeof(MDRawThreadName)) { 2175 BPLOG(ERROR) << "MinidumpThreadNameList size mismatch, " << expected_size 2176 << " != " 2177 << sizeof(thread_name_count) + 2178 thread_name_count * sizeof(MDRawThreadName); 2179 return false; 2180 } 2181 2182 if (thread_name_count > MinidumpThreadList::max_threads()) { 2183 BPLOG(ERROR) << "MinidumpThreadNameList count " << thread_name_count 2184 << " exceeds maximum " << MinidumpThreadList::max_threads(); 2185 return false; 2186 } 2187 2188 if (thread_name_count != 0) { 2189 scoped_ptr<MinidumpThreadNames> thread_names(new MinidumpThreadNames( 2190 thread_name_count, MinidumpThreadName(minidump_))); 2191 2192 for (unsigned int thread_name_index = 0; 2193 thread_name_index < thread_name_count; ++thread_name_index) { 2194 MinidumpThreadName* thread_name = &(*thread_names)[thread_name_index]; 2195 2196 // Assume that the file offset is correct after the last read. 2197 if (!thread_name->Read()) { 2198 BPLOG(ERROR) << "MinidumpThreadNameList cannot read thread name " 2199 << thread_name_index << "/" << thread_name_count; 2200 return false; 2201 } 2202 } 2203 2204 for (unsigned int thread_name_index = 0; 2205 thread_name_index < thread_name_count; ++thread_name_index) { 2206 MinidumpThreadName* thread_name = &(*thread_names)[thread_name_index]; 2207 2208 if (!thread_name->ReadAuxiliaryData() && !thread_name->valid()) { 2209 BPLOG(ERROR) << "MinidumpThreadNameList cannot read thread name " 2210 << thread_name_index << "/" << thread_name_count; 2211 return false; 2212 } 2213 } 2214 2215 thread_names_ = thread_names.release(); 2216 } 2217 2218 thread_name_count_ = thread_name_count; 2219 2220 valid_ = true; 2221 return true; 2222 } 2223 2224 MinidumpThreadName* MinidumpThreadNameList::GetThreadNameAtIndex( 2225 unsigned int index) const { 2226 if (!valid_) { 2227 BPLOG(ERROR) << "Invalid MinidumpThreadNameList for GetThreadNameAtIndex"; 2228 return NULL; 2229 } 2230 2231 if (index >= thread_name_count_) { 2232 BPLOG(ERROR) << "MinidumpThreadNameList index out of range: " << index 2233 << "/" << thread_name_count_; 2234 return NULL; 2235 } 2236 2237 return &(*thread_names_)[index]; 2238 } 2239 2240 void MinidumpThreadNameList::Print() { 2241 if (!valid_) { 2242 BPLOG(ERROR) << "MinidumpThreadNameList cannot print invalid data"; 2243 return; 2244 } 2245 2246 printf("MinidumpThreadNameList\n"); 2247 printf(" thread_name_count = %d\n", thread_name_count_); 2248 printf("\n"); 2249 2250 for (unsigned int thread_name_index = 0; 2251 thread_name_index < thread_name_count_; ++thread_name_index) { 2252 printf("thread_name[%d]\n", thread_name_index); 2253 2254 (*thread_names_)[thread_name_index].Print(); 2255 } 2256 } 2257 2258 // 2259 // MinidumpModule 2260 // 2261 2262 2263 uint32_t MinidumpModule::max_cv_bytes_ = 32768; 2264 uint32_t MinidumpModule::max_misc_bytes_ = 32768; 2265 2266 2267 MinidumpModule::MinidumpModule(Minidump* minidump) 2268 : MinidumpObject(minidump), 2269 module_valid_(false), 2270 has_debug_info_(false), 2271 module_(), 2272 name_(NULL), 2273 cv_record_(NULL), 2274 cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE), 2275 misc_record_(NULL) { 2276 } 2277 2278 2279 MinidumpModule::~MinidumpModule() { 2280 delete name_; 2281 delete cv_record_; 2282 delete misc_record_; 2283 } 2284 2285 2286 bool MinidumpModule::Read() { 2287 // Invalidate cached data. 2288 delete name_; 2289 name_ = NULL; 2290 delete cv_record_; 2291 cv_record_ = NULL; 2292 cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE; 2293 delete misc_record_; 2294 misc_record_ = NULL; 2295 2296 module_valid_ = false; 2297 has_debug_info_ = false; 2298 valid_ = false; 2299 2300 if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) { 2301 BPLOG(ERROR) << "MinidumpModule cannot read module"; 2302 return false; 2303 } 2304 2305 if (minidump_->swap()) { 2306 Swap(&module_.base_of_image); 2307 Swap(&module_.size_of_image); 2308 Swap(&module_.checksum); 2309 Swap(&module_.time_date_stamp); 2310 Swap(&module_.module_name_rva); 2311 Swap(&module_.version_info.signature); 2312 Swap(&module_.version_info.struct_version); 2313 Swap(&module_.version_info.file_version_hi); 2314 Swap(&module_.version_info.file_version_lo); 2315 Swap(&module_.version_info.product_version_hi); 2316 Swap(&module_.version_info.product_version_lo); 2317 Swap(&module_.version_info.file_flags_mask); 2318 Swap(&module_.version_info.file_flags); 2319 Swap(&module_.version_info.file_os); 2320 Swap(&module_.version_info.file_type); 2321 Swap(&module_.version_info.file_subtype); 2322 Swap(&module_.version_info.file_date_hi); 2323 Swap(&module_.version_info.file_date_lo); 2324 Swap(&module_.cv_record); 2325 Swap(&module_.misc_record); 2326 // Don't swap reserved fields because their contents are unknown (as 2327 // are their proper widths). 2328 } 2329 2330 // Check for base + size overflow or undersize. 2331 if (module_.size_of_image == 0 || 2332 module_.size_of_image > 2333 numeric_limits<uint64_t>::max() - module_.base_of_image) { 2334 BPLOG(ERROR) << "MinidumpModule has a module problem, " << 2335 HexString(module_.base_of_image) << "+" << 2336 HexString(module_.size_of_image); 2337 return false; 2338 } 2339 2340 module_valid_ = true; 2341 return true; 2342 } 2343 2344 2345 bool MinidumpModule::ReadAuxiliaryData() { 2346 if (!module_valid_) { 2347 BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData"; 2348 return false; 2349 } 2350 2351 // Each module must have a name. 2352 name_ = minidump_->ReadString(module_.module_name_rva); 2353 if (!name_) { 2354 BPLOG(ERROR) << "MinidumpModule could not read name"; 2355 return false; 2356 } 2357 2358 // At this point, we have enough info for the module to be valid. 2359 valid_ = true; 2360 2361 // CodeView and miscellaneous debug records are only required if the 2362 // module indicates that they exist. 2363 if (module_.cv_record.data_size && !GetCVRecord(NULL)) { 2364 BPLOG(ERROR) << "MinidumpModule has no CodeView record, " 2365 "but one was expected"; 2366 return false; 2367 } 2368 2369 if (module_.misc_record.data_size && !GetMiscRecord(NULL)) { 2370 BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, " 2371 "but one was expected"; 2372 return false; 2373 } 2374 2375 has_debug_info_ = true; 2376 return true; 2377 } 2378 2379 2380 string MinidumpModule::code_file() const { 2381 if (!valid_) { 2382 BPLOG(ERROR) << "Invalid MinidumpModule for code_file"; 2383 return ""; 2384 } 2385 2386 return *name_; 2387 } 2388 2389 2390 string MinidumpModule::code_identifier() const { 2391 if (!valid_) { 2392 BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier"; 2393 return ""; 2394 } 2395 2396 if (!has_debug_info_) 2397 return ""; 2398 2399 MinidumpSystemInfo* minidump_system_info = minidump_->GetSystemInfo(); 2400 if (!minidump_system_info) { 2401 BPLOG(ERROR) << "MinidumpModule code_identifier requires " 2402 "MinidumpSystemInfo"; 2403 return ""; 2404 } 2405 2406 const MDRawSystemInfo* raw_system_info = minidump_system_info->system_info(); 2407 if (!raw_system_info) { 2408 BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo"; 2409 return ""; 2410 } 2411 2412 string identifier; 2413 2414 switch (raw_system_info->platform_id) { 2415 case MD_OS_WIN32_NT: 2416 case MD_OS_WIN32_WINDOWS: { 2417 // Use the same format that the MS symbol server uses in filesystem 2418 // hierarchies. 2419 char identifier_string[17]; 2420 snprintf(identifier_string, sizeof(identifier_string), "%08X%x", 2421 module_.time_date_stamp, module_.size_of_image); 2422 identifier = identifier_string; 2423 break; 2424 } 2425 2426 case MD_OS_ANDROID: 2427 case MD_OS_FUCHSIA: 2428 case MD_OS_LINUX: { 2429 // If ELF CodeView data is present, return the debug id. 2430 if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { 2431 const MDCVInfoELF* cv_record_elf = 2432 reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); 2433 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); 2434 2435 for (unsigned int build_id_index = 0; 2436 build_id_index < (cv_record_->size() - MDCVInfoELF_minsize); 2437 ++build_id_index) { 2438 char hexbyte[3]; 2439 snprintf(hexbyte, sizeof(hexbyte), "%02x", 2440 cv_record_elf->build_id[build_id_index]); 2441 identifier += hexbyte; 2442 } 2443 break; 2444 } 2445 // Otherwise fall through to the case below. 2446 BP_FALLTHROUGH; 2447 } 2448 2449 case MD_OS_MAC_OS_X: 2450 case MD_OS_IOS: 2451 case MD_OS_SOLARIS: 2452 case MD_OS_NACL: 2453 case MD_OS_PS3: { 2454 // TODO(mmentovai): support uuid extension if present, otherwise fall 2455 // back to version (from LC_ID_DYLIB?), otherwise fall back to something 2456 // else. 2457 identifier = "id"; 2458 break; 2459 } 2460 2461 default: { 2462 // Without knowing what OS generated the dump, we can't generate a good 2463 // identifier. Return an empty string, signalling failure. 2464 BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, " 2465 "found " << HexString(raw_system_info->platform_id); 2466 break; 2467 } 2468 } 2469 2470 return identifier; 2471 } 2472 2473 2474 string MinidumpModule::debug_file() const { 2475 if (!valid_) { 2476 BPLOG(ERROR) << "Invalid MinidumpModule for debug_file"; 2477 return ""; 2478 } 2479 2480 if (!has_debug_info_) 2481 return ""; 2482 2483 string file; 2484 // Prefer the CodeView record if present. 2485 if (cv_record_) { 2486 if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { 2487 // It's actually an MDCVInfoPDB70 structure. 2488 const MDCVInfoPDB70* cv_record_70 = 2489 reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); 2490 assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); 2491 2492 // GetCVRecord guarantees pdb_file_name is null-terminated. 2493 file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name); 2494 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { 2495 // It's actually an MDCVInfoPDB20 structure. 2496 const MDCVInfoPDB20* cv_record_20 = 2497 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); 2498 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); 2499 2500 // GetCVRecord guarantees pdb_file_name is null-terminated. 2501 file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name); 2502 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { 2503 // It's actually an MDCVInfoELF structure. 2504 assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])-> 2505 cv_signature == MD_CVINFOELF_SIGNATURE); 2506 2507 // For MDCVInfoELF, the debug file is the code file. 2508 file = *name_; 2509 } 2510 2511 // If there's a CodeView record but it doesn't match a known signature, 2512 // try the miscellaneous record. 2513 } 2514 2515 if (file.empty()) { 2516 // No usable CodeView record. Try the miscellaneous debug record. 2517 if (misc_record_) { 2518 const MDImageDebugMisc* misc_record = 2519 reinterpret_cast<const MDImageDebugMisc*>(&(*misc_record_)[0]); 2520 if (!misc_record->unicode) { 2521 // If it's not Unicode, just stuff it into the string. It's unclear 2522 // if misc_record->data is 0-terminated, so use an explicit size. 2523 file = string( 2524 reinterpret_cast<const char*>(misc_record->data), 2525 module_.misc_record.data_size - MDImageDebugMisc_minsize); 2526 } else { 2527 // There's a misc_record but it encodes the debug filename in UTF-16. 2528 // (Actually, because miscellaneous records are so old, it's probably 2529 // UCS-2.) Convert it to UTF-8 for congruity with the other strings 2530 // that this method (and all other methods in the Minidump family) 2531 // return. 2532 2533 size_t bytes = 2534 module_.misc_record.data_size - MDImageDebugMisc_minsize; 2535 if (bytes % 2 == 0) { 2536 size_t utf16_words = bytes / 2; 2537 2538 // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one 2539 // and copy the UTF-16 data into it. 2540 vector<uint16_t> string_utf16(utf16_words); 2541 if (utf16_words) 2542 memcpy(&string_utf16[0], &misc_record->data, bytes); 2543 2544 // GetMiscRecord already byte-swapped the data[] field if it contains 2545 // UTF-16, so pass false as the swap argument. 2546 scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false)); 2547 if (new_file.get() != nullptr) { 2548 file = *new_file; 2549 } 2550 } 2551 } 2552 } 2553 } 2554 2555 // Relatively common case 2556 BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine " 2557 "debug_file for " << *name_; 2558 2559 return file; 2560 } 2561 2562 static string guid_and_age_to_debug_id(const MDGUID& guid, 2563 uint32_t age) { 2564 char identifier_string[41]; 2565 snprintf(identifier_string, sizeof(identifier_string), 2566 "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", 2567 guid.data1, 2568 guid.data2, 2569 guid.data3, 2570 guid.data4[0], 2571 guid.data4[1], 2572 guid.data4[2], 2573 guid.data4[3], 2574 guid.data4[4], 2575 guid.data4[5], 2576 guid.data4[6], 2577 guid.data4[7], 2578 age); 2579 return identifier_string; 2580 } 2581 2582 string MinidumpModule::debug_identifier() const { 2583 if (!valid_) { 2584 BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier"; 2585 return ""; 2586 } 2587 2588 if (!has_debug_info_) 2589 return ""; 2590 2591 string identifier; 2592 2593 // Use the CodeView record if present. 2594 if (cv_record_) { 2595 if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { 2596 // It's actually an MDCVInfoPDB70 structure. 2597 const MDCVInfoPDB70* cv_record_70 = 2598 reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); 2599 assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); 2600 2601 // Use the same format that the MS symbol server uses in filesystem 2602 // hierarchies. 2603 identifier = guid_and_age_to_debug_id(cv_record_70->signature, 2604 cv_record_70->age); 2605 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { 2606 // It's actually an MDCVInfoPDB20 structure. 2607 const MDCVInfoPDB20* cv_record_20 = 2608 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); 2609 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); 2610 2611 // Use the same format that the MS symbol server uses in filesystem 2612 // hierarchies. 2613 char identifier_string[17]; 2614 snprintf(identifier_string, sizeof(identifier_string), 2615 "%08X%x", cv_record_20->signature, cv_record_20->age); 2616 identifier = identifier_string; 2617 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { 2618 // It's actually an MDCVInfoELF structure. 2619 const MDCVInfoELF* cv_record_elf = 2620 reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); 2621 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); 2622 2623 // For backwards-compatibility, stuff as many bytes as will fit into 2624 // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does 2625 // with age = 0. Historically Breakpad would do this during dump 2626 // writing to fit the build id data into a MDCVInfoPDB70 struct. 2627 // The full build id is available by calling code_identifier. 2628 MDGUID guid = {0}; 2629 memcpy(&guid, &cv_record_elf->build_id, 2630 std::min(cv_record_->size() - MDCVInfoELF_minsize, 2631 sizeof(MDGUID))); 2632 identifier = guid_and_age_to_debug_id(guid, 0); 2633 } 2634 } 2635 2636 // TODO(mmentovai): if there's no usable CodeView record, there might be a 2637 // miscellaneous debug record. It only carries a filename, though, and no 2638 // identifier. I'm not sure what the right thing to do for the identifier 2639 // is in that case, but I don't expect to find many modules without a 2640 // CodeView record (or some other Breakpad extension structure in place of 2641 // a CodeView record). Treat it as an error (empty identifier) for now. 2642 2643 // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). 2644 2645 // Relatively common case 2646 BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine " 2647 "debug_identifier for " << *name_; 2648 2649 return identifier; 2650 } 2651 2652 2653 string MinidumpModule::version() const { 2654 if (!valid_) { 2655 BPLOG(ERROR) << "Invalid MinidumpModule for version"; 2656 return ""; 2657 } 2658 2659 string version; 2660 2661 if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE && 2662 module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) { 2663 char version_string[24]; 2664 snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u", 2665 module_.version_info.file_version_hi >> 16, 2666 module_.version_info.file_version_hi & 0xffff, 2667 module_.version_info.file_version_lo >> 16, 2668 module_.version_info.file_version_lo & 0xffff); 2669 version = version_string; 2670 } 2671 2672 // TODO(mmentovai): possibly support other struct types in place of 2673 // the one used with MD_VSFIXEDFILEINFO_SIGNATURE. We can possibly use 2674 // a different structure that better represents versioning facilities on 2675 // Mac OS X and Linux, instead of forcing them to adhere to the dotted 2676 // quad of 16-bit ints that Windows uses. 2677 2678 BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine " 2679 "version for " << *name_; 2680 2681 return version; 2682 } 2683 2684 2685 CodeModule* MinidumpModule::Copy() const { 2686 return new BasicCodeModule(this); 2687 } 2688 2689 2690 uint64_t MinidumpModule::shrink_down_delta() const { 2691 return 0; 2692 } 2693 2694 void MinidumpModule::SetShrinkDownDelta(uint64_t shrink_down_delta) { 2695 // Not implemented 2696 assert(false); 2697 } 2698 2699 2700 const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { 2701 if (!module_valid_) { 2702 BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord"; 2703 return NULL; 2704 } 2705 2706 if (!cv_record_) { 2707 // This just guards against 0-sized CodeView records; more specific checks 2708 // are used when the signature is checked against various structure types. 2709 if (module_.cv_record.data_size == 0) { 2710 return NULL; 2711 } 2712 2713 if (!minidump_->SeekSet(module_.cv_record.rva)) { 2714 BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record"; 2715 return NULL; 2716 } 2717 2718 if (module_.cv_record.data_size > max_cv_bytes_) { 2719 BPLOG(ERROR) << "MinidumpModule CodeView record size " << 2720 module_.cv_record.data_size << " exceeds maximum " << 2721 max_cv_bytes_; 2722 return NULL; 2723 } 2724 2725 // Allocating something that will be accessed as MDCVInfoPDB70 or 2726 // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment 2727 // problems. x86 and ppc are able to cope, though. This allocation 2728 // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are 2729 // variable-sized due to their pdb_file_name fields; these structures 2730 // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating 2731 // them as such would result in incomplete structures or overruns. 2732 scoped_ptr< vector<uint8_t> > cv_record( 2733 new vector<uint8_t>(module_.cv_record.data_size)); 2734 2735 if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) { 2736 BPLOG(ERROR) << "MinidumpModule could not read CodeView record"; 2737 return NULL; 2738 } 2739 2740 uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE; 2741 if (module_.cv_record.data_size > sizeof(signature)) { 2742 MDCVInfoPDB70* cv_record_signature = 2743 reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); 2744 signature = cv_record_signature->cv_signature; 2745 if (minidump_->swap()) 2746 Swap(&signature); 2747 } 2748 2749 if (signature == MD_CVINFOPDB70_SIGNATURE) { 2750 // Now that the structure type is known, recheck the size, 2751 // ensuring at least one byte for the null terminator. 2752 if (MDCVInfoPDB70_minsize + 1 > module_.cv_record.data_size) { 2753 BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " << 2754 MDCVInfoPDB70_minsize << " > " << 2755 module_.cv_record.data_size; 2756 return NULL; 2757 } 2758 2759 if (minidump_->swap()) { 2760 MDCVInfoPDB70* cv_record_70 = 2761 reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); 2762 Swap(&cv_record_70->cv_signature); 2763 Swap(&cv_record_70->signature); 2764 Swap(&cv_record_70->age); 2765 // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit 2766 // quantities. (It's a path, is it UTF-8?) 2767 } 2768 2769 // The last field of either structure is null-terminated 8-bit character 2770 // data. Ensure that it's null-terminated. 2771 if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { 2772 BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not " 2773 "0-terminated"; 2774 return NULL; 2775 } 2776 } else if (signature == MD_CVINFOPDB20_SIGNATURE) { 2777 // Now that the structure type is known, recheck the size, 2778 // ensuring at least one byte for the null terminator. 2779 if (MDCVInfoPDB20_minsize + 1 > module_.cv_record.data_size) { 2780 BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " << 2781 MDCVInfoPDB20_minsize << " > " << 2782 module_.cv_record.data_size; 2783 return NULL; 2784 } 2785 if (minidump_->swap()) { 2786 MDCVInfoPDB20* cv_record_20 = 2787 reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]); 2788 Swap(&cv_record_20->cv_header.signature); 2789 Swap(&cv_record_20->cv_header.offset); 2790 Swap(&cv_record_20->signature); 2791 Swap(&cv_record_20->age); 2792 // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit 2793 // quantities. (It's a path, is it UTF-8?) 2794 } 2795 2796 // The last field of either structure is null-terminated 8-bit character 2797 // data. Ensure that it's null-terminated. 2798 if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { 2799 BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " 2800 "0-terminated"; 2801 return NULL; 2802 } 2803 } else if (signature == MD_CVINFOELF_SIGNATURE) { 2804 // Now that the structure type is known, recheck the size. 2805 if (MDCVInfoELF_minsize > module_.cv_record.data_size) { 2806 BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " << 2807 MDCVInfoELF_minsize << " > " << 2808 module_.cv_record.data_size; 2809 return NULL; 2810 } 2811 if (minidump_->swap()) { 2812 MDCVInfoELF* cv_record_elf = 2813 reinterpret_cast<MDCVInfoELF*>(&(*cv_record)[0]); 2814 Swap(&cv_record_elf->cv_signature); 2815 } 2816 } 2817 2818 // If the signature doesn't match something above, it's not something 2819 // that Breakpad can presently handle directly. Because some modules in 2820 // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, 2821 // don't bail out here - allow the data to be returned to the user, 2822 // although byte-swapping can't be done. 2823 2824 // Store the vector type because that's how storage was allocated, but 2825 // return it casted to uint8_t*. 2826 cv_record_ = cv_record.release(); 2827 cv_record_signature_ = signature; 2828 } 2829 2830 if (size) 2831 *size = module_.cv_record.data_size; 2832 2833 return &(*cv_record_)[0]; 2834 } 2835 2836 2837 const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { 2838 if (!module_valid_) { 2839 BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord"; 2840 return NULL; 2841 } 2842 2843 if (!misc_record_) { 2844 if (module_.misc_record.data_size == 0) { 2845 return NULL; 2846 } 2847 2848 if (MDImageDebugMisc_minsize > module_.misc_record.data_size) { 2849 BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record " 2850 "size mismatch, " << MDImageDebugMisc_minsize << " > " << 2851 module_.misc_record.data_size; 2852 return NULL; 2853 } 2854 2855 if (!minidump_->SeekSet(module_.misc_record.rva)) { 2856 BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous " 2857 "debugging record"; 2858 return NULL; 2859 } 2860 2861 if (module_.misc_record.data_size > max_misc_bytes_) { 2862 BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " << 2863 module_.misc_record.data_size << " exceeds maximum " << 2864 max_misc_bytes_; 2865 return NULL; 2866 } 2867 2868 // Allocating something that will be accessed as MDImageDebugMisc but 2869 // is allocated as uint8_t[] can cause alignment problems. x86 and 2870 // ppc are able to cope, though. This allocation style is needed 2871 // because the MDImageDebugMisc is variable-sized due to its data field; 2872 // this structure is not MDImageDebugMisc_minsize and treating it as such 2873 // would result in an incomplete structure or an overrun. 2874 scoped_ptr< vector<uint8_t> > misc_record_mem( 2875 new vector<uint8_t>(module_.misc_record.data_size)); 2876 MDImageDebugMisc* misc_record = 2877 reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]); 2878 2879 if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) { 2880 BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging " 2881 "record"; 2882 return NULL; 2883 } 2884 2885 if (minidump_->swap()) { 2886 Swap(&misc_record->data_type); 2887 Swap(&misc_record->length); 2888 // Don't swap misc_record.unicode because it's an 8-bit quantity. 2889 // Don't swap the reserved fields for the same reason, and because 2890 // they don't contain any valid data. 2891 if (misc_record->unicode) { 2892 // There is a potential alignment problem, but shouldn't be a problem 2893 // in practice due to the layout of MDImageDebugMisc. 2894 uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data)); 2895 size_t dataBytes = module_.misc_record.data_size - 2896 MDImageDebugMisc_minsize; 2897 Swap(data16, dataBytes); 2898 } 2899 } 2900 2901 if (module_.misc_record.data_size != misc_record->length) { 2902 BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data " 2903 "size mismatch, " << module_.misc_record.data_size << 2904 " != " << misc_record->length; 2905 return NULL; 2906 } 2907 2908 // Store the vector type because that's how storage was allocated, but 2909 // return it casted to MDImageDebugMisc*. 2910 misc_record_ = misc_record_mem.release(); 2911 } 2912 2913 if (size) 2914 *size = module_.misc_record.data_size; 2915 2916 return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]); 2917 } 2918 2919 2920 void MinidumpModule::Print() { 2921 if (!valid_) { 2922 BPLOG(ERROR) << "MinidumpModule cannot print invalid data"; 2923 return; 2924 } 2925 2926 printf("MDRawModule\n"); 2927 printf(" base_of_image = 0x%" PRIx64 "\n", 2928 module_.base_of_image); 2929 printf(" size_of_image = 0x%x\n", 2930 module_.size_of_image); 2931 printf(" checksum = 0x%x\n", 2932 module_.checksum); 2933 printf(" time_date_stamp = 0x%x %s\n", 2934 module_.time_date_stamp, 2935 TimeTToUTCString(module_.time_date_stamp).c_str()); 2936 printf(" module_name_rva = 0x%x\n", 2937 module_.module_name_rva); 2938 printf(" version_info.signature = 0x%x\n", 2939 module_.version_info.signature); 2940 printf(" version_info.struct_version = 0x%x\n", 2941 module_.version_info.struct_version); 2942 printf(" version_info.file_version = 0x%x:0x%x\n", 2943 module_.version_info.file_version_hi, 2944 module_.version_info.file_version_lo); 2945 printf(" version_info.product_version = 0x%x:0x%x\n", 2946 module_.version_info.product_version_hi, 2947 module_.version_info.product_version_lo); 2948 printf(" version_info.file_flags_mask = 0x%x\n", 2949 module_.version_info.file_flags_mask); 2950 printf(" version_info.file_flags = 0x%x\n", 2951 module_.version_info.file_flags); 2952 printf(" version_info.file_os = 0x%x\n", 2953 module_.version_info.file_os); 2954 printf(" version_info.file_type = 0x%x\n", 2955 module_.version_info.file_type); 2956 printf(" version_info.file_subtype = 0x%x\n", 2957 module_.version_info.file_subtype); 2958 printf(" version_info.file_date = 0x%x:0x%x\n", 2959 module_.version_info.file_date_hi, 2960 module_.version_info.file_date_lo); 2961 printf(" cv_record.data_size = %d\n", 2962 module_.cv_record.data_size); 2963 printf(" cv_record.rva = 0x%x\n", 2964 module_.cv_record.rva); 2965 printf(" misc_record.data_size = %d\n", 2966 module_.misc_record.data_size); 2967 printf(" misc_record.rva = 0x%x\n", 2968 module_.misc_record.rva); 2969 2970 printf(" (code_file) = \"%s\"\n", code_file().c_str()); 2971 printf(" (code_identifier) = \"%s\"\n", 2972 code_identifier().c_str()); 2973 2974 uint32_t cv_record_size; 2975 const uint8_t* cv_record = GetCVRecord(&cv_record_size); 2976 if (cv_record) { 2977 if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { 2978 const MDCVInfoPDB70* cv_record_70 = 2979 reinterpret_cast<const MDCVInfoPDB70*>(cv_record); 2980 assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); 2981 2982 printf(" (cv_record).cv_signature = 0x%x\n", 2983 cv_record_70->cv_signature); 2984 printf(" (cv_record).signature = %s\n", 2985 MDGUIDToString(cv_record_70->signature).c_str()); 2986 printf(" (cv_record).age = %d\n", 2987 cv_record_70->age); 2988 printf(" (cv_record).pdb_file_name = \"%s\"\n", 2989 cv_record_70->pdb_file_name); 2990 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { 2991 const MDCVInfoPDB20* cv_record_20 = 2992 reinterpret_cast<const MDCVInfoPDB20*>(cv_record); 2993 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); 2994 2995 printf(" (cv_record).cv_header.signature = 0x%x\n", 2996 cv_record_20->cv_header.signature); 2997 printf(" (cv_record).cv_header.offset = 0x%x\n", 2998 cv_record_20->cv_header.offset); 2999 printf(" (cv_record).signature = 0x%x %s\n", 3000 cv_record_20->signature, 3001 TimeTToUTCString(cv_record_20->signature).c_str()); 3002 printf(" (cv_record).age = %d\n", 3003 cv_record_20->age); 3004 printf(" (cv_record).pdb_file_name = \"%s\"\n", 3005 cv_record_20->pdb_file_name); 3006 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { 3007 const MDCVInfoELF* cv_record_elf = 3008 reinterpret_cast<const MDCVInfoELF*>(cv_record); 3009 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); 3010 3011 printf(" (cv_record).cv_signature = 0x%x\n", 3012 cv_record_elf->cv_signature); 3013 printf(" (cv_record).build_id = "); 3014 for (unsigned int build_id_index = 0; 3015 build_id_index < (cv_record_size - MDCVInfoELF_minsize); 3016 ++build_id_index) { 3017 printf("%02x", cv_record_elf->build_id[build_id_index]); 3018 } 3019 printf("\n"); 3020 } else { 3021 printf(" (cv_record) = "); 3022 for (unsigned int cv_byte_index = 0; 3023 cv_byte_index < cv_record_size; 3024 ++cv_byte_index) { 3025 printf("%02x", cv_record[cv_byte_index]); 3026 } 3027 printf("\n"); 3028 } 3029 } else { 3030 printf(" (cv_record) = (null)\n"); 3031 } 3032 3033 const MDImageDebugMisc* misc_record = GetMiscRecord(NULL); 3034 if (misc_record) { 3035 printf(" (misc_record).data_type = 0x%x\n", 3036 misc_record->data_type); 3037 printf(" (misc_record).length = 0x%x\n", 3038 misc_record->length); 3039 printf(" (misc_record).unicode = %d\n", 3040 misc_record->unicode); 3041 if (misc_record->unicode) { 3042 string misc_record_data_utf8; 3043 ConvertUTF16BufferToUTF8String( 3044 reinterpret_cast<const uint16_t*>(misc_record->data), 3045 misc_record->length - offsetof(MDImageDebugMisc, data), 3046 &misc_record_data_utf8, 3047 false); // already swapped 3048 printf(" (misc_record).data = \"%s\"\n", 3049 misc_record_data_utf8.c_str()); 3050 } else { 3051 printf(" (misc_record).data = \"%s\"\n", 3052 misc_record->data); 3053 } 3054 } else { 3055 printf(" (misc_record) = (null)\n"); 3056 } 3057 3058 printf(" (debug_file) = \"%s\"\n", debug_file().c_str()); 3059 printf(" (debug_identifier) = \"%s\"\n", 3060 debug_identifier().c_str()); 3061 printf(" (version) = \"%s\"\n", version().c_str()); 3062 printf("\n"); 3063 } 3064 3065 3066 // 3067 // MinidumpModuleList 3068 // 3069 3070 3071 uint32_t MinidumpModuleList::max_modules_ = 2048; 3072 3073 3074 MinidumpModuleList::MinidumpModuleList(Minidump* minidump) 3075 : MinidumpStream(minidump), 3076 range_map_(new RangeMap<uint64_t, unsigned int>()), 3077 modules_(NULL), 3078 module_count_(0) { 3079 MDOSPlatform platform; 3080 if (minidump_->GetPlatform(&platform) && 3081 (platform == MD_OS_ANDROID || platform == MD_OS_LINUX)) { 3082 range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower); 3083 } 3084 } 3085 3086 3087 MinidumpModuleList::~MinidumpModuleList() { 3088 delete range_map_; 3089 delete modules_; 3090 } 3091 3092 3093 bool MinidumpModuleList::Read(uint32_t expected_size) { 3094 // Invalidate cached data. 3095 range_map_->Clear(); 3096 delete modules_; 3097 modules_ = NULL; 3098 module_count_ = 0; 3099 3100 valid_ = false; 3101 3102 uint32_t module_count; 3103 if (expected_size < sizeof(module_count)) { 3104 BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " << 3105 expected_size << " < " << sizeof(module_count); 3106 return false; 3107 } 3108 if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) { 3109 BPLOG(ERROR) << "MinidumpModuleList could not read module count"; 3110 return false; 3111 } 3112 3113 if (minidump_->swap()) 3114 Swap(&module_count); 3115 3116 if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) { 3117 BPLOG(ERROR) << "MinidumpModuleList module count " << module_count << 3118 " would cause multiplication overflow"; 3119 return false; 3120 } 3121 3122 if (expected_size != sizeof(module_count) + 3123 module_count * MD_MODULE_SIZE) { 3124 // may be padded with 4 bytes on 64bit ABIs for alignment 3125 if (expected_size == sizeof(module_count) + 4 + 3126 module_count * MD_MODULE_SIZE) { 3127 uint32_t useless; 3128 if (!minidump_->ReadBytes(&useless, 4)) { 3129 BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded " 3130 "bytes"; 3131 return false; 3132 } 3133 } else { 3134 BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << 3135 " != " << sizeof(module_count) + 3136 module_count * MD_MODULE_SIZE; 3137 return false; 3138 } 3139 } 3140 3141 if (module_count > max_modules_) { 3142 BPLOG(ERROR) << "MinidumpModuleList count " << module_count << 3143 " exceeds maximum " << max_modules_; 3144 return false; 3145 } 3146 3147 if (module_count != 0) { 3148 scoped_ptr<MinidumpModules> modules( 3149 new MinidumpModules(module_count, MinidumpModule(minidump_))); 3150 3151 for (uint32_t module_index = 0; module_index < module_count; 3152 ++module_index) { 3153 MinidumpModule* module = &(*modules)[module_index]; 3154 3155 // Assume that the file offset is correct after the last read. 3156 if (!module->Read()) { 3157 BPLOG(ERROR) << "MinidumpModuleList could not read module " << 3158 module_index << "/" << module_count; 3159 return false; 3160 } 3161 } 3162 3163 // Loop through the module list once more to read additional data and 3164 // build the range map. This is done in a second pass because 3165 // MinidumpModule::ReadAuxiliaryData seeks around, and if it were 3166 // included in the loop above, additional seeks would be needed where 3167 // none are now to read contiguous data. 3168 uint64_t last_end_address = 0; 3169 for (uint32_t module_index = 0; module_index < module_count; 3170 ++module_index) { 3171 MinidumpModule& module = (*modules)[module_index]; 3172 3173 // ReadAuxiliaryData fails if any data that the module indicates should 3174 // exist is missing, but we treat some such cases as valid anyway. See 3175 // issue #222: if a debugging record is of a format that's too large to 3176 // handle, it shouldn't render the entire dump invalid. Check module 3177 // validity before giving up. 3178 if (!module.ReadAuxiliaryData() && !module.valid()) { 3179 BPLOG(ERROR) << "MinidumpModuleList could not read required module " 3180 "auxiliary data for module " << 3181 module_index << "/" << module_count; 3182 return false; 3183 } 3184 3185 // It is safe to use module->code_file() after successfully calling 3186 // module->ReadAuxiliaryData or noting that the module is valid. 3187 3188 uint64_t base_address = module.base_address(); 3189 uint64_t module_size = module.size(); 3190 if (base_address == static_cast<uint64_t>(-1)) { 3191 BPLOG(ERROR) << "MinidumpModuleList found bad base address for module " 3192 << module_index << "/" << module_count << ", " 3193 << module.code_file(); 3194 return false; 3195 } 3196 3197 // Some minidumps have additional modules in the list that are duplicates. 3198 // Ignore them. See https://crbug.com/838322 3199 uint32_t existing_module_index; 3200 if (range_map_->RetrieveRange(base_address, &existing_module_index, 3201 nullptr, nullptr, nullptr) && 3202 existing_module_index < module_count) { 3203 const MinidumpModule& existing_module = 3204 (*modules)[existing_module_index]; 3205 if (existing_module.base_address() == module.base_address() && 3206 existing_module.size() == module.size() && 3207 existing_module.code_file() == module.code_file() && 3208 existing_module.code_identifier() == module.code_identifier()) { 3209 continue; 3210 } 3211 } 3212 3213 const bool is_android = minidump_->IsAndroid(); 3214 if (!StoreRange(module, base_address, module_index, module_count, 3215 is_android)) { 3216 if (!is_android || base_address >= last_end_address) { 3217 BPLOG(ERROR) << "MinidumpModuleList could not store module " 3218 << module_index << "/" << module_count << ", " 3219 << module.code_file() << ", " << HexString(base_address) 3220 << "+" << HexString(module_size); 3221 return false; 3222 } 3223 3224 // If failed due to apparent range overlap the cause may be the client 3225 // correction applied for Android packed relocations. If this is the 3226 // case, back out the client correction and retry. 3227 assert(is_android); 3228 module_size -= last_end_address - base_address; 3229 base_address = last_end_address; 3230 if (!range_map_->StoreRange(base_address, module_size, module_index)) { 3231 BPLOG(ERROR) << "MinidumpModuleList could not store module " 3232 << module_index << "/" << module_count << ", " 3233 << module.code_file() << ", " << HexString(base_address) 3234 << "+" << HexString(module_size) << ", after adjusting"; 3235 return false; 3236 } 3237 } 3238 last_end_address = base_address + module_size; 3239 } 3240 3241 modules_ = modules.release(); 3242 } 3243 3244 module_count_ = module_count; 3245 3246 valid_ = true; 3247 return true; 3248 } 3249 3250 bool MinidumpModuleList::StoreRange(const MinidumpModule& module, 3251 uint64_t base_address, 3252 uint32_t module_index, 3253 uint32_t module_count, 3254 bool is_android) { 3255 if (range_map_->StoreRange(base_address, module.size(), module_index)) 3256 return true; 3257 3258 // Android's shared memory implementation /dev/ashmem can contain duplicate 3259 // entries for JITted code, so ignore these. 3260 // TODO(wfh): Remove this code when Android is fixed. 3261 // See https://crbug.com/439531 3262 if (is_android && IsDevAshmem(module.code_file())) { 3263 BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module " 3264 << module_index << "/" << module_count << ", " 3265 << module.code_file() << ", " << HexString(base_address) << "+" 3266 << HexString(module.size()); 3267 return true; 3268 } 3269 3270 return false; 3271 } 3272 3273 const MinidumpModule* MinidumpModuleList::GetModuleForAddress( 3274 uint64_t address) const { 3275 if (!valid_) { 3276 BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress"; 3277 return NULL; 3278 } 3279 3280 unsigned int module_index; 3281 if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */, 3282 NULL /* delta */, NULL /* size */)) { 3283 BPLOG(INFO) << "MinidumpModuleList has no module at " << 3284 HexString(address); 3285 return NULL; 3286 } 3287 3288 return GetModuleAtIndex(module_index); 3289 } 3290 3291 3292 const MinidumpModule* MinidumpModuleList::GetMainModule() const { 3293 if (!valid_) { 3294 BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule"; 3295 return NULL; 3296 } 3297 3298 // The main code module is the first one present in a minidump file's 3299 // MDRawModuleList. 3300 return GetModuleAtIndex(0); 3301 } 3302 3303 3304 const MinidumpModule* MinidumpModuleList::GetModuleAtSequence( 3305 unsigned int sequence) const { 3306 if (!valid_) { 3307 BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence"; 3308 return NULL; 3309 } 3310 3311 if (sequence >= module_count_) { 3312 BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " << 3313 sequence << "/" << module_count_; 3314 return NULL; 3315 } 3316 3317 unsigned int module_index; 3318 if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, 3319 NULL /* base */, NULL /* delta */, 3320 NULL /* size */)) { 3321 BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence; 3322 return NULL; 3323 } 3324 3325 return GetModuleAtIndex(module_index); 3326 } 3327 3328 3329 const MinidumpModule* MinidumpModuleList::GetModuleAtIndex( 3330 unsigned int index) const { 3331 if (!valid_) { 3332 BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex"; 3333 return NULL; 3334 } 3335 3336 if (index >= module_count_) { 3337 BPLOG(ERROR) << "MinidumpModuleList index out of range: " << 3338 index << "/" << module_count_; 3339 return NULL; 3340 } 3341 3342 return &(*modules_)[index]; 3343 } 3344 3345 3346 const CodeModules* MinidumpModuleList::Copy() const { 3347 return new BasicCodeModules(this, range_map_->GetMergeStrategy()); 3348 } 3349 3350 vector<linked_ptr<const CodeModule> > 3351 MinidumpModuleList::GetShrunkRangeModules() const { 3352 return vector<linked_ptr<const CodeModule> >(); 3353 } 3354 3355 void MinidumpModuleList::Print() { 3356 if (!valid_) { 3357 BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data"; 3358 return; 3359 } 3360 3361 printf("MinidumpModuleList\n"); 3362 printf(" module_count = %d\n", module_count_); 3363 printf("\n"); 3364 3365 for (unsigned int module_index = 0; 3366 module_index < module_count_; 3367 ++module_index) { 3368 printf("module[%d]\n", module_index); 3369 3370 (*modules_)[module_index].Print(); 3371 } 3372 } 3373 3374 3375 // 3376 // MinidumpMemoryList 3377 // 3378 3379 3380 uint32_t MinidumpMemoryList::max_regions_ = 4096; 3381 3382 3383 MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) 3384 : MinidumpStream(minidump), 3385 range_map_(new RangeMap<uint64_t, unsigned int>()), 3386 descriptors_(NULL), 3387 regions_(NULL), 3388 region_count_(0) { 3389 } 3390 3391 3392 MinidumpMemoryList::~MinidumpMemoryList() { 3393 delete range_map_; 3394 delete descriptors_; 3395 delete regions_; 3396 } 3397 3398 3399 bool MinidumpMemoryList::Read(uint32_t expected_size) { 3400 // Invalidate cached data. 3401 delete descriptors_; 3402 descriptors_ = NULL; 3403 delete regions_; 3404 regions_ = NULL; 3405 range_map_->Clear(); 3406 region_count_ = 0; 3407 3408 valid_ = false; 3409 3410 uint32_t region_count; 3411 if (expected_size < sizeof(region_count)) { 3412 BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " << 3413 expected_size << " < " << sizeof(region_count); 3414 return false; 3415 } 3416 if (!minidump_->ReadBytes(®ion_count, sizeof(region_count))) { 3417 BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count"; 3418 return false; 3419 } 3420 3421 if (minidump_->swap()) 3422 Swap(®ion_count); 3423 3424 if (region_count > 3425 numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) { 3426 BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count << 3427 " would cause multiplication overflow"; 3428 return false; 3429 } 3430 3431 if (expected_size != sizeof(region_count) + 3432 region_count * sizeof(MDMemoryDescriptor)) { 3433 // may be padded with 4 bytes on 64bit ABIs for alignment 3434 if (expected_size == sizeof(region_count) + 4 + 3435 region_count * sizeof(MDMemoryDescriptor)) { 3436 uint32_t useless; 3437 if (!minidump_->ReadBytes(&useless, 4)) { 3438 BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded " 3439 "bytes"; 3440 return false; 3441 } 3442 } else { 3443 BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << 3444 " != " << sizeof(region_count) + 3445 region_count * sizeof(MDMemoryDescriptor); 3446 return false; 3447 } 3448 } 3449 3450 if (region_count > max_regions_) { 3451 BPLOG(ERROR) << "MinidumpMemoryList count " << region_count << 3452 " exceeds maximum " << max_regions_; 3453 return false; 3454 } 3455 3456 if (region_count != 0) { 3457 scoped_ptr<MemoryDescriptors> descriptors( 3458 new MemoryDescriptors(region_count)); 3459 3460 // Read the entire array in one fell swoop, instead of reading one entry 3461 // at a time in the loop. 3462 if (!minidump_->ReadBytes(&(*descriptors)[0], 3463 sizeof(MDMemoryDescriptor) * region_count)) { 3464 BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list"; 3465 return false; 3466 } 3467 3468 scoped_ptr<MemoryRegions> regions( 3469 new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); 3470 3471 for (unsigned int region_index = 0; 3472 region_index < region_count; 3473 ++region_index) { 3474 MDMemoryDescriptor* descriptor = &(*descriptors)[region_index]; 3475 3476 if (minidump_->swap()) 3477 Swap(descriptor); 3478 3479 uint64_t base_address = descriptor->start_of_memory_range; 3480 uint32_t region_size = descriptor->memory.data_size; 3481 3482 // Check for base + size overflow or undersize. 3483 if (region_size == 0 || 3484 region_size > numeric_limits<uint64_t>::max() - base_address) { 3485 BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " << 3486 " region " << region_index << "/" << region_count << 3487 ", " << HexString(base_address) << "+" << 3488 HexString(region_size); 3489 return false; 3490 } 3491 3492 if (!range_map_->StoreRange(base_address, region_size, region_index)) { 3493 BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " << 3494 region_index << "/" << region_count << ", " << 3495 HexString(base_address) << "+" << 3496 HexString(region_size); 3497 return false; 3498 } 3499 3500 (*regions)[region_index].SetDescriptor(descriptor); 3501 } 3502 3503 descriptors_ = descriptors.release(); 3504 regions_ = regions.release(); 3505 } 3506 3507 region_count_ = region_count; 3508 3509 valid_ = true; 3510 return true; 3511 } 3512 3513 3514 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex( 3515 unsigned int index) { 3516 if (!valid_) { 3517 BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex"; 3518 return NULL; 3519 } 3520 3521 if (index >= region_count_) { 3522 BPLOG(ERROR) << "MinidumpMemoryList index out of range: " << 3523 index << "/" << region_count_; 3524 return NULL; 3525 } 3526 3527 return &(*regions_)[index]; 3528 } 3529 3530 3531 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress( 3532 uint64_t address) { 3533 if (!valid_) { 3534 BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress"; 3535 return NULL; 3536 } 3537 3538 unsigned int region_index; 3539 if (!range_map_->RetrieveRange(address, ®ion_index, NULL /* base */, 3540 NULL /* delta */, NULL /* size */)) { 3541 BPLOG(INFO) << "MinidumpMemoryList has no memory region at " << 3542 HexString(address); 3543 return NULL; 3544 } 3545 3546 return GetMemoryRegionAtIndex(region_index); 3547 } 3548 3549 3550 void MinidumpMemoryList::Print() { 3551 if (!valid_) { 3552 BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data"; 3553 return; 3554 } 3555 3556 printf("MinidumpMemoryList\n"); 3557 printf(" region_count = %d\n", region_count_); 3558 printf("\n"); 3559 3560 for (unsigned int region_index = 0; 3561 region_index < region_count_; 3562 ++region_index) { 3563 MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index]; 3564 printf("region[%d]\n", region_index); 3565 printf("MDMemoryDescriptor\n"); 3566 printf(" start_of_memory_range = 0x%" PRIx64 "\n", 3567 descriptor->start_of_memory_range); 3568 printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size); 3569 printf(" memory.rva = 0x%x\n", descriptor->memory.rva); 3570 MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index); 3571 if (region) { 3572 printf("Memory\n"); 3573 region->Print(); 3574 } else { 3575 printf("No memory\n"); 3576 } 3577 printf("\n"); 3578 } 3579 } 3580 3581 3582 // 3583 // MinidumpException 3584 // 3585 3586 3587 MinidumpException::MinidumpException(Minidump* minidump) 3588 : MinidumpStream(minidump), 3589 exception_(), 3590 context_(NULL) { 3591 } 3592 3593 3594 MinidumpException::~MinidumpException() { 3595 delete context_; 3596 } 3597 3598 3599 bool MinidumpException::Read(uint32_t expected_size) { 3600 // Invalidate cached data. 3601 delete context_; 3602 context_ = NULL; 3603 3604 valid_ = false; 3605 3606 if (expected_size != sizeof(exception_)) { 3607 BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size << 3608 " != " << sizeof(exception_); 3609 return false; 3610 } 3611 3612 if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) { 3613 BPLOG(ERROR) << "MinidumpException cannot read exception"; 3614 return false; 3615 } 3616 3617 if (minidump_->swap()) { 3618 Swap(&exception_.thread_id); 3619 // exception_.__align is for alignment only and does not need to be 3620 // swapped. 3621 Swap(&exception_.exception_record.exception_code); 3622 Swap(&exception_.exception_record.exception_flags); 3623 Swap(&exception_.exception_record.exception_record); 3624 Swap(&exception_.exception_record.exception_address); 3625 Swap(&exception_.exception_record.number_parameters); 3626 // exception_.exception_record.__align is for alignment only and does not 3627 // need to be swapped. 3628 for (unsigned int parameter_index = 0; 3629 parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS; 3630 ++parameter_index) { 3631 Swap(&exception_.exception_record.exception_information[parameter_index]); 3632 } 3633 Swap(&exception_.thread_context); 3634 } 3635 3636 valid_ = true; 3637 return true; 3638 } 3639 3640 3641 bool MinidumpException::GetThreadID(uint32_t* thread_id) const { 3642 BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires " 3643 "|thread_id|"; 3644 assert(thread_id); 3645 *thread_id = 0; 3646 3647 if (!valid_) { 3648 BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID"; 3649 return false; 3650 } 3651 3652 *thread_id = exception_.thread_id; 3653 return true; 3654 } 3655 3656 3657 MinidumpContext* MinidumpException::GetContext() { 3658 if (!valid_) { 3659 BPLOG(ERROR) << "Invalid MinidumpException for GetContext"; 3660 return NULL; 3661 } 3662 3663 if (!context_) { 3664 if (!minidump_->SeekSet(exception_.thread_context.rva)) { 3665 BPLOG(ERROR) << "MinidumpException cannot seek to context"; 3666 return NULL; 3667 } 3668 3669 scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); 3670 3671 // Don't log as an error if we can still fall back on the thread's context 3672 // (which must be possible if we got this far.) 3673 if (!context->Read(exception_.thread_context.data_size)) { 3674 BPLOG(INFO) << "MinidumpException cannot read context"; 3675 return NULL; 3676 } 3677 3678 context_ = context.release(); 3679 } 3680 3681 return context_; 3682 } 3683 3684 3685 void MinidumpException::Print() { 3686 if (!valid_) { 3687 BPLOG(ERROR) << "MinidumpException cannot print invalid data"; 3688 return; 3689 } 3690 3691 printf("MDException\n"); 3692 printf(" thread_id = 0x%x\n", 3693 exception_.thread_id); 3694 printf(" exception_record.exception_code = 0x%x\n", 3695 exception_.exception_record.exception_code); 3696 printf(" exception_record.exception_flags = 0x%x\n", 3697 exception_.exception_record.exception_flags); 3698 printf(" exception_record.exception_record = 0x%" PRIx64 "\n", 3699 exception_.exception_record.exception_record); 3700 printf(" exception_record.exception_address = 0x%" PRIx64 "\n", 3701 exception_.exception_record.exception_address); 3702 printf(" exception_record.number_parameters = %d\n", 3703 exception_.exception_record.number_parameters); 3704 for (unsigned int parameterIndex = 0; 3705 parameterIndex < exception_.exception_record.number_parameters; 3706 ++parameterIndex) { 3707 printf(" exception_record.exception_information[%2d] = 0x%" PRIx64 "\n", 3708 parameterIndex, 3709 exception_.exception_record.exception_information[parameterIndex]); 3710 } 3711 printf(" thread_context.data_size = %d\n", 3712 exception_.thread_context.data_size); 3713 printf(" thread_context.rva = 0x%x\n", 3714 exception_.thread_context.rva); 3715 MinidumpContext* context = GetContext(); 3716 if (context) { 3717 printf("\n"); 3718 context->Print(); 3719 } else { 3720 printf(" (no context)\n"); 3721 printf("\n"); 3722 } 3723 } 3724 3725 // 3726 // MinidumpAssertion 3727 // 3728 3729 3730 MinidumpAssertion::MinidumpAssertion(Minidump* minidump) 3731 : MinidumpStream(minidump), 3732 assertion_(), 3733 expression_(), 3734 function_(), 3735 file_() { 3736 } 3737 3738 3739 MinidumpAssertion::~MinidumpAssertion() { 3740 } 3741 3742 3743 bool MinidumpAssertion::Read(uint32_t expected_size) { 3744 // Invalidate cached data. 3745 valid_ = false; 3746 3747 if (expected_size != sizeof(assertion_)) { 3748 BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size << 3749 " != " << sizeof(assertion_); 3750 return false; 3751 } 3752 3753 if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) { 3754 BPLOG(ERROR) << "MinidumpAssertion cannot read assertion"; 3755 return false; 3756 } 3757 3758 // Each of {expression, function, file} is a UTF-16 string, 3759 // we'll convert them to UTF-8 for ease of use. 3760 ConvertUTF16BufferToUTF8String(assertion_.expression, 3761 sizeof(assertion_.expression), &expression_, 3762 minidump_->swap()); 3763 ConvertUTF16BufferToUTF8String(assertion_.function, 3764 sizeof(assertion_.function), &function_, 3765 minidump_->swap()); 3766 ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file), 3767 &file_, minidump_->swap()); 3768 3769 if (minidump_->swap()) { 3770 Swap(&assertion_.line); 3771 Swap(&assertion_.type); 3772 } 3773 3774 valid_ = true; 3775 return true; 3776 } 3777 3778 void MinidumpAssertion::Print() { 3779 if (!valid_) { 3780 BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data"; 3781 return; 3782 } 3783 3784 printf("MDAssertion\n"); 3785 printf(" expression = %s\n", 3786 expression_.c_str()); 3787 printf(" function = %s\n", 3788 function_.c_str()); 3789 printf(" file = %s\n", 3790 file_.c_str()); 3791 printf(" line = %u\n", 3792 assertion_.line); 3793 printf(" type = %u\n", 3794 assertion_.type); 3795 printf("\n"); 3796 } 3797 3798 // 3799 // MinidumpSystemInfo 3800 // 3801 3802 3803 MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) 3804 : MinidumpStream(minidump), 3805 system_info_(), 3806 csd_version_(NULL), 3807 cpu_vendor_(NULL) { 3808 } 3809 3810 3811 MinidumpSystemInfo::~MinidumpSystemInfo() { 3812 delete csd_version_; 3813 delete cpu_vendor_; 3814 } 3815 3816 3817 bool MinidumpSystemInfo::Read(uint32_t expected_size) { 3818 // Invalidate cached data. 3819 delete csd_version_; 3820 csd_version_ = NULL; 3821 delete cpu_vendor_; 3822 cpu_vendor_ = NULL; 3823 3824 valid_ = false; 3825 3826 if (expected_size != sizeof(system_info_)) { 3827 BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size << 3828 " != " << sizeof(system_info_); 3829 return false; 3830 } 3831 3832 if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) { 3833 BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info"; 3834 return false; 3835 } 3836 3837 if (minidump_->swap()) { 3838 Swap(&system_info_.processor_architecture); 3839 Swap(&system_info_.processor_level); 3840 Swap(&system_info_.processor_revision); 3841 // number_of_processors and product_type are 8-bit quantities and need no 3842 // swapping. 3843 Swap(&system_info_.major_version); 3844 Swap(&system_info_.minor_version); 3845 Swap(&system_info_.build_number); 3846 Swap(&system_info_.platform_id); 3847 Swap(&system_info_.csd_version_rva); 3848 Swap(&system_info_.suite_mask); 3849 // Don't swap the reserved2 field because its contents are unknown. 3850 3851 if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || 3852 system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { 3853 for (unsigned int i = 0; i < 3; ++i) 3854 Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]); 3855 Swap(&system_info_.cpu.x86_cpu_info.version_information); 3856 Swap(&system_info_.cpu.x86_cpu_info.feature_information); 3857 Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); 3858 } else { 3859 for (unsigned int i = 0; i < 2; ++i) 3860 Swap(&system_info_.cpu.other_cpu_info.processor_features[i]); 3861 } 3862 } 3863 3864 valid_ = true; 3865 return true; 3866 } 3867 3868 3869 string MinidumpSystemInfo::GetOS() { 3870 string os; 3871 3872 if (!valid_) { 3873 BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS"; 3874 return os; 3875 } 3876 3877 switch (system_info_.platform_id) { 3878 case MD_OS_WIN32_NT: 3879 case MD_OS_WIN32_WINDOWS: 3880 os = "windows"; 3881 break; 3882 3883 case MD_OS_MAC_OS_X: 3884 os = "mac"; 3885 break; 3886 3887 case MD_OS_IOS: 3888 os = "ios"; 3889 break; 3890 3891 case MD_OS_LINUX: 3892 os = "linux"; 3893 break; 3894 3895 case MD_OS_SOLARIS: 3896 os = "solaris"; 3897 break; 3898 3899 case MD_OS_ANDROID: 3900 os = "android"; 3901 break; 3902 3903 case MD_OS_PS3: 3904 os = "ps3"; 3905 break; 3906 3907 case MD_OS_NACL: 3908 os = "nacl"; 3909 break; 3910 3911 case MD_OS_FUCHSIA: 3912 os = "fuchsia"; 3913 break; 3914 3915 default: 3916 BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " << 3917 HexString(system_info_.platform_id); 3918 break; 3919 } 3920 3921 return os; 3922 } 3923 3924 3925 string MinidumpSystemInfo::GetCPU() { 3926 if (!valid_) { 3927 BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU"; 3928 return ""; 3929 } 3930 3931 string cpu; 3932 3933 switch (system_info_.processor_architecture) { 3934 case MD_CPU_ARCHITECTURE_X86: 3935 case MD_CPU_ARCHITECTURE_X86_WIN64: 3936 cpu = "x86"; 3937 break; 3938 3939 case MD_CPU_ARCHITECTURE_AMD64: 3940 cpu = "x86-64"; 3941 break; 3942 3943 case MD_CPU_ARCHITECTURE_PPC: 3944 cpu = "ppc"; 3945 break; 3946 3947 case MD_CPU_ARCHITECTURE_PPC64: 3948 cpu = "ppc64"; 3949 break; 3950 3951 case MD_CPU_ARCHITECTURE_SPARC: 3952 cpu = "sparc"; 3953 break; 3954 3955 case MD_CPU_ARCHITECTURE_ARM: 3956 cpu = "arm"; 3957 break; 3958 3959 case MD_CPU_ARCHITECTURE_ARM64: 3960 case MD_CPU_ARCHITECTURE_ARM64_OLD: 3961 cpu = "arm64"; 3962 break; 3963 3964 case MD_CPU_ARCHITECTURE_RISCV: 3965 cpu = "riscv"; 3966 break; 3967 3968 case MD_CPU_ARCHITECTURE_RISCV64: 3969 cpu = "riscv64"; 3970 break; 3971 3972 default: 3973 BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " << 3974 HexString(system_info_.processor_architecture); 3975 break; 3976 } 3977 3978 return cpu; 3979 } 3980 3981 3982 const string* MinidumpSystemInfo::GetCSDVersion() { 3983 if (!valid_) { 3984 BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion"; 3985 return NULL; 3986 } 3987 3988 if (!csd_version_) 3989 csd_version_ = minidump_->ReadString(system_info_.csd_version_rva); 3990 3991 BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read " 3992 "CSD version"; 3993 3994 return csd_version_; 3995 } 3996 3997 3998 const string* MinidumpSystemInfo::GetCPUVendor() { 3999 if (!valid_) { 4000 BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor"; 4001 return NULL; 4002 } 4003 4004 // CPU vendor information can only be determined from x86 minidumps. 4005 if (!cpu_vendor_ && 4006 (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || 4007 system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) { 4008 char cpu_vendor_string[13]; 4009 snprintf(cpu_vendor_string, sizeof(cpu_vendor_string), 4010 "%c%c%c%c%c%c%c%c%c%c%c%c", 4011 system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff, 4012 (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff, 4013 (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff, 4014 (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff, 4015 system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff, 4016 (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff, 4017 (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff, 4018 (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff, 4019 system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff, 4020 (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff, 4021 (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff, 4022 (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff); 4023 cpu_vendor_ = new string(cpu_vendor_string); 4024 } 4025 4026 return cpu_vendor_; 4027 } 4028 4029 4030 void MinidumpSystemInfo::Print() { 4031 if (!valid_) { 4032 BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data"; 4033 return; 4034 } 4035 4036 printf("MDRawSystemInfo\n"); 4037 printf(" processor_architecture = 0x%x (%s)\n", 4038 system_info_.processor_architecture, GetCPU().c_str()); 4039 printf(" processor_level = %d\n", 4040 system_info_.processor_level); 4041 printf(" processor_revision = 0x%x\n", 4042 system_info_.processor_revision); 4043 printf(" number_of_processors = %d\n", 4044 system_info_.number_of_processors); 4045 printf(" product_type = %d\n", 4046 system_info_.product_type); 4047 printf(" major_version = %d\n", 4048 system_info_.major_version); 4049 printf(" minor_version = %d\n", 4050 system_info_.minor_version); 4051 printf(" build_number = %d\n", 4052 system_info_.build_number); 4053 printf(" platform_id = 0x%x (%s)\n", 4054 system_info_.platform_id, GetOS().c_str()); 4055 printf(" csd_version_rva = 0x%x\n", 4056 system_info_.csd_version_rva); 4057 printf(" suite_mask = 0x%x\n", 4058 system_info_.suite_mask); 4059 if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || 4060 system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { 4061 printf(" cpu.x86_cpu_info (valid):\n"); 4062 } else { 4063 printf(" cpu.x86_cpu_info (invalid):\n"); 4064 } 4065 for (unsigned int i = 0; i < 3; ++i) { 4066 printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n", 4067 i, system_info_.cpu.x86_cpu_info.vendor_id[i]); 4068 } 4069 printf(" cpu.x86_cpu_info.version_information = 0x%x\n", 4070 system_info_.cpu.x86_cpu_info.version_information); 4071 printf(" cpu.x86_cpu_info.feature_information = 0x%x\n", 4072 system_info_.cpu.x86_cpu_info.feature_information); 4073 printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n", 4074 system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); 4075 if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 && 4076 system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) { 4077 printf(" cpu.other_cpu_info (valid):\n"); 4078 for (unsigned int i = 0; i < 2; ++i) { 4079 printf(" cpu.other_cpu_info.processor_features[%d] = 0x%" PRIx64 "\n", 4080 i, system_info_.cpu.other_cpu_info.processor_features[i]); 4081 } 4082 } 4083 const string* csd_version = GetCSDVersion(); 4084 if (csd_version) { 4085 printf(" (csd_version) = \"%s\"\n", 4086 csd_version->c_str()); 4087 } else { 4088 printf(" (csd_version) = (null)\n"); 4089 } 4090 const string* cpu_vendor = GetCPUVendor(); 4091 if (cpu_vendor) { 4092 printf(" (cpu_vendor) = \"%s\"\n", 4093 cpu_vendor->c_str()); 4094 } else { 4095 printf(" (cpu_vendor) = (null)\n"); 4096 } 4097 printf("\n"); 4098 } 4099 4100 4101 // 4102 // MinidumpUnloadedModule 4103 // 4104 4105 4106 MinidumpUnloadedModule::MinidumpUnloadedModule(Minidump* minidump) 4107 : MinidumpObject(minidump), 4108 module_valid_(false), 4109 unloaded_module_(), 4110 name_(NULL) { 4111 4112 } 4113 4114 MinidumpUnloadedModule::~MinidumpUnloadedModule() { 4115 delete name_; 4116 } 4117 4118 string MinidumpUnloadedModule::code_file() const { 4119 if (!valid_) { 4120 BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_file"; 4121 return ""; 4122 } 4123 4124 return *name_; 4125 } 4126 4127 string MinidumpUnloadedModule::code_identifier() const { 4128 if (!valid_) { 4129 BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_identifier"; 4130 return ""; 4131 } 4132 4133 MinidumpSystemInfo* minidump_system_info = minidump_->GetSystemInfo(); 4134 if (!minidump_system_info) { 4135 BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires " 4136 "MinidumpSystemInfo"; 4137 return ""; 4138 } 4139 4140 const MDRawSystemInfo* raw_system_info = minidump_system_info->system_info(); 4141 if (!raw_system_info) { 4142 BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires " 4143 << "MDRawSystemInfo"; 4144 return ""; 4145 } 4146 4147 string identifier; 4148 4149 switch (raw_system_info->platform_id) { 4150 case MD_OS_WIN32_NT: 4151 case MD_OS_WIN32_WINDOWS: { 4152 // Use the same format that the MS symbol server uses in filesystem 4153 // hierarchies. 4154 char identifier_string[17]; 4155 snprintf(identifier_string, sizeof(identifier_string), "%08X%x", 4156 unloaded_module_.time_date_stamp, 4157 unloaded_module_.size_of_image); 4158 identifier = identifier_string; 4159 break; 4160 } 4161 4162 case MD_OS_ANDROID: 4163 case MD_OS_LINUX: 4164 case MD_OS_MAC_OS_X: 4165 case MD_OS_IOS: 4166 case MD_OS_SOLARIS: 4167 case MD_OS_NACL: 4168 case MD_OS_PS3: { 4169 // TODO(mmentovai): support uuid extension if present, otherwise fall 4170 // back to version (from LC_ID_DYLIB?), otherwise fall back to something 4171 // else. 4172 identifier = "id"; 4173 break; 4174 } 4175 4176 default: { 4177 // Without knowing what OS generated the dump, we can't generate a good 4178 // identifier. Return an empty string, signalling failure. 4179 BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires known " 4180 << "platform, found " 4181 << HexString(raw_system_info->platform_id); 4182 break; 4183 } 4184 } 4185 4186 return identifier; 4187 } 4188 4189 string MinidumpUnloadedModule::debug_file() const { 4190 return ""; // No debug info provided with unloaded modules 4191 } 4192 4193 string MinidumpUnloadedModule::debug_identifier() const { 4194 return ""; // No debug info provided with unloaded modules 4195 } 4196 4197 string MinidumpUnloadedModule::version() const { 4198 return ""; // No version info provided with unloaded modules 4199 } 4200 4201 CodeModule* MinidumpUnloadedModule::Copy() const { 4202 return new BasicCodeModule(this); 4203 } 4204 4205 uint64_t MinidumpUnloadedModule::shrink_down_delta() const { 4206 return 0; 4207 } 4208 4209 void MinidumpUnloadedModule::SetShrinkDownDelta(uint64_t shrink_down_delta) { 4210 // Not implemented 4211 assert(false); 4212 } 4213 4214 bool MinidumpUnloadedModule::Read(uint32_t expected_size) { 4215 4216 delete name_; 4217 valid_ = false; 4218 4219 if (expected_size < sizeof(unloaded_module_)) { 4220 BPLOG(ERROR) << "MinidumpUnloadedModule expected size is less than size " 4221 << "of struct " << expected_size << " < " 4222 << sizeof(unloaded_module_); 4223 return false; 4224 } 4225 4226 if (!minidump_->ReadBytes(&unloaded_module_, sizeof(unloaded_module_))) { 4227 BPLOG(ERROR) << "MinidumpUnloadedModule cannot read module"; 4228 return false; 4229 } 4230 4231 if (expected_size > sizeof(unloaded_module_)) { 4232 uint32_t module_bytes_remaining = expected_size - sizeof(unloaded_module_); 4233 off_t pos = minidump_->Tell(); 4234 if (!minidump_->SeekSet(pos + module_bytes_remaining)) { 4235 BPLOG(ERROR) << "MinidumpUnloadedModule unable to seek to end of module"; 4236 return false; 4237 } 4238 } 4239 4240 if (minidump_->swap()) { 4241 Swap(&unloaded_module_.base_of_image); 4242 Swap(&unloaded_module_.size_of_image); 4243 Swap(&unloaded_module_.checksum); 4244 Swap(&unloaded_module_.time_date_stamp); 4245 Swap(&unloaded_module_.module_name_rva); 4246 } 4247 4248 // Check for base + size overflow or undersize. 4249 if (unloaded_module_.size_of_image == 0 || 4250 unloaded_module_.size_of_image > 4251 numeric_limits<uint64_t>::max() - unloaded_module_.base_of_image) { 4252 BPLOG(ERROR) << "MinidumpUnloadedModule has a module problem, " << 4253 HexString(unloaded_module_.base_of_image) << "+" << 4254 HexString(unloaded_module_.size_of_image); 4255 return false; 4256 } 4257 4258 4259 module_valid_ = true; 4260 return true; 4261 } 4262 4263 bool MinidumpUnloadedModule::ReadAuxiliaryData() { 4264 if (!module_valid_) { 4265 BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for ReadAuxiliaryData"; 4266 return false; 4267 } 4268 4269 // Each module must have a name. 4270 name_ = minidump_->ReadString(unloaded_module_.module_name_rva); 4271 if (!name_) { 4272 BPLOG(ERROR) << "MinidumpUnloadedModule could not read name"; 4273 return false; 4274 } 4275 4276 // At this point, we have enough info for the module to be valid. 4277 valid_ = true; 4278 return true; 4279 } 4280 4281 // 4282 // MinidumpUnloadedModuleList 4283 // 4284 4285 4286 uint32_t MinidumpUnloadedModuleList::max_modules_ = 2048; 4287 4288 4289 MinidumpUnloadedModuleList::MinidumpUnloadedModuleList(Minidump* minidump) 4290 : MinidumpStream(minidump), 4291 range_map_(new RangeMap<uint64_t, unsigned int>()), 4292 unloaded_modules_(NULL), 4293 module_count_(0) { 4294 range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower); 4295 } 4296 4297 MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() { 4298 delete range_map_; 4299 delete unloaded_modules_; 4300 } 4301 4302 4303 bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) { 4304 range_map_->Clear(); 4305 delete unloaded_modules_; 4306 unloaded_modules_ = NULL; 4307 module_count_ = 0; 4308 4309 valid_ = false; 4310 4311 uint32_t size_of_header; 4312 if (!minidump_->ReadBytes(&size_of_header, sizeof(size_of_header))) { 4313 BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read header size"; 4314 return false; 4315 } 4316 4317 uint32_t size_of_entry; 4318 if (!minidump_->ReadBytes(&size_of_entry, sizeof(size_of_entry))) { 4319 BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read entry size"; 4320 return false; 4321 } 4322 4323 uint32_t number_of_entries; 4324 if (!minidump_->ReadBytes(&number_of_entries, sizeof(number_of_entries))) { 4325 BPLOG(ERROR) << 4326 "MinidumpUnloadedModuleList could not read number of entries"; 4327 return false; 4328 } 4329 4330 if (minidump_->swap()) { 4331 Swap(&size_of_header); 4332 Swap(&size_of_entry); 4333 Swap(&number_of_entries); 4334 } 4335 4336 uint32_t header_bytes_remaining = size_of_header - sizeof(size_of_header) - 4337 sizeof(size_of_entry) - sizeof(number_of_entries); 4338 if (header_bytes_remaining) { 4339 off_t pos = minidump_->Tell(); 4340 if (!minidump_->SeekSet(pos + header_bytes_remaining)) { 4341 BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read header sized " 4342 << size_of_header; 4343 return false; 4344 } 4345 } 4346 4347 if (expected_size != size_of_header + (size_of_entry * number_of_entries)) { 4348 BPLOG(ERROR) << "MinidumpUnloadedModuleList expected_size mismatch " << 4349 expected_size << " != " << size_of_header << " + (" << 4350 size_of_entry << " * " << number_of_entries << ")"; 4351 return false; 4352 } 4353 4354 if (number_of_entries > max_modules_) { 4355 BPLOG(ERROR) << "MinidumpUnloadedModuleList count " << 4356 number_of_entries << " exceeds maximum " << max_modules_; 4357 return false; 4358 } 4359 4360 if (number_of_entries != 0) { 4361 scoped_ptr<MinidumpUnloadedModules> modules( 4362 new MinidumpUnloadedModules(number_of_entries, 4363 MinidumpUnloadedModule(minidump_))); 4364 4365 for (unsigned int module_index = 0; 4366 module_index < number_of_entries; 4367 ++module_index) { 4368 MinidumpUnloadedModule* module = &(*modules)[module_index]; 4369 4370 if (!module->Read(size_of_entry)) { 4371 BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read module " << 4372 module_index << "/" << number_of_entries; 4373 return false; 4374 } 4375 } 4376 4377 for (unsigned int module_index = 0; 4378 module_index < number_of_entries; 4379 ++module_index) { 4380 MinidumpUnloadedModule* module = &(*modules)[module_index]; 4381 4382 if (!module->ReadAuxiliaryData()) { 4383 BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read required " 4384 "module auxiliary data for module " << 4385 module_index << "/" << number_of_entries; 4386 return false; 4387 } 4388 4389 uint64_t base_address = module->base_address(); 4390 uint64_t module_size = module->size(); 4391 4392 // Ignore any failures for conflicting address ranges 4393 range_map_->StoreRange(base_address, module_size, module_index); 4394 4395 } 4396 unloaded_modules_ = modules.release(); 4397 } 4398 4399 module_count_ = number_of_entries; 4400 valid_ = true; 4401 return true; 4402 } 4403 4404 const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetModuleForAddress( 4405 uint64_t address) const { 4406 if (!valid_) { 4407 BPLOG(ERROR) 4408 << "Invalid MinidumpUnloadedModuleList for GetModuleForAddress"; 4409 return NULL; 4410 } 4411 4412 unsigned int module_index; 4413 if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */, 4414 NULL /* delta */, NULL /* size */)) { 4415 BPLOG(INFO) << "MinidumpUnloadedModuleList has no module at " 4416 << HexString(address); 4417 return NULL; 4418 } 4419 4420 return GetModuleAtIndex(module_index); 4421 } 4422 4423 const MinidumpUnloadedModule* 4424 MinidumpUnloadedModuleList::GetMainModule() const { 4425 return NULL; 4426 } 4427 4428 const MinidumpUnloadedModule* 4429 MinidumpUnloadedModuleList::GetModuleAtSequence(unsigned int sequence) const { 4430 if (!valid_) { 4431 BPLOG(ERROR) 4432 << "Invalid MinidumpUnloadedModuleList for GetModuleAtSequence"; 4433 return NULL; 4434 } 4435 4436 if (sequence >= module_count_) { 4437 BPLOG(ERROR) << "MinidumpUnloadedModuleList sequence out of range: " 4438 << sequence << "/" << module_count_; 4439 return NULL; 4440 } 4441 4442 unsigned int module_index; 4443 if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, 4444 NULL /* base */, NULL /* delta */, 4445 NULL /* size */)) { 4446 BPLOG(ERROR) << "MinidumpUnloadedModuleList has no module at sequence " 4447 << sequence; 4448 return NULL; 4449 } 4450 4451 return GetModuleAtIndex(module_index); 4452 } 4453 4454 const MinidumpUnloadedModule* 4455 MinidumpUnloadedModuleList::GetModuleAtIndex( 4456 unsigned int index) const { 4457 if (!valid_) { 4458 BPLOG(ERROR) << "Invalid MinidumpUnloadedModuleList for GetModuleAtIndex"; 4459 return NULL; 4460 } 4461 4462 if (index >= module_count_) { 4463 BPLOG(ERROR) << "MinidumpUnloadedModuleList index out of range: " 4464 << index << "/" << module_count_; 4465 return NULL; 4466 } 4467 4468 return &(*unloaded_modules_)[index]; 4469 } 4470 4471 const CodeModules* MinidumpUnloadedModuleList::Copy() const { 4472 return new BasicCodeModules(this, range_map_->GetMergeStrategy()); 4473 } 4474 4475 vector<linked_ptr<const CodeModule>> 4476 MinidumpUnloadedModuleList::GetShrunkRangeModules() const { 4477 return vector<linked_ptr<const CodeModule> >(); 4478 } 4479 4480 4481 // 4482 // MinidumpMiscInfo 4483 // 4484 4485 4486 MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump) 4487 : MinidumpStream(minidump), 4488 misc_info_() { 4489 } 4490 4491 4492 bool MinidumpMiscInfo::Read(uint32_t expected_size) { 4493 valid_ = false; 4494 4495 size_t padding = 0; 4496 if (expected_size != MD_MISCINFO_SIZE && 4497 expected_size != MD_MISCINFO2_SIZE && 4498 expected_size != MD_MISCINFO3_SIZE && 4499 expected_size != MD_MISCINFO4_SIZE && 4500 expected_size != MD_MISCINFO5_SIZE) { 4501 if (expected_size > MD_MISCINFO5_SIZE) { 4502 // Only read the part of the misc info structure we know how to handle 4503 BPLOG(INFO) << "MinidumpMiscInfo size larger than expected " 4504 << expected_size << ", skipping over the unknown part"; 4505 padding = expected_size - MD_MISCINFO5_SIZE; 4506 expected_size = MD_MISCINFO5_SIZE; 4507 } else { 4508 BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size 4509 << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE 4510 << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE 4511 << ", " << MD_MISCINFO5_SIZE << ")"; 4512 return false; 4513 } 4514 } 4515 4516 if (!minidump_->ReadBytes(&misc_info_, expected_size)) { 4517 BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info"; 4518 return false; 4519 } 4520 4521 if (padding != 0) { 4522 off_t saved_position = minidump_->Tell(); 4523 if (saved_position == -1) { 4524 BPLOG(ERROR) << "MinidumpMiscInfo could not tell the current position"; 4525 return false; 4526 } 4527 4528 if (!minidump_->SeekSet(saved_position + static_cast<off_t>(padding))) { 4529 BPLOG(ERROR) << "MinidumpMiscInfo could not seek past the miscellaneous " 4530 << "info structure"; 4531 return false; 4532 } 4533 } 4534 4535 if (minidump_->swap()) { 4536 // Swap version 1 fields 4537 Swap(&misc_info_.size_of_info); 4538 Swap(&misc_info_.flags1); 4539 Swap(&misc_info_.process_id); 4540 Swap(&misc_info_.process_create_time); 4541 Swap(&misc_info_.process_user_time); 4542 Swap(&misc_info_.process_kernel_time); 4543 if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { 4544 // Swap version 2 fields 4545 Swap(&misc_info_.processor_max_mhz); 4546 Swap(&misc_info_.processor_current_mhz); 4547 Swap(&misc_info_.processor_mhz_limit); 4548 Swap(&misc_info_.processor_max_idle_state); 4549 Swap(&misc_info_.processor_current_idle_state); 4550 } 4551 if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { 4552 // Swap version 3 fields 4553 Swap(&misc_info_.process_integrity_level); 4554 Swap(&misc_info_.process_execute_flags); 4555 Swap(&misc_info_.protected_process); 4556 Swap(&misc_info_.time_zone_id); 4557 Swap(&misc_info_.time_zone); 4558 } 4559 if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { 4560 // Swap version 4 fields. 4561 // Do not swap UTF-16 strings. The swap is done as part of the 4562 // conversion to UTF-8 (code follows below). 4563 } 4564 if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { 4565 // Swap version 5 fields 4566 Swap(&misc_info_.xstate_data); 4567 Swap(&misc_info_.process_cookie); 4568 } 4569 } 4570 4571 if (expected_size + padding != misc_info_.size_of_info) { 4572 BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << 4573 expected_size << " != " << misc_info_.size_of_info; 4574 return false; 4575 } 4576 4577 // Convert UTF-16 strings 4578 if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { 4579 // Convert UTF-16 strings in version 3 fields 4580 ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name, 4581 sizeof(misc_info_.time_zone.standard_name), 4582 &standard_name_, minidump_->swap()); 4583 ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name, 4584 sizeof(misc_info_.time_zone.daylight_name), 4585 &daylight_name_, minidump_->swap()); 4586 } 4587 if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { 4588 // Convert UTF-16 strings in version 4 fields 4589 ConvertUTF16BufferToUTF8String(misc_info_.build_string, 4590 sizeof(misc_info_.build_string), 4591 &build_string_, minidump_->swap()); 4592 ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str, 4593 sizeof(misc_info_.dbg_bld_str), 4594 &dbg_bld_str_, minidump_->swap()); 4595 } 4596 4597 valid_ = true; 4598 return true; 4599 } 4600 4601 4602 void MinidumpMiscInfo::Print() { 4603 if (!valid_) { 4604 BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data"; 4605 return; 4606 } 4607 4608 printf("MDRawMiscInfo\n"); 4609 // Print version 1 fields 4610 printf(" size_of_info = %d\n", misc_info_.size_of_info); 4611 printf(" flags1 = 0x%x\n", misc_info_.flags1); 4612 printf(" process_id = "); 4613 PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID, 4614 kNumberFormatDecimal, misc_info_.process_id); 4615 if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) { 4616 printf(" process_create_time = 0x%x %s\n", 4617 misc_info_.process_create_time, 4618 TimeTToUTCString(misc_info_.process_create_time).c_str()); 4619 } else { 4620 printf(" process_create_time = (invalid)\n"); 4621 } 4622 printf(" process_user_time = "); 4623 PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, 4624 kNumberFormatDecimal, misc_info_.process_user_time); 4625 printf(" process_kernel_time = "); 4626 PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, 4627 kNumberFormatDecimal, misc_info_.process_kernel_time); 4628 if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { 4629 // Print version 2 fields 4630 printf(" processor_max_mhz = "); 4631 PrintValueOrInvalid(misc_info_.flags1 & 4632 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, 4633 kNumberFormatDecimal, misc_info_.processor_max_mhz); 4634 printf(" processor_current_mhz = "); 4635 PrintValueOrInvalid(misc_info_.flags1 & 4636 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, 4637 kNumberFormatDecimal, misc_info_.processor_current_mhz); 4638 printf(" processor_mhz_limit = "); 4639 PrintValueOrInvalid(misc_info_.flags1 & 4640 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, 4641 kNumberFormatDecimal, misc_info_.processor_mhz_limit); 4642 printf(" processor_max_idle_state = "); 4643 PrintValueOrInvalid(misc_info_.flags1 & 4644 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, 4645 kNumberFormatDecimal, 4646 misc_info_.processor_max_idle_state); 4647 printf(" processor_current_idle_state = "); 4648 PrintValueOrInvalid(misc_info_.flags1 & 4649 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, 4650 kNumberFormatDecimal, 4651 misc_info_.processor_current_idle_state); 4652 } 4653 if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { 4654 // Print version 3 fields 4655 printf(" process_integrity_level = "); 4656 PrintValueOrInvalid(misc_info_.flags1 & 4657 MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY, 4658 kNumberFormatHexadecimal, 4659 misc_info_.process_integrity_level); 4660 printf(" process_execute_flags = "); 4661 PrintValueOrInvalid(misc_info_.flags1 & 4662 MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS, 4663 kNumberFormatHexadecimal, 4664 misc_info_.process_execute_flags); 4665 printf(" protected_process = "); 4666 PrintValueOrInvalid(misc_info_.flags1 & 4667 MD_MISCINFO_FLAGS1_PROTECTED_PROCESS, 4668 kNumberFormatDecimal, misc_info_.protected_process); 4669 printf(" time_zone_id = "); 4670 PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE, 4671 kNumberFormatDecimal, misc_info_.time_zone_id); 4672 if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) { 4673 printf(" time_zone.bias = %d\n", 4674 misc_info_.time_zone.bias); 4675 printf(" time_zone.standard_name = %s\n", standard_name_.c_str()); 4676 printf(" time_zone.standard_date = " 4677 "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", 4678 misc_info_.time_zone.standard_date.year, 4679 misc_info_.time_zone.standard_date.month, 4680 misc_info_.time_zone.standard_date.day, 4681 misc_info_.time_zone.standard_date.day_of_week, 4682 misc_info_.time_zone.standard_date.hour, 4683 misc_info_.time_zone.standard_date.minute, 4684 misc_info_.time_zone.standard_date.second, 4685 misc_info_.time_zone.standard_date.milliseconds); 4686 printf(" time_zone.standard_bias = %d\n", 4687 misc_info_.time_zone.standard_bias); 4688 printf(" time_zone.daylight_name = %s\n", daylight_name_.c_str()); 4689 printf(" time_zone.daylight_date = " 4690 "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", 4691 misc_info_.time_zone.daylight_date.year, 4692 misc_info_.time_zone.daylight_date.month, 4693 misc_info_.time_zone.daylight_date.day, 4694 misc_info_.time_zone.daylight_date.day_of_week, 4695 misc_info_.time_zone.daylight_date.hour, 4696 misc_info_.time_zone.daylight_date.minute, 4697 misc_info_.time_zone.daylight_date.second, 4698 misc_info_.time_zone.daylight_date.milliseconds); 4699 printf(" time_zone.daylight_bias = %d\n", 4700 misc_info_.time_zone.daylight_bias); 4701 } else { 4702 printf(" time_zone.bias = (invalid)\n"); 4703 printf(" time_zone.standard_name = (invalid)\n"); 4704 printf(" time_zone.standard_date = (invalid)\n"); 4705 printf(" time_zone.standard_bias = (invalid)\n"); 4706 printf(" time_zone.daylight_name = (invalid)\n"); 4707 printf(" time_zone.daylight_date = (invalid)\n"); 4708 printf(" time_zone.daylight_bias = (invalid)\n"); 4709 } 4710 } 4711 if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { 4712 // Print version 4 fields 4713 if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) { 4714 printf(" build_string = %s\n", build_string_.c_str()); 4715 printf(" dbg_bld_str = %s\n", dbg_bld_str_.c_str()); 4716 } else { 4717 printf(" build_string = (invalid)\n"); 4718 printf(" dbg_bld_str = (invalid)\n"); 4719 } 4720 } 4721 if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { 4722 // Print version 5 fields 4723 if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_COOKIE) { 4724 printf(" xstate_data.size_of_info = %d\n", 4725 misc_info_.xstate_data.size_of_info); 4726 printf(" xstate_data.context_size = %d\n", 4727 misc_info_.xstate_data.context_size); 4728 printf(" xstate_data.enabled_features = 0x%" PRIx64 "\n", 4729 misc_info_.xstate_data.enabled_features); 4730 for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) { 4731 if ((misc_info_.xstate_data.enabled_features >> i) & 1) { 4732 printf(" xstate_data.features[%02zu] = { %d, %d }\n", i, 4733 misc_info_.xstate_data.features[i].offset, 4734 misc_info_.xstate_data.features[i].size); 4735 } 4736 } 4737 if (misc_info_.xstate_data.enabled_features == 0) { 4738 printf(" xstate_data.features[] = (empty)\n"); 4739 } 4740 printf(" process_cookie = %d\n", 4741 misc_info_.process_cookie); 4742 } else { 4743 printf(" xstate_data.size_of_info = (invalid)\n"); 4744 printf(" xstate_data.context_size = (invalid)\n"); 4745 printf(" xstate_data.enabled_features = (invalid)\n"); 4746 printf(" xstate_data.features[] = (invalid)\n"); 4747 printf(" process_cookie = (invalid)\n"); 4748 } 4749 } 4750 printf("\n"); 4751 } 4752 4753 4754 // 4755 // MinidumpBreakpadInfo 4756 // 4757 4758 4759 MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump) 4760 : MinidumpStream(minidump), 4761 breakpad_info_() { 4762 } 4763 4764 4765 bool MinidumpBreakpadInfo::Read(uint32_t expected_size) { 4766 valid_ = false; 4767 4768 if (expected_size != sizeof(breakpad_info_)) { 4769 BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size << 4770 " != " << sizeof(breakpad_info_); 4771 return false; 4772 } 4773 4774 if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) { 4775 BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info"; 4776 return false; 4777 } 4778 4779 if (minidump_->swap()) { 4780 Swap(&breakpad_info_.validity); 4781 Swap(&breakpad_info_.dump_thread_id); 4782 Swap(&breakpad_info_.requesting_thread_id); 4783 } 4784 4785 valid_ = true; 4786 return true; 4787 } 4788 4789 4790 bool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t* thread_id) const { 4791 BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID " 4792 "requires |thread_id|"; 4793 assert(thread_id); 4794 *thread_id = 0; 4795 4796 if (!valid_) { 4797 BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID"; 4798 return false; 4799 } 4800 4801 if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) { 4802 BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread"; 4803 return false; 4804 } 4805 4806 *thread_id = breakpad_info_.dump_thread_id; 4807 return true; 4808 } 4809 4810 4811 bool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t* thread_id) 4812 const { 4813 BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID " 4814 "requires |thread_id|"; 4815 assert(thread_id); 4816 *thread_id = 0; 4817 4818 if (!thread_id || !valid_) { 4819 BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID"; 4820 return false; 4821 } 4822 4823 if (!(breakpad_info_.validity & 4824 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) { 4825 BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread"; 4826 return false; 4827 } 4828 4829 *thread_id = breakpad_info_.requesting_thread_id; 4830 return true; 4831 } 4832 4833 4834 void MinidumpBreakpadInfo::Print() { 4835 if (!valid_) { 4836 BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data"; 4837 return; 4838 } 4839 4840 printf("MDRawBreakpadInfo\n"); 4841 printf(" validity = 0x%x\n", breakpad_info_.validity); 4842 printf(" dump_thread_id = "); 4843 PrintValueOrInvalid(breakpad_info_.validity & 4844 MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID, 4845 kNumberFormatHexadecimal, breakpad_info_.dump_thread_id); 4846 printf(" requesting_thread_id = "); 4847 PrintValueOrInvalid(breakpad_info_.validity & 4848 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID, 4849 kNumberFormatHexadecimal, 4850 breakpad_info_.requesting_thread_id); 4851 4852 printf("\n"); 4853 } 4854 4855 4856 // 4857 // MinidumpMemoryInfo 4858 // 4859 4860 4861 MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump) 4862 : MinidumpObject(minidump), 4863 memory_info_() { 4864 } 4865 4866 4867 bool MinidumpMemoryInfo::IsExecutable() const { 4868 uint32_t protection = 4869 memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; 4870 return protection == MD_MEMORY_PROTECT_EXECUTE || 4871 protection == MD_MEMORY_PROTECT_EXECUTE_READ || 4872 protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE; 4873 } 4874 4875 4876 bool MinidumpMemoryInfo::IsWritable() const { 4877 uint32_t protection = 4878 memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; 4879 return protection == MD_MEMORY_PROTECT_READWRITE || 4880 protection == MD_MEMORY_PROTECT_WRITECOPY || 4881 protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE || 4882 protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY; 4883 } 4884 4885 4886 bool MinidumpMemoryInfo::Read() { 4887 valid_ = false; 4888 4889 if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) { 4890 BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info"; 4891 return false; 4892 } 4893 4894 if (minidump_->swap()) { 4895 Swap(&memory_info_.base_address); 4896 Swap(&memory_info_.allocation_base); 4897 Swap(&memory_info_.allocation_protection); 4898 Swap(&memory_info_.region_size); 4899 Swap(&memory_info_.state); 4900 Swap(&memory_info_.protection); 4901 Swap(&memory_info_.type); 4902 } 4903 4904 // Check for base + size overflow or undersize. 4905 if (memory_info_.region_size == 0 || 4906 memory_info_.region_size > numeric_limits<uint64_t>::max() - 4907 memory_info_.base_address) { 4908 BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " << 4909 HexString(memory_info_.base_address) << "+" << 4910 HexString(memory_info_.region_size); 4911 return false; 4912 } 4913 4914 valid_ = true; 4915 return true; 4916 } 4917 4918 4919 void MinidumpMemoryInfo::Print() { 4920 if (!valid_) { 4921 BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data"; 4922 return; 4923 } 4924 4925 printf("MDRawMemoryInfo\n"); 4926 printf(" base_address = 0x%" PRIx64 "\n", 4927 memory_info_.base_address); 4928 printf(" allocation_base = 0x%" PRIx64 "\n", 4929 memory_info_.allocation_base); 4930 printf(" allocation_protection = 0x%x\n", 4931 memory_info_.allocation_protection); 4932 printf(" region_size = 0x%" PRIx64 "\n", memory_info_.region_size); 4933 printf(" state = 0x%x\n", memory_info_.state); 4934 printf(" protection = 0x%x\n", memory_info_.protection); 4935 printf(" type = 0x%x\n", memory_info_.type); 4936 } 4937 4938 4939 // 4940 // MinidumpMemoryInfoList 4941 // 4942 4943 4944 MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump) 4945 : MinidumpStream(minidump), 4946 range_map_(new RangeMap<uint64_t, unsigned int>()), 4947 infos_(NULL), 4948 info_count_(0) { 4949 } 4950 4951 4952 MinidumpMemoryInfoList::~MinidumpMemoryInfoList() { 4953 delete range_map_; 4954 delete infos_; 4955 } 4956 4957 4958 bool MinidumpMemoryInfoList::Read(uint32_t expected_size) { 4959 // Invalidate cached data. 4960 delete infos_; 4961 infos_ = NULL; 4962 range_map_->Clear(); 4963 info_count_ = 0; 4964 4965 valid_ = false; 4966 4967 MDRawMemoryInfoList header; 4968 if (expected_size < sizeof(MDRawMemoryInfoList)) { 4969 BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " << 4970 expected_size << " < " << sizeof(MDRawMemoryInfoList); 4971 return false; 4972 } 4973 if (!minidump_->ReadBytes(&header, sizeof(header))) { 4974 BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header"; 4975 return false; 4976 } 4977 4978 if (minidump_->swap()) { 4979 Swap(&header.size_of_header); 4980 Swap(&header.size_of_entry); 4981 Swap(&header.number_of_entries); 4982 } 4983 4984 // Sanity check that the header is the expected size. 4985 // TODO(ted): could possibly handle this more gracefully, assuming 4986 // that future versions of the structs would be backwards-compatible. 4987 if (header.size_of_header != sizeof(MDRawMemoryInfoList)) { 4988 BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " << 4989 header.size_of_header << " != " << 4990 sizeof(MDRawMemoryInfoList); 4991 return false; 4992 } 4993 4994 // Sanity check that the entries are the expected size. 4995 if (header.size_of_entry != sizeof(MDRawMemoryInfo)) { 4996 BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " << 4997 header.size_of_entry << " != " << 4998 sizeof(MDRawMemoryInfo); 4999 return false; 5000 } 5001 5002 if (header.number_of_entries > 5003 numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) { 5004 BPLOG(ERROR) << "MinidumpMemoryInfoList info count " << 5005 header.number_of_entries << 5006 " would cause multiplication overflow"; 5007 return false; 5008 } 5009 5010 if (expected_size != sizeof(MDRawMemoryInfoList) + 5011 header.number_of_entries * sizeof(MDRawMemoryInfo)) { 5012 BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size << 5013 " != " << sizeof(MDRawMemoryInfoList) + 5014 header.number_of_entries * sizeof(MDRawMemoryInfo); 5015 return false; 5016 } 5017 5018 // Check for data loss when converting header.number_of_entries from 5019 // uint64_t into MinidumpMemoryInfos::size_type (uint32_t) 5020 MinidumpMemoryInfos::size_type header_number_of_entries = 5021 static_cast<unsigned int>(header.number_of_entries); 5022 if (static_cast<uint64_t>(header_number_of_entries) != 5023 header.number_of_entries) { 5024 BPLOG(ERROR) << "Data loss detected when converting " 5025 "the header's number_of_entries"; 5026 return false; 5027 } 5028 5029 if (header.number_of_entries != 0) { 5030 scoped_ptr<MinidumpMemoryInfos> infos( 5031 new MinidumpMemoryInfos(header_number_of_entries, 5032 MinidumpMemoryInfo(minidump_))); 5033 5034 for (unsigned int index = 0; 5035 index < header.number_of_entries; 5036 ++index) { 5037 MinidumpMemoryInfo* info = &(*infos)[index]; 5038 5039 // Assume that the file offset is correct after the last read. 5040 if (!info->Read()) { 5041 BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " << 5042 index << "/" << header.number_of_entries; 5043 return false; 5044 } 5045 5046 uint64_t base_address = info->GetBase(); 5047 uint64_t region_size = info->GetSize(); 5048 5049 if (!range_map_->StoreRange(base_address, region_size, index)) { 5050 BPLOG(ERROR) << "MinidumpMemoryInfoList could not store" 5051 " memory region " << 5052 index << "/" << header.number_of_entries << ", " << 5053 HexString(base_address) << "+" << 5054 HexString(region_size); 5055 return false; 5056 } 5057 } 5058 5059 infos_ = infos.release(); 5060 } 5061 5062 info_count_ = static_cast<uint32_t>(header_number_of_entries); 5063 5064 valid_ = true; 5065 return true; 5066 } 5067 5068 5069 const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex( 5070 unsigned int index) const { 5071 if (!valid_) { 5072 BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex"; 5073 return NULL; 5074 } 5075 5076 if (index >= info_count_) { 5077 BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " << 5078 index << "/" << info_count_; 5079 return NULL; 5080 } 5081 5082 return &(*infos_)[index]; 5083 } 5084 5085 5086 const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress( 5087 uint64_t address) const { 5088 if (!valid_) { 5089 BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for" 5090 " GetMemoryInfoForAddress"; 5091 return NULL; 5092 } 5093 5094 unsigned int info_index; 5095 if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */, 5096 NULL /* delta */, NULL /* size */)) { 5097 BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " << 5098 HexString(address); 5099 return NULL; 5100 } 5101 5102 return GetMemoryInfoAtIndex(info_index); 5103 } 5104 5105 5106 void MinidumpMemoryInfoList::Print() { 5107 if (!valid_) { 5108 BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data"; 5109 return; 5110 } 5111 5112 printf("MinidumpMemoryInfoList\n"); 5113 printf(" info_count = %d\n", info_count_); 5114 printf("\n"); 5115 5116 for (unsigned int info_index = 0; 5117 info_index < info_count_; 5118 ++info_index) { 5119 printf("info[%d]\n", info_index); 5120 (*infos_)[info_index].Print(); 5121 printf("\n"); 5122 } 5123 } 5124 5125 // 5126 // MinidumpLinuxMaps 5127 // 5128 5129 MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump* minidump) 5130 : MinidumpObject(minidump) { 5131 } 5132 5133 void MinidumpLinuxMaps::Print() const { 5134 if (!valid_) { 5135 BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data"; 5136 return; 5137 } 5138 std::cout << region_.line << std::endl; 5139 } 5140 5141 // 5142 // MinidumpLinuxMapsList 5143 // 5144 5145 MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump* minidump) 5146 : MinidumpStream(minidump), 5147 maps_(NULL), 5148 maps_count_(0) { 5149 } 5150 5151 MinidumpLinuxMapsList::~MinidumpLinuxMapsList() { 5152 if (maps_) { 5153 for (unsigned int i = 0; i < maps_->size(); i++) { 5154 delete (*maps_)[i]; 5155 } 5156 delete maps_; 5157 } 5158 } 5159 5160 const MinidumpLinuxMaps* MinidumpLinuxMapsList::GetLinuxMapsForAddress( 5161 uint64_t address) const { 5162 if (!valid_ || (maps_ == NULL)) { 5163 BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress"; 5164 return NULL; 5165 } 5166 5167 // Search every memory mapping. 5168 for (unsigned int index = 0; index < maps_count_; index++) { 5169 // Check if address is within bounds of the current memory region. 5170 if ((*maps_)[index]->GetBase() <= address && 5171 (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) { 5172 return (*maps_)[index]; 5173 } 5174 } 5175 5176 // No mapping encloses the memory address. 5177 BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at " 5178 << HexString(address); 5179 return NULL; 5180 } 5181 5182 const MinidumpLinuxMaps* MinidumpLinuxMapsList::GetLinuxMapsAtIndex( 5183 unsigned int index) const { 5184 if (!valid_ || (maps_ == NULL)) { 5185 BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex"; 5186 return NULL; 5187 } 5188 5189 // Index out of bounds. 5190 if (index >= maps_count_ || (maps_ == NULL)) { 5191 BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: " 5192 << index 5193 << "/" 5194 << maps_count_; 5195 return NULL; 5196 } 5197 return (*maps_)[index]; 5198 } 5199 5200 bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { 5201 // Invalidate cached data. 5202 if (maps_) { 5203 for (unsigned int i = 0; i < maps_->size(); i++) { 5204 delete (*maps_)[i]; 5205 } 5206 delete maps_; 5207 } 5208 maps_ = NULL; 5209 maps_count_ = 0; 5210 5211 valid_ = false; 5212 5213 // Load and check expected stream length. 5214 uint32_t length = 0; 5215 if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) { 5216 BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found"; 5217 return false; 5218 } 5219 if (expected_size != length) { 5220 BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: " 5221 << expected_size 5222 << " != " 5223 << length; 5224 return false; 5225 } 5226 5227 // Create a vector to read stream data. The vector needs to have 5228 // at least enough capacity to read all the data. 5229 vector<char> mapping_bytes(length); 5230 if (!minidump_->ReadBytes(&mapping_bytes[0], length)) { 5231 BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes"; 5232 return false; 5233 } 5234 string map_string(mapping_bytes.begin(), mapping_bytes.end()); 5235 vector<MappedMemoryRegion> all_regions; 5236 5237 // Parse string into mapping data. 5238 if (!ParseProcMaps(map_string, &all_regions)) { 5239 return false; 5240 } 5241 5242 scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings()); 5243 5244 // Push mapping data into wrapper classes. 5245 for (size_t i = 0; i < all_regions.size(); i++) { 5246 scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_)); 5247 ele->region_ = all_regions[i]; 5248 ele->valid_ = true; 5249 maps->push_back(ele.release()); 5250 } 5251 5252 // Set instance variables. 5253 maps_ = maps.release(); 5254 maps_count_ = static_cast<uint32_t>(maps_->size()); 5255 valid_ = true; 5256 return true; 5257 } 5258 5259 void MinidumpLinuxMapsList::Print() const { 5260 if (!valid_ || (maps_ == NULL)) { 5261 BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data"; 5262 return; 5263 } 5264 for (size_t i = 0; i < maps_->size(); i++) { 5265 (*maps_)[i]->Print(); 5266 } 5267 } 5268 5269 // 5270 // MinidumpCrashpadInfo 5271 // 5272 5273 5274 MinidumpCrashpadInfo::MinidumpCrashpadInfo(Minidump* minidump) 5275 : MinidumpStream(minidump), 5276 crashpad_info_(), 5277 module_crashpad_info_links_(), 5278 module_crashpad_info_(), 5279 module_crashpad_info_list_annotations_(), 5280 module_crashpad_info_simple_annotations_(), 5281 module_crashpad_info_annotation_objects_(), 5282 simple_annotations_() { 5283 } 5284 5285 5286 bool MinidumpCrashpadInfo::Read(uint32_t expected_size) { 5287 valid_ = false; 5288 5289 // Support old minidumps that do not implement newer crashpad_info_ 5290 // fields, currently limited to the address mask. 5291 static_assert(sizeof(crashpad_info_) == 64, 5292 "Updated ::Read for new crashpad_info field."); 5293 5294 constexpr size_t crashpad_info_min_size = 5295 offsetof(decltype(crashpad_info_), reserved); 5296 if (expected_size < crashpad_info_min_size) { 5297 BPLOG(ERROR) << "MinidumpCrashpadInfo size mismatch, " << expected_size 5298 << " < " << crashpad_info_min_size; 5299 return false; 5300 } 5301 5302 if (!minidump_->ReadBytes(&crashpad_info_, crashpad_info_min_size)) { 5303 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad info"; 5304 return false; 5305 } 5306 expected_size -= crashpad_info_min_size; 5307 5308 // Read `reserved` if available. 5309 size_t crashpad_reserved_size = sizeof(crashpad_info_.reserved); 5310 if (expected_size >= crashpad_reserved_size) { 5311 if (!minidump_->ReadBytes( 5312 &crashpad_info_.reserved, 5313 crashpad_reserved_size)) { 5314 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read reserved"; 5315 return false; 5316 } 5317 expected_size -= crashpad_reserved_size; 5318 } else { 5319 crashpad_info_.reserved = 0; 5320 } 5321 5322 // Read `address_mask` if available. 5323 size_t crashpad_address_mask_size = sizeof(crashpad_info_.address_mask); 5324 if (expected_size >= crashpad_address_mask_size) { 5325 if (!minidump_->ReadBytes( 5326 &crashpad_info_.address_mask, 5327 crashpad_address_mask_size)) { 5328 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read address mask"; 5329 return false; 5330 } 5331 expected_size -= crashpad_address_mask_size; 5332 } else { 5333 crashpad_info_.address_mask = 0; 5334 } 5335 5336 if (minidump_->swap()) { 5337 Swap(&crashpad_info_.version); 5338 Swap(&crashpad_info_.report_id); 5339 Swap(&crashpad_info_.client_id); 5340 Swap(&crashpad_info_.simple_annotations); 5341 Swap(&crashpad_info_.module_list); 5342 Swap(&crashpad_info_.reserved); 5343 Swap(&crashpad_info_.address_mask); 5344 } 5345 5346 if (crashpad_info_.simple_annotations.data_size) { 5347 if (!minidump_->ReadSimpleStringDictionary( 5348 crashpad_info_.simple_annotations.rva, 5349 &simple_annotations_)) { 5350 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read simple_annotations"; 5351 return false; 5352 } 5353 } 5354 5355 if (crashpad_info_.module_list.data_size) { 5356 if (!minidump_->SeekSet(crashpad_info_.module_list.rva)) { 5357 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot seek to module_list"; 5358 return false; 5359 } 5360 5361 uint32_t count; 5362 if (!minidump_->ReadBytes(&count, sizeof(count))) { 5363 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read module_list count"; 5364 return false; 5365 } 5366 5367 if (minidump_->swap()) { 5368 Swap(&count); 5369 } 5370 5371 scoped_array<MDRawModuleCrashpadInfoLink> module_crashpad_info_links( 5372 new MDRawModuleCrashpadInfoLink[count]); 5373 5374 // Read the entire array in one fell swoop, instead of reading one entry 5375 // at a time in the loop. 5376 if (!minidump_->ReadBytes( 5377 &module_crashpad_info_links[0], 5378 sizeof(MDRawModuleCrashpadInfoLink) * count)) { 5379 BPLOG(ERROR) 5380 << "MinidumpCrashpadInfo could not read Crashpad module links"; 5381 return false; 5382 } 5383 5384 for (uint32_t index = 0; index < count; ++index) { 5385 if (minidump_->swap()) { 5386 Swap(&module_crashpad_info_links[index].minidump_module_list_index); 5387 Swap(&module_crashpad_info_links[index].location); 5388 } 5389 5390 if (!minidump_->SeekSet(module_crashpad_info_links[index].location.rva)) { 5391 BPLOG(ERROR) 5392 << "MinidumpCrashpadInfo cannot seek to Crashpad module info"; 5393 return false; 5394 } 5395 5396 MDRawModuleCrashpadInfo module_crashpad_info; 5397 if (!minidump_->ReadBytes(&module_crashpad_info, 5398 sizeof(module_crashpad_info))) { 5399 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module info"; 5400 return false; 5401 } 5402 5403 if (minidump_->swap()) { 5404 Swap(&module_crashpad_info.version); 5405 Swap(&module_crashpad_info.list_annotations); 5406 Swap(&module_crashpad_info.simple_annotations); 5407 Swap(&module_crashpad_info.annotation_objects); 5408 } 5409 5410 std::vector<std::string> list_annotations; 5411 if (module_crashpad_info.list_annotations.data_size) { 5412 if (!minidump_->ReadStringList( 5413 module_crashpad_info.list_annotations.rva, 5414 &list_annotations)) { 5415 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module " 5416 "info list annotations"; 5417 return false; 5418 } 5419 } 5420 5421 std::map<std::string, std::string> simple_annotations; 5422 if (module_crashpad_info.simple_annotations.data_size) { 5423 if (!minidump_->ReadSimpleStringDictionary( 5424 module_crashpad_info.simple_annotations.rva, 5425 &simple_annotations)) { 5426 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module " 5427 "info simple annotations"; 5428 return false; 5429 } 5430 } 5431 5432 std::vector<MinidumpCrashpadInfo::AnnotationObject> annotation_objects; 5433 if (module_crashpad_info.annotation_objects.data_size) { 5434 if (!minidump_->ReadCrashpadAnnotationsList( 5435 module_crashpad_info.annotation_objects.rva, 5436 &annotation_objects)) { 5437 BPLOG(ERROR) 5438 << "MinidumpCrashpadInfo cannot read Crashpad annotations list"; 5439 return false; 5440 } 5441 } 5442 5443 module_crashpad_info_links_.push_back( 5444 module_crashpad_info_links[index].minidump_module_list_index); 5445 module_crashpad_info_.push_back(module_crashpad_info); 5446 module_crashpad_info_list_annotations_.push_back(list_annotations); 5447 module_crashpad_info_simple_annotations_.push_back(simple_annotations); 5448 module_crashpad_info_annotation_objects_.push_back(annotation_objects); 5449 } 5450 } 5451 5452 valid_ = true; 5453 return true; 5454 } 5455 5456 5457 void MinidumpCrashpadInfo::Print() { 5458 if (!valid_) { 5459 BPLOG(ERROR) << "MinidumpCrashpadInfo cannot print invalid data"; 5460 return; 5461 } 5462 5463 printf("MDRawCrashpadInfo\n"); 5464 printf(" version = %d\n", crashpad_info_.version); 5465 printf(" report_id = %s\n", 5466 MDGUIDToString(crashpad_info_.report_id).c_str()); 5467 printf(" client_id = %s\n", 5468 MDGUIDToString(crashpad_info_.client_id).c_str()); 5469 for (const auto& annot : simple_annotations_) { 5470 printf(" simple_annotations[\"%s\"] = %s\n", annot.first.c_str(), 5471 annot.second.c_str()); 5472 } 5473 for (uint32_t module_index = 0; 5474 module_index < module_crashpad_info_links_.size(); 5475 ++module_index) { 5476 printf(" module_list[%d].minidump_module_list_index = %d\n", 5477 module_index, module_crashpad_info_links_[module_index]); 5478 printf(" module_list[%d].version = %d\n", 5479 module_index, module_crashpad_info_[module_index].version); 5480 const auto& list_annots = 5481 module_crashpad_info_list_annotations_[module_index]; 5482 for (uint32_t annotation_index = 0; annotation_index < list_annots.size(); 5483 ++annotation_index) { 5484 printf(" module_list[%d].list_annotations[%d] = %s\n", module_index, 5485 annotation_index, list_annots[annotation_index].c_str()); 5486 } 5487 const auto& simple_annots = 5488 module_crashpad_info_simple_annotations_[module_index]; 5489 for (const auto& annot : simple_annots) { 5490 printf(" module_list[%d].simple_annotations[\"%s\"] = %s\n", 5491 module_index, annot.first.c_str(), annot.second.c_str()); 5492 } 5493 const auto& crashpad_annots = 5494 module_crashpad_info_annotation_objects_[module_index]; 5495 for (const AnnotationObject& annot : crashpad_annots) { 5496 std::string str_value; 5497 if (annot.type == 1) { 5498 // Value represents a C-style string. 5499 for (const uint8_t& v : annot.value) { 5500 str_value.append(1, static_cast<char>(v)); 5501 } 5502 } else { 5503 // Value represents something else. 5504 char buffer[3]; 5505 for (const uint8_t& v : annot.value) { 5506 snprintf(buffer, sizeof(buffer), "%02X", v); 5507 str_value.append(buffer); 5508 } 5509 } 5510 printf( 5511 " module_list[%d].crashpad_annotations[\"%s\"] (type = %u) = %s\n", 5512 module_index, annot.name.c_str(), annot.type, str_value.c_str()); 5513 } 5514 printf(" address_mask = %" PRIu64 "\n", crashpad_info_.address_mask); 5515 } 5516 5517 printf("\n"); 5518 } 5519 5520 5521 // 5522 // Minidump 5523 // 5524 5525 5526 uint32_t Minidump::max_streams_ = 128; 5527 unsigned int Minidump::max_string_length_ = 1024; 5528 5529 5530 Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width) 5531 : header_(), 5532 directory_(NULL), 5533 stream_map_(new MinidumpStreamMap()), 5534 path_(path), 5535 stream_(NULL), 5536 swap_(false), 5537 is_big_endian_(false), 5538 valid_(false), 5539 hexdump_(hexdump), 5540 hexdump_width_(hexdump_width) { 5541 } 5542 5543 Minidump::Minidump(istream& stream) 5544 : header_(), 5545 directory_(NULL), 5546 stream_map_(new MinidumpStreamMap()), 5547 path_(), 5548 stream_(&stream), 5549 swap_(false), 5550 is_big_endian_(false), 5551 valid_(false), 5552 hexdump_(false), 5553 hexdump_width_(0) { 5554 } 5555 5556 Minidump::~Minidump() { 5557 if (stream_) { 5558 BPLOG(INFO) << "Minidump closing minidump"; 5559 } 5560 if (!path_.empty()) { 5561 delete stream_; 5562 } 5563 delete directory_; 5564 delete stream_map_; 5565 } 5566 5567 5568 bool Minidump::Open() { 5569 if (stream_ != NULL) { 5570 BPLOG(INFO) << "Minidump reopening minidump " << path_; 5571 5572 // The file is already open. Seek to the beginning, which is the position 5573 // the file would be at if it were opened anew. 5574 return SeekSet(0); 5575 } 5576 5577 stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary); 5578 if (!stream_ || !stream_->good()) { 5579 string error_string; 5580 int error_code = ErrnoString(&error_string); 5581 BPLOG(ERROR) << "Minidump could not open minidump " << path_ << 5582 ", error " << error_code << ": " << error_string; 5583 return false; 5584 } 5585 5586 BPLOG(INFO) << "Minidump opened minidump " << path_; 5587 return true; 5588 } 5589 5590 bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t* context_cpu_flags) { 5591 // Initialize output parameters 5592 *context_cpu_flags = 0; 5593 5594 // Save the current stream position 5595 off_t saved_position = Tell(); 5596 if (saved_position == -1) { 5597 // Failed to save the current stream position. 5598 // Returns true because the current position of the stream is preserved. 5599 return true; 5600 } 5601 5602 const MDRawSystemInfo* system_info = 5603 GetSystemInfo() ? GetSystemInfo()->system_info() : NULL; 5604 5605 if (system_info != NULL) { 5606 switch (system_info->processor_architecture) { 5607 case MD_CPU_ARCHITECTURE_X86: 5608 *context_cpu_flags = MD_CONTEXT_X86; 5609 break; 5610 case MD_CPU_ARCHITECTURE_MIPS: 5611 *context_cpu_flags = MD_CONTEXT_MIPS; 5612 break; 5613 case MD_CPU_ARCHITECTURE_MIPS64: 5614 *context_cpu_flags = MD_CONTEXT_MIPS64; 5615 break; 5616 case MD_CPU_ARCHITECTURE_ALPHA: 5617 *context_cpu_flags = MD_CONTEXT_ALPHA; 5618 break; 5619 case MD_CPU_ARCHITECTURE_PPC: 5620 *context_cpu_flags = MD_CONTEXT_PPC; 5621 break; 5622 case MD_CPU_ARCHITECTURE_PPC64: 5623 *context_cpu_flags = MD_CONTEXT_PPC64; 5624 break; 5625 case MD_CPU_ARCHITECTURE_SHX: 5626 *context_cpu_flags = MD_CONTEXT_SHX; 5627 break; 5628 case MD_CPU_ARCHITECTURE_ARM: 5629 *context_cpu_flags = MD_CONTEXT_ARM; 5630 break; 5631 case MD_CPU_ARCHITECTURE_ARM64: 5632 *context_cpu_flags = MD_CONTEXT_ARM64; 5633 break; 5634 case MD_CPU_ARCHITECTURE_ARM64_OLD: 5635 *context_cpu_flags = MD_CONTEXT_ARM64_OLD; 5636 break; 5637 case MD_CPU_ARCHITECTURE_IA64: 5638 *context_cpu_flags = MD_CONTEXT_IA64; 5639 break; 5640 case MD_CPU_ARCHITECTURE_ALPHA64: 5641 *context_cpu_flags = 0; 5642 break; 5643 case MD_CPU_ARCHITECTURE_MSIL: 5644 *context_cpu_flags = 0; 5645 break; 5646 case MD_CPU_ARCHITECTURE_AMD64: 5647 *context_cpu_flags = MD_CONTEXT_AMD64; 5648 break; 5649 case MD_CPU_ARCHITECTURE_X86_WIN64: 5650 *context_cpu_flags = 0; 5651 break; 5652 case MD_CPU_ARCHITECTURE_SPARC: 5653 *context_cpu_flags = MD_CONTEXT_SPARC; 5654 break; 5655 case MD_CPU_ARCHITECTURE_RISCV: 5656 *context_cpu_flags = MD_CONTEXT_RISCV; 5657 break; 5658 case MD_CPU_ARCHITECTURE_RISCV64: 5659 *context_cpu_flags = MD_CONTEXT_RISCV64; 5660 break; 5661 case MD_CPU_ARCHITECTURE_UNKNOWN: 5662 *context_cpu_flags = 0; 5663 break; 5664 default: 5665 *context_cpu_flags = 0; 5666 break; 5667 } 5668 } 5669 5670 // Restore position and return 5671 return SeekSet(saved_position); 5672 } 5673 5674 5675 bool Minidump::Read() { 5676 // Invalidate cached data. 5677 delete directory_; 5678 directory_ = NULL; 5679 stream_map_->clear(); 5680 5681 valid_ = false; 5682 5683 if (!Open()) { 5684 BPLOG(ERROR) << "Minidump cannot open minidump"; 5685 return false; 5686 } 5687 5688 if (!ReadBytes(&header_, sizeof(MDRawHeader))) { 5689 BPLOG(ERROR) << "Minidump cannot read header"; 5690 return false; 5691 } 5692 5693 if (header_.signature != MD_HEADER_SIGNATURE) { 5694 // The file may be byte-swapped. Under the present architecture, these 5695 // classes don't know or need to know what CPU (or endianness) the 5696 // minidump was produced on in order to parse it. Use the signature as 5697 // a byte order marker. 5698 uint32_t signature_swapped = header_.signature; 5699 Swap(&signature_swapped); 5700 if (signature_swapped != MD_HEADER_SIGNATURE) { 5701 // This isn't a minidump or a byte-swapped minidump. 5702 BPLOG(ERROR) << "Minidump header signature mismatch: (" << 5703 HexString(header_.signature) << ", " << 5704 HexString(signature_swapped) << ") != " << 5705 HexString(MD_HEADER_SIGNATURE); 5706 return false; 5707 } 5708 swap_ = true; 5709 } else { 5710 // The file is not byte-swapped. Set swap_ false (it may have been true 5711 // if the object is being reused?) 5712 swap_ = false; 5713 } 5714 5715 #if defined(__BIG_ENDIAN__) || \ 5716 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 5717 is_big_endian_ = !swap_; 5718 #else 5719 is_big_endian_ = swap_; 5720 #endif 5721 5722 BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") << 5723 "byte-swapping minidump"; 5724 5725 if (swap_) { 5726 Swap(&header_.signature); 5727 Swap(&header_.version); 5728 Swap(&header_.stream_count); 5729 Swap(&header_.stream_directory_rva); 5730 Swap(&header_.checksum); 5731 Swap(&header_.time_date_stamp); 5732 Swap(&header_.flags); 5733 } 5734 5735 // Version check. The high 16 bits of header_.version contain something 5736 // else "implementation specific." 5737 if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) { 5738 BPLOG(ERROR) << "Minidump version mismatch: " << 5739 HexString(header_.version & 0x0000ffff) << " != " << 5740 HexString(MD_HEADER_VERSION); 5741 return false; 5742 } 5743 5744 if (!SeekSet(header_.stream_directory_rva)) { 5745 BPLOG(ERROR) << "Minidump cannot seek to stream directory"; 5746 return false; 5747 } 5748 5749 if (header_.stream_count > max_streams_) { 5750 BPLOG(ERROR) << "Minidump stream count " << header_.stream_count << 5751 " exceeds maximum " << max_streams_; 5752 return false; 5753 } 5754 5755 if (header_.stream_count != 0) { 5756 scoped_ptr<MinidumpDirectoryEntries> directory( 5757 new MinidumpDirectoryEntries(header_.stream_count)); 5758 5759 // Read the entire array in one fell swoop, instead of reading one entry 5760 // at a time in the loop. 5761 if (!ReadBytes(&(*directory)[0], 5762 sizeof(MDRawDirectory) * header_.stream_count)) { 5763 BPLOG(ERROR) << "Minidump cannot read stream directory"; 5764 return false; 5765 } 5766 5767 for (unsigned int stream_index = 0; 5768 stream_index < header_.stream_count; 5769 ++stream_index) { 5770 MDRawDirectory* directory_entry = &(*directory)[stream_index]; 5771 5772 if (swap_) { 5773 Swap(&directory_entry->stream_type); 5774 Swap(&directory_entry->location); 5775 } 5776 5777 // Initialize the stream_map_ map, which speeds locating a stream by 5778 // type. 5779 unsigned int stream_type = directory_entry->stream_type; 5780 switch (stream_type) { 5781 case MD_THREAD_LIST_STREAM: 5782 case MD_THREAD_NAME_LIST_STREAM: 5783 case MD_MODULE_LIST_STREAM: 5784 case MD_MEMORY_LIST_STREAM: 5785 case MD_EXCEPTION_STREAM: 5786 case MD_SYSTEM_INFO_STREAM: 5787 case MD_MISC_INFO_STREAM: 5788 case MD_BREAKPAD_INFO_STREAM: 5789 case MD_CRASHPAD_INFO_STREAM: { 5790 if (stream_map_->find(stream_type) != stream_map_->end()) { 5791 // Another stream with this type was already found. A minidump 5792 // file should contain at most one of each of these stream types. 5793 BPLOG(ERROR) << "Minidump found multiple streams of type " << 5794 stream_type << ", but can only deal with one"; 5795 return false; 5796 } 5797 BP_FALLTHROUGH; 5798 } 5799 5800 default: { 5801 // Overwrites for stream types other than those above, but it's 5802 // expected to be the user's burden in that case. 5803 (*stream_map_)[stream_type].stream_index = stream_index; 5804 } 5805 } 5806 } 5807 5808 directory_ = directory.release(); 5809 } 5810 5811 valid_ = true; 5812 return true; 5813 } 5814 5815 5816 MinidumpThreadList* Minidump::GetThreadList() { 5817 MinidumpThreadList* thread_list; 5818 return GetStream(&thread_list); 5819 } 5820 5821 MinidumpThreadNameList* Minidump::GetThreadNameList() { 5822 MinidumpThreadNameList* thread_name_list; 5823 return GetStream(&thread_name_list); 5824 } 5825 5826 MinidumpModuleList* Minidump::GetModuleList() { 5827 MinidumpModuleList* module_list; 5828 return GetStream(&module_list); 5829 } 5830 5831 5832 MinidumpMemoryList* Minidump::GetMemoryList() { 5833 MinidumpMemoryList* memory_list; 5834 return GetStream(&memory_list); 5835 } 5836 5837 5838 MinidumpException* Minidump::GetException() { 5839 MinidumpException* exception; 5840 return GetStream(&exception); 5841 } 5842 5843 MinidumpAssertion* Minidump::GetAssertion() { 5844 MinidumpAssertion* assertion; 5845 return GetStream(&assertion); 5846 } 5847 5848 5849 MinidumpSystemInfo* Minidump::GetSystemInfo() { 5850 MinidumpSystemInfo* system_info; 5851 return GetStream(&system_info); 5852 } 5853 5854 5855 MinidumpUnloadedModuleList* Minidump::GetUnloadedModuleList() { 5856 MinidumpUnloadedModuleList* unloaded_module_list; 5857 return GetStream(&unloaded_module_list); 5858 } 5859 5860 5861 MinidumpMiscInfo* Minidump::GetMiscInfo() { 5862 MinidumpMiscInfo* misc_info; 5863 return GetStream(&misc_info); 5864 } 5865 5866 5867 MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() { 5868 MinidumpBreakpadInfo* breakpad_info; 5869 return GetStream(&breakpad_info); 5870 } 5871 5872 MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() { 5873 MinidumpMemoryInfoList* memory_info_list; 5874 return GetStream(&memory_info_list); 5875 } 5876 5877 MinidumpLinuxMapsList* Minidump::GetLinuxMapsList() { 5878 MinidumpLinuxMapsList* linux_maps_list; 5879 return GetStream(&linux_maps_list); 5880 } 5881 5882 bool Minidump::IsAndroid() { 5883 MDOSPlatform platform; 5884 return GetPlatform(&platform) && platform == MD_OS_ANDROID; 5885 } 5886 5887 bool Minidump::GetPlatform(MDOSPlatform* platform) { 5888 // Save the current stream position 5889 off_t saved_position = Tell(); 5890 if (saved_position == -1) { 5891 return false; 5892 } 5893 const MDRawSystemInfo* system_info = 5894 GetSystemInfo() ? GetSystemInfo()->system_info() : NULL; 5895 5896 // Restore position and return 5897 if (!SeekSet(saved_position)) { 5898 BPLOG(ERROR) << "Couldn't seek back to saved position"; 5899 return false; 5900 } 5901 5902 if (!system_info) { 5903 return false; 5904 } 5905 *platform = static_cast<MDOSPlatform>(system_info->platform_id); 5906 return true; 5907 } 5908 5909 MinidumpCrashpadInfo* Minidump::GetCrashpadInfo() { 5910 MinidumpCrashpadInfo* crashpad_info; 5911 return GetStream(&crashpad_info); 5912 } 5913 5914 static const char* get_stream_name(uint32_t stream_type) { 5915 switch (stream_type) { 5916 case MD_UNUSED_STREAM: 5917 return "MD_UNUSED_STREAM"; 5918 case MD_RESERVED_STREAM_0: 5919 return "MD_RESERVED_STREAM_0"; 5920 case MD_RESERVED_STREAM_1: 5921 return "MD_RESERVED_STREAM_1"; 5922 case MD_THREAD_LIST_STREAM: 5923 return "MD_THREAD_LIST_STREAM"; 5924 case MD_THREAD_NAME_LIST_STREAM: 5925 return "MD_THREAD_NAME_LIST_STREAM"; 5926 case MD_MODULE_LIST_STREAM: 5927 return "MD_MODULE_LIST_STREAM"; 5928 case MD_MEMORY_LIST_STREAM: 5929 return "MD_MEMORY_LIST_STREAM"; 5930 case MD_EXCEPTION_STREAM: 5931 return "MD_EXCEPTION_STREAM"; 5932 case MD_SYSTEM_INFO_STREAM: 5933 return "MD_SYSTEM_INFO_STREAM"; 5934 case MD_THREAD_EX_LIST_STREAM: 5935 return "MD_THREAD_EX_LIST_STREAM"; 5936 case MD_MEMORY_64_LIST_STREAM: 5937 return "MD_MEMORY_64_LIST_STREAM"; 5938 case MD_COMMENT_STREAM_A: 5939 return "MD_COMMENT_STREAM_A"; 5940 case MD_COMMENT_STREAM_W: 5941 return "MD_COMMENT_STREAM_W"; 5942 case MD_HANDLE_DATA_STREAM: 5943 return "MD_HANDLE_DATA_STREAM"; 5944 case MD_FUNCTION_TABLE_STREAM: 5945 return "MD_FUNCTION_TABLE_STREAM"; 5946 case MD_UNLOADED_MODULE_LIST_STREAM: 5947 return "MD_UNLOADED_MODULE_LIST_STREAM"; 5948 case MD_MISC_INFO_STREAM: 5949 return "MD_MISC_INFO_STREAM"; 5950 case MD_MEMORY_INFO_LIST_STREAM: 5951 return "MD_MEMORY_INFO_LIST_STREAM"; 5952 case MD_THREAD_INFO_LIST_STREAM: 5953 return "MD_THREAD_INFO_LIST_STREAM"; 5954 case MD_HANDLE_OPERATION_LIST_STREAM: 5955 return "MD_HANDLE_OPERATION_LIST_STREAM"; 5956 case MD_TOKEN_STREAM: 5957 return "MD_TOKEN_STREAM"; 5958 case MD_JAVASCRIPT_DATA_STREAM: 5959 return "MD_JAVASCRIPT_DATA_STREAM"; 5960 case MD_SYSTEM_MEMORY_INFO_STREAM: 5961 return "MD_SYSTEM_MEMORY_INFO_STREAM"; 5962 case MD_PROCESS_VM_COUNTERS_STREAM: 5963 return "MD_PROCESS_VM_COUNTERS_STREAM"; 5964 case MD_LAST_RESERVED_STREAM: 5965 return "MD_LAST_RESERVED_STREAM"; 5966 case MD_BREAKPAD_INFO_STREAM: 5967 return "MD_BREAKPAD_INFO_STREAM"; 5968 case MD_ASSERTION_INFO_STREAM: 5969 return "MD_ASSERTION_INFO_STREAM"; 5970 case MD_LINUX_CPU_INFO: 5971 return "MD_LINUX_CPU_INFO"; 5972 case MD_LINUX_PROC_STATUS: 5973 return "MD_LINUX_PROC_STATUS"; 5974 case MD_LINUX_LSB_RELEASE: 5975 return "MD_LINUX_LSB_RELEASE"; 5976 case MD_LINUX_CMD_LINE: 5977 return "MD_LINUX_CMD_LINE"; 5978 case MD_LINUX_ENVIRON: 5979 return "MD_LINUX_ENVIRON"; 5980 case MD_LINUX_AUXV: 5981 return "MD_LINUX_AUXV"; 5982 case MD_LINUX_MAPS: 5983 return "MD_LINUX_MAPS"; 5984 case MD_LINUX_DSO_DEBUG: 5985 return "MD_LINUX_DSO_DEBUG"; 5986 case MD_CRASHPAD_INFO_STREAM: 5987 return "MD_CRASHPAD_INFO_STREAM"; 5988 default: 5989 return "unknown"; 5990 } 5991 } 5992 5993 void Minidump::Print() { 5994 if (!valid_) { 5995 BPLOG(ERROR) << "Minidump cannot print invalid data"; 5996 return; 5997 } 5998 5999 printf("MDRawHeader\n"); 6000 printf(" signature = 0x%x\n", header_.signature); 6001 printf(" version = 0x%x\n", header_.version); 6002 printf(" stream_count = %d\n", header_.stream_count); 6003 printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); 6004 printf(" checksum = 0x%x\n", header_.checksum); 6005 printf(" time_date_stamp = 0x%x %s\n", 6006 header_.time_date_stamp, 6007 TimeTToUTCString(header_.time_date_stamp).c_str()); 6008 printf(" flags = 0x%" PRIx64 "\n", header_.flags); 6009 printf("\n"); 6010 6011 for (unsigned int stream_index = 0; 6012 stream_index < header_.stream_count; 6013 ++stream_index) { 6014 MDRawDirectory* directory_entry = &(*directory_)[stream_index]; 6015 6016 printf("mDirectory[%d]\n", stream_index); 6017 printf("MDRawDirectory\n"); 6018 printf(" stream_type = 0x%x (%s)\n", directory_entry->stream_type, 6019 get_stream_name(directory_entry->stream_type)); 6020 printf(" location.data_size = %d\n", 6021 directory_entry->location.data_size); 6022 printf(" location.rva = 0x%x\n", directory_entry->location.rva); 6023 printf("\n"); 6024 } 6025 6026 printf("Streams:\n"); 6027 for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin(); 6028 iterator != stream_map_->end(); 6029 ++iterator) { 6030 uint32_t stream_type = iterator->first; 6031 const MinidumpStreamInfo& info = iterator->second; 6032 printf(" stream type 0x%x (%s) at index %d\n", stream_type, 6033 get_stream_name(stream_type), 6034 info.stream_index); 6035 } 6036 printf("\n"); 6037 } 6038 6039 6040 const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index) 6041 const { 6042 if (!valid_) { 6043 BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex"; 6044 return NULL; 6045 } 6046 6047 if (index >= header_.stream_count) { 6048 BPLOG(ERROR) << "Minidump stream directory index out of range: " << 6049 index << "/" << header_.stream_count; 6050 return NULL; 6051 } 6052 6053 return &(*directory_)[index]; 6054 } 6055 6056 6057 bool Minidump::ReadBytes(void* bytes, size_t count) { 6058 // Can't check valid_ because Read needs to call this method before 6059 // validity can be determined. 6060 if (!stream_) { 6061 return false; 6062 } 6063 stream_->read(static_cast<char*>(bytes), count); 6064 std::streamsize bytes_read = stream_->gcount(); 6065 if (bytes_read == -1) { 6066 string error_string; 6067 int error_code = ErrnoString(&error_string); 6068 BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string; 6069 return false; 6070 } 6071 6072 // Convert to size_t and check for data loss 6073 size_t bytes_read_converted = static_cast<size_t>(bytes_read); 6074 if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) { 6075 BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting " 6076 << bytes_read << " to " << bytes_read_converted; 6077 return false; 6078 } 6079 6080 if (bytes_read_converted != count) { 6081 BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count; 6082 return false; 6083 } 6084 6085 return true; 6086 } 6087 6088 6089 bool Minidump::SeekSet(off_t offset) { 6090 // Can't check valid_ because Read needs to call this method before 6091 // validity can be determined. 6092 if (!stream_) { 6093 return false; 6094 } 6095 stream_->seekg(offset, std::ios_base::beg); 6096 if (!stream_->good()) { 6097 string error_string; 6098 int error_code = ErrnoString(&error_string); 6099 BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string; 6100 return false; 6101 } 6102 return true; 6103 } 6104 6105 off_t Minidump::Tell() { 6106 if (!valid_ || !stream_) { 6107 return (off_t)-1; 6108 } 6109 6110 // Check for conversion data loss 6111 std::streamoff std_streamoff = stream_->tellg(); 6112 off_t rv = static_cast<off_t>(std_streamoff); 6113 if (static_cast<std::streamoff>(rv) == std_streamoff) { 6114 return rv; 6115 } else { 6116 BPLOG(ERROR) << "Data loss detected"; 6117 return (off_t)-1; 6118 } 6119 } 6120 6121 6122 string* Minidump::ReadString(off_t offset) { 6123 if (!valid_) { 6124 BPLOG(ERROR) << "Invalid Minidump for ReadString"; 6125 return NULL; 6126 } 6127 if (!SeekSet(offset)) { 6128 BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; 6129 return NULL; 6130 } 6131 6132 uint32_t bytes; 6133 if (!ReadBytes(&bytes, sizeof(bytes))) { 6134 BPLOG(ERROR) << "ReadString could not read string size at offset " << 6135 offset; 6136 return NULL; 6137 } 6138 if (swap_) 6139 Swap(&bytes); 6140 6141 if (bytes % 2 != 0) { 6142 BPLOG(ERROR) << "ReadString found odd-sized " << bytes << 6143 "-byte string at offset " << offset; 6144 return NULL; 6145 } 6146 unsigned int utf16_words = bytes / 2; 6147 6148 if (utf16_words > max_string_length_) { 6149 BPLOG(ERROR) << "ReadString string length " << utf16_words << 6150 " exceeds maximum " << max_string_length_ << 6151 " at offset " << offset; 6152 return NULL; 6153 } 6154 6155 vector<uint16_t> string_utf16(utf16_words); 6156 6157 if (utf16_words) { 6158 if (!ReadBytes(&string_utf16[0], bytes)) { 6159 BPLOG(ERROR) << "ReadString could not read " << bytes << 6160 "-byte string at offset " << offset; 6161 return NULL; 6162 } 6163 } 6164 6165 return UTF16ToUTF8(string_utf16, swap_); 6166 } 6167 6168 6169 bool Minidump::ReadUTF8String(off_t offset, string* string_utf8) { 6170 if (!valid_) { 6171 BPLOG(ERROR) << "Invalid Minidump for ReadString"; 6172 return false; 6173 } 6174 if (!SeekSet(offset)) { 6175 BPLOG(ERROR) << "ReadUTF8String could not seek to string at offset " 6176 << offset; 6177 return false; 6178 } 6179 6180 uint32_t bytes; 6181 if (!ReadBytes(&bytes, sizeof(bytes))) { 6182 BPLOG(ERROR) << "ReadUTF8String could not read string size at offset " << 6183 offset; 6184 return false; 6185 } 6186 6187 if (swap_) { 6188 Swap(&bytes); 6189 } 6190 6191 if (bytes > max_string_length_) { 6192 BPLOG(ERROR) << "ReadUTF8String string length " << bytes << 6193 " exceeds maximum " << max_string_length_ << 6194 " at offset " << offset; 6195 return false; 6196 } 6197 6198 string_utf8->resize(bytes); 6199 6200 if (!ReadBytes(&(*string_utf8)[0], bytes)) { 6201 BPLOG(ERROR) << "ReadUTF8String could not read " << bytes << 6202 "-byte string at offset " << offset; 6203 return false; 6204 } 6205 6206 return true; 6207 } 6208 6209 6210 bool Minidump::ReadStringList( 6211 off_t offset, 6212 std::vector<std::string>* string_list) { 6213 string_list->clear(); 6214 6215 if (!SeekSet(offset)) { 6216 BPLOG(ERROR) << "Minidump cannot seek to string_list"; 6217 return false; 6218 } 6219 6220 uint32_t count; 6221 if (!ReadBytes(&count, sizeof(count))) { 6222 BPLOG(ERROR) << "Minidump cannot read string_list count"; 6223 return false; 6224 } 6225 6226 if (swap_) { 6227 Swap(&count); 6228 } 6229 6230 scoped_array<MDRVA> rvas(new MDRVA[count]); 6231 6232 // Read the entire array in one fell swoop, instead of reading one entry 6233 // at a time in the loop. 6234 if (!ReadBytes(&rvas[0], sizeof(MDRVA) * count)) { 6235 BPLOG(ERROR) << "Minidump could not read string_list"; 6236 return false; 6237 } 6238 6239 for (uint32_t index = 0; index < count; ++index) { 6240 if (swap()) { 6241 Swap(&rvas[index]); 6242 } 6243 6244 string entry; 6245 if (!ReadUTF8String(rvas[index], &entry)) { 6246 BPLOG(ERROR) << "Minidump could not read string_list entry"; 6247 return false; 6248 } 6249 6250 string_list->push_back(entry); 6251 } 6252 6253 return true; 6254 } 6255 6256 6257 bool Minidump::ReadSimpleStringDictionary( 6258 off_t offset, 6259 std::map<std::string, std::string>* simple_string_dictionary) { 6260 simple_string_dictionary->clear(); 6261 6262 if (!SeekSet(offset)) { 6263 BPLOG(ERROR) << "Minidump cannot seek to simple_string_dictionary"; 6264 return false; 6265 } 6266 6267 uint32_t count; 6268 if (!ReadBytes(&count, sizeof(count))) { 6269 BPLOG(ERROR) 6270 << "Minidump cannot read simple_string_dictionary count"; 6271 return false; 6272 } 6273 6274 if (swap()) { 6275 Swap(&count); 6276 } 6277 6278 scoped_array<MDRawSimpleStringDictionaryEntry> entries( 6279 new MDRawSimpleStringDictionaryEntry[count]); 6280 6281 // Read the entire array in one fell swoop, instead of reading one entry 6282 // at a time in the loop. 6283 if (!ReadBytes( 6284 &entries[0], 6285 sizeof(MDRawSimpleStringDictionaryEntry) * count)) { 6286 BPLOG(ERROR) << "Minidump could not read simple_string_dictionary"; 6287 return false; 6288 } 6289 6290 for (uint32_t index = 0; index < count; ++index) { 6291 if (swap()) { 6292 Swap(&entries[index]); 6293 } 6294 6295 string key; 6296 if (!ReadUTF8String(entries[index].key, &key)) { 6297 BPLOG(ERROR) << "Minidump could not read simple_string_dictionary key"; 6298 return false; 6299 } 6300 6301 string value; 6302 if (!ReadUTF8String(entries[index].value, &value)) { 6303 BPLOG(ERROR) << "Minidump could not read simple_string_dictionary value"; 6304 return false; 6305 } 6306 6307 if (simple_string_dictionary->find(key) != 6308 simple_string_dictionary->end()) { 6309 BPLOG(ERROR) 6310 << "Minidump: discarding duplicate simple_string_dictionary value " 6311 << value << " for key " << key; 6312 } else { 6313 simple_string_dictionary->insert(std::make_pair(key, value)); 6314 } 6315 } 6316 6317 return true; 6318 } 6319 6320 bool Minidump::ReadCrashpadAnnotationsList( 6321 off_t offset, 6322 std::vector<MinidumpCrashpadInfo::AnnotationObject>* annotations_list) { 6323 annotations_list->clear(); 6324 6325 if (!SeekSet(offset)) { 6326 BPLOG(ERROR) << "Minidump cannot seek to annotations_list"; 6327 return false; 6328 } 6329 6330 uint32_t count; 6331 if (!ReadBytes(&count, sizeof(count))) { 6332 BPLOG(ERROR) << "Minidump cannot read annotations_list count"; 6333 return false; 6334 } 6335 6336 if (swap_) { 6337 Swap(&count); 6338 } 6339 6340 scoped_array<MDRawCrashpadAnnotation> objects( 6341 new MDRawCrashpadAnnotation[count]); 6342 6343 // Read the entire array in one fell swoop, instead of reading one entry 6344 // at a time in the loop. 6345 if (!ReadBytes(&objects[0], sizeof(MDRawCrashpadAnnotation) * count)) { 6346 BPLOG(ERROR) << "Minidump could not read annotations_list"; 6347 return false; 6348 } 6349 6350 for (uint32_t index = 0; index < count; ++index) { 6351 MDRawCrashpadAnnotation annotation = objects[index]; 6352 6353 if (swap_) { 6354 Swap(&annotation); 6355 } 6356 6357 string name; 6358 if (!ReadUTF8String(annotation.name, &name)) { 6359 BPLOG(ERROR) << "Minidump could not read annotation name"; 6360 return false; 6361 } 6362 6363 if (!SeekSet(annotation.value)) { 6364 BPLOG(ERROR) << "Minidump cannot seek to annotations value"; 6365 return false; 6366 } 6367 6368 uint32_t value_length; 6369 if (!ReadBytes(&value_length, sizeof(value_length))) { 6370 BPLOG(ERROR) << "Minidump could not read annotation value length"; 6371 return false; 6372 } 6373 6374 std::vector<uint8_t> value_data(value_length); 6375 if (!ReadBytes(value_data.data(), value_length)) { 6376 BPLOG(ERROR) << "Minidump could not read annotation value"; 6377 return false; 6378 } 6379 6380 MinidumpCrashpadInfo::AnnotationObject object = {annotation.type, name, 6381 value_data}; 6382 annotations_list->push_back(object); 6383 } 6384 6385 return true; 6386 } 6387 6388 bool Minidump::SeekToStreamType(uint32_t stream_type, 6389 uint32_t* stream_length) { 6390 BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires " 6391 "|stream_length|"; 6392 assert(stream_length); 6393 *stream_length = 0; 6394 6395 if (!valid_) { 6396 BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType"; 6397 return false; 6398 } 6399 6400 MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type); 6401 if (iterator == stream_map_->end()) { 6402 // This stream type didn't exist in the directory. 6403 BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present"; 6404 return false; 6405 } 6406 6407 const MinidumpStreamInfo& info = iterator->second; 6408 if (info.stream_index >= header_.stream_count) { 6409 BPLOG(ERROR) << "SeekToStreamType: type " << stream_type << 6410 " out of range: " << 6411 info.stream_index << "/" << header_.stream_count; 6412 return false; 6413 } 6414 6415 MDRawDirectory* directory_entry = &(*directory_)[info.stream_index]; 6416 if (!SeekSet(directory_entry->location.rva)) { 6417 BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " << 6418 stream_type; 6419 return false; 6420 } 6421 6422 *stream_length = directory_entry->location.data_size; 6423 6424 return true; 6425 } 6426 6427 6428 template<typename T> 6429 T* Minidump::GetStream(T** stream) { 6430 // stream is a garbage parameter that's present only to account for C++'s 6431 // inability to overload a method based solely on its return type. 6432 6433 const uint32_t stream_type = T::kStreamType; 6434 6435 BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type << 6436 " requires |stream|"; 6437 assert(stream); 6438 *stream = NULL; 6439 6440 if (!valid_) { 6441 BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type; 6442 return NULL; 6443 } 6444 6445 MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type); 6446 if (iterator == stream_map_->end()) { 6447 // This stream type didn't exist in the directory. 6448 BPLOG(INFO) << "GetStream: type " << stream_type << " not present"; 6449 return NULL; 6450 } 6451 6452 // Get a pointer so that the stored stream field can be altered. 6453 MinidumpStreamInfo* info = &iterator->second; 6454 6455 if (info->stream) { 6456 // This cast is safe because info.stream is only populated by this 6457 // method, and there is a direct correlation between T and stream_type. 6458 *stream = static_cast<T*>(info->stream); 6459 return *stream; 6460 } 6461 6462 uint32_t stream_length; 6463 if (!SeekToStreamType(stream_type, &stream_length)) { 6464 BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type; 6465 return NULL; 6466 } 6467 6468 scoped_ptr<T> new_stream(new T(this)); 6469 6470 if (!new_stream->Read(stream_length)) { 6471 BPLOG(ERROR) << "GetStream could not read stream type " << stream_type; 6472 return NULL; 6473 } 6474 6475 *stream = new_stream.release(); 6476 info->stream = *stream; 6477 return *stream; 6478 } 6479 6480 } // namespace google_breakpad