| File: | root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/crashreporter/google-breakpad/src/processor/./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc |
| Warning: | line 266, column 16 Value stored to 'high_word' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // Copyright (c) 2010 Google Inc. |
| 2 | // All rights reserved. |
| 3 | // |
| 4 | // Redistribution and use in source and binary forms, with or without |
| 5 | // modification, are permitted provided that the following conditions are |
| 6 | // met: |
| 7 | // |
| 8 | // * Redistributions of source code must retain the above copyright |
| 9 | // notice, this list of conditions and the following disclaimer. |
| 10 | // * Redistributions in binary form must reproduce the above |
| 11 | // copyright notice, this list of conditions and the following disclaimer |
| 12 | // in the documentation and/or other materials provided with the |
| 13 | // distribution. |
| 14 | // * Neither the name of Google Inc. nor the names of its |
| 15 | // contributors may be used to endorse or promote products derived from |
| 16 | // this software without specific prior written permission. |
| 17 | // |
| 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | |
| 30 | // minidump.cc: A minidump reader. |
| 31 | // |
| 32 | // See minidump.h for documentation. |
| 33 | // |
| 34 | // Author: Mark Mentovai |
| 35 | |
| 36 | #include "google_breakpad/processor/minidump.h" |
| 37 | |
| 38 | #include <assert.h> |
| 39 | #include <fcntl.h> |
| 40 | #include <stddef.h> |
| 41 | #include <string.h> |
| 42 | #include <time.h> |
| 43 | |
| 44 | #ifdef _WIN32 |
| 45 | #include <io.h> |
| 46 | #else // _WIN32 |
| 47 | #include <unistd.h> |
| 48 | #endif // _WIN32 |
| 49 | |
| 50 | #include <algorithm> |
| 51 | #include <fstream> |
| 52 | #include <limits> |
| 53 | #include <utility> |
| 54 | |
| 55 | #include "processor/range_map-inl.h" |
| 56 | |
| 57 | #include "common/macros.h" |
| 58 | #include "common/scoped_ptr.h" |
| 59 | #include "common/stdio_wrapper.h" |
| 60 | #include "google_breakpad/processor/dump_context.h" |
| 61 | #include "processor/basic_code_module.h" |
| 62 | #include "processor/basic_code_modules.h" |
| 63 | #include "processor/convert_old_arm64_context.h" |
| 64 | #include "processor/logging.h" |
| 65 | |
| 66 | namespace google_breakpad { |
| 67 | |
| 68 | using std::istream; |
| 69 | using std::ifstream; |
| 70 | using std::numeric_limits; |
| 71 | using std::vector; |
| 72 | |
| 73 | namespace { |
| 74 | |
| 75 | // Returns true iff |context_size| matches exactly one of the sizes of the |
| 76 | // various MDRawContext* types. |
| 77 | // TODO(blundell): This function can be removed once |
| 78 | // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 is fixed. |
| 79 | bool IsContextSizeUnique(uint32_t context_size) { |
| 80 | int num_matching_contexts = 0; |
| 81 | if (context_size == sizeof(MDRawContextX86)) |
| 82 | num_matching_contexts++; |
| 83 | if (context_size == sizeof(MDRawContextPPC)) |
| 84 | num_matching_contexts++; |
| 85 | if (context_size == sizeof(MDRawContextPPC64)) |
| 86 | num_matching_contexts++; |
| 87 | if (context_size == sizeof(MDRawContextAMD64)) |
| 88 | num_matching_contexts++; |
| 89 | if (context_size == sizeof(MDRawContextSPARC)) |
| 90 | num_matching_contexts++; |
| 91 | if (context_size == sizeof(MDRawContextARM)) |
| 92 | num_matching_contexts++; |
| 93 | if (context_size == sizeof(MDRawContextARM64)) |
| 94 | num_matching_contexts++; |
| 95 | if (context_size == sizeof(MDRawContextARM64_Old)) |
| 96 | num_matching_contexts++; |
| 97 | if (context_size == sizeof(MDRawContextMIPS)) |
| 98 | num_matching_contexts++; |
| 99 | return num_matching_contexts == 1; |
| 100 | } |
| 101 | |
| 102 | // |
| 103 | // Swapping routines |
| 104 | // |
| 105 | // Inlining these doesn't increase code size significantly, and it saves |
| 106 | // a whole lot of unnecessary jumping back and forth. |
| 107 | // |
| 108 | |
| 109 | |
| 110 | // Swapping an 8-bit quantity is a no-op. This function is only provided |
| 111 | // to account for certain templatized operations that require swapping for |
| 112 | // wider types but handle uint8_t too |
| 113 | // (MinidumpMemoryRegion::GetMemoryAtAddressInternal). |
| 114 | inline void Swap(uint8_t* value) {} |
| 115 | |
| 116 | // Optimization: don't need to AND the furthest right shift, because we're |
| 117 | // shifting an unsigned quantity. The standard requires zero-filling in this |
| 118 | // case. If the quantities were signed, a bitmask whould be needed for this |
| 119 | // right shift to avoid an arithmetic shift (which retains the sign bit). |
| 120 | // The furthest left shift never needs to be ANDed bitmask. |
| 121 | |
| 122 | inline void Swap(uint16_t* value) { |
| 123 | *value = (*value >> 8) | (*value << 8); |
| 124 | } |
| 125 | |
| 126 | inline void Swap(uint32_t* value) { |
| 127 | *value = (*value >> 24) | |
| 128 | ((*value >> 8) & 0x0000ff00) | |
| 129 | ((*value << 8) & 0x00ff0000) | |
| 130 | (*value << 24); |
| 131 | } |
| 132 | |
| 133 | inline void Swap(uint64_t* value) { |
| 134 | uint32_t* value32 = reinterpret_cast<uint32_t*>(value); |
| 135 | Swap(&value32[0]); |
| 136 | Swap(&value32[1]); |
| 137 | uint32_t temp = value32[0]; |
| 138 | value32[0] = value32[1]; |
| 139 | value32[1] = temp; |
| 140 | } |
| 141 | |
| 142 | |
| 143 | // Given a pointer to a 128-bit int in the minidump data, set the "low" |
| 144 | // and "high" fields appropriately. |
| 145 | void Normalize128(uint128_struct* value, bool is_big_endian) { |
| 146 | // The struct format is [high, low], so if the format is big-endian, |
| 147 | // the most significant bytes will already be in the high field. |
| 148 | if (!is_big_endian) { |
| 149 | uint64_t temp = value->low; |
| 150 | value->low = value->high; |
| 151 | value->high = temp; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // This just swaps each int64 half of the 128-bit value. |
| 156 | // The value should also be normalized by calling Normalize128(). |
| 157 | void Swap(uint128_struct* value) { |
| 158 | Swap(&value->low); |
| 159 | Swap(&value->high); |
| 160 | } |
| 161 | |
| 162 | // Swapping signed integers |
| 163 | inline void Swap(int32_t* value) { |
| 164 | Swap(reinterpret_cast<uint32_t*>(value)); |
| 165 | } |
| 166 | |
| 167 | inline void Swap(MDLocationDescriptor* location_descriptor) { |
| 168 | Swap(&location_descriptor->data_size); |
| 169 | Swap(&location_descriptor->rva); |
| 170 | } |
| 171 | |
| 172 | inline void Swap(MDMemoryDescriptor* memory_descriptor) { |
| 173 | Swap(&memory_descriptor->start_of_memory_range); |
| 174 | Swap(&memory_descriptor->memory); |
| 175 | } |
| 176 | |
| 177 | inline void Swap(MDGUID* guid) { |
| 178 | Swap(&guid->data1); |
| 179 | Swap(&guid->data2); |
| 180 | Swap(&guid->data3); |
| 181 | // Don't swap guid->data4[] because it contains 8-bit quantities. |
| 182 | } |
| 183 | |
| 184 | inline void Swap(MDSystemTime* system_time) { |
| 185 | Swap(&system_time->year); |
| 186 | Swap(&system_time->month); |
| 187 | Swap(&system_time->day_of_week); |
| 188 | Swap(&system_time->day); |
| 189 | Swap(&system_time->hour); |
| 190 | Swap(&system_time->minute); |
| 191 | Swap(&system_time->second); |
| 192 | Swap(&system_time->milliseconds); |
| 193 | } |
| 194 | |
| 195 | inline void Swap(MDXStateFeature* xstate_feature) { |
| 196 | Swap(&xstate_feature->offset); |
| 197 | Swap(&xstate_feature->size); |
| 198 | } |
| 199 | |
| 200 | inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) { |
| 201 | Swap(&xstate_feature_info->size_of_info); |
| 202 | Swap(&xstate_feature_info->context_size); |
| 203 | Swap(&xstate_feature_info->enabled_features); |
| 204 | |
| 205 | for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES64; i++) { |
| 206 | Swap(&xstate_feature_info->features[i]); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | inline void Swap(MDRawSimpleStringDictionaryEntry* entry) { |
| 211 | Swap(&entry->key); |
| 212 | Swap(&entry->value); |
| 213 | } |
| 214 | |
| 215 | inline void Swap(uint16_t* data, size_t size_in_bytes) { |
| 216 | size_t data_length = size_in_bytes / sizeof(data[0]); |
| 217 | for (size_t i = 0; i < data_length; i++) { |
| 218 | Swap(&data[i]); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | // |
| 223 | // Character conversion routines |
| 224 | // |
| 225 | |
| 226 | |
| 227 | // Standard wide-character conversion routines depend on the system's own |
| 228 | // idea of what width a wide character should be: some use 16 bits, and |
| 229 | // some use 32 bits. For the purposes of a minidump, wide strings are |
| 230 | // always represented with 16-bit UTF-16 chracters. iconv isn't available |
| 231 | // everywhere, and its interface varies where it is available. iconv also |
| 232 | // deals purely with char* pointers, so in addition to considering the swap |
| 233 | // parameter, a converter that uses iconv would also need to take the host |
| 234 | // CPU's endianness into consideration. It doesn't seems worth the trouble |
| 235 | // of making it a dependency when we don't care about anything but UTF-16. |
| 236 | string* UTF16ToUTF8(const vector<uint16_t>& in, bool swap) { |
| 237 | scoped_ptr<string> out(new string()); |
| 238 | |
| 239 | // Set the string's initial capacity to the number of UTF-16 characters, |
| 240 | // because the UTF-8 representation will always be at least this long. |
| 241 | // If the UTF-8 representation is longer, the string will grow dynamically. |
| 242 | out->reserve(in.size()); |
| 243 | |
| 244 | for (vector<uint16_t>::const_iterator iterator = in.begin(); |
| 245 | iterator != in.end(); |
| 246 | ++iterator) { |
| 247 | // Get a 16-bit value from the input |
| 248 | uint16_t in_word = *iterator; |
| 249 | if (swap) |
| 250 | Swap(&in_word); |
| 251 | |
| 252 | // Convert the input value (in_word) into a Unicode code point (unichar). |
| 253 | uint32_t unichar; |
| 254 | if (in_word >= 0xdc00 && in_word <= 0xdcff) { |
| 255 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 255)) << "UTF16ToUTF8 found low surrogate " << |
| 256 | HexString(in_word) << " without high"; |
| 257 | return NULL__null; |
| 258 | } else if (in_word >= 0xd800 && in_word <= 0xdbff) { |
| 259 | // High surrogate. |
| 260 | unichar = (in_word - 0xd7c0) << 10; |
| 261 | if (++iterator == in.end()) { |
| 262 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 262)) << "UTF16ToUTF8 found high surrogate " << |
| 263 | HexString(in_word) << " at end of string"; |
| 264 | return NULL__null; |
| 265 | } |
| 266 | uint32_t high_word = in_word; |
Value stored to 'high_word' during its initialization is never read | |
| 267 | in_word = *iterator; |
| 268 | if (in_word < 0xdc00 || in_word > 0xdcff) { |
| 269 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 269)) << "UTF16ToUTF8 found high surrogate " << |
| 270 | HexString(high_word) << " without low " << |
| 271 | HexString(in_word); |
| 272 | return NULL__null; |
| 273 | } |
| 274 | unichar |= in_word & 0x03ff; |
| 275 | } else { |
| 276 | // The ordinary case, a single non-surrogate Unicode character encoded |
| 277 | // as a single 16-bit value. |
| 278 | unichar = in_word; |
| 279 | } |
| 280 | |
| 281 | // Convert the Unicode code point (unichar) into its UTF-8 representation, |
| 282 | // appending it to the out string. |
| 283 | if (unichar < 0x80) { |
| 284 | (*out) += static_cast<char>(unichar); |
| 285 | } else if (unichar < 0x800) { |
| 286 | (*out) += 0xc0 | static_cast<char>(unichar >> 6); |
| 287 | (*out) += 0x80 | static_cast<char>(unichar & 0x3f); |
| 288 | } else if (unichar < 0x10000) { |
| 289 | (*out) += 0xe0 | static_cast<char>(unichar >> 12); |
| 290 | (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); |
| 291 | (*out) += 0x80 | static_cast<char>(unichar & 0x3f); |
| 292 | } else if (unichar < 0x200000) { |
| 293 | (*out) += 0xf0 | static_cast<char>(unichar >> 18); |
| 294 | (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f); |
| 295 | (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); |
| 296 | (*out) += 0x80 | static_cast<char>(unichar & 0x3f); |
| 297 | } else { |
| 298 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 298)) << "UTF16ToUTF8 cannot represent high value " << |
| 299 | HexString(unichar) << " in UTF-8"; |
| 300 | return NULL__null; |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | return out.release(); |
| 305 | } |
| 306 | |
| 307 | // Return the smaller of the number of code units in the UTF-16 string, |
| 308 | // not including the terminating null word, or maxlen. |
| 309 | size_t UTF16codeunits(const uint16_t* string, size_t maxlen) { |
| 310 | size_t count = 0; |
| 311 | while (count < maxlen && string[count] != 0) |
| 312 | count++; |
| 313 | return count; |
| 314 | } |
| 315 | |
| 316 | inline void Swap(MDTimeZoneInformation* time_zone) { |
| 317 | Swap(&time_zone->bias); |
| 318 | // Skip time_zone->standard_name. No need to swap UTF-16 fields. |
| 319 | // The swap will be done as part of the conversion to UTF-8. |
| 320 | Swap(&time_zone->standard_date); |
| 321 | Swap(&time_zone->standard_bias); |
| 322 | // Skip time_zone->daylight_name. No need to swap UTF-16 fields. |
| 323 | // The swap will be done as part of the conversion to UTF-8. |
| 324 | Swap(&time_zone->daylight_date); |
| 325 | Swap(&time_zone->daylight_bias); |
| 326 | } |
| 327 | |
| 328 | void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data, |
| 329 | size_t max_length_in_bytes, |
| 330 | string* utf8_result, |
| 331 | bool swap) { |
| 332 | // Since there is no explicit byte length for each string, use |
| 333 | // UTF16codeunits to calculate word length, then derive byte |
| 334 | // length from that. |
| 335 | size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]); |
| 336 | size_t word_length = UTF16codeunits(utf16_data, max_word_length); |
| 337 | if (word_length > 0) { |
| 338 | size_t byte_length = word_length * sizeof(utf16_data[0]); |
| 339 | vector<uint16_t> utf16_vector(word_length); |
| 340 | memcpy(&utf16_vector[0], &utf16_data[0], byte_length); |
| 341 | scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap)); |
| 342 | if (temp.get()) { |
| 343 | utf8_result->assign(*temp); |
| 344 | } |
| 345 | } else { |
| 346 | utf8_result->clear(); |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | |
| 351 | // For fields that may or may not be valid, PrintValueOrInvalid will print the |
| 352 | // string "(invalid)" if the field is not valid, and will print the value if |
| 353 | // the field is valid. The value is printed as hexadecimal or decimal. |
| 354 | |
| 355 | enum NumberFormat { |
| 356 | kNumberFormatDecimal, |
| 357 | kNumberFormatHexadecimal, |
| 358 | }; |
| 359 | |
| 360 | void PrintValueOrInvalid(bool valid, |
| 361 | NumberFormat number_format, |
| 362 | uint32_t value) { |
| 363 | if (!valid) { |
| 364 | printf("(invalid)\n"); |
| 365 | } else if (number_format == kNumberFormatDecimal) { |
| 366 | printf("%d\n", value); |
| 367 | } else { |
| 368 | printf("0x%x\n", value); |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | // Converts a time_t to a string showing the time in UTC. |
| 373 | string TimeTToUTCString(time_t tt) { |
| 374 | struct tm timestruct; |
| 375 | #ifdef _WIN32 |
| 376 | gmtime_s(×truct, &tt); |
| 377 | #else |
| 378 | gmtime_r(&tt, ×truct); |
| 379 | #endif |
| 380 | |
| 381 | char timestr[20]; |
| 382 | size_t rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); |
| 383 | if (rv == 0) { |
| 384 | return string(); |
| 385 | } |
| 386 | |
| 387 | return string(timestr); |
| 388 | } |
| 389 | |
| 390 | string MDGUIDToString(const MDGUID& uuid) { |
| 391 | char buf[37]; |
| 392 | snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
| 393 | uuid.data1, |
| 394 | uuid.data2, |
| 395 | uuid.data3, |
| 396 | uuid.data4[0], |
| 397 | uuid.data4[1], |
| 398 | uuid.data4[2], |
| 399 | uuid.data4[3], |
| 400 | uuid.data4[4], |
| 401 | uuid.data4[5], |
| 402 | uuid.data4[6], |
| 403 | uuid.data4[7]); |
| 404 | return std::string(buf); |
| 405 | } |
| 406 | |
| 407 | bool IsDevAshmem(const string& filename) { |
| 408 | const string kDevAshmem("/dev/ashmem/"); |
| 409 | return filename.compare(0, kDevAshmem.length(), kDevAshmem) == 0; |
| 410 | } |
| 411 | |
| 412 | } // namespace |
| 413 | |
| 414 | // |
| 415 | // MinidumpObject |
| 416 | // |
| 417 | |
| 418 | |
| 419 | MinidumpObject::MinidumpObject(Minidump* minidump) |
| 420 | : DumpObject(), |
| 421 | minidump_(minidump) { |
| 422 | } |
| 423 | |
| 424 | |
| 425 | // |
| 426 | // MinidumpStream |
| 427 | // |
| 428 | |
| 429 | |
| 430 | MinidumpStream::MinidumpStream(Minidump* minidump) |
| 431 | : MinidumpObject(minidump) { |
| 432 | } |
| 433 | |
| 434 | |
| 435 | // |
| 436 | // MinidumpContext |
| 437 | // |
| 438 | |
| 439 | |
| 440 | MinidumpContext::MinidumpContext(Minidump* minidump) |
| 441 | : DumpContext(), |
| 442 | minidump_(minidump) { |
| 443 | } |
| 444 | |
| 445 | MinidumpContext::~MinidumpContext() { |
| 446 | } |
| 447 | |
| 448 | bool MinidumpContext::Read(uint32_t expected_size) { |
| 449 | valid_ = false; |
| 450 | |
| 451 | // Certain raw context types are currently assumed to have unique sizes. |
| 452 | if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) { |
| 453 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 453)) << "sizeof(MDRawContextPPC64) cannot match the size of any " |
| 454 | << "other raw context"; |
| 455 | return false; |
| 456 | } |
| 457 | if (!IsContextSizeUnique(sizeof(MDRawContextARM64_Old))) { |
| 458 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 458)) << "sizeof(MDRawContextARM64_Old) cannot match the size of any " |
| 459 | << "other raw context"; |
| 460 | return false; |
| 461 | } |
| 462 | |
| 463 | FreeContext(); |
| 464 | |
| 465 | if (expected_size == sizeof(MDRawContextPPC64)) { |
| 466 | // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext |
| 467 | // in the else case have 32 bits |context_flags|, so special case it here. |
| 468 | uint64_t context_flags; |
| 469 | if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { |
| 470 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 470)) << "MinidumpContext could not read context flags"; |
| 471 | return false; |
| 472 | } |
| 473 | if (minidump_->swap()) |
| 474 | Swap(&context_flags); |
| 475 | |
| 476 | uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK0xffffff00; |
| 477 | scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64()); |
| 478 | |
| 479 | if (cpu_type == 0) { |
| 480 | if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { |
| 481 | context_ppc64->context_flags |= cpu_type; |
| 482 | } else { |
| 483 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 483)) << "Failed to preserve the current stream position"; |
| 484 | return false; |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | if (cpu_type != MD_CONTEXT_PPC640x01000000) { |
| 489 | // TODO: Fall through to switch below. |
| 490 | // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 |
| 491 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 491)) << "MinidumpContext not actually ppc64 context"; |
| 492 | return false; |
| 493 | } |
| 494 | |
| 495 | // Set the context_flags member, which has already been read, and |
| 496 | // read the rest of the structure beginning with the first member |
| 497 | // after context_flags. |
| 498 | context_ppc64->context_flags = context_flags; |
| 499 | |
| 500 | size_t flags_size = sizeof(context_ppc64->context_flags); |
| 501 | uint8_t* context_after_flags = |
| 502 | reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size; |
| 503 | if (!minidump_->ReadBytes(context_after_flags, |
| 504 | sizeof(MDRawContextPPC64) - flags_size)) { |
| 505 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 505)) << "MinidumpContext could not read ppc64 context"; |
| 506 | return false; |
| 507 | } |
| 508 | |
| 509 | // Do this after reading the entire MDRawContext structure because |
| 510 | // GetSystemInfo may seek minidump to a new position. |
| 511 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 512 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 512)) << "MinidumpContext ppc64 does not match system info"; |
| 513 | return false; |
| 514 | } |
| 515 | if (minidump_->swap()) { |
| 516 | // context_ppc64->context_flags was already swapped. |
| 517 | Swap(&context_ppc64->srr0); |
| 518 | Swap(&context_ppc64->srr1); |
| 519 | for (unsigned int gpr_index = 0; |
| 520 | gpr_index < MD_CONTEXT_PPC64_GPR_COUNT32; |
| 521 | ++gpr_index) { |
| 522 | Swap(&context_ppc64->gpr[gpr_index]); |
| 523 | } |
| 524 | Swap(&context_ppc64->cr); |
| 525 | Swap(&context_ppc64->xer); |
| 526 | Swap(&context_ppc64->lr); |
| 527 | Swap(&context_ppc64->ctr); |
| 528 | Swap(&context_ppc64->vrsave); |
| 529 | for (unsigned int fpr_index = 0; |
| 530 | fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT32; |
| 531 | ++fpr_index) { |
| 532 | Swap(&context_ppc64->float_save.fpregs[fpr_index]); |
| 533 | } |
| 534 | // Don't swap context_ppc64->float_save.fpscr_pad because it is only |
| 535 | // used for padding. |
| 536 | Swap(&context_ppc64->float_save.fpscr); |
| 537 | for (unsigned int vr_index = 0; |
| 538 | vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT32; |
| 539 | ++vr_index) { |
| 540 | Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true); |
| 541 | Swap(&context_ppc64->vector_save.save_vr[vr_index]); |
| 542 | } |
| 543 | Swap(&context_ppc64->vector_save.save_vscr); |
| 544 | // Don't swap the padding fields in vector_save. |
| 545 | Swap(&context_ppc64->vector_save.save_vrvalid); |
| 546 | } |
| 547 | |
| 548 | SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags)); |
| 549 | |
| 550 | // Check for data loss when converting context flags from uint64_t into |
| 551 | // uint32_t |
| 552 | if (static_cast<uint64_t>(GetContextFlags()) != |
| 553 | context_ppc64->context_flags) { |
| 554 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 554)) << "Data loss detected when converting PPC64 context_flags"; |
| 555 | return false; |
| 556 | } |
| 557 | |
| 558 | SetContextPPC64(context_ppc64.release()); |
| 559 | } else if (expected_size == sizeof(MDRawContextARM64_Old)) { |
| 560 | // |context_flags| of MDRawContextARM64_Old is 64 bits, but other MDRawContext |
| 561 | // in the else case have 32 bits |context_flags|, so special case it here. |
| 562 | uint64_t context_flags; |
| 563 | |
| 564 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 564)) << "MinidumpContext: looks like ARM64 context"; |
| 565 | |
| 566 | if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { |
| 567 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 567)) << "MinidumpContext could not read context flags"; |
| 568 | return false; |
| 569 | } |
| 570 | if (minidump_->swap()) |
| 571 | Swap(&context_flags); |
| 572 | |
| 573 | scoped_ptr<MDRawContextARM64_Old> context_arm64(new MDRawContextARM64_Old()); |
| 574 | |
| 575 | uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK0xffffff00; |
| 576 | if (cpu_type == 0) { |
| 577 | if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { |
| 578 | context_arm64->context_flags |= cpu_type; |
| 579 | } else { |
| 580 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 580)) << "Failed to preserve the current stream position"; |
| 581 | return false; |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | if (cpu_type != MD_CONTEXT_ARM64_OLD0x80000000) { |
| 586 | // TODO: Fall through to switch below. |
| 587 | // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 |
| 588 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 588)) << "MinidumpContext not actually arm64 context"; |
| 589 | return false; |
| 590 | } |
| 591 | |
| 592 | // Set the context_flags member, which has already been read, and |
| 593 | // read the rest of the structure beginning with the first member |
| 594 | // after context_flags. |
| 595 | context_arm64->context_flags = context_flags; |
| 596 | |
| 597 | size_t flags_size = sizeof(context_arm64->context_flags); |
| 598 | uint8_t* context_after_flags = |
| 599 | reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size; |
| 600 | if (!minidump_->ReadBytes(context_after_flags, |
| 601 | sizeof(MDRawContextARM64_Old) - flags_size)) { |
| 602 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 602)) << "MinidumpContext could not read arm64 context"; |
| 603 | return false; |
| 604 | } |
| 605 | |
| 606 | // Do this after reading the entire MDRawContext structure because |
| 607 | // GetSystemInfo may seek minidump to a new position. |
| 608 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 609 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 609)) << "MinidumpContext arm64 does not match system info"; |
| 610 | return false; |
| 611 | } |
| 612 | |
| 613 | if (minidump_->swap()) { |
| 614 | // context_arm64->context_flags was already swapped. |
| 615 | for (unsigned int ireg_index = 0; |
| 616 | ireg_index < MD_CONTEXT_ARM64_GPR_COUNT33; |
| 617 | ++ireg_index) { |
| 618 | Swap(&context_arm64->iregs[ireg_index]); |
| 619 | } |
| 620 | Swap(&context_arm64->cpsr); |
| 621 | Swap(&context_arm64->float_save.fpsr); |
| 622 | Swap(&context_arm64->float_save.fpcr); |
| 623 | for (unsigned int fpr_index = 0; |
| 624 | fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT32; |
| 625 | ++fpr_index) { |
| 626 | Normalize128(&context_arm64->float_save.regs[fpr_index], |
| 627 | minidump_->is_big_endian()); |
| 628 | Swap(&context_arm64->float_save.regs[fpr_index]); |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64()); |
| 633 | ConvertOldARM64Context(*context_arm64.get(), new_context.get()); |
| 634 | SetContextFlags(new_context->context_flags); |
| 635 | SetContextARM64(new_context.release()); |
| 636 | } else { |
| 637 | uint32_t cpu_type = 0; |
| 638 | if (!minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { |
| 639 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 639)) << "Failed to preserve the current stream position"; |
| 640 | return false; |
| 641 | } |
| 642 | |
| 643 | uint32_t context_flags = 0; |
| 644 | if ((cpu_type == 0) || cpu_type != MD_CONTEXT_AMD640x00100000) { |
| 645 | if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { |
| 646 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 646)) << "MinidumpContext could not read context flags"; |
| 647 | return false; |
| 648 | } |
| 649 | |
| 650 | if (minidump_->swap()) |
| 651 | Swap(&context_flags); |
| 652 | |
| 653 | if ((context_flags & MD_CONTEXT_CPU_MASK0xffffff00) == 0) { |
| 654 | // Unfortunately the flag for MD_CONTEXT_ARM that was taken |
| 655 | // from a Windows CE SDK header conflicts in practice with |
| 656 | // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered, |
| 657 | // but handle dumps with the legacy value gracefully here. |
| 658 | if (context_flags & MD_CONTEXT_ARM_OLD0x00000040) { |
| 659 | context_flags |= MD_CONTEXT_ARM0x40000000; |
| 660 | context_flags &= ~MD_CONTEXT_ARM_OLD0x00000040; |
| 661 | cpu_type = MD_CONTEXT_ARM0x40000000; |
| 662 | } else { |
| 663 | context_flags |= cpu_type; |
| 664 | } |
| 665 | } else { |
| 666 | cpu_type = context_flags & MD_CONTEXT_CPU_MASK0xffffff00; |
| 667 | } |
| 668 | } |
| 669 | |
| 670 | // Allocate the context structure for the correct CPU and fill it. The |
| 671 | // casts are slightly unorthodox, but it seems better to do that than to |
| 672 | // maintain a separate pointer for each type of CPU context structure |
| 673 | // when only one of them will be used. |
| 674 | switch (cpu_type) { |
| 675 | case MD_CONTEXT_AMD640x00100000: { |
| 676 | if (expected_size != sizeof(MDRawContextAMD64)) { |
| 677 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 677)) << "MinidumpContext AMD64 size mismatch, " << |
| 678 | expected_size << " != " << sizeof(MDRawContextAMD64); |
| 679 | } |
| 680 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 680)) << "MinidumpContext: looks like AMD64 context"; |
| 681 | |
| 682 | scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64()); |
| 683 | if (!minidump_->ReadBytes(context_amd64.get(), |
| 684 | sizeof(MDRawContextAMD64))) { |
| 685 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 685)) << "MinidumpContext could not read amd64 context"; |
| 686 | return false; |
| 687 | } |
| 688 | |
| 689 | if (minidump_->swap()) |
| 690 | Swap(&context_amd64->context_flags); |
| 691 | |
| 692 | // Update context_flags since we haven't done it yet |
| 693 | context_flags = context_amd64->context_flags; |
| 694 | |
| 695 | if (cpu_type != (context_flags & MD_CONTEXT_CPU_MASK0xffffff00)) { |
| 696 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 696)) << "MinidumpContext amd64 does not match system info"; |
| 697 | return false; |
| 698 | } |
| 699 | |
| 700 | // Normalize the 128-bit types in the dump. |
| 701 | // Since this is AMD64, by definition, the values are little-endian. |
| 702 | for (unsigned int vr_index = 0; |
| 703 | vr_index < MD_CONTEXT_AMD64_VR_COUNT26; |
| 704 | ++vr_index) |
| 705 | Normalize128(&context_amd64->vector_register[vr_index], false); |
| 706 | |
| 707 | if (minidump_->swap()) { |
| 708 | Swap(&context_amd64->p1_home); |
| 709 | Swap(&context_amd64->p2_home); |
| 710 | Swap(&context_amd64->p3_home); |
| 711 | Swap(&context_amd64->p4_home); |
| 712 | Swap(&context_amd64->p5_home); |
| 713 | Swap(&context_amd64->p6_home); |
| 714 | // context_flags is already swapped |
| 715 | Swap(&context_amd64->mx_csr); |
| 716 | Swap(&context_amd64->cs); |
| 717 | Swap(&context_amd64->ds); |
| 718 | Swap(&context_amd64->es); |
| 719 | Swap(&context_amd64->fs); |
| 720 | Swap(&context_amd64->ss); |
| 721 | Swap(&context_amd64->eflags); |
| 722 | Swap(&context_amd64->dr0); |
| 723 | Swap(&context_amd64->dr1); |
| 724 | Swap(&context_amd64->dr2); |
| 725 | Swap(&context_amd64->dr3); |
| 726 | Swap(&context_amd64->dr6); |
| 727 | Swap(&context_amd64->dr7); |
| 728 | Swap(&context_amd64->rax); |
| 729 | Swap(&context_amd64->rcx); |
| 730 | Swap(&context_amd64->rdx); |
| 731 | Swap(&context_amd64->rbx); |
| 732 | Swap(&context_amd64->rsp); |
| 733 | Swap(&context_amd64->rbp); |
| 734 | Swap(&context_amd64->rsi); |
| 735 | Swap(&context_amd64->rdi); |
| 736 | Swap(&context_amd64->r8); |
| 737 | Swap(&context_amd64->r9); |
| 738 | Swap(&context_amd64->r10); |
| 739 | Swap(&context_amd64->r11); |
| 740 | Swap(&context_amd64->r12); |
| 741 | Swap(&context_amd64->r13); |
| 742 | Swap(&context_amd64->r14); |
| 743 | Swap(&context_amd64->r15); |
| 744 | Swap(&context_amd64->rip); |
| 745 | // FIXME: I'm not sure what actually determines |
| 746 | // which member of the union {flt_save, sse_registers} |
| 747 | // is valid. We're not currently using either, |
| 748 | // but it would be good to have them swapped properly. |
| 749 | |
| 750 | for (unsigned int vr_index = 0; |
| 751 | vr_index < MD_CONTEXT_AMD64_VR_COUNT26; |
| 752 | ++vr_index) |
| 753 | Swap(&context_amd64->vector_register[vr_index]); |
| 754 | Swap(&context_amd64->vector_control); |
| 755 | Swap(&context_amd64->debug_control); |
| 756 | Swap(&context_amd64->last_branch_to_rip); |
| 757 | Swap(&context_amd64->last_branch_from_rip); |
| 758 | Swap(&context_amd64->last_exception_to_rip); |
| 759 | Swap(&context_amd64->last_exception_from_rip); |
| 760 | } |
| 761 | |
| 762 | SetContextFlags(context_amd64->context_flags); |
| 763 | |
| 764 | SetContextAMD64(context_amd64.release()); |
| 765 | minidump_->SeekSet( |
| 766 | (minidump_->Tell() - sizeof(MDRawContextAMD64)) + expected_size); |
| 767 | break; |
| 768 | } |
| 769 | case MD_CONTEXT_X860x00010000: { |
| 770 | if (expected_size != sizeof(MDRawContextX86)) { |
| 771 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 771)) << "MinidumpContext x86 size mismatch, " << |
| 772 | expected_size << " != " << sizeof(MDRawContextX86); |
| 773 | } |
| 774 | |
| 775 | scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86()); |
| 776 | |
| 777 | // Set the context_flags member, which has already been read, and |
| 778 | // read the rest of the structure beginning with the first member |
| 779 | // after context_flags. |
| 780 | context_x86->context_flags = context_flags; |
| 781 | |
| 782 | size_t flags_size = sizeof(context_x86->context_flags); |
| 783 | uint8_t* context_after_flags = |
| 784 | reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size; |
| 785 | if (!minidump_->ReadBytes(context_after_flags, |
| 786 | sizeof(MDRawContextX86) - flags_size)) { |
| 787 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 787)) << "MinidumpContext could not read x86 context"; |
| 788 | return false; |
| 789 | } |
| 790 | |
| 791 | // Do this after reading the entire MDRawContext structure because |
| 792 | // GetSystemInfo may seek minidump to a new position. |
| 793 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 794 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 794)) << "MinidumpContext x86 does not match system info"; |
| 795 | return false; |
| 796 | } |
| 797 | |
| 798 | if (minidump_->swap()) { |
| 799 | // context_x86->context_flags was already swapped. |
| 800 | Swap(&context_x86->dr0); |
| 801 | Swap(&context_x86->dr1); |
| 802 | Swap(&context_x86->dr2); |
| 803 | Swap(&context_x86->dr3); |
| 804 | Swap(&context_x86->dr6); |
| 805 | Swap(&context_x86->dr7); |
| 806 | Swap(&context_x86->float_save.control_word); |
| 807 | Swap(&context_x86->float_save.status_word); |
| 808 | Swap(&context_x86->float_save.tag_word); |
| 809 | Swap(&context_x86->float_save.error_offset); |
| 810 | Swap(&context_x86->float_save.error_selector); |
| 811 | Swap(&context_x86->float_save.data_offset); |
| 812 | Swap(&context_x86->float_save.data_selector); |
| 813 | // context_x86->float_save.register_area[] contains 8-bit quantities |
| 814 | // and does not need to be swapped. |
| 815 | Swap(&context_x86->float_save.cr0_npx_state); |
| 816 | Swap(&context_x86->gs); |
| 817 | Swap(&context_x86->fs); |
| 818 | Swap(&context_x86->es); |
| 819 | Swap(&context_x86->ds); |
| 820 | Swap(&context_x86->edi); |
| 821 | Swap(&context_x86->esi); |
| 822 | Swap(&context_x86->ebx); |
| 823 | Swap(&context_x86->edx); |
| 824 | Swap(&context_x86->ecx); |
| 825 | Swap(&context_x86->eax); |
| 826 | Swap(&context_x86->ebp); |
| 827 | Swap(&context_x86->eip); |
| 828 | Swap(&context_x86->cs); |
| 829 | Swap(&context_x86->eflags); |
| 830 | Swap(&context_x86->esp); |
| 831 | Swap(&context_x86->ss); |
| 832 | // context_x86->extended_registers[] contains 8-bit quantities and |
| 833 | // does not need to be swapped. |
| 834 | } |
| 835 | |
| 836 | SetContextX86(context_x86.release()); |
| 837 | minidump_->SeekSet( |
| 838 | (minidump_->Tell() - sizeof(MDRawContextX86)) + expected_size); |
| 839 | |
| 840 | break; |
| 841 | } |
| 842 | |
| 843 | case MD_CONTEXT_PPC0x20000000: { |
| 844 | if (expected_size != sizeof(MDRawContextPPC)) { |
| 845 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 845)) << "MinidumpContext ppc size mismatch, " << |
| 846 | expected_size << " != " << sizeof(MDRawContextPPC); |
| 847 | return false; |
| 848 | } |
| 849 | |
| 850 | scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC()); |
| 851 | |
| 852 | // Set the context_flags member, which has already been read, and |
| 853 | // read the rest of the structure beginning with the first member |
| 854 | // after context_flags. |
| 855 | context_ppc->context_flags = context_flags; |
| 856 | |
| 857 | size_t flags_size = sizeof(context_ppc->context_flags); |
| 858 | uint8_t* context_after_flags = |
| 859 | reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size; |
| 860 | if (!minidump_->ReadBytes(context_after_flags, |
| 861 | sizeof(MDRawContextPPC) - flags_size)) { |
| 862 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 862)) << "MinidumpContext could not read ppc context"; |
| 863 | return false; |
| 864 | } |
| 865 | |
| 866 | // Do this after reading the entire MDRawContext structure because |
| 867 | // GetSystemInfo may seek minidump to a new position. |
| 868 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 869 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 869)) << "MinidumpContext ppc does not match system info"; |
| 870 | return false; |
| 871 | } |
| 872 | |
| 873 | // Normalize the 128-bit types in the dump. |
| 874 | // Since this is PowerPC, by definition, the values are big-endian. |
| 875 | for (unsigned int vr_index = 0; |
| 876 | vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT32; |
| 877 | ++vr_index) { |
| 878 | Normalize128(&context_ppc->vector_save.save_vr[vr_index], true); |
| 879 | } |
| 880 | |
| 881 | if (minidump_->swap()) { |
| 882 | // context_ppc->context_flags was already swapped. |
| 883 | Swap(&context_ppc->srr0); |
| 884 | Swap(&context_ppc->srr1); |
| 885 | for (unsigned int gpr_index = 0; |
| 886 | gpr_index < MD_CONTEXT_PPC_GPR_COUNT32; |
| 887 | ++gpr_index) { |
| 888 | Swap(&context_ppc->gpr[gpr_index]); |
| 889 | } |
| 890 | Swap(&context_ppc->cr); |
| 891 | Swap(&context_ppc->xer); |
| 892 | Swap(&context_ppc->lr); |
| 893 | Swap(&context_ppc->ctr); |
| 894 | Swap(&context_ppc->mq); |
| 895 | Swap(&context_ppc->vrsave); |
| 896 | for (unsigned int fpr_index = 0; |
| 897 | fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT32; |
| 898 | ++fpr_index) { |
| 899 | Swap(&context_ppc->float_save.fpregs[fpr_index]); |
| 900 | } |
| 901 | // Don't swap context_ppc->float_save.fpscr_pad because it is only |
| 902 | // used for padding. |
| 903 | Swap(&context_ppc->float_save.fpscr); |
| 904 | for (unsigned int vr_index = 0; |
| 905 | vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT32; |
| 906 | ++vr_index) { |
| 907 | Swap(&context_ppc->vector_save.save_vr[vr_index]); |
| 908 | } |
| 909 | Swap(&context_ppc->vector_save.save_vscr); |
| 910 | // Don't swap the padding fields in vector_save. |
| 911 | Swap(&context_ppc->vector_save.save_vrvalid); |
| 912 | } |
| 913 | |
| 914 | SetContextPPC(context_ppc.release()); |
| 915 | |
| 916 | break; |
| 917 | } |
| 918 | |
| 919 | case MD_CONTEXT_SPARC0x10000000: { |
| 920 | if (expected_size != sizeof(MDRawContextSPARC)) { |
| 921 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 921)) << "MinidumpContext sparc size mismatch, " << |
| 922 | expected_size << " != " << sizeof(MDRawContextSPARC); |
| 923 | return false; |
| 924 | } |
| 925 | |
| 926 | scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC()); |
| 927 | |
| 928 | // Set the context_flags member, which has already been read, and |
| 929 | // read the rest of the structure beginning with the first member |
| 930 | // after context_flags. |
| 931 | context_sparc->context_flags = context_flags; |
| 932 | |
| 933 | size_t flags_size = sizeof(context_sparc->context_flags); |
| 934 | uint8_t* context_after_flags = |
| 935 | reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size; |
| 936 | if (!minidump_->ReadBytes(context_after_flags, |
| 937 | sizeof(MDRawContextSPARC) - flags_size)) { |
| 938 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 938)) << "MinidumpContext could not read sparc context"; |
| 939 | return false; |
| 940 | } |
| 941 | |
| 942 | // Do this after reading the entire MDRawContext structure because |
| 943 | // GetSystemInfo may seek minidump to a new position. |
| 944 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 945 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 945)) << "MinidumpContext sparc does not match system info"; |
| 946 | return false; |
| 947 | } |
| 948 | |
| 949 | if (minidump_->swap()) { |
| 950 | // context_sparc->context_flags was already swapped. |
| 951 | for (unsigned int gpr_index = 0; |
| 952 | gpr_index < MD_CONTEXT_SPARC_GPR_COUNT32; |
| 953 | ++gpr_index) { |
| 954 | Swap(&context_sparc->g_r[gpr_index]); |
| 955 | } |
| 956 | Swap(&context_sparc->ccr); |
| 957 | Swap(&context_sparc->pc); |
| 958 | Swap(&context_sparc->npc); |
| 959 | Swap(&context_sparc->y); |
| 960 | Swap(&context_sparc->asi); |
| 961 | Swap(&context_sparc->fprs); |
| 962 | for (unsigned int fpr_index = 0; |
| 963 | fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT32; |
| 964 | ++fpr_index) { |
| 965 | Swap(&context_sparc->float_save.regs[fpr_index]); |
| 966 | } |
| 967 | Swap(&context_sparc->float_save.filler); |
| 968 | Swap(&context_sparc->float_save.fsr); |
| 969 | } |
| 970 | SetContextSPARC(context_sparc.release()); |
| 971 | |
| 972 | break; |
| 973 | } |
| 974 | |
| 975 | case MD_CONTEXT_ARM0x40000000: { |
| 976 | if (expected_size != sizeof(MDRawContextARM)) { |
| 977 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 977)) << "MinidumpContext arm size mismatch, " << |
| 978 | expected_size << " != " << sizeof(MDRawContextARM); |
| 979 | return false; |
| 980 | } |
| 981 | |
| 982 | scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM()); |
| 983 | |
| 984 | // Set the context_flags member, which has already been read, and |
| 985 | // read the rest of the structure beginning with the first member |
| 986 | // after context_flags. |
| 987 | context_arm->context_flags = context_flags; |
| 988 | |
| 989 | size_t flags_size = sizeof(context_arm->context_flags); |
| 990 | uint8_t* context_after_flags = |
| 991 | reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size; |
| 992 | if (!minidump_->ReadBytes(context_after_flags, |
| 993 | sizeof(MDRawContextARM) - flags_size)) { |
| 994 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 994)) << "MinidumpContext could not read arm context"; |
| 995 | return false; |
| 996 | } |
| 997 | |
| 998 | // Do this after reading the entire MDRawContext structure because |
| 999 | // GetSystemInfo may seek minidump to a new position. |
| 1000 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 1001 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1001)) << "MinidumpContext arm does not match system info"; |
| 1002 | return false; |
| 1003 | } |
| 1004 | |
| 1005 | if (minidump_->swap()) { |
| 1006 | // context_arm->context_flags was already swapped. |
| 1007 | for (unsigned int ireg_index = 0; |
| 1008 | ireg_index < MD_CONTEXT_ARM_GPR_COUNT16; |
| 1009 | ++ireg_index) { |
| 1010 | Swap(&context_arm->iregs[ireg_index]); |
| 1011 | } |
| 1012 | Swap(&context_arm->cpsr); |
| 1013 | Swap(&context_arm->float_save.fpscr); |
| 1014 | for (unsigned int fpr_index = 0; |
| 1015 | fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT32; |
| 1016 | ++fpr_index) { |
| 1017 | Swap(&context_arm->float_save.regs[fpr_index]); |
| 1018 | } |
| 1019 | for (unsigned int fpe_index = 0; |
| 1020 | fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT8; |
| 1021 | ++fpe_index) { |
| 1022 | Swap(&context_arm->float_save.extra[fpe_index]); |
| 1023 | } |
| 1024 | } |
| 1025 | SetContextARM(context_arm.release()); |
| 1026 | |
| 1027 | break; |
| 1028 | } |
| 1029 | |
| 1030 | case MD_CONTEXT_ARM640x00400000: { |
| 1031 | if (expected_size != sizeof(MDRawContextARM64)) { |
| 1032 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1032)) << "MinidumpContext arm64 size mismatch, " << |
| 1033 | expected_size << " != " << sizeof(MDRawContextARM64); |
| 1034 | return false; |
| 1035 | } |
| 1036 | |
| 1037 | scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64()); |
| 1038 | |
| 1039 | // Set the context_flags member, which has already been read, and |
| 1040 | // read the rest of the structure beginning with the first member |
| 1041 | // after context_flags. |
| 1042 | context_arm64->context_flags = context_flags; |
| 1043 | |
| 1044 | size_t flags_size = sizeof(context_arm64->context_flags); |
| 1045 | uint8_t* context_after_flags = |
| 1046 | reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size; |
| 1047 | if (!minidump_->ReadBytes(context_after_flags, |
| 1048 | sizeof(*context_arm64) - flags_size)) { |
| 1049 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1049)) << "MinidumpContext could not read arm64 context"; |
| 1050 | return false; |
| 1051 | } |
| 1052 | |
| 1053 | // Do this after reading the entire MDRawContext structure because |
| 1054 | // GetSystemInfo may seek minidump to a new position. |
| 1055 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 1056 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1056)) << "MinidumpContext arm does not match system info"; |
| 1057 | return false; |
| 1058 | } |
| 1059 | |
| 1060 | if (minidump_->swap()) { |
| 1061 | // context_arm64->context_flags was already swapped. |
| 1062 | for (unsigned int ireg_index = 0; |
| 1063 | ireg_index < MD_CONTEXT_ARM64_GPR_COUNT33; |
| 1064 | ++ireg_index) { |
| 1065 | Swap(&context_arm64->iregs[ireg_index]); |
| 1066 | } |
| 1067 | Swap(&context_arm64->cpsr); |
| 1068 | Swap(&context_arm64->float_save.fpsr); |
| 1069 | Swap(&context_arm64->float_save.fpcr); |
| 1070 | for (unsigned int fpr_index = 0; |
| 1071 | fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT32; |
| 1072 | ++fpr_index) { |
| 1073 | Normalize128(&context_arm64->float_save.regs[fpr_index], |
| 1074 | minidump_->is_big_endian()); |
| 1075 | Swap(&context_arm64->float_save.regs[fpr_index]); |
| 1076 | } |
| 1077 | } |
| 1078 | SetContextARM64(context_arm64.release()); |
| 1079 | break; |
| 1080 | } |
| 1081 | |
| 1082 | case MD_CONTEXT_MIPS0x00040000: |
| 1083 | case MD_CONTEXT_MIPS640x00080000: { |
| 1084 | if (expected_size != sizeof(MDRawContextMIPS)) { |
| 1085 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1085)) << "MinidumpContext MIPS size mismatch, " |
| 1086 | << expected_size |
| 1087 | << " != " |
| 1088 | << sizeof(MDRawContextMIPS); |
| 1089 | return false; |
| 1090 | } |
| 1091 | |
| 1092 | scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS()); |
| 1093 | |
| 1094 | // Set the context_flags member, which has already been read, and |
| 1095 | // read the rest of the structure beginning with the first member |
| 1096 | // after context_flags. |
| 1097 | context_mips->context_flags = context_flags; |
| 1098 | |
| 1099 | size_t flags_size = sizeof(context_mips->context_flags); |
| 1100 | uint8_t* context_after_flags = |
| 1101 | reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size; |
| 1102 | if (!minidump_->ReadBytes(context_after_flags, |
| 1103 | sizeof(MDRawContextMIPS) - flags_size)) { |
| 1104 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1104)) << "MinidumpContext could not read MIPS context"; |
| 1105 | return false; |
| 1106 | } |
| 1107 | |
| 1108 | // Do this after reading the entire MDRawContext structure because |
| 1109 | // GetSystemInfo may seek minidump to a new position. |
| 1110 | if (!CheckAgainstSystemInfo(cpu_type)) { |
| 1111 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1111)) << "MinidumpContext MIPS does not match system info"; |
| 1112 | return false; |
| 1113 | } |
| 1114 | |
| 1115 | if (minidump_->swap()) { |
| 1116 | // context_mips->context_flags was already swapped. |
| 1117 | for (int ireg_index = 0; |
| 1118 | ireg_index < MD_CONTEXT_MIPS_GPR_COUNT32; |
| 1119 | ++ireg_index) { |
| 1120 | Swap(&context_mips->iregs[ireg_index]); |
| 1121 | } |
| 1122 | Swap(&context_mips->mdhi); |
| 1123 | Swap(&context_mips->mdlo); |
| 1124 | for (int dsp_index = 0; |
| 1125 | dsp_index < MD_CONTEXT_MIPS_DSP_COUNT3; |
| 1126 | ++dsp_index) { |
| 1127 | Swap(&context_mips->hi[dsp_index]); |
| 1128 | Swap(&context_mips->lo[dsp_index]); |
| 1129 | } |
| 1130 | Swap(&context_mips->dsp_control); |
| 1131 | Swap(&context_mips->epc); |
| 1132 | Swap(&context_mips->badvaddr); |
| 1133 | Swap(&context_mips->status); |
| 1134 | Swap(&context_mips->cause); |
| 1135 | for (int fpr_index = 0; |
| 1136 | fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT32; |
| 1137 | ++fpr_index) { |
| 1138 | Swap(&context_mips->float_save.regs[fpr_index]); |
| 1139 | } |
| 1140 | Swap(&context_mips->float_save.fpcsr); |
| 1141 | Swap(&context_mips->float_save.fir); |
| 1142 | } |
| 1143 | SetContextMIPS(context_mips.release()); |
| 1144 | |
| 1145 | break; |
| 1146 | } |
| 1147 | |
| 1148 | default: { |
| 1149 | // Unknown context type - Don't log as an error yet. Let the |
| 1150 | // caller work that out. |
| 1151 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1151)) << "MinidumpContext unknown context type " << |
| 1152 | HexString(cpu_type); |
| 1153 | return false; |
| 1154 | break; |
| 1155 | } |
| 1156 | } |
| 1157 | SetContextFlags(context_flags); |
| 1158 | } |
| 1159 | |
| 1160 | valid_ = true; |
| 1161 | return true; |
| 1162 | } |
| 1163 | |
| 1164 | bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { |
| 1165 | // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM, |
| 1166 | // as this function just implements a sanity check. |
| 1167 | MinidumpSystemInfo* system_info = minidump_->GetSystemInfo(); |
| 1168 | if (!system_info) { |
| 1169 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1169)) << "MinidumpContext could not be compared against " |
| 1170 | "MinidumpSystemInfo"; |
| 1171 | return true; |
| 1172 | } |
| 1173 | |
| 1174 | // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info. |
| 1175 | const MDRawSystemInfo* raw_system_info = system_info->system_info(); |
| 1176 | if (!raw_system_info) { |
| 1177 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1177)) << "MinidumpContext could not be compared against " |
| 1178 | "MDRawSystemInfo"; |
| 1179 | return false; |
| 1180 | } |
| 1181 | |
| 1182 | MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>( |
| 1183 | raw_system_info->processor_architecture); |
| 1184 | |
| 1185 | // Compare the CPU type of the context record to the CPU type in the |
| 1186 | // minidump's system info stream. |
| 1187 | bool return_value = false; |
| 1188 | switch (context_cpu_type) { |
| 1189 | case MD_CONTEXT_X860x00010000: |
| 1190 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 || |
| 1191 | system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 || |
| 1192 | system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) { |
| 1193 | return_value = true; |
| 1194 | } |
| 1195 | break; |
| 1196 | |
| 1197 | case MD_CONTEXT_PPC0x20000000: |
| 1198 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC) |
| 1199 | return_value = true; |
| 1200 | break; |
| 1201 | |
| 1202 | case MD_CONTEXT_PPC640x01000000: |
| 1203 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64) |
| 1204 | return_value = true; |
| 1205 | break; |
| 1206 | |
| 1207 | case MD_CONTEXT_AMD640x00100000: |
| 1208 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) |
| 1209 | return_value = true; |
| 1210 | break; |
| 1211 | |
| 1212 | case MD_CONTEXT_SPARC0x10000000: |
| 1213 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) |
| 1214 | return_value = true; |
| 1215 | break; |
| 1216 | |
| 1217 | case MD_CONTEXT_ARM0x40000000: |
| 1218 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM) |
| 1219 | return_value = true; |
| 1220 | break; |
| 1221 | |
| 1222 | case MD_CONTEXT_ARM640x00400000: |
| 1223 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64) |
| 1224 | return_value = true; |
| 1225 | break; |
| 1226 | |
| 1227 | case MD_CONTEXT_ARM64_OLD0x80000000: |
| 1228 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64_OLD) |
| 1229 | return_value = true; |
| 1230 | break; |
| 1231 | |
| 1232 | case MD_CONTEXT_MIPS0x00040000: |
| 1233 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS) |
| 1234 | return_value = true; |
| 1235 | break; |
| 1236 | |
| 1237 | case MD_CONTEXT_MIPS640x00080000: |
| 1238 | if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS64) |
| 1239 | return_value = true; |
| 1240 | break; |
| 1241 | } |
| 1242 | |
| 1243 | BPLOG_IF(ERROR, !return_value)!(((!return_value) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1243)) << "MinidumpContext CPU " << |
| 1244 | HexString(context_cpu_type) << |
| 1245 | " wrong for MinidumpSystemInfo CPU " << |
| 1246 | HexString(system_info_cpu_type); |
| 1247 | |
| 1248 | return return_value; |
| 1249 | } |
| 1250 | |
| 1251 | |
| 1252 | // |
| 1253 | // MinidumpMemoryRegion |
| 1254 | // |
| 1255 | |
| 1256 | |
| 1257 | uint32_t MinidumpMemoryRegion::max_bytes_ = 64 * 1024 * 1024; // 64MB |
| 1258 | |
| 1259 | |
| 1260 | MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) |
| 1261 | : MinidumpObject(minidump), |
| 1262 | descriptor_(NULL__null), |
| 1263 | memory_(NULL__null) { |
| 1264 | hexdump_width_ = minidump_ ? minidump_->HexdumpMode() : 0; |
| 1265 | hexdump_ = hexdump_width_ != 0; |
| 1266 | } |
| 1267 | |
| 1268 | |
| 1269 | MinidumpMemoryRegion::~MinidumpMemoryRegion() { |
| 1270 | delete memory_; |
| 1271 | } |
| 1272 | |
| 1273 | |
| 1274 | void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { |
| 1275 | descriptor_ = descriptor; |
| 1276 | valid_ = descriptor && |
| 1277 | descriptor_->memory.data_size <= |
| 1278 | numeric_limits<uint64_t>::max() - |
| 1279 | descriptor_->start_of_memory_range; |
| 1280 | } |
| 1281 | |
| 1282 | |
| 1283 | const uint8_t* MinidumpMemoryRegion::GetMemory() const { |
| 1284 | if (!valid_) { |
| 1285 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1285)) << "Invalid MinidumpMemoryRegion for GetMemory"; |
| 1286 | return NULL__null; |
| 1287 | } |
| 1288 | |
| 1289 | if (!memory_) { |
| 1290 | if (descriptor_->memory.data_size == 0) { |
| 1291 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1291)) << "MinidumpMemoryRegion is empty"; |
| 1292 | return NULL__null; |
| 1293 | } |
| 1294 | |
| 1295 | if (!minidump_->SeekSet(descriptor_->memory.rva)) { |
| 1296 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1296)) << "MinidumpMemoryRegion could not seek to memory region"; |
| 1297 | return NULL__null; |
| 1298 | } |
| 1299 | |
| 1300 | if (descriptor_->memory.data_size > max_bytes_) { |
| 1301 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1301)) << "MinidumpMemoryRegion size " << |
| 1302 | descriptor_->memory.data_size << " exceeds maximum " << |
| 1303 | max_bytes_; |
| 1304 | return NULL__null; |
| 1305 | } |
| 1306 | |
| 1307 | scoped_ptr< vector<uint8_t> > memory( |
| 1308 | new vector<uint8_t>(descriptor_->memory.data_size)); |
| 1309 | |
| 1310 | if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) { |
| 1311 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1311)) << "MinidumpMemoryRegion could not read memory region"; |
| 1312 | return NULL__null; |
| 1313 | } |
| 1314 | |
| 1315 | memory_ = memory.release(); |
| 1316 | } |
| 1317 | |
| 1318 | return &(*memory_)[0]; |
| 1319 | } |
| 1320 | |
| 1321 | |
| 1322 | uint64_t MinidumpMemoryRegion::GetBase() const { |
| 1323 | if (!valid_) { |
| 1324 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1324)) << "Invalid MinidumpMemoryRegion for GetBase"; |
| 1325 | return static_cast<uint64_t>(-1); |
| 1326 | } |
| 1327 | |
| 1328 | return descriptor_->start_of_memory_range; |
| 1329 | } |
| 1330 | |
| 1331 | |
| 1332 | uint32_t MinidumpMemoryRegion::GetSize() const { |
| 1333 | if (!valid_) { |
| 1334 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1334)) << "Invalid MinidumpMemoryRegion for GetSize"; |
| 1335 | return 0; |
| 1336 | } |
| 1337 | |
| 1338 | return descriptor_->memory.data_size; |
| 1339 | } |
| 1340 | |
| 1341 | |
| 1342 | void MinidumpMemoryRegion::FreeMemory() { |
| 1343 | delete memory_; |
| 1344 | memory_ = NULL__null; |
| 1345 | } |
| 1346 | |
| 1347 | |
| 1348 | template<typename T> |
| 1349 | bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address, |
| 1350 | T* value) const { |
| 1351 | BPLOG_IF(ERROR, !value)!(((!value) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1351)) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal " |
| 1352 | "requires |value|"; |
| 1353 | assert(value)(static_cast <bool> (value) ? void (0) : __assert_fail ( "value", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 1354 | *value = 0; |
| 1355 | |
| 1356 | if (!valid_) { |
| 1357 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1357)) << "Invalid MinidumpMemoryRegion for " |
| 1358 | "GetMemoryAtAddressInternal"; |
| 1359 | return false; |
| 1360 | } |
| 1361 | |
| 1362 | // Common failure case |
| 1363 | if (address < descriptor_->start_of_memory_range || |
| 1364 | sizeof(T) > numeric_limits<uint64_t>::max() - address || |
| 1365 | address + sizeof(T) > descriptor_->start_of_memory_range + |
| 1366 | descriptor_->memory.data_size) { |
| 1367 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1367)) << "MinidumpMemoryRegion request out of range: " << |
| 1368 | HexString(address) << "+" << sizeof(T) << "/" << |
| 1369 | HexString(descriptor_->start_of_memory_range) << "+" << |
| 1370 | HexString(descriptor_->memory.data_size); |
| 1371 | return false; |
| 1372 | } |
| 1373 | |
| 1374 | const uint8_t* memory = GetMemory(); |
| 1375 | if (!memory) { |
| 1376 | // GetMemory already logged a perfectly good message. |
| 1377 | return false; |
| 1378 | } |
| 1379 | |
| 1380 | // If the CPU requires memory accesses to be aligned, this can crash. |
| 1381 | // x86 and ppc are able to cope, though. |
| 1382 | *value = *reinterpret_cast<const T*>( |
| 1383 | &memory[address - descriptor_->start_of_memory_range]); |
| 1384 | |
| 1385 | if (minidump_->swap()) |
| 1386 | Swap(value); |
| 1387 | |
| 1388 | return true; |
| 1389 | } |
| 1390 | |
| 1391 | |
| 1392 | bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, |
| 1393 | uint8_t* value) const { |
| 1394 | return GetMemoryAtAddressInternal(address, value); |
| 1395 | } |
| 1396 | |
| 1397 | |
| 1398 | bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, |
| 1399 | uint16_t* value) const { |
| 1400 | return GetMemoryAtAddressInternal(address, value); |
| 1401 | } |
| 1402 | |
| 1403 | |
| 1404 | bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, |
| 1405 | uint32_t* value) const { |
| 1406 | return GetMemoryAtAddressInternal(address, value); |
| 1407 | } |
| 1408 | |
| 1409 | |
| 1410 | bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, |
| 1411 | uint64_t* value) const { |
| 1412 | return GetMemoryAtAddressInternal(address, value); |
| 1413 | } |
| 1414 | |
| 1415 | |
| 1416 | void MinidumpMemoryRegion::Print() const { |
| 1417 | if (!valid_) { |
| 1418 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1418)) << "MinidumpMemoryRegion cannot print invalid data"; |
| 1419 | return; |
| 1420 | } |
| 1421 | |
| 1422 | const uint8_t* memory = GetMemory(); |
| 1423 | if (memory) { |
| 1424 | if (hexdump_) { |
| 1425 | // Pretty hexdump view. |
| 1426 | for (unsigned int byte_index = 0; |
| 1427 | byte_index < descriptor_->memory.data_size; |
| 1428 | byte_index += hexdump_width_) { |
| 1429 | // In case the memory won't fill a whole line. |
| 1430 | unsigned int num_bytes = std::min( |
| 1431 | descriptor_->memory.data_size - byte_index, hexdump_width_); |
| 1432 | |
| 1433 | // Display the leading address. |
| 1434 | printf("%08x ", byte_index); |
| 1435 | |
| 1436 | // Show the bytes in hex. |
| 1437 | for (unsigned int i = 0; i < hexdump_width_; ++i) { |
| 1438 | if (i < num_bytes) { |
| 1439 | // Show the single byte of memory in hex. |
| 1440 | printf("%02x ", memory[byte_index + i]); |
| 1441 | } else { |
| 1442 | // If this line doesn't fill up, pad it out. |
| 1443 | printf(" "); |
| 1444 | } |
| 1445 | |
| 1446 | // Insert a space every 8 bytes to make it more readable. |
| 1447 | if (((i + 1) % 8) == 0) { |
| 1448 | printf(" "); |
| 1449 | } |
| 1450 | } |
| 1451 | |
| 1452 | // Decode the line as ASCII. |
| 1453 | printf("|"); |
| 1454 | for (unsigned int i = 0; i < hexdump_width_; ++i) { |
| 1455 | if (i < num_bytes) { |
| 1456 | uint8_t byte = memory[byte_index + i]; |
| 1457 | printf("%c", isprint(byte) ? byte : '.'); |
| 1458 | } else { |
| 1459 | // If this line doesn't fill up, pad it out. |
| 1460 | printf(" "); |
| 1461 | } |
| 1462 | } |
| 1463 | printf("|\n"); |
| 1464 | } |
| 1465 | } else { |
| 1466 | // Ugly raw string view. |
| 1467 | printf("0x"); |
| 1468 | for (unsigned int i = 0; |
| 1469 | i < descriptor_->memory.data_size; |
| 1470 | i++) { |
| 1471 | printf("%02x", memory[i]); |
| 1472 | } |
| 1473 | printf("\n"); |
| 1474 | } |
| 1475 | } else { |
| 1476 | printf("No memory\n"); |
| 1477 | } |
| 1478 | } |
| 1479 | |
| 1480 | |
| 1481 | void MinidumpMemoryRegion::SetPrintMode(bool hexdump, |
| 1482 | unsigned int hexdump_width) { |
| 1483 | // Require the width to be a multiple of 8 bytes. |
| 1484 | if (hexdump_width == 0 || (hexdump_width % 8) != 0) { |
| 1485 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1485)) << "MinidumpMemoryRegion print hexdump_width must be " |
| 1486 | "multiple of 8, not " << hexdump_width; |
| 1487 | return; |
| 1488 | } |
| 1489 | |
| 1490 | hexdump_ = hexdump; |
| 1491 | hexdump_width_ = hexdump_width; |
| 1492 | } |
| 1493 | |
| 1494 | |
| 1495 | // |
| 1496 | // MinidumpThread |
| 1497 | // |
| 1498 | |
| 1499 | |
| 1500 | MinidumpThread::MinidumpThread(Minidump* minidump) |
| 1501 | : MinidumpObject(minidump), |
| 1502 | thread_(), |
| 1503 | memory_(NULL__null), |
| 1504 | context_(NULL__null) { |
| 1505 | } |
| 1506 | |
| 1507 | |
| 1508 | MinidumpThread::~MinidumpThread() { |
| 1509 | delete memory_; |
| 1510 | delete context_; |
| 1511 | } |
| 1512 | |
| 1513 | |
| 1514 | bool MinidumpThread::Read() { |
| 1515 | // Invalidate cached data. |
| 1516 | delete memory_; |
| 1517 | memory_ = NULL__null; |
| 1518 | delete context_; |
| 1519 | context_ = NULL__null; |
| 1520 | |
| 1521 | valid_ = false; |
| 1522 | |
| 1523 | if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) { |
| 1524 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1524)) << "MinidumpThread cannot read thread"; |
| 1525 | return false; |
| 1526 | } |
| 1527 | |
| 1528 | if (minidump_->swap()) { |
| 1529 | Swap(&thread_.thread_id); |
| 1530 | Swap(&thread_.suspend_count); |
| 1531 | Swap(&thread_.priority_class); |
| 1532 | Swap(&thread_.priority); |
| 1533 | Swap(&thread_.teb); |
| 1534 | Swap(&thread_.stack); |
| 1535 | Swap(&thread_.thread_context); |
| 1536 | } |
| 1537 | |
| 1538 | // Check for base + size overflow or undersize. |
| 1539 | if (thread_.stack.memory.rva == 0 || |
| 1540 | thread_.stack.memory.data_size == 0 || |
| 1541 | thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() - |
| 1542 | thread_.stack.start_of_memory_range) { |
| 1543 | // This is ok, but log an error anyway. |
| 1544 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1544)) << "MinidumpThread has a memory region problem, " << |
| 1545 | HexString(thread_.stack.start_of_memory_range) << "+" << |
| 1546 | HexString(thread_.stack.memory.data_size) << |
| 1547 | ", RVA 0x" << HexString(thread_.stack.memory.rva); |
| 1548 | } else { |
| 1549 | memory_ = new MinidumpMemoryRegion(minidump_); |
| 1550 | memory_->SetDescriptor(&thread_.stack); |
| 1551 | } |
| 1552 | |
| 1553 | valid_ = true; |
| 1554 | return true; |
| 1555 | } |
| 1556 | |
| 1557 | uint64_t MinidumpThread::GetStartOfStackMemoryRange() const { |
| 1558 | if (!valid_) { |
| 1559 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1559)) << "GetStartOfStackMemoryRange: Invalid MinidumpThread"; |
| 1560 | return 0; |
| 1561 | } |
| 1562 | |
| 1563 | return thread_.stack.start_of_memory_range; |
| 1564 | } |
| 1565 | |
| 1566 | MinidumpMemoryRegion* MinidumpThread::GetMemory() { |
| 1567 | if (!valid_) { |
| 1568 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1568)) << "Invalid MinidumpThread for GetMemory"; |
| 1569 | return NULL__null; |
| 1570 | } |
| 1571 | |
| 1572 | return memory_; |
| 1573 | } |
| 1574 | |
| 1575 | uint32_t MinidumpThread::GetLastError() { |
| 1576 | if (!valid_) { |
| 1577 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1577)) << "Cannot retrieve GetLastError() from an invalid thread"; |
| 1578 | return 0; |
| 1579 | } |
| 1580 | |
| 1581 | if (!thread_.teb) { |
| 1582 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1582)) << "Cannot retrieve GetLastError() without a valid TEB pointer"; |
| 1583 | return 0; |
| 1584 | } |
| 1585 | |
| 1586 | auto memory = minidump_->GetMemoryList(); |
| 1587 | if (!memory) { |
| 1588 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1588)) << "Cannot retrieve GetLastError() without a valid memory list"; |
| 1589 | return 0; |
| 1590 | } |
| 1591 | |
| 1592 | auto context = GetContext(); |
| 1593 | if (!context) { |
| 1594 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1594)) << "Cannot retrieve GetLastError()'s without a valid context"; |
| 1595 | return 0; |
| 1596 | } |
| 1597 | |
| 1598 | uint64_t pointer_width = 0; |
| 1599 | switch (context_->GetContextCPU()) { |
| 1600 | case MD_CONTEXT_X860x00010000: |
| 1601 | pointer_width = 4; |
| 1602 | break; |
| 1603 | case MD_CONTEXT_AMD640x00100000: |
| 1604 | case MD_CONTEXT_ARM640x00400000: |
| 1605 | pointer_width = 8; |
| 1606 | break; |
| 1607 | default: |
| 1608 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1608)) << "GetLastError() isn't implemented for this CPU type yet"; |
| 1609 | return 0; |
| 1610 | } |
| 1611 | |
| 1612 | auto region = memory->GetMemoryRegionForAddress(thread_.teb); |
| 1613 | if (!region) { |
| 1614 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1614)) << "GetLastError()'s memory isn't mapped in this minidump"; |
| 1615 | return 0; |
| 1616 | } |
| 1617 | |
| 1618 | // The TEB is opaque but we know the value we want lives at this offset |
| 1619 | // from reverse engineering. |
| 1620 | uint64_t offset = pointer_width * 13; |
| 1621 | uint32_t error = 0; |
| 1622 | if (!region->GetMemoryAtAddress(thread_.teb + offset, &error)) { |
| 1623 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1623)) << "GetLastError()'s memory isn't mapped in this minidump"; |
| 1624 | return 0; |
| 1625 | } |
| 1626 | |
| 1627 | if (minidump_->swap()) { |
| 1628 | Swap(&error); |
| 1629 | } |
| 1630 | |
| 1631 | return error; |
| 1632 | } |
| 1633 | |
| 1634 | |
| 1635 | |
| 1636 | MinidumpContext* MinidumpThread::GetContext() { |
| 1637 | if (!valid_) { |
| 1638 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1638)) << "Invalid MinidumpThread for GetContext"; |
| 1639 | return NULL__null; |
| 1640 | } |
| 1641 | |
| 1642 | if (!context_) { |
| 1643 | if (!minidump_->SeekSet(thread_.thread_context.rva)) { |
| 1644 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1644)) << "MinidumpThread cannot seek to context"; |
| 1645 | return NULL__null; |
| 1646 | } |
| 1647 | |
| 1648 | scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); |
| 1649 | |
| 1650 | if (!context->Read(thread_.thread_context.data_size)) { |
| 1651 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1651)) << "MinidumpThread cannot read context"; |
| 1652 | return NULL__null; |
| 1653 | } |
| 1654 | |
| 1655 | context_ = context.release(); |
| 1656 | } |
| 1657 | |
| 1658 | return context_; |
| 1659 | } |
| 1660 | |
| 1661 | |
| 1662 | bool MinidumpThread::GetThreadID(uint32_t *thread_id) const { |
| 1663 | BPLOG_IF(ERROR, !thread_id)!(((!thread_id) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1663)) << "MinidumpThread::GetThreadID requires " |
| 1664 | "|thread_id|"; |
| 1665 | assert(thread_id)(static_cast <bool> (thread_id) ? void (0) : __assert_fail ("thread_id", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 1666 | *thread_id = 0; |
| 1667 | |
| 1668 | if (!valid_) { |
| 1669 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1669)) << "Invalid MinidumpThread for GetThreadID"; |
| 1670 | return false; |
| 1671 | } |
| 1672 | |
| 1673 | *thread_id = thread_.thread_id; |
| 1674 | return true; |
| 1675 | } |
| 1676 | |
| 1677 | |
| 1678 | void MinidumpThread::Print() { |
| 1679 | if (!valid_) { |
| 1680 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1680)) << "MinidumpThread cannot print invalid data"; |
| 1681 | return; |
| 1682 | } |
| 1683 | |
| 1684 | printf("MDRawThread\n"); |
| 1685 | printf(" thread_id = 0x%x\n", thread_.thread_id); |
| 1686 | printf(" suspend_count = %d\n", thread_.suspend_count); |
| 1687 | printf(" priority_class = 0x%x\n", thread_.priority_class); |
| 1688 | printf(" priority = 0x%x\n", thread_.priority); |
| 1689 | printf(" teb = 0x%" PRIx64"l" "x" "\n", thread_.teb); |
| 1690 | printf(" stack.start_of_memory_range = 0x%" PRIx64"l" "x" "\n", |
| 1691 | thread_.stack.start_of_memory_range); |
| 1692 | printf(" stack.memory.data_size = 0x%x\n", |
| 1693 | thread_.stack.memory.data_size); |
| 1694 | printf(" stack.memory.rva = 0x%x\n", thread_.stack.memory.rva); |
| 1695 | printf(" thread_context.data_size = 0x%x\n", |
| 1696 | thread_.thread_context.data_size); |
| 1697 | printf(" thread_context.rva = 0x%x\n", |
| 1698 | thread_.thread_context.rva); |
| 1699 | |
| 1700 | MinidumpContext* context = GetContext(); |
| 1701 | if (context) { |
| 1702 | printf("\n"); |
| 1703 | context->Print(); |
| 1704 | } else { |
| 1705 | printf(" (no context)\n"); |
| 1706 | printf("\n"); |
| 1707 | } |
| 1708 | |
| 1709 | MinidumpMemoryRegion* memory = GetMemory(); |
| 1710 | if (memory) { |
| 1711 | printf("Stack\n"); |
| 1712 | memory->Print(); |
| 1713 | } else { |
| 1714 | printf("No stack\n"); |
| 1715 | } |
| 1716 | printf("\n"); |
| 1717 | } |
| 1718 | |
| 1719 | |
| 1720 | // |
| 1721 | // MinidumpThreadList |
| 1722 | // |
| 1723 | |
| 1724 | |
| 1725 | uint32_t MinidumpThreadList::max_threads_ = 4096; |
| 1726 | |
| 1727 | |
| 1728 | MinidumpThreadList::MinidumpThreadList(Minidump* minidump) |
| 1729 | : MinidumpStream(minidump), |
| 1730 | id_to_thread_map_(), |
| 1731 | threads_(NULL__null), |
| 1732 | thread_count_(0) { |
| 1733 | } |
| 1734 | |
| 1735 | |
| 1736 | MinidumpThreadList::~MinidumpThreadList() { |
| 1737 | delete threads_; |
| 1738 | } |
| 1739 | |
| 1740 | |
| 1741 | bool MinidumpThreadList::Read(uint32_t expected_size) { |
| 1742 | // Invalidate cached data. |
| 1743 | id_to_thread_map_.clear(); |
| 1744 | delete threads_; |
| 1745 | threads_ = NULL__null; |
| 1746 | thread_count_ = 0; |
| 1747 | |
| 1748 | valid_ = false; |
| 1749 | |
| 1750 | uint32_t thread_count; |
| 1751 | if (expected_size < sizeof(thread_count)) { |
| 1752 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1752)) << "MinidumpThreadList count size mismatch, " << |
| 1753 | expected_size << " < " << sizeof(thread_count); |
| 1754 | return false; |
| 1755 | } |
| 1756 | if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) { |
| 1757 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1757)) << "MinidumpThreadList cannot read thread count"; |
| 1758 | return false; |
| 1759 | } |
| 1760 | |
| 1761 | if (minidump_->swap()) |
| 1762 | Swap(&thread_count); |
| 1763 | |
| 1764 | if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) { |
| 1765 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1765)) << "MinidumpThreadList thread count " << thread_count << |
| 1766 | " would cause multiplication overflow"; |
| 1767 | return false; |
| 1768 | } |
| 1769 | |
| 1770 | if (expected_size != sizeof(thread_count) + |
| 1771 | thread_count * sizeof(MDRawThread)) { |
| 1772 | // may be padded with 4 bytes on 64bit ABIs for alignment |
| 1773 | if (expected_size == sizeof(thread_count) + 4 + |
| 1774 | thread_count * sizeof(MDRawThread)) { |
| 1775 | uint32_t useless; |
| 1776 | if (!minidump_->ReadBytes(&useless, 4)) { |
| 1777 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1777)) << "MinidumpThreadList cannot read threadlist padded " |
| 1778 | "bytes"; |
| 1779 | return false; |
| 1780 | } |
| 1781 | } else { |
| 1782 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1782)) << "MinidumpThreadList size mismatch, " << expected_size << |
| 1783 | " != " << sizeof(thread_count) + |
| 1784 | thread_count * sizeof(MDRawThread); |
| 1785 | return false; |
| 1786 | } |
| 1787 | } |
| 1788 | |
| 1789 | |
| 1790 | if (thread_count > max_threads_) { |
| 1791 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1791)) << "MinidumpThreadList count " << thread_count << |
| 1792 | " exceeds maximum " << max_threads_; |
| 1793 | return false; |
| 1794 | } |
| 1795 | |
| 1796 | if (thread_count != 0) { |
| 1797 | scoped_ptr<MinidumpThreads> threads( |
| 1798 | new MinidumpThreads(thread_count, MinidumpThread(minidump_))); |
| 1799 | |
| 1800 | for (unsigned int thread_index = 0; |
| 1801 | thread_index < thread_count; |
| 1802 | ++thread_index) { |
| 1803 | MinidumpThread* thread = &(*threads)[thread_index]; |
| 1804 | |
| 1805 | // Assume that the file offset is correct after the last read. |
| 1806 | if (!thread->Read()) { |
| 1807 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1807)) << "MinidumpThreadList cannot read thread " << |
| 1808 | thread_index << "/" << thread_count; |
| 1809 | return false; |
| 1810 | } |
| 1811 | |
| 1812 | uint32_t thread_id; |
| 1813 | if (!thread->GetThreadID(&thread_id)) { |
| 1814 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1814)) << "MinidumpThreadList cannot get thread ID for thread " << |
| 1815 | thread_index << "/" << thread_count; |
| 1816 | return false; |
| 1817 | } |
| 1818 | |
| 1819 | if (GetThreadByID(thread_id)) { |
| 1820 | // Another thread with this ID is already in the list. Data error. |
| 1821 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1821)) << "MinidumpThreadList found multiple threads with ID " << |
| 1822 | HexString(thread_id) << " at thread " << |
| 1823 | thread_index << "/" << thread_count; |
| 1824 | return false; |
| 1825 | } |
| 1826 | id_to_thread_map_[thread_id] = thread; |
| 1827 | } |
| 1828 | |
| 1829 | threads_ = threads.release(); |
| 1830 | } |
| 1831 | |
| 1832 | thread_count_ = thread_count; |
| 1833 | |
| 1834 | valid_ = true; |
| 1835 | return true; |
| 1836 | } |
| 1837 | |
| 1838 | |
| 1839 | MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index) |
| 1840 | const { |
| 1841 | if (!valid_) { |
| 1842 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1842)) << "Invalid MinidumpThreadList for GetThreadAtIndex"; |
| 1843 | return NULL__null; |
| 1844 | } |
| 1845 | |
| 1846 | if (index >= thread_count_) { |
| 1847 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1847)) << "MinidumpThreadList index out of range: " << |
| 1848 | index << "/" << thread_count_; |
| 1849 | return NULL__null; |
| 1850 | } |
| 1851 | |
| 1852 | return &(*threads_)[index]; |
| 1853 | } |
| 1854 | |
| 1855 | |
| 1856 | MinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) { |
| 1857 | // Don't check valid_. Read calls this method before everything is |
| 1858 | // validated. It is safe to not check valid_ here. |
| 1859 | return id_to_thread_map_[thread_id]; |
| 1860 | } |
| 1861 | |
| 1862 | |
| 1863 | void MinidumpThreadList::Print() { |
| 1864 | if (!valid_) { |
| 1865 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1865)) << "MinidumpThreadList cannot print invalid data"; |
| 1866 | return; |
| 1867 | } |
| 1868 | |
| 1869 | printf("MinidumpThreadList\n"); |
| 1870 | printf(" thread_count = %d\n", thread_count_); |
| 1871 | printf("\n"); |
| 1872 | |
| 1873 | for (unsigned int thread_index = 0; |
| 1874 | thread_index < thread_count_; |
| 1875 | ++thread_index) { |
| 1876 | printf("thread[%d]\n", thread_index); |
| 1877 | |
| 1878 | (*threads_)[thread_index].Print(); |
| 1879 | } |
| 1880 | } |
| 1881 | |
| 1882 | |
| 1883 | // |
| 1884 | // MinidumpModule |
| 1885 | // |
| 1886 | |
| 1887 | |
| 1888 | uint32_t MinidumpModule::max_cv_bytes_ = 32768; |
| 1889 | uint32_t MinidumpModule::max_misc_bytes_ = 32768; |
| 1890 | |
| 1891 | |
| 1892 | MinidumpModule::MinidumpModule(Minidump* minidump) |
| 1893 | : MinidumpObject(minidump), |
| 1894 | module_valid_(false), |
| 1895 | has_debug_info_(false), |
| 1896 | module_(), |
| 1897 | name_(NULL__null), |
| 1898 | cv_record_(NULL__null), |
| 1899 | cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE0xffffffff), |
| 1900 | misc_record_(NULL__null) { |
| 1901 | } |
| 1902 | |
| 1903 | |
| 1904 | MinidumpModule::~MinidumpModule() { |
| 1905 | delete name_; |
| 1906 | delete cv_record_; |
| 1907 | delete misc_record_; |
| 1908 | } |
| 1909 | |
| 1910 | |
| 1911 | bool MinidumpModule::Read() { |
| 1912 | // Invalidate cached data. |
| 1913 | delete name_; |
| 1914 | name_ = NULL__null; |
| 1915 | delete cv_record_; |
| 1916 | cv_record_ = NULL__null; |
| 1917 | cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE0xffffffff; |
| 1918 | delete misc_record_; |
| 1919 | misc_record_ = NULL__null; |
| 1920 | |
| 1921 | module_valid_ = false; |
| 1922 | has_debug_info_ = false; |
| 1923 | valid_ = false; |
| 1924 | |
| 1925 | if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE108)) { |
| 1926 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1926)) << "MinidumpModule cannot read module"; |
| 1927 | return false; |
| 1928 | } |
| 1929 | |
| 1930 | if (minidump_->swap()) { |
| 1931 | Swap(&module_.base_of_image); |
| 1932 | Swap(&module_.size_of_image); |
| 1933 | Swap(&module_.checksum); |
| 1934 | Swap(&module_.time_date_stamp); |
| 1935 | Swap(&module_.module_name_rva); |
| 1936 | Swap(&module_.version_info.signature); |
| 1937 | Swap(&module_.version_info.struct_version); |
| 1938 | Swap(&module_.version_info.file_version_hi); |
| 1939 | Swap(&module_.version_info.file_version_lo); |
| 1940 | Swap(&module_.version_info.product_version_hi); |
| 1941 | Swap(&module_.version_info.product_version_lo); |
| 1942 | Swap(&module_.version_info.file_flags_mask); |
| 1943 | Swap(&module_.version_info.file_flags); |
| 1944 | Swap(&module_.version_info.file_os); |
| 1945 | Swap(&module_.version_info.file_type); |
| 1946 | Swap(&module_.version_info.file_subtype); |
| 1947 | Swap(&module_.version_info.file_date_hi); |
| 1948 | Swap(&module_.version_info.file_date_lo); |
| 1949 | Swap(&module_.cv_record); |
| 1950 | Swap(&module_.misc_record); |
| 1951 | // Don't swap reserved fields because their contents are unknown (as |
| 1952 | // are their proper widths). |
| 1953 | } |
| 1954 | |
| 1955 | // Check for base + size overflow or undersize. |
| 1956 | if (module_.size_of_image == 0 || |
| 1957 | module_.size_of_image > |
| 1958 | numeric_limits<uint64_t>::max() - module_.base_of_image) { |
| 1959 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1959)) << "MinidumpModule has a module problem, " << |
| 1960 | HexString(module_.base_of_image) << "+" << |
| 1961 | HexString(module_.size_of_image); |
| 1962 | return false; |
| 1963 | } |
| 1964 | |
| 1965 | module_valid_ = true; |
| 1966 | return true; |
| 1967 | } |
| 1968 | |
| 1969 | |
| 1970 | bool MinidumpModule::ReadAuxiliaryData() { |
| 1971 | if (!module_valid_) { |
| 1972 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1972)) << "Invalid MinidumpModule for ReadAuxiliaryData"; |
| 1973 | return false; |
| 1974 | } |
| 1975 | |
| 1976 | // Each module must have a name. |
| 1977 | name_ = minidump_->ReadString(module_.module_name_rva); |
| 1978 | if (!name_) { |
| 1979 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1979)) << "MinidumpModule could not read name"; |
| 1980 | return false; |
| 1981 | } |
| 1982 | |
| 1983 | // At this point, we have enough info for the module to be valid. |
| 1984 | valid_ = true; |
| 1985 | |
| 1986 | // CodeView and miscellaneous debug records are only required if the |
| 1987 | // module indicates that they exist. |
| 1988 | if (module_.cv_record.data_size && !GetCVRecord(NULL__null)) { |
| 1989 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1989)) << "MinidumpModule has no CodeView record, " |
| 1990 | "but one was expected"; |
| 1991 | return false; |
| 1992 | } |
| 1993 | |
| 1994 | if (module_.misc_record.data_size && !GetMiscRecord(NULL__null)) { |
| 1995 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 1995)) << "MinidumpModule has no miscellaneous debug record, " |
| 1996 | "but one was expected"; |
| 1997 | return false; |
| 1998 | } |
| 1999 | |
| 2000 | has_debug_info_ = true; |
| 2001 | return true; |
| 2002 | } |
| 2003 | |
| 2004 | |
| 2005 | string MinidumpModule::code_file() const { |
| 2006 | if (!valid_) { |
| 2007 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2007)) << "Invalid MinidumpModule for code_file"; |
| 2008 | return ""; |
| 2009 | } |
| 2010 | |
| 2011 | return *name_; |
| 2012 | } |
| 2013 | |
| 2014 | |
| 2015 | string MinidumpModule::code_identifier() const { |
| 2016 | if (!valid_) { |
| 2017 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2017)) << "Invalid MinidumpModule for code_identifier"; |
| 2018 | return ""; |
| 2019 | } |
| 2020 | |
| 2021 | if (!has_debug_info_) |
| 2022 | return ""; |
| 2023 | |
| 2024 | MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo(); |
| 2025 | if (!minidump_system_info) { |
| 2026 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2026)) << "MinidumpModule code_identifier requires " |
| 2027 | "MinidumpSystemInfo"; |
| 2028 | return ""; |
| 2029 | } |
| 2030 | |
| 2031 | const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info(); |
| 2032 | if (!raw_system_info) { |
| 2033 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2033)) << "MinidumpModule code_identifier requires MDRawSystemInfo"; |
| 2034 | return ""; |
| 2035 | } |
| 2036 | |
| 2037 | string identifier; |
| 2038 | |
| 2039 | switch (raw_system_info->platform_id) { |
| 2040 | case MD_OS_WIN32_NT: |
| 2041 | case MD_OS_WIN32_WINDOWS: { |
| 2042 | // Use the same format that the MS symbol server uses in filesystem |
| 2043 | // hierarchies. |
| 2044 | char identifier_string[17]; |
| 2045 | snprintf(identifier_string, sizeof(identifier_string), "%08X%x", |
| 2046 | module_.time_date_stamp, module_.size_of_image); |
| 2047 | identifier = identifier_string; |
| 2048 | break; |
| 2049 | } |
| 2050 | |
| 2051 | case MD_OS_ANDROID: |
| 2052 | case MD_OS_FUCHSIA: |
| 2053 | case MD_OS_LINUX: { |
| 2054 | // If ELF CodeView data is present, return the debug id. |
| 2055 | if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE0x4270454c) { |
| 2056 | const MDCVInfoELF* cv_record_elf = |
| 2057 | reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); |
| 2058 | assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE)(static_cast <bool> (cv_record_elf->cv_signature == 0x4270454c ) ? void (0) : __assert_fail ("cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2059 | |
| 2060 | for (unsigned int build_id_index = 0; |
| 2061 | build_id_index < (cv_record_->size() - MDCVInfoELF_minsize); |
| 2062 | ++build_id_index) { |
| 2063 | char hexbyte[3]; |
| 2064 | snprintf(hexbyte, sizeof(hexbyte), "%02x", |
| 2065 | cv_record_elf->build_id[build_id_index]); |
| 2066 | identifier += hexbyte; |
| 2067 | } |
| 2068 | break; |
| 2069 | } |
| 2070 | // Otherwise fall through to the case below. |
| 2071 | BP_FALLTHROUGH[[clang::fallthrough]]; |
| 2072 | } |
| 2073 | |
| 2074 | case MD_OS_MAC_OS_X: |
| 2075 | case MD_OS_IOS: |
| 2076 | case MD_OS_SOLARIS: |
| 2077 | case MD_OS_NACL: |
| 2078 | case MD_OS_PS3: { |
| 2079 | // TODO(mmentovai): support uuid extension if present, otherwise fall |
| 2080 | // back to version (from LC_ID_DYLIB?), otherwise fall back to something |
| 2081 | // else. |
| 2082 | identifier = "id"; |
| 2083 | break; |
| 2084 | } |
| 2085 | |
| 2086 | default: { |
| 2087 | // Without knowing what OS generated the dump, we can't generate a good |
| 2088 | // identifier. Return an empty string, signalling failure. |
| 2089 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2089)) << "MinidumpModule code_identifier requires known platform, " |
| 2090 | "found " << HexString(raw_system_info->platform_id); |
| 2091 | break; |
| 2092 | } |
| 2093 | } |
| 2094 | |
| 2095 | return identifier; |
| 2096 | } |
| 2097 | |
| 2098 | |
| 2099 | string MinidumpModule::debug_file() const { |
| 2100 | if (!valid_) { |
| 2101 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2101)) << "Invalid MinidumpModule for debug_file"; |
| 2102 | return ""; |
| 2103 | } |
| 2104 | |
| 2105 | if (!has_debug_info_) |
| 2106 | return ""; |
| 2107 | |
| 2108 | string file; |
| 2109 | // Prefer the CodeView record if present. |
| 2110 | if (cv_record_) { |
| 2111 | if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE0x53445352) { |
| 2112 | // It's actually an MDCVInfoPDB70 structure. |
| 2113 | const MDCVInfoPDB70* cv_record_70 = |
| 2114 | reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); |
| 2115 | assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE)(static_cast <bool> (cv_record_70->cv_signature == 0x53445352 ) ? void (0) : __assert_fail ("cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2116 | |
| 2117 | // GetCVRecord guarantees pdb_file_name is null-terminated. |
| 2118 | file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name); |
| 2119 | } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE0x3031424e) { |
| 2120 | // It's actually an MDCVInfoPDB20 structure. |
| 2121 | const MDCVInfoPDB20* cv_record_20 = |
| 2122 | reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); |
| 2123 | assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE)(static_cast <bool> (cv_record_20->cv_header.signature == 0x3031424e) ? void (0) : __assert_fail ("cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2124 | |
| 2125 | // GetCVRecord guarantees pdb_file_name is null-terminated. |
| 2126 | file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name); |
| 2127 | } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE0x4270454c) { |
| 2128 | // It's actually an MDCVInfoELF structure. |
| 2129 | assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])->(static_cast <bool> (reinterpret_cast<const MDCVInfoELF *>(&(*cv_record_)[0])-> cv_signature == 0x4270454c) ? void (0) : __assert_fail ("reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])-> cv_signature == MD_CVINFOELF_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )) |
| 2130 | cv_signature == MD_CVINFOELF_SIGNATURE)(static_cast <bool> (reinterpret_cast<const MDCVInfoELF *>(&(*cv_record_)[0])-> cv_signature == 0x4270454c) ? void (0) : __assert_fail ("reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])-> cv_signature == MD_CVINFOELF_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2131 | |
| 2132 | // For MDCVInfoELF, the debug file is the code file. |
| 2133 | file = *name_; |
| 2134 | } |
| 2135 | |
| 2136 | // If there's a CodeView record but it doesn't match a known signature, |
| 2137 | // try the miscellaneous record. |
| 2138 | } |
| 2139 | |
| 2140 | if (file.empty()) { |
| 2141 | // No usable CodeView record. Try the miscellaneous debug record. |
| 2142 | if (misc_record_) { |
| 2143 | const MDImageDebugMisc* misc_record = |
| 2144 | reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]); |
| 2145 | if (!misc_record->unicode) { |
| 2146 | // If it's not Unicode, just stuff it into the string. It's unclear |
| 2147 | // if misc_record->data is 0-terminated, so use an explicit size. |
| 2148 | file = string( |
| 2149 | reinterpret_cast<const char*>(misc_record->data), |
| 2150 | module_.misc_record.data_size - MDImageDebugMisc_minsize); |
| 2151 | } else { |
| 2152 | // There's a misc_record but it encodes the debug filename in UTF-16. |
| 2153 | // (Actually, because miscellaneous records are so old, it's probably |
| 2154 | // UCS-2.) Convert it to UTF-8 for congruity with the other strings |
| 2155 | // that this method (and all other methods in the Minidump family) |
| 2156 | // return. |
| 2157 | |
| 2158 | size_t bytes = |
| 2159 | module_.misc_record.data_size - MDImageDebugMisc_minsize; |
| 2160 | if (bytes % 2 == 0) { |
| 2161 | size_t utf16_words = bytes / 2; |
| 2162 | |
| 2163 | // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one |
| 2164 | // and copy the UTF-16 data into it. |
| 2165 | vector<uint16_t> string_utf16(utf16_words); |
| 2166 | if (utf16_words) |
| 2167 | memcpy(&string_utf16[0], &misc_record->data, bytes); |
| 2168 | |
| 2169 | // GetMiscRecord already byte-swapped the data[] field if it contains |
| 2170 | // UTF-16, so pass false as the swap argument. |
| 2171 | scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false)); |
| 2172 | if (new_file.get() != nullptr) { |
| 2173 | file = *new_file; |
| 2174 | } |
| 2175 | } |
| 2176 | } |
| 2177 | } |
| 2178 | } |
| 2179 | |
| 2180 | // Relatively common case |
| 2181 | BPLOG_IF(INFO, file.empty())!(((file.empty()) && ((google_breakpad::LogStream::SEVERITY_INFO ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::clog, google_breakpad::LogStream::SEVERITY_INFO , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2181)) << "MinidumpModule could not determine " |
| 2182 | "debug_file for " << *name_; |
| 2183 | |
| 2184 | return file; |
| 2185 | } |
| 2186 | |
| 2187 | static string guid_and_age_to_debug_id(const MDGUID& guid, |
| 2188 | uint32_t age) { |
| 2189 | char identifier_string[41]; |
| 2190 | snprintf(identifier_string, sizeof(identifier_string), |
| 2191 | "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", |
| 2192 | guid.data1, |
| 2193 | guid.data2, |
| 2194 | guid.data3, |
| 2195 | guid.data4[0], |
| 2196 | guid.data4[1], |
| 2197 | guid.data4[2], |
| 2198 | guid.data4[3], |
| 2199 | guid.data4[4], |
| 2200 | guid.data4[5], |
| 2201 | guid.data4[6], |
| 2202 | guid.data4[7], |
| 2203 | age); |
| 2204 | return identifier_string; |
| 2205 | } |
| 2206 | |
| 2207 | string MinidumpModule::debug_identifier() const { |
| 2208 | if (!valid_) { |
| 2209 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2209)) << "Invalid MinidumpModule for debug_identifier"; |
| 2210 | return ""; |
| 2211 | } |
| 2212 | |
| 2213 | if (!has_debug_info_) |
| 2214 | return ""; |
| 2215 | |
| 2216 | string identifier; |
| 2217 | |
| 2218 | // Use the CodeView record if present. |
| 2219 | if (cv_record_) { |
| 2220 | if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE0x53445352) { |
| 2221 | // It's actually an MDCVInfoPDB70 structure. |
| 2222 | const MDCVInfoPDB70* cv_record_70 = |
| 2223 | reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); |
| 2224 | assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE)(static_cast <bool> (cv_record_70->cv_signature == 0x53445352 ) ? void (0) : __assert_fail ("cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2225 | |
| 2226 | // Use the same format that the MS symbol server uses in filesystem |
| 2227 | // hierarchies. |
| 2228 | identifier = guid_and_age_to_debug_id(cv_record_70->signature, |
| 2229 | cv_record_70->age); |
| 2230 | } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE0x3031424e) { |
| 2231 | // It's actually an MDCVInfoPDB20 structure. |
| 2232 | const MDCVInfoPDB20* cv_record_20 = |
| 2233 | reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); |
| 2234 | assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE)(static_cast <bool> (cv_record_20->cv_header.signature == 0x3031424e) ? void (0) : __assert_fail ("cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2235 | |
| 2236 | // Use the same format that the MS symbol server uses in filesystem |
| 2237 | // hierarchies. |
| 2238 | char identifier_string[17]; |
| 2239 | snprintf(identifier_string, sizeof(identifier_string), |
| 2240 | "%08X%x", cv_record_20->signature, cv_record_20->age); |
| 2241 | identifier = identifier_string; |
| 2242 | } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE0x4270454c) { |
| 2243 | // It's actually an MDCVInfoELF structure. |
| 2244 | const MDCVInfoELF* cv_record_elf = |
| 2245 | reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); |
| 2246 | assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE)(static_cast <bool> (cv_record_elf->cv_signature == 0x4270454c ) ? void (0) : __assert_fail ("cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2247 | |
| 2248 | // For backwards-compatibility, stuff as many bytes as will fit into |
| 2249 | // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does |
| 2250 | // with age = 0. Historically Breakpad would do this during dump |
| 2251 | // writing to fit the build id data into a MDCVInfoPDB70 struct. |
| 2252 | // The full build id is available by calling code_identifier. |
| 2253 | MDGUID guid = {0}; |
| 2254 | memcpy(&guid, &cv_record_elf->build_id, |
| 2255 | std::min(cv_record_->size() - MDCVInfoELF_minsize, |
| 2256 | sizeof(MDGUID))); |
| 2257 | identifier = guid_and_age_to_debug_id(guid, 0); |
| 2258 | } |
| 2259 | } |
| 2260 | |
| 2261 | // TODO(mmentovai): if there's no usable CodeView record, there might be a |
| 2262 | // miscellaneous debug record. It only carries a filename, though, and no |
| 2263 | // identifier. I'm not sure what the right thing to do for the identifier |
| 2264 | // is in that case, but I don't expect to find many modules without a |
| 2265 | // CodeView record (or some other Breakpad extension structure in place of |
| 2266 | // a CodeView record). Treat it as an error (empty identifier) for now. |
| 2267 | |
| 2268 | // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). |
| 2269 | |
| 2270 | // Relatively common case |
| 2271 | BPLOG_IF(INFO, identifier.empty())!(((identifier.empty()) && ((google_breakpad::LogStream ::SEVERITY_INFO) >= (google_breakpad::LogStream::SEVERITY_CRITICAL )))) ? (void) 0 : google_breakpad::LogMessageVoidify() & ( google_breakpad::LogStream(std::clog, google_breakpad::LogStream ::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2271)) << "MinidumpModule could not determine " |
| 2272 | "debug_identifier for " << *name_; |
| 2273 | |
| 2274 | return identifier; |
| 2275 | } |
| 2276 | |
| 2277 | |
| 2278 | string MinidumpModule::version() const { |
| 2279 | if (!valid_) { |
| 2280 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2280)) << "Invalid MinidumpModule for version"; |
| 2281 | return ""; |
| 2282 | } |
| 2283 | |
| 2284 | string version; |
| 2285 | |
| 2286 | if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE0xfeef04bd && |
| 2287 | module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION0x00010000) { |
| 2288 | char version_string[24]; |
| 2289 | snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u", |
| 2290 | module_.version_info.file_version_hi >> 16, |
| 2291 | module_.version_info.file_version_hi & 0xffff, |
| 2292 | module_.version_info.file_version_lo >> 16, |
| 2293 | module_.version_info.file_version_lo & 0xffff); |
| 2294 | version = version_string; |
| 2295 | } |
| 2296 | |
| 2297 | // TODO(mmentovai): possibly support other struct types in place of |
| 2298 | // the one used with MD_VSFIXEDFILEINFO_SIGNATURE. We can possibly use |
| 2299 | // a different structure that better represents versioning facilities on |
| 2300 | // Mac OS X and Linux, instead of forcing them to adhere to the dotted |
| 2301 | // quad of 16-bit ints that Windows uses. |
| 2302 | |
| 2303 | BPLOG_IF(INFO, version.empty())!(((version.empty()) && ((google_breakpad::LogStream:: SEVERITY_INFO) >= (google_breakpad::LogStream::SEVERITY_CRITICAL )))) ? (void) 0 : google_breakpad::LogMessageVoidify() & ( google_breakpad::LogStream(std::clog, google_breakpad::LogStream ::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2303)) << "MinidumpModule could not determine " |
| 2304 | "version for " << *name_; |
| 2305 | |
| 2306 | return version; |
| 2307 | } |
| 2308 | |
| 2309 | |
| 2310 | CodeModule* MinidumpModule::Copy() const { |
| 2311 | return new BasicCodeModule(this); |
| 2312 | } |
| 2313 | |
| 2314 | |
| 2315 | uint64_t MinidumpModule::shrink_down_delta() const { |
| 2316 | return 0; |
| 2317 | } |
| 2318 | |
| 2319 | void MinidumpModule::SetShrinkDownDelta(uint64_t shrink_down_delta) { |
| 2320 | // Not implemented |
| 2321 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2322 | } |
| 2323 | |
| 2324 | |
| 2325 | const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { |
| 2326 | if (!module_valid_) { |
| 2327 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2327)) << "Invalid MinidumpModule for GetCVRecord"; |
| 2328 | return NULL__null; |
| 2329 | } |
| 2330 | |
| 2331 | if (!cv_record_) { |
| 2332 | // This just guards against 0-sized CodeView records; more specific checks |
| 2333 | // are used when the signature is checked against various structure types. |
| 2334 | if (module_.cv_record.data_size == 0) { |
| 2335 | return NULL__null; |
| 2336 | } |
| 2337 | |
| 2338 | if (!minidump_->SeekSet(module_.cv_record.rva)) { |
| 2339 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2339)) << "MinidumpModule could not seek to CodeView record"; |
| 2340 | return NULL__null; |
| 2341 | } |
| 2342 | |
| 2343 | if (module_.cv_record.data_size > max_cv_bytes_) { |
| 2344 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2344)) << "MinidumpModule CodeView record size " << |
| 2345 | module_.cv_record.data_size << " exceeds maximum " << |
| 2346 | max_cv_bytes_; |
| 2347 | return NULL__null; |
| 2348 | } |
| 2349 | |
| 2350 | // Allocating something that will be accessed as MDCVInfoPDB70 or |
| 2351 | // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment |
| 2352 | // problems. x86 and ppc are able to cope, though. This allocation |
| 2353 | // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are |
| 2354 | // variable-sized due to their pdb_file_name fields; these structures |
| 2355 | // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating |
| 2356 | // them as such would result in incomplete structures or overruns. |
| 2357 | scoped_ptr< vector<uint8_t> > cv_record( |
| 2358 | new vector<uint8_t>(module_.cv_record.data_size)); |
| 2359 | |
| 2360 | if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) { |
| 2361 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2361)) << "MinidumpModule could not read CodeView record"; |
| 2362 | return NULL__null; |
| 2363 | } |
| 2364 | |
| 2365 | uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE0xffffffff; |
| 2366 | if (module_.cv_record.data_size > sizeof(signature)) { |
| 2367 | MDCVInfoPDB70* cv_record_signature = |
| 2368 | reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); |
| 2369 | signature = cv_record_signature->cv_signature; |
| 2370 | if (minidump_->swap()) |
| 2371 | Swap(&signature); |
| 2372 | } |
| 2373 | |
| 2374 | if (signature == MD_CVINFOPDB70_SIGNATURE0x53445352) { |
| 2375 | // Now that the structure type is known, recheck the size, |
| 2376 | // ensuring at least one byte for the null terminator. |
| 2377 | if (MDCVInfoPDB70_minsize + 1 > module_.cv_record.data_size) { |
| 2378 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2378)) << "MinidumpModule CodeView7 record size mismatch, " << |
| 2379 | MDCVInfoPDB70_minsize << " > " << |
| 2380 | module_.cv_record.data_size; |
| 2381 | return NULL__null; |
| 2382 | } |
| 2383 | |
| 2384 | if (minidump_->swap()) { |
| 2385 | MDCVInfoPDB70* cv_record_70 = |
| 2386 | reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); |
| 2387 | Swap(&cv_record_70->cv_signature); |
| 2388 | Swap(&cv_record_70->signature); |
| 2389 | Swap(&cv_record_70->age); |
| 2390 | // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit |
| 2391 | // quantities. (It's a path, is it UTF-8?) |
| 2392 | } |
| 2393 | |
| 2394 | // The last field of either structure is null-terminated 8-bit character |
| 2395 | // data. Ensure that it's null-terminated. |
| 2396 | if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { |
| 2397 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2397)) << "MinidumpModule CodeView7 record string is not " |
| 2398 | "0-terminated"; |
| 2399 | return NULL__null; |
| 2400 | } |
| 2401 | } else if (signature == MD_CVINFOPDB20_SIGNATURE0x3031424e) { |
| 2402 | // Now that the structure type is known, recheck the size, |
| 2403 | // ensuring at least one byte for the null terminator. |
| 2404 | if (MDCVInfoPDB20_minsize + 1 > module_.cv_record.data_size) { |
| 2405 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2405)) << "MinidumpModule CodeView2 record size mismatch, " << |
| 2406 | MDCVInfoPDB20_minsize << " > " << |
| 2407 | module_.cv_record.data_size; |
| 2408 | return NULL__null; |
| 2409 | } |
| 2410 | if (minidump_->swap()) { |
| 2411 | MDCVInfoPDB20* cv_record_20 = |
| 2412 | reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]); |
| 2413 | Swap(&cv_record_20->cv_header.signature); |
| 2414 | Swap(&cv_record_20->cv_header.offset); |
| 2415 | Swap(&cv_record_20->signature); |
| 2416 | Swap(&cv_record_20->age); |
| 2417 | // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit |
| 2418 | // quantities. (It's a path, is it UTF-8?) |
| 2419 | } |
| 2420 | |
| 2421 | // The last field of either structure is null-terminated 8-bit character |
| 2422 | // data. Ensure that it's null-terminated. |
| 2423 | if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { |
| 2424 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2424)) << "MindumpModule CodeView2 record string is not " |
| 2425 | "0-terminated"; |
| 2426 | return NULL__null; |
| 2427 | } |
| 2428 | } else if (signature == MD_CVINFOELF_SIGNATURE0x4270454c) { |
| 2429 | // Now that the structure type is known, recheck the size. |
| 2430 | if (MDCVInfoELF_minsize > module_.cv_record.data_size) { |
| 2431 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2431)) << "MinidumpModule CodeViewELF record size mismatch, " << |
| 2432 | MDCVInfoELF_minsize << " > " << |
| 2433 | module_.cv_record.data_size; |
| 2434 | return NULL__null; |
| 2435 | } |
| 2436 | if (minidump_->swap()) { |
| 2437 | MDCVInfoELF* cv_record_elf = |
| 2438 | reinterpret_cast<MDCVInfoELF*>(&(*cv_record)[0]); |
| 2439 | Swap(&cv_record_elf->cv_signature); |
| 2440 | } |
| 2441 | } |
| 2442 | |
| 2443 | // If the signature doesn't match something above, it's not something |
| 2444 | // that Breakpad can presently handle directly. Because some modules in |
| 2445 | // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, |
| 2446 | // don't bail out here - allow the data to be returned to the user, |
| 2447 | // although byte-swapping can't be done. |
| 2448 | |
| 2449 | // Store the vector type because that's how storage was allocated, but |
| 2450 | // return it casted to uint8_t*. |
| 2451 | cv_record_ = cv_record.release(); |
| 2452 | cv_record_signature_ = signature; |
| 2453 | } |
| 2454 | |
| 2455 | if (size) |
| 2456 | *size = module_.cv_record.data_size; |
| 2457 | |
| 2458 | return &(*cv_record_)[0]; |
| 2459 | } |
| 2460 | |
| 2461 | |
| 2462 | const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { |
| 2463 | if (!module_valid_) { |
| 2464 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2464)) << "Invalid MinidumpModule for GetMiscRecord"; |
| 2465 | return NULL__null; |
| 2466 | } |
| 2467 | |
| 2468 | if (!misc_record_) { |
| 2469 | if (module_.misc_record.data_size == 0) { |
| 2470 | return NULL__null; |
| 2471 | } |
| 2472 | |
| 2473 | if (MDImageDebugMisc_minsize > module_.misc_record.data_size) { |
| 2474 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2474)) << "MinidumpModule miscellaneous debugging record " |
| 2475 | "size mismatch, " << MDImageDebugMisc_minsize << " > " << |
| 2476 | module_.misc_record.data_size; |
| 2477 | return NULL__null; |
| 2478 | } |
| 2479 | |
| 2480 | if (!minidump_->SeekSet(module_.misc_record.rva)) { |
| 2481 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2481)) << "MinidumpModule could not seek to miscellaneous " |
| 2482 | "debugging record"; |
| 2483 | return NULL__null; |
| 2484 | } |
| 2485 | |
| 2486 | if (module_.misc_record.data_size > max_misc_bytes_) { |
| 2487 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2487)) << "MinidumpModule miscellaneous debugging record size " << |
| 2488 | module_.misc_record.data_size << " exceeds maximum " << |
| 2489 | max_misc_bytes_; |
| 2490 | return NULL__null; |
| 2491 | } |
| 2492 | |
| 2493 | // Allocating something that will be accessed as MDImageDebugMisc but |
| 2494 | // is allocated as uint8_t[] can cause alignment problems. x86 and |
| 2495 | // ppc are able to cope, though. This allocation style is needed |
| 2496 | // because the MDImageDebugMisc is variable-sized due to its data field; |
| 2497 | // this structure is not MDImageDebugMisc_minsize and treating it as such |
| 2498 | // would result in an incomplete structure or an overrun. |
| 2499 | scoped_ptr< vector<uint8_t> > misc_record_mem( |
| 2500 | new vector<uint8_t>(module_.misc_record.data_size)); |
| 2501 | MDImageDebugMisc* misc_record = |
| 2502 | reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]); |
| 2503 | |
| 2504 | if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) { |
| 2505 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2505)) << "MinidumpModule could not read miscellaneous debugging " |
| 2506 | "record"; |
| 2507 | return NULL__null; |
| 2508 | } |
| 2509 | |
| 2510 | if (minidump_->swap()) { |
| 2511 | Swap(&misc_record->data_type); |
| 2512 | Swap(&misc_record->length); |
| 2513 | // Don't swap misc_record.unicode because it's an 8-bit quantity. |
| 2514 | // Don't swap the reserved fields for the same reason, and because |
| 2515 | // they don't contain any valid data. |
| 2516 | if (misc_record->unicode) { |
| 2517 | // There is a potential alignment problem, but shouldn't be a problem |
| 2518 | // in practice due to the layout of MDImageDebugMisc. |
| 2519 | uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data)); |
| 2520 | size_t dataBytes = module_.misc_record.data_size - |
| 2521 | MDImageDebugMisc_minsize; |
| 2522 | Swap(data16, dataBytes); |
| 2523 | } |
| 2524 | } |
| 2525 | |
| 2526 | if (module_.misc_record.data_size != misc_record->length) { |
| 2527 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2527)) << "MinidumpModule miscellaneous debugging record data " |
| 2528 | "size mismatch, " << module_.misc_record.data_size << |
| 2529 | " != " << misc_record->length; |
| 2530 | return NULL__null; |
| 2531 | } |
| 2532 | |
| 2533 | // Store the vector type because that's how storage was allocated, but |
| 2534 | // return it casted to MDImageDebugMisc*. |
| 2535 | misc_record_ = misc_record_mem.release(); |
| 2536 | } |
| 2537 | |
| 2538 | if (size) |
| 2539 | *size = module_.misc_record.data_size; |
| 2540 | |
| 2541 | return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]); |
| 2542 | } |
| 2543 | |
| 2544 | |
| 2545 | void MinidumpModule::Print() { |
| 2546 | if (!valid_) { |
| 2547 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2547)) << "MinidumpModule cannot print invalid data"; |
| 2548 | return; |
| 2549 | } |
| 2550 | |
| 2551 | printf("MDRawModule\n"); |
| 2552 | printf(" base_of_image = 0x%" PRIx64"l" "x" "\n", |
| 2553 | module_.base_of_image); |
| 2554 | printf(" size_of_image = 0x%x\n", |
| 2555 | module_.size_of_image); |
| 2556 | printf(" checksum = 0x%x\n", |
| 2557 | module_.checksum); |
| 2558 | printf(" time_date_stamp = 0x%x %s\n", |
| 2559 | module_.time_date_stamp, |
| 2560 | TimeTToUTCString(module_.time_date_stamp).c_str()); |
| 2561 | printf(" module_name_rva = 0x%x\n", |
| 2562 | module_.module_name_rva); |
| 2563 | printf(" version_info.signature = 0x%x\n", |
| 2564 | module_.version_info.signature); |
| 2565 | printf(" version_info.struct_version = 0x%x\n", |
| 2566 | module_.version_info.struct_version); |
| 2567 | printf(" version_info.file_version = 0x%x:0x%x\n", |
| 2568 | module_.version_info.file_version_hi, |
| 2569 | module_.version_info.file_version_lo); |
| 2570 | printf(" version_info.product_version = 0x%x:0x%x\n", |
| 2571 | module_.version_info.product_version_hi, |
| 2572 | module_.version_info.product_version_lo); |
| 2573 | printf(" version_info.file_flags_mask = 0x%x\n", |
| 2574 | module_.version_info.file_flags_mask); |
| 2575 | printf(" version_info.file_flags = 0x%x\n", |
| 2576 | module_.version_info.file_flags); |
| 2577 | printf(" version_info.file_os = 0x%x\n", |
| 2578 | module_.version_info.file_os); |
| 2579 | printf(" version_info.file_type = 0x%x\n", |
| 2580 | module_.version_info.file_type); |
| 2581 | printf(" version_info.file_subtype = 0x%x\n", |
| 2582 | module_.version_info.file_subtype); |
| 2583 | printf(" version_info.file_date = 0x%x:0x%x\n", |
| 2584 | module_.version_info.file_date_hi, |
| 2585 | module_.version_info.file_date_lo); |
| 2586 | printf(" cv_record.data_size = %d\n", |
| 2587 | module_.cv_record.data_size); |
| 2588 | printf(" cv_record.rva = 0x%x\n", |
| 2589 | module_.cv_record.rva); |
| 2590 | printf(" misc_record.data_size = %d\n", |
| 2591 | module_.misc_record.data_size); |
| 2592 | printf(" misc_record.rva = 0x%x\n", |
| 2593 | module_.misc_record.rva); |
| 2594 | |
| 2595 | printf(" (code_file) = \"%s\"\n", code_file().c_str()); |
| 2596 | printf(" (code_identifier) = \"%s\"\n", |
| 2597 | code_identifier().c_str()); |
| 2598 | |
| 2599 | uint32_t cv_record_size; |
| 2600 | const uint8_t *cv_record = GetCVRecord(&cv_record_size); |
| 2601 | if (cv_record) { |
| 2602 | if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE0x53445352) { |
| 2603 | const MDCVInfoPDB70* cv_record_70 = |
| 2604 | reinterpret_cast<const MDCVInfoPDB70*>(cv_record); |
| 2605 | assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE)(static_cast <bool> (cv_record_70->cv_signature == 0x53445352 ) ? void (0) : __assert_fail ("cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2606 | |
| 2607 | printf(" (cv_record).cv_signature = 0x%x\n", |
| 2608 | cv_record_70->cv_signature); |
| 2609 | printf(" (cv_record).signature = %s\n", |
| 2610 | MDGUIDToString(cv_record_70->signature).c_str()); |
| 2611 | printf(" (cv_record).age = %d\n", |
| 2612 | cv_record_70->age); |
| 2613 | printf(" (cv_record).pdb_file_name = \"%s\"\n", |
| 2614 | cv_record_70->pdb_file_name); |
| 2615 | } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE0x3031424e) { |
| 2616 | const MDCVInfoPDB20* cv_record_20 = |
| 2617 | reinterpret_cast<const MDCVInfoPDB20*>(cv_record); |
| 2618 | assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE)(static_cast <bool> (cv_record_20->cv_header.signature == 0x3031424e) ? void (0) : __assert_fail ("cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2619 | |
| 2620 | printf(" (cv_record).cv_header.signature = 0x%x\n", |
| 2621 | cv_record_20->cv_header.signature); |
| 2622 | printf(" (cv_record).cv_header.offset = 0x%x\n", |
| 2623 | cv_record_20->cv_header.offset); |
| 2624 | printf(" (cv_record).signature = 0x%x %s\n", |
| 2625 | cv_record_20->signature, |
| 2626 | TimeTToUTCString(cv_record_20->signature).c_str()); |
| 2627 | printf(" (cv_record).age = %d\n", |
| 2628 | cv_record_20->age); |
| 2629 | printf(" (cv_record).pdb_file_name = \"%s\"\n", |
| 2630 | cv_record_20->pdb_file_name); |
| 2631 | } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE0x4270454c) { |
| 2632 | const MDCVInfoELF* cv_record_elf = |
| 2633 | reinterpret_cast<const MDCVInfoELF*>(cv_record); |
| 2634 | assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE)(static_cast <bool> (cv_record_elf->cv_signature == 0x4270454c ) ? void (0) : __assert_fail ("cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 2635 | |
| 2636 | printf(" (cv_record).cv_signature = 0x%x\n", |
| 2637 | cv_record_elf->cv_signature); |
| 2638 | printf(" (cv_record).build_id = "); |
| 2639 | for (unsigned int build_id_index = 0; |
| 2640 | build_id_index < (cv_record_size - MDCVInfoELF_minsize); |
| 2641 | ++build_id_index) { |
| 2642 | printf("%02x", cv_record_elf->build_id[build_id_index]); |
| 2643 | } |
| 2644 | printf("\n"); |
| 2645 | } else { |
| 2646 | printf(" (cv_record) = "); |
| 2647 | for (unsigned int cv_byte_index = 0; |
| 2648 | cv_byte_index < cv_record_size; |
| 2649 | ++cv_byte_index) { |
| 2650 | printf("%02x", cv_record[cv_byte_index]); |
| 2651 | } |
| 2652 | printf("\n"); |
| 2653 | } |
| 2654 | } else { |
| 2655 | printf(" (cv_record) = (null)\n"); |
| 2656 | } |
| 2657 | |
| 2658 | const MDImageDebugMisc* misc_record = GetMiscRecord(NULL__null); |
| 2659 | if (misc_record) { |
| 2660 | printf(" (misc_record).data_type = 0x%x\n", |
| 2661 | misc_record->data_type); |
| 2662 | printf(" (misc_record).length = 0x%x\n", |
| 2663 | misc_record->length); |
| 2664 | printf(" (misc_record).unicode = %d\n", |
| 2665 | misc_record->unicode); |
| 2666 | if (misc_record->unicode) { |
| 2667 | string misc_record_data_utf8; |
| 2668 | ConvertUTF16BufferToUTF8String( |
| 2669 | reinterpret_cast<const uint16_t*>(misc_record->data), |
| 2670 | misc_record->length - offsetof(MDImageDebugMisc, data)__builtin_offsetof(MDImageDebugMisc, data), |
| 2671 | &misc_record_data_utf8, |
| 2672 | false); // already swapped |
| 2673 | printf(" (misc_record).data = \"%s\"\n", |
| 2674 | misc_record_data_utf8.c_str()); |
| 2675 | } else { |
| 2676 | printf(" (misc_record).data = \"%s\"\n", |
| 2677 | misc_record->data); |
| 2678 | } |
| 2679 | } else { |
| 2680 | printf(" (misc_record) = (null)\n"); |
| 2681 | } |
| 2682 | |
| 2683 | printf(" (debug_file) = \"%s\"\n", debug_file().c_str()); |
| 2684 | printf(" (debug_identifier) = \"%s\"\n", |
| 2685 | debug_identifier().c_str()); |
| 2686 | printf(" (version) = \"%s\"\n", version().c_str()); |
| 2687 | printf("\n"); |
| 2688 | } |
| 2689 | |
| 2690 | |
| 2691 | // |
| 2692 | // MinidumpModuleList |
| 2693 | // |
| 2694 | |
| 2695 | |
| 2696 | uint32_t MinidumpModuleList::max_modules_ = 2048; |
| 2697 | |
| 2698 | |
| 2699 | MinidumpModuleList::MinidumpModuleList(Minidump* minidump) |
| 2700 | : MinidumpStream(minidump), |
| 2701 | range_map_(new RangeMap<uint64_t, unsigned int>()), |
| 2702 | modules_(NULL__null), |
| 2703 | module_count_(0) { |
| 2704 | MDOSPlatform platform; |
| 2705 | if (minidump_->GetPlatform(&platform) && |
| 2706 | (platform == MD_OS_ANDROID || platform == MD_OS_LINUX)) { |
| 2707 | range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower); |
| 2708 | } |
| 2709 | } |
| 2710 | |
| 2711 | |
| 2712 | MinidumpModuleList::~MinidumpModuleList() { |
| 2713 | delete range_map_; |
| 2714 | delete modules_; |
| 2715 | } |
| 2716 | |
| 2717 | |
| 2718 | bool MinidumpModuleList::Read(uint32_t expected_size) { |
| 2719 | // Invalidate cached data. |
| 2720 | range_map_->Clear(); |
| 2721 | delete modules_; |
| 2722 | modules_ = NULL__null; |
| 2723 | module_count_ = 0; |
| 2724 | |
| 2725 | valid_ = false; |
| 2726 | |
| 2727 | uint32_t module_count; |
| 2728 | if (expected_size < sizeof(module_count)) { |
| 2729 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2729)) << "MinidumpModuleList count size mismatch, " << |
| 2730 | expected_size << " < " << sizeof(module_count); |
| 2731 | return false; |
| 2732 | } |
| 2733 | if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) { |
| 2734 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2734)) << "MinidumpModuleList could not read module count"; |
| 2735 | return false; |
| 2736 | } |
| 2737 | |
| 2738 | if (minidump_->swap()) |
| 2739 | Swap(&module_count); |
| 2740 | |
| 2741 | if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE108) { |
| 2742 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2742)) << "MinidumpModuleList module count " << module_count << |
| 2743 | " would cause multiplication overflow"; |
| 2744 | return false; |
| 2745 | } |
| 2746 | |
| 2747 | if (expected_size != sizeof(module_count) + |
| 2748 | module_count * MD_MODULE_SIZE108) { |
| 2749 | // may be padded with 4 bytes on 64bit ABIs for alignment |
| 2750 | if (expected_size == sizeof(module_count) + 4 + |
| 2751 | module_count * MD_MODULE_SIZE108) { |
| 2752 | uint32_t useless; |
| 2753 | if (!minidump_->ReadBytes(&useless, 4)) { |
| 2754 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2754)) << "MinidumpModuleList cannot read modulelist padded " |
| 2755 | "bytes"; |
| 2756 | return false; |
| 2757 | } |
| 2758 | } else { |
| 2759 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2759)) << "MinidumpModuleList size mismatch, " << expected_size << |
| 2760 | " != " << sizeof(module_count) + |
| 2761 | module_count * MD_MODULE_SIZE108; |
| 2762 | return false; |
| 2763 | } |
| 2764 | } |
| 2765 | |
| 2766 | if (module_count > max_modules_) { |
| 2767 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2767)) << "MinidumpModuleList count " << module_count << |
| 2768 | " exceeds maximum " << max_modules_; |
| 2769 | return false; |
| 2770 | } |
| 2771 | |
| 2772 | if (module_count != 0) { |
| 2773 | scoped_ptr<MinidumpModules> modules( |
| 2774 | new MinidumpModules(module_count, MinidumpModule(minidump_))); |
| 2775 | |
| 2776 | for (uint32_t module_index = 0; module_index < module_count; |
| 2777 | ++module_index) { |
| 2778 | MinidumpModule* module = &(*modules)[module_index]; |
| 2779 | |
| 2780 | // Assume that the file offset is correct after the last read. |
| 2781 | if (!module->Read()) { |
| 2782 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2782)) << "MinidumpModuleList could not read module " << |
| 2783 | module_index << "/" << module_count; |
| 2784 | return false; |
| 2785 | } |
| 2786 | } |
| 2787 | |
| 2788 | // Loop through the module list once more to read additional data and |
| 2789 | // build the range map. This is done in a second pass because |
| 2790 | // MinidumpModule::ReadAuxiliaryData seeks around, and if it were |
| 2791 | // included in the loop above, additional seeks would be needed where |
| 2792 | // none are now to read contiguous data. |
| 2793 | uint64_t last_end_address = 0; |
| 2794 | for (uint32_t module_index = 0; module_index < module_count; |
| 2795 | ++module_index) { |
| 2796 | MinidumpModule& module = (*modules)[module_index]; |
| 2797 | |
| 2798 | // ReadAuxiliaryData fails if any data that the module indicates should |
| 2799 | // exist is missing, but we treat some such cases as valid anyway. See |
| 2800 | // issue #222: if a debugging record is of a format that's too large to |
| 2801 | // handle, it shouldn't render the entire dump invalid. Check module |
| 2802 | // validity before giving up. |
| 2803 | if (!module.ReadAuxiliaryData() && !module.valid()) { |
| 2804 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2804)) << "MinidumpModuleList could not read required module " |
| 2805 | "auxiliary data for module " << |
| 2806 | module_index << "/" << module_count; |
| 2807 | return false; |
| 2808 | } |
| 2809 | |
| 2810 | // It is safe to use module->code_file() after successfully calling |
| 2811 | // module->ReadAuxiliaryData or noting that the module is valid. |
| 2812 | |
| 2813 | uint64_t base_address = module.base_address(); |
| 2814 | uint64_t module_size = module.size(); |
| 2815 | if (base_address == static_cast<uint64_t>(-1)) { |
| 2816 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2816)) << "MinidumpModuleList found bad base address for module " |
| 2817 | << module_index << "/" << module_count << ", " |
| 2818 | << module.code_file(); |
| 2819 | return false; |
| 2820 | } |
| 2821 | |
| 2822 | // Some minidumps have additional modules in the list that are duplicates. |
| 2823 | // Ignore them. See https://crbug.com/838322 |
| 2824 | uint32_t existing_module_index; |
| 2825 | if (range_map_->RetrieveRange(base_address, &existing_module_index, |
| 2826 | nullptr, nullptr, nullptr) && |
| 2827 | existing_module_index < module_count) { |
| 2828 | const MinidumpModule& existing_module = |
| 2829 | (*modules)[existing_module_index]; |
| 2830 | if (existing_module.base_address() == module.base_address() && |
| 2831 | existing_module.size() == module.size() && |
| 2832 | existing_module.code_file() == module.code_file() && |
| 2833 | existing_module.code_identifier() == module.code_identifier()) { |
| 2834 | continue; |
| 2835 | } |
| 2836 | } |
| 2837 | |
| 2838 | const bool is_android = minidump_->IsAndroid(); |
| 2839 | if (!StoreRange(module, base_address, module_index, module_count, |
| 2840 | is_android)) { |
| 2841 | if (!is_android || base_address >= last_end_address) { |
| 2842 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2842)) << "MinidumpModuleList could not store module " |
| 2843 | << module_index << "/" << module_count << ", " |
| 2844 | << module.code_file() << ", " << HexString(base_address) |
| 2845 | << "+" << HexString(module_size); |
| 2846 | return false; |
| 2847 | } |
| 2848 | |
| 2849 | // If failed due to apparent range overlap the cause may be the client |
| 2850 | // correction applied for Android packed relocations. If this is the |
| 2851 | // case, back out the client correction and retry. |
| 2852 | assert(is_android)(static_cast <bool> (is_android) ? void (0) : __assert_fail ("is_android", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 2853 | module_size -= last_end_address - base_address; |
| 2854 | base_address = last_end_address; |
| 2855 | if (!range_map_->StoreRange(base_address, module_size, module_index)) { |
| 2856 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2856)) << "MinidumpModuleList could not store module " |
| 2857 | << module_index << "/" << module_count << ", " |
| 2858 | << module.code_file() << ", " << HexString(base_address) |
| 2859 | << "+" << HexString(module_size) << ", after adjusting"; |
| 2860 | return false; |
| 2861 | } |
| 2862 | } |
| 2863 | last_end_address = base_address + module_size; |
| 2864 | } |
| 2865 | |
| 2866 | modules_ = modules.release(); |
| 2867 | } |
| 2868 | |
| 2869 | module_count_ = module_count; |
| 2870 | |
| 2871 | valid_ = true; |
| 2872 | return true; |
| 2873 | } |
| 2874 | |
| 2875 | bool MinidumpModuleList::StoreRange(const MinidumpModule& module, |
| 2876 | uint64_t base_address, |
| 2877 | uint32_t module_index, |
| 2878 | uint32_t module_count, |
| 2879 | bool is_android) { |
| 2880 | if (range_map_->StoreRange(base_address, module.size(), module_index)) |
| 2881 | return true; |
| 2882 | |
| 2883 | // Android's shared memory implementation /dev/ashmem can contain duplicate |
| 2884 | // entries for JITted code, so ignore these. |
| 2885 | // TODO(wfh): Remove this code when Android is fixed. |
| 2886 | // See https://crbug.com/439531 |
| 2887 | if (is_android && IsDevAshmem(module.code_file())) { |
| 2888 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2888)) << "MinidumpModuleList ignoring overlapping module " |
| 2889 | << module_index << "/" << module_count << ", " |
| 2890 | << module.code_file() << ", " << HexString(base_address) << "+" |
| 2891 | << HexString(module.size()); |
| 2892 | return true; |
| 2893 | } |
| 2894 | |
| 2895 | return false; |
| 2896 | } |
| 2897 | |
| 2898 | const MinidumpModule* MinidumpModuleList::GetModuleForAddress( |
| 2899 | uint64_t address) const { |
| 2900 | if (!valid_) { |
| 2901 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2901)) << "Invalid MinidumpModuleList for GetModuleForAddress"; |
| 2902 | return NULL__null; |
| 2903 | } |
| 2904 | |
| 2905 | unsigned int module_index; |
| 2906 | if (!range_map_->RetrieveRange(address, &module_index, NULL__null /* base */, |
| 2907 | NULL__null /* delta */, NULL__null /* size */)) { |
| 2908 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2908)) << "MinidumpModuleList has no module at " << |
| 2909 | HexString(address); |
| 2910 | return NULL__null; |
| 2911 | } |
| 2912 | |
| 2913 | return GetModuleAtIndex(module_index); |
| 2914 | } |
| 2915 | |
| 2916 | |
| 2917 | const MinidumpModule* MinidumpModuleList::GetMainModule() const { |
| 2918 | if (!valid_) { |
| 2919 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2919)) << "Invalid MinidumpModuleList for GetMainModule"; |
| 2920 | return NULL__null; |
| 2921 | } |
| 2922 | |
| 2923 | // The main code module is the first one present in a minidump file's |
| 2924 | // MDRawModuleList. |
| 2925 | return GetModuleAtIndex(0); |
| 2926 | } |
| 2927 | |
| 2928 | |
| 2929 | const MinidumpModule* MinidumpModuleList::GetModuleAtSequence( |
| 2930 | unsigned int sequence) const { |
| 2931 | if (!valid_) { |
| 2932 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2932)) << "Invalid MinidumpModuleList for GetModuleAtSequence"; |
| 2933 | return NULL__null; |
| 2934 | } |
| 2935 | |
| 2936 | if (sequence >= module_count_) { |
| 2937 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2937)) << "MinidumpModuleList sequence out of range: " << |
| 2938 | sequence << "/" << module_count_; |
| 2939 | return NULL__null; |
| 2940 | } |
| 2941 | |
| 2942 | unsigned int module_index; |
| 2943 | if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, |
| 2944 | NULL__null /* base */, NULL__null /* delta */, |
| 2945 | NULL__null /* size */)) { |
| 2946 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2946)) << "MinidumpModuleList has no module at sequence " << sequence; |
| 2947 | return NULL__null; |
| 2948 | } |
| 2949 | |
| 2950 | return GetModuleAtIndex(module_index); |
| 2951 | } |
| 2952 | |
| 2953 | |
| 2954 | const MinidumpModule* MinidumpModuleList::GetModuleAtIndex( |
| 2955 | unsigned int index) const { |
| 2956 | if (!valid_) { |
| 2957 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2957)) << "Invalid MinidumpModuleList for GetModuleAtIndex"; |
| 2958 | return NULL__null; |
| 2959 | } |
| 2960 | |
| 2961 | if (index >= module_count_) { |
| 2962 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2962)) << "MinidumpModuleList index out of range: " << |
| 2963 | index << "/" << module_count_; |
| 2964 | return NULL__null; |
| 2965 | } |
| 2966 | |
| 2967 | return &(*modules_)[index]; |
| 2968 | } |
| 2969 | |
| 2970 | |
| 2971 | const CodeModules* MinidumpModuleList::Copy() const { |
| 2972 | return new BasicCodeModules(this, range_map_->GetMergeStrategy()); |
| 2973 | } |
| 2974 | |
| 2975 | vector<linked_ptr<const CodeModule> > |
| 2976 | MinidumpModuleList::GetShrunkRangeModules() const { |
| 2977 | return vector<linked_ptr<const CodeModule> >(); |
| 2978 | } |
| 2979 | |
| 2980 | void MinidumpModuleList::Print() { |
| 2981 | if (!valid_) { |
| 2982 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 2982)) << "MinidumpModuleList cannot print invalid data"; |
| 2983 | return; |
| 2984 | } |
| 2985 | |
| 2986 | printf("MinidumpModuleList\n"); |
| 2987 | printf(" module_count = %d\n", module_count_); |
| 2988 | printf("\n"); |
| 2989 | |
| 2990 | for (unsigned int module_index = 0; |
| 2991 | module_index < module_count_; |
| 2992 | ++module_index) { |
| 2993 | printf("module[%d]\n", module_index); |
| 2994 | |
| 2995 | (*modules_)[module_index].Print(); |
| 2996 | } |
| 2997 | } |
| 2998 | |
| 2999 | |
| 3000 | // |
| 3001 | // MinidumpMemoryList |
| 3002 | // |
| 3003 | |
| 3004 | |
| 3005 | uint32_t MinidumpMemoryList::max_regions_ = 4096; |
| 3006 | |
| 3007 | |
| 3008 | MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) |
| 3009 | : MinidumpStream(minidump), |
| 3010 | range_map_(new RangeMap<uint64_t, unsigned int>()), |
| 3011 | descriptors_(NULL__null), |
| 3012 | regions_(NULL__null), |
| 3013 | region_count_(0) { |
| 3014 | } |
| 3015 | |
| 3016 | |
| 3017 | MinidumpMemoryList::~MinidumpMemoryList() { |
| 3018 | delete range_map_; |
| 3019 | delete descriptors_; |
| 3020 | delete regions_; |
| 3021 | } |
| 3022 | |
| 3023 | |
| 3024 | bool MinidumpMemoryList::Read(uint32_t expected_size) { |
| 3025 | // Invalidate cached data. |
| 3026 | delete descriptors_; |
| 3027 | descriptors_ = NULL__null; |
| 3028 | delete regions_; |
| 3029 | regions_ = NULL__null; |
| 3030 | range_map_->Clear(); |
| 3031 | region_count_ = 0; |
| 3032 | |
| 3033 | valid_ = false; |
| 3034 | |
| 3035 | uint32_t region_count; |
| 3036 | if (expected_size < sizeof(region_count)) { |
| 3037 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3037)) << "MinidumpMemoryList count size mismatch, " << |
| 3038 | expected_size << " < " << sizeof(region_count); |
| 3039 | return false; |
| 3040 | } |
| 3041 | if (!minidump_->ReadBytes(®ion_count, sizeof(region_count))) { |
| 3042 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3042)) << "MinidumpMemoryList could not read memory region count"; |
| 3043 | return false; |
| 3044 | } |
| 3045 | |
| 3046 | if (minidump_->swap()) |
| 3047 | Swap(®ion_count); |
| 3048 | |
| 3049 | if (region_count > |
| 3050 | numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) { |
| 3051 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3051)) << "MinidumpMemoryList region count " << region_count << |
| 3052 | " would cause multiplication overflow"; |
| 3053 | return false; |
| 3054 | } |
| 3055 | |
| 3056 | if (expected_size != sizeof(region_count) + |
| 3057 | region_count * sizeof(MDMemoryDescriptor)) { |
| 3058 | // may be padded with 4 bytes on 64bit ABIs for alignment |
| 3059 | if (expected_size == sizeof(region_count) + 4 + |
| 3060 | region_count * sizeof(MDMemoryDescriptor)) { |
| 3061 | uint32_t useless; |
| 3062 | if (!minidump_->ReadBytes(&useless, 4)) { |
| 3063 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3063)) << "MinidumpMemoryList cannot read memorylist padded " |
| 3064 | "bytes"; |
| 3065 | return false; |
| 3066 | } |
| 3067 | } else { |
| 3068 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3068)) << "MinidumpMemoryList size mismatch, " << expected_size << |
| 3069 | " != " << sizeof(region_count) + |
| 3070 | region_count * sizeof(MDMemoryDescriptor); |
| 3071 | return false; |
| 3072 | } |
| 3073 | } |
| 3074 | |
| 3075 | if (region_count > max_regions_) { |
| 3076 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3076)) << "MinidumpMemoryList count " << region_count << |
| 3077 | " exceeds maximum " << max_regions_; |
| 3078 | return false; |
| 3079 | } |
| 3080 | |
| 3081 | if (region_count != 0) { |
| 3082 | scoped_ptr<MemoryDescriptors> descriptors( |
| 3083 | new MemoryDescriptors(region_count)); |
| 3084 | |
| 3085 | // Read the entire array in one fell swoop, instead of reading one entry |
| 3086 | // at a time in the loop. |
| 3087 | if (!minidump_->ReadBytes(&(*descriptors)[0], |
| 3088 | sizeof(MDMemoryDescriptor) * region_count)) { |
| 3089 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3089)) << "MinidumpMemoryList could not read memory region list"; |
| 3090 | return false; |
| 3091 | } |
| 3092 | |
| 3093 | scoped_ptr<MemoryRegions> regions( |
| 3094 | new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); |
| 3095 | |
| 3096 | for (unsigned int region_index = 0; |
| 3097 | region_index < region_count; |
| 3098 | ++region_index) { |
| 3099 | MDMemoryDescriptor* descriptor = &(*descriptors)[region_index]; |
| 3100 | |
| 3101 | if (minidump_->swap()) |
| 3102 | Swap(descriptor); |
| 3103 | |
| 3104 | uint64_t base_address = descriptor->start_of_memory_range; |
| 3105 | uint32_t region_size = descriptor->memory.data_size; |
| 3106 | |
| 3107 | // Check for base + size overflow or undersize. |
| 3108 | if (region_size == 0 || |
| 3109 | region_size > numeric_limits<uint64_t>::max() - base_address) { |
| 3110 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3110)) << "MinidumpMemoryList has a memory region problem, " << |
| 3111 | " region " << region_index << "/" << region_count << |
| 3112 | ", " << HexString(base_address) << "+" << |
| 3113 | HexString(region_size); |
| 3114 | return false; |
| 3115 | } |
| 3116 | |
| 3117 | if (!range_map_->StoreRange(base_address, region_size, region_index)) { |
| 3118 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3118)) << "MinidumpMemoryList could not store memory region " << |
| 3119 | region_index << "/" << region_count << ", " << |
| 3120 | HexString(base_address) << "+" << |
| 3121 | HexString(region_size); |
| 3122 | return false; |
| 3123 | } |
| 3124 | |
| 3125 | (*regions)[region_index].SetDescriptor(descriptor); |
| 3126 | } |
| 3127 | |
| 3128 | descriptors_ = descriptors.release(); |
| 3129 | regions_ = regions.release(); |
| 3130 | } |
| 3131 | |
| 3132 | region_count_ = region_count; |
| 3133 | |
| 3134 | valid_ = true; |
| 3135 | return true; |
| 3136 | } |
| 3137 | |
| 3138 | |
| 3139 | MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex( |
| 3140 | unsigned int index) { |
| 3141 | if (!valid_) { |
| 3142 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3142)) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex"; |
| 3143 | return NULL__null; |
| 3144 | } |
| 3145 | |
| 3146 | if (index >= region_count_) { |
| 3147 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3147)) << "MinidumpMemoryList index out of range: " << |
| 3148 | index << "/" << region_count_; |
| 3149 | return NULL__null; |
| 3150 | } |
| 3151 | |
| 3152 | return &(*regions_)[index]; |
| 3153 | } |
| 3154 | |
| 3155 | |
| 3156 | MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress( |
| 3157 | uint64_t address) { |
| 3158 | if (!valid_) { |
| 3159 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3159)) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress"; |
| 3160 | return NULL__null; |
| 3161 | } |
| 3162 | |
| 3163 | unsigned int region_index; |
| 3164 | if (!range_map_->RetrieveRange(address, ®ion_index, NULL__null /* base */, |
| 3165 | NULL__null /* delta */, NULL__null /* size */)) { |
| 3166 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3166)) << "MinidumpMemoryList has no memory region at " << |
| 3167 | HexString(address); |
| 3168 | return NULL__null; |
| 3169 | } |
| 3170 | |
| 3171 | return GetMemoryRegionAtIndex(region_index); |
| 3172 | } |
| 3173 | |
| 3174 | |
| 3175 | void MinidumpMemoryList::Print() { |
| 3176 | if (!valid_) { |
| 3177 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3177)) << "MinidumpMemoryList cannot print invalid data"; |
| 3178 | return; |
| 3179 | } |
| 3180 | |
| 3181 | printf("MinidumpMemoryList\n"); |
| 3182 | printf(" region_count = %d\n", region_count_); |
| 3183 | printf("\n"); |
| 3184 | |
| 3185 | for (unsigned int region_index = 0; |
| 3186 | region_index < region_count_; |
| 3187 | ++region_index) { |
| 3188 | MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index]; |
| 3189 | printf("region[%d]\n", region_index); |
| 3190 | printf("MDMemoryDescriptor\n"); |
| 3191 | printf(" start_of_memory_range = 0x%" PRIx64"l" "x" "\n", |
| 3192 | descriptor->start_of_memory_range); |
| 3193 | printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size); |
| 3194 | printf(" memory.rva = 0x%x\n", descriptor->memory.rva); |
| 3195 | MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index); |
| 3196 | if (region) { |
| 3197 | printf("Memory\n"); |
| 3198 | region->Print(); |
| 3199 | } else { |
| 3200 | printf("No memory\n"); |
| 3201 | } |
| 3202 | printf("\n"); |
| 3203 | } |
| 3204 | } |
| 3205 | |
| 3206 | |
| 3207 | // |
| 3208 | // MinidumpException |
| 3209 | // |
| 3210 | |
| 3211 | |
| 3212 | MinidumpException::MinidumpException(Minidump* minidump) |
| 3213 | : MinidumpStream(minidump), |
| 3214 | exception_(), |
| 3215 | context_(NULL__null) { |
| 3216 | } |
| 3217 | |
| 3218 | |
| 3219 | MinidumpException::~MinidumpException() { |
| 3220 | delete context_; |
| 3221 | } |
| 3222 | |
| 3223 | |
| 3224 | bool MinidumpException::Read(uint32_t expected_size) { |
| 3225 | // Invalidate cached data. |
| 3226 | delete context_; |
| 3227 | context_ = NULL__null; |
| 3228 | |
| 3229 | valid_ = false; |
| 3230 | |
| 3231 | if (expected_size != sizeof(exception_)) { |
| 3232 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3232)) << "MinidumpException size mismatch, " << expected_size << |
| 3233 | " != " << sizeof(exception_); |
| 3234 | return false; |
| 3235 | } |
| 3236 | |
| 3237 | if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) { |
| 3238 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3238)) << "MinidumpException cannot read exception"; |
| 3239 | return false; |
| 3240 | } |
| 3241 | |
| 3242 | if (minidump_->swap()) { |
| 3243 | Swap(&exception_.thread_id); |
| 3244 | // exception_.__align is for alignment only and does not need to be |
| 3245 | // swapped. |
| 3246 | Swap(&exception_.exception_record.exception_code); |
| 3247 | Swap(&exception_.exception_record.exception_flags); |
| 3248 | Swap(&exception_.exception_record.exception_record); |
| 3249 | Swap(&exception_.exception_record.exception_address); |
| 3250 | Swap(&exception_.exception_record.number_parameters); |
| 3251 | // exception_.exception_record.__align is for alignment only and does not |
| 3252 | // need to be swapped. |
| 3253 | for (unsigned int parameter_index = 0; |
| 3254 | parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS15; |
| 3255 | ++parameter_index) { |
| 3256 | Swap(&exception_.exception_record.exception_information[parameter_index]); |
| 3257 | } |
| 3258 | Swap(&exception_.thread_context); |
| 3259 | } |
| 3260 | |
| 3261 | valid_ = true; |
| 3262 | return true; |
| 3263 | } |
| 3264 | |
| 3265 | |
| 3266 | bool MinidumpException::GetThreadID(uint32_t *thread_id) const { |
| 3267 | BPLOG_IF(ERROR, !thread_id)!(((!thread_id) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3267)) << "MinidumpException::GetThreadID requires " |
| 3268 | "|thread_id|"; |
| 3269 | assert(thread_id)(static_cast <bool> (thread_id) ? void (0) : __assert_fail ("thread_id", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 3270 | *thread_id = 0; |
| 3271 | |
| 3272 | if (!valid_) { |
| 3273 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3273)) << "Invalid MinidumpException for GetThreadID"; |
| 3274 | return false; |
| 3275 | } |
| 3276 | |
| 3277 | *thread_id = exception_.thread_id; |
| 3278 | return true; |
| 3279 | } |
| 3280 | |
| 3281 | |
| 3282 | MinidumpContext* MinidumpException::GetContext() { |
| 3283 | if (!valid_) { |
| 3284 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3284)) << "Invalid MinidumpException for GetContext"; |
| 3285 | return NULL__null; |
| 3286 | } |
| 3287 | |
| 3288 | if (!context_) { |
| 3289 | if (!minidump_->SeekSet(exception_.thread_context.rva)) { |
| 3290 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3290)) << "MinidumpException cannot seek to context"; |
| 3291 | return NULL__null; |
| 3292 | } |
| 3293 | |
| 3294 | scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); |
| 3295 | |
| 3296 | // Don't log as an error if we can still fall back on the thread's context |
| 3297 | // (which must be possible if we got this far.) |
| 3298 | if (!context->Read(exception_.thread_context.data_size)) { |
| 3299 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3299)) << "MinidumpException cannot read context"; |
| 3300 | return NULL__null; |
| 3301 | } |
| 3302 | |
| 3303 | context_ = context.release(); |
| 3304 | } |
| 3305 | |
| 3306 | return context_; |
| 3307 | } |
| 3308 | |
| 3309 | |
| 3310 | void MinidumpException::Print() { |
| 3311 | if (!valid_) { |
| 3312 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3312)) << "MinidumpException cannot print invalid data"; |
| 3313 | return; |
| 3314 | } |
| 3315 | |
| 3316 | printf("MDException\n"); |
| 3317 | printf(" thread_id = 0x%x\n", |
| 3318 | exception_.thread_id); |
| 3319 | printf(" exception_record.exception_code = 0x%x\n", |
| 3320 | exception_.exception_record.exception_code); |
| 3321 | printf(" exception_record.exception_flags = 0x%x\n", |
| 3322 | exception_.exception_record.exception_flags); |
| 3323 | printf(" exception_record.exception_record = 0x%" PRIx64"l" "x" "\n", |
| 3324 | exception_.exception_record.exception_record); |
| 3325 | printf(" exception_record.exception_address = 0x%" PRIx64"l" "x" "\n", |
| 3326 | exception_.exception_record.exception_address); |
| 3327 | printf(" exception_record.number_parameters = %d\n", |
| 3328 | exception_.exception_record.number_parameters); |
| 3329 | for (unsigned int parameterIndex = 0; |
| 3330 | parameterIndex < exception_.exception_record.number_parameters; |
| 3331 | ++parameterIndex) { |
| 3332 | printf(" exception_record.exception_information[%2d] = 0x%" PRIx64"l" "x" "\n", |
| 3333 | parameterIndex, |
| 3334 | exception_.exception_record.exception_information[parameterIndex]); |
| 3335 | } |
| 3336 | printf(" thread_context.data_size = %d\n", |
| 3337 | exception_.thread_context.data_size); |
| 3338 | printf(" thread_context.rva = 0x%x\n", |
| 3339 | exception_.thread_context.rva); |
| 3340 | MinidumpContext* context = GetContext(); |
| 3341 | if (context) { |
| 3342 | printf("\n"); |
| 3343 | context->Print(); |
| 3344 | } else { |
| 3345 | printf(" (no context)\n"); |
| 3346 | printf("\n"); |
| 3347 | } |
| 3348 | } |
| 3349 | |
| 3350 | // |
| 3351 | // MinidumpAssertion |
| 3352 | // |
| 3353 | |
| 3354 | |
| 3355 | MinidumpAssertion::MinidumpAssertion(Minidump* minidump) |
| 3356 | : MinidumpStream(minidump), |
| 3357 | assertion_(), |
| 3358 | expression_(), |
| 3359 | function_(), |
| 3360 | file_() { |
| 3361 | } |
| 3362 | |
| 3363 | |
| 3364 | MinidumpAssertion::~MinidumpAssertion() { |
| 3365 | } |
| 3366 | |
| 3367 | |
| 3368 | bool MinidumpAssertion::Read(uint32_t expected_size) { |
| 3369 | // Invalidate cached data. |
| 3370 | valid_ = false; |
| 3371 | |
| 3372 | if (expected_size != sizeof(assertion_)) { |
| 3373 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3373)) << "MinidumpAssertion size mismatch, " << expected_size << |
| 3374 | " != " << sizeof(assertion_); |
| 3375 | return false; |
| 3376 | } |
| 3377 | |
| 3378 | if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) { |
| 3379 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3379)) << "MinidumpAssertion cannot read assertion"; |
| 3380 | return false; |
| 3381 | } |
| 3382 | |
| 3383 | // Each of {expression, function, file} is a UTF-16 string, |
| 3384 | // we'll convert them to UTF-8 for ease of use. |
| 3385 | ConvertUTF16BufferToUTF8String(assertion_.expression, |
| 3386 | sizeof(assertion_.expression), &expression_, |
| 3387 | minidump_->swap()); |
| 3388 | ConvertUTF16BufferToUTF8String(assertion_.function, |
| 3389 | sizeof(assertion_.function), &function_, |
| 3390 | minidump_->swap()); |
| 3391 | ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file), |
| 3392 | &file_, minidump_->swap()); |
| 3393 | |
| 3394 | if (minidump_->swap()) { |
| 3395 | Swap(&assertion_.line); |
| 3396 | Swap(&assertion_.type); |
| 3397 | } |
| 3398 | |
| 3399 | valid_ = true; |
| 3400 | return true; |
| 3401 | } |
| 3402 | |
| 3403 | void MinidumpAssertion::Print() { |
| 3404 | if (!valid_) { |
| 3405 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3405)) << "MinidumpAssertion cannot print invalid data"; |
| 3406 | return; |
| 3407 | } |
| 3408 | |
| 3409 | printf("MDAssertion\n"); |
| 3410 | printf(" expression = %s\n", |
| 3411 | expression_.c_str()); |
| 3412 | printf(" function = %s\n", |
| 3413 | function_.c_str()); |
| 3414 | printf(" file = %s\n", |
| 3415 | file_.c_str()); |
| 3416 | printf(" line = %u\n", |
| 3417 | assertion_.line); |
| 3418 | printf(" type = %u\n", |
| 3419 | assertion_.type); |
| 3420 | printf("\n"); |
| 3421 | } |
| 3422 | |
| 3423 | // |
| 3424 | // MinidumpSystemInfo |
| 3425 | // |
| 3426 | |
| 3427 | |
| 3428 | MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) |
| 3429 | : MinidumpStream(minidump), |
| 3430 | system_info_(), |
| 3431 | csd_version_(NULL__null), |
| 3432 | cpu_vendor_(NULL__null) { |
| 3433 | } |
| 3434 | |
| 3435 | |
| 3436 | MinidumpSystemInfo::~MinidumpSystemInfo() { |
| 3437 | delete csd_version_; |
| 3438 | delete cpu_vendor_; |
| 3439 | } |
| 3440 | |
| 3441 | |
| 3442 | bool MinidumpSystemInfo::Read(uint32_t expected_size) { |
| 3443 | // Invalidate cached data. |
| 3444 | delete csd_version_; |
| 3445 | csd_version_ = NULL__null; |
| 3446 | delete cpu_vendor_; |
| 3447 | cpu_vendor_ = NULL__null; |
| 3448 | |
| 3449 | valid_ = false; |
| 3450 | |
| 3451 | if (expected_size != sizeof(system_info_)) { |
| 3452 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3452)) << "MinidumpSystemInfo size mismatch, " << expected_size << |
| 3453 | " != " << sizeof(system_info_); |
| 3454 | return false; |
| 3455 | } |
| 3456 | |
| 3457 | if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) { |
| 3458 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3458)) << "MinidumpSystemInfo cannot read system info"; |
| 3459 | return false; |
| 3460 | } |
| 3461 | |
| 3462 | if (minidump_->swap()) { |
| 3463 | Swap(&system_info_.processor_architecture); |
| 3464 | Swap(&system_info_.processor_level); |
| 3465 | Swap(&system_info_.processor_revision); |
| 3466 | // number_of_processors and product_type are 8-bit quantities and need no |
| 3467 | // swapping. |
| 3468 | Swap(&system_info_.major_version); |
| 3469 | Swap(&system_info_.minor_version); |
| 3470 | Swap(&system_info_.build_number); |
| 3471 | Swap(&system_info_.platform_id); |
| 3472 | Swap(&system_info_.csd_version_rva); |
| 3473 | Swap(&system_info_.suite_mask); |
| 3474 | // Don't swap the reserved2 field because its contents are unknown. |
| 3475 | |
| 3476 | if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || |
| 3477 | system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { |
| 3478 | for (unsigned int i = 0; i < 3; ++i) |
| 3479 | Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]); |
| 3480 | Swap(&system_info_.cpu.x86_cpu_info.version_information); |
| 3481 | Swap(&system_info_.cpu.x86_cpu_info.feature_information); |
| 3482 | Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); |
| 3483 | } else { |
| 3484 | for (unsigned int i = 0; i < 2; ++i) |
| 3485 | Swap(&system_info_.cpu.other_cpu_info.processor_features[i]); |
| 3486 | } |
| 3487 | } |
| 3488 | |
| 3489 | valid_ = true; |
| 3490 | return true; |
| 3491 | } |
| 3492 | |
| 3493 | |
| 3494 | string MinidumpSystemInfo::GetOS() { |
| 3495 | string os; |
| 3496 | |
| 3497 | if (!valid_) { |
| 3498 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3498)) << "Invalid MinidumpSystemInfo for GetOS"; |
| 3499 | return os; |
| 3500 | } |
| 3501 | |
| 3502 | switch (system_info_.platform_id) { |
| 3503 | case MD_OS_WIN32_NT: |
| 3504 | case MD_OS_WIN32_WINDOWS: |
| 3505 | os = "windows"; |
| 3506 | break; |
| 3507 | |
| 3508 | case MD_OS_MAC_OS_X: |
| 3509 | os = "mac"; |
| 3510 | break; |
| 3511 | |
| 3512 | case MD_OS_IOS: |
| 3513 | os = "ios"; |
| 3514 | break; |
| 3515 | |
| 3516 | case MD_OS_LINUX: |
| 3517 | os = "linux"; |
| 3518 | break; |
| 3519 | |
| 3520 | case MD_OS_SOLARIS: |
| 3521 | os = "solaris"; |
| 3522 | break; |
| 3523 | |
| 3524 | case MD_OS_ANDROID: |
| 3525 | os = "android"; |
| 3526 | break; |
| 3527 | |
| 3528 | case MD_OS_PS3: |
| 3529 | os = "ps3"; |
| 3530 | break; |
| 3531 | |
| 3532 | case MD_OS_NACL: |
| 3533 | os = "nacl"; |
| 3534 | break; |
| 3535 | |
| 3536 | case MD_OS_FUCHSIA: |
| 3537 | os = "fuchsia"; |
| 3538 | break; |
| 3539 | |
| 3540 | default: |
| 3541 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3541)) << "MinidumpSystemInfo unknown OS for platform " << |
| 3542 | HexString(system_info_.platform_id); |
| 3543 | break; |
| 3544 | } |
| 3545 | |
| 3546 | return os; |
| 3547 | } |
| 3548 | |
| 3549 | |
| 3550 | string MinidumpSystemInfo::GetCPU() { |
| 3551 | if (!valid_) { |
| 3552 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3552)) << "Invalid MinidumpSystemInfo for GetCPU"; |
| 3553 | return ""; |
| 3554 | } |
| 3555 | |
| 3556 | string cpu; |
| 3557 | |
| 3558 | switch (system_info_.processor_architecture) { |
| 3559 | case MD_CPU_ARCHITECTURE_X86: |
| 3560 | case MD_CPU_ARCHITECTURE_X86_WIN64: |
| 3561 | cpu = "x86"; |
| 3562 | break; |
| 3563 | |
| 3564 | case MD_CPU_ARCHITECTURE_AMD64: |
| 3565 | cpu = "x86-64"; |
| 3566 | break; |
| 3567 | |
| 3568 | case MD_CPU_ARCHITECTURE_PPC: |
| 3569 | cpu = "ppc"; |
| 3570 | break; |
| 3571 | |
| 3572 | case MD_CPU_ARCHITECTURE_PPC64: |
| 3573 | cpu = "ppc64"; |
| 3574 | break; |
| 3575 | |
| 3576 | case MD_CPU_ARCHITECTURE_SPARC: |
| 3577 | cpu = "sparc"; |
| 3578 | break; |
| 3579 | |
| 3580 | case MD_CPU_ARCHITECTURE_ARM: |
| 3581 | cpu = "arm"; |
| 3582 | break; |
| 3583 | |
| 3584 | case MD_CPU_ARCHITECTURE_ARM64: |
| 3585 | case MD_CPU_ARCHITECTURE_ARM64_OLD: |
| 3586 | cpu = "arm64"; |
| 3587 | break; |
| 3588 | |
| 3589 | default: |
| 3590 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3590)) << "MinidumpSystemInfo unknown CPU for architecture " << |
| 3591 | HexString(system_info_.processor_architecture); |
| 3592 | break; |
| 3593 | } |
| 3594 | |
| 3595 | return cpu; |
| 3596 | } |
| 3597 | |
| 3598 | |
| 3599 | const string* MinidumpSystemInfo::GetCSDVersion() { |
| 3600 | if (!valid_) { |
| 3601 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3601)) << "Invalid MinidumpSystemInfo for GetCSDVersion"; |
| 3602 | return NULL__null; |
| 3603 | } |
| 3604 | |
| 3605 | if (!csd_version_) |
| 3606 | csd_version_ = minidump_->ReadString(system_info_.csd_version_rva); |
| 3607 | |
| 3608 | BPLOG_IF(ERROR, !csd_version_)!(((!csd_version_) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3608)) << "MinidumpSystemInfo could not read " |
| 3609 | "CSD version"; |
| 3610 | |
| 3611 | return csd_version_; |
| 3612 | } |
| 3613 | |
| 3614 | |
| 3615 | const string* MinidumpSystemInfo::GetCPUVendor() { |
| 3616 | if (!valid_) { |
| 3617 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3617)) << "Invalid MinidumpSystemInfo for GetCPUVendor"; |
| 3618 | return NULL__null; |
| 3619 | } |
| 3620 | |
| 3621 | // CPU vendor information can only be determined from x86 minidumps. |
| 3622 | if (!cpu_vendor_ && |
| 3623 | (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || |
| 3624 | system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) { |
| 3625 | char cpu_vendor_string[13]; |
| 3626 | snprintf(cpu_vendor_string, sizeof(cpu_vendor_string), |
| 3627 | "%c%c%c%c%c%c%c%c%c%c%c%c", |
| 3628 | system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff, |
| 3629 | (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff, |
| 3630 | (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff, |
| 3631 | (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff, |
| 3632 | system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff, |
| 3633 | (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff, |
| 3634 | (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff, |
| 3635 | (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff, |
| 3636 | system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff, |
| 3637 | (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff, |
| 3638 | (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff, |
| 3639 | (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff); |
| 3640 | cpu_vendor_ = new string(cpu_vendor_string); |
| 3641 | } |
| 3642 | |
| 3643 | return cpu_vendor_; |
| 3644 | } |
| 3645 | |
| 3646 | |
| 3647 | void MinidumpSystemInfo::Print() { |
| 3648 | if (!valid_) { |
| 3649 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3649)) << "MinidumpSystemInfo cannot print invalid data"; |
| 3650 | return; |
| 3651 | } |
| 3652 | |
| 3653 | printf("MDRawSystemInfo\n"); |
| 3654 | printf(" processor_architecture = 0x%x\n", |
| 3655 | system_info_.processor_architecture); |
| 3656 | printf(" processor_level = %d\n", |
| 3657 | system_info_.processor_level); |
| 3658 | printf(" processor_revision = 0x%x\n", |
| 3659 | system_info_.processor_revision); |
| 3660 | printf(" number_of_processors = %d\n", |
| 3661 | system_info_.number_of_processors); |
| 3662 | printf(" product_type = %d\n", |
| 3663 | system_info_.product_type); |
| 3664 | printf(" major_version = %d\n", |
| 3665 | system_info_.major_version); |
| 3666 | printf(" minor_version = %d\n", |
| 3667 | system_info_.minor_version); |
| 3668 | printf(" build_number = %d\n", |
| 3669 | system_info_.build_number); |
| 3670 | printf(" platform_id = 0x%x\n", |
| 3671 | system_info_.platform_id); |
| 3672 | printf(" csd_version_rva = 0x%x\n", |
| 3673 | system_info_.csd_version_rva); |
| 3674 | printf(" suite_mask = 0x%x\n", |
| 3675 | system_info_.suite_mask); |
| 3676 | if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || |
| 3677 | system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { |
| 3678 | printf(" cpu.x86_cpu_info (valid):\n"); |
| 3679 | } else { |
| 3680 | printf(" cpu.x86_cpu_info (invalid):\n"); |
| 3681 | } |
| 3682 | for (unsigned int i = 0; i < 3; ++i) { |
| 3683 | printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n", |
| 3684 | i, system_info_.cpu.x86_cpu_info.vendor_id[i]); |
| 3685 | } |
| 3686 | printf(" cpu.x86_cpu_info.version_information = 0x%x\n", |
| 3687 | system_info_.cpu.x86_cpu_info.version_information); |
| 3688 | printf(" cpu.x86_cpu_info.feature_information = 0x%x\n", |
| 3689 | system_info_.cpu.x86_cpu_info.feature_information); |
| 3690 | printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n", |
| 3691 | system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); |
| 3692 | if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 && |
| 3693 | system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) { |
| 3694 | printf(" cpu.other_cpu_info (valid):\n"); |
| 3695 | for (unsigned int i = 0; i < 2; ++i) { |
| 3696 | printf(" cpu.other_cpu_info.processor_features[%d] = 0x%" PRIx64"l" "x" "\n", |
| 3697 | i, system_info_.cpu.other_cpu_info.processor_features[i]); |
| 3698 | } |
| 3699 | } |
| 3700 | const string* csd_version = GetCSDVersion(); |
| 3701 | if (csd_version) { |
| 3702 | printf(" (csd_version) = \"%s\"\n", |
| 3703 | csd_version->c_str()); |
| 3704 | } else { |
| 3705 | printf(" (csd_version) = (null)\n"); |
| 3706 | } |
| 3707 | const string* cpu_vendor = GetCPUVendor(); |
| 3708 | if (cpu_vendor) { |
| 3709 | printf(" (cpu_vendor) = \"%s\"\n", |
| 3710 | cpu_vendor->c_str()); |
| 3711 | } else { |
| 3712 | printf(" (cpu_vendor) = (null)\n"); |
| 3713 | } |
| 3714 | printf("\n"); |
| 3715 | } |
| 3716 | |
| 3717 | |
| 3718 | // |
| 3719 | // MinidumpUnloadedModule |
| 3720 | // |
| 3721 | |
| 3722 | |
| 3723 | MinidumpUnloadedModule::MinidumpUnloadedModule(Minidump* minidump) |
| 3724 | : MinidumpObject(minidump), |
| 3725 | module_valid_(false), |
| 3726 | unloaded_module_(), |
| 3727 | name_(NULL__null) { |
| 3728 | |
| 3729 | } |
| 3730 | |
| 3731 | MinidumpUnloadedModule::~MinidumpUnloadedModule() { |
| 3732 | delete name_; |
| 3733 | } |
| 3734 | |
| 3735 | void MinidumpUnloadedModule::Print() { |
| 3736 | if (!valid_) { |
| 3737 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3737)) << "MinidumpUnloadedModule cannot print invalid data"; |
| 3738 | return; |
| 3739 | } |
| 3740 | |
| 3741 | printf("MDRawUnloadedModule\n"); |
| 3742 | printf(" base_of_image = 0x%" PRIx64"l" "x" "\n", |
| 3743 | unloaded_module_.base_of_image); |
| 3744 | printf(" size_of_image = 0x%x\n", |
| 3745 | unloaded_module_.size_of_image); |
| 3746 | printf(" checksum = 0x%x\n", |
| 3747 | unloaded_module_.checksum); |
| 3748 | printf(" time_date_stamp = 0x%x %s\n", |
| 3749 | unloaded_module_.time_date_stamp, |
| 3750 | TimeTToUTCString(unloaded_module_.time_date_stamp).c_str()); |
| 3751 | printf(" module_name_rva = 0x%x\n", |
| 3752 | unloaded_module_.module_name_rva); |
| 3753 | |
| 3754 | printf(" (code_file) = \"%s\"\n", code_file().c_str()); |
| 3755 | printf(" (code_identifier) = \"%s\"\n", |
| 3756 | code_identifier().c_str()); |
| 3757 | |
| 3758 | printf(" (debug_file) = \"%s\"\n", debug_file().c_str()); |
| 3759 | printf(" (debug_identifier) = \"%s\"\n", |
| 3760 | debug_identifier().c_str()); |
| 3761 | printf(" (version) = \"%s\"\n", version().c_str()); |
| 3762 | printf("\n"); |
| 3763 | } |
| 3764 | |
| 3765 | string MinidumpUnloadedModule::code_file() const { |
| 3766 | if (!valid_) { |
| 3767 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3767)) << "Invalid MinidumpUnloadedModule for code_file"; |
| 3768 | return ""; |
| 3769 | } |
| 3770 | |
| 3771 | return *name_; |
| 3772 | } |
| 3773 | |
| 3774 | string MinidumpUnloadedModule::code_identifier() const { |
| 3775 | if (!valid_) { |
| 3776 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3776)) << "Invalid MinidumpUnloadedModule for code_identifier"; |
| 3777 | return ""; |
| 3778 | } |
| 3779 | |
| 3780 | MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo(); |
| 3781 | if (!minidump_system_info) { |
| 3782 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3782)) << "MinidumpUnloadedModule code_identifier requires " |
| 3783 | "MinidumpSystemInfo"; |
| 3784 | return ""; |
| 3785 | } |
| 3786 | |
| 3787 | const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info(); |
| 3788 | if (!raw_system_info) { |
| 3789 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3789)) << "MinidumpUnloadedModule code_identifier requires " |
| 3790 | << "MDRawSystemInfo"; |
| 3791 | return ""; |
| 3792 | } |
| 3793 | |
| 3794 | string identifier; |
| 3795 | |
| 3796 | switch (raw_system_info->platform_id) { |
| 3797 | case MD_OS_WIN32_NT: |
| 3798 | case MD_OS_WIN32_WINDOWS: { |
| 3799 | // Use the same format that the MS symbol server uses in filesystem |
| 3800 | // hierarchies. |
| 3801 | char identifier_string[17]; |
| 3802 | snprintf(identifier_string, sizeof(identifier_string), "%08X%x", |
| 3803 | unloaded_module_.time_date_stamp, |
| 3804 | unloaded_module_.size_of_image); |
| 3805 | identifier = identifier_string; |
| 3806 | break; |
| 3807 | } |
| 3808 | |
| 3809 | case MD_OS_ANDROID: |
| 3810 | case MD_OS_LINUX: |
| 3811 | case MD_OS_MAC_OS_X: |
| 3812 | case MD_OS_IOS: |
| 3813 | case MD_OS_SOLARIS: |
| 3814 | case MD_OS_NACL: |
| 3815 | case MD_OS_PS3: { |
| 3816 | // TODO(mmentovai): support uuid extension if present, otherwise fall |
| 3817 | // back to version (from LC_ID_DYLIB?), otherwise fall back to something |
| 3818 | // else. |
| 3819 | identifier = "id"; |
| 3820 | break; |
| 3821 | } |
| 3822 | |
| 3823 | default: { |
| 3824 | // Without knowing what OS generated the dump, we can't generate a good |
| 3825 | // identifier. Return an empty string, signalling failure. |
| 3826 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3826)) << "MinidumpUnloadedModule code_identifier requires known " |
| 3827 | << "platform, found " |
| 3828 | << HexString(raw_system_info->platform_id); |
| 3829 | break; |
| 3830 | } |
| 3831 | } |
| 3832 | |
| 3833 | return identifier; |
| 3834 | } |
| 3835 | |
| 3836 | string MinidumpUnloadedModule::debug_file() const { |
| 3837 | return ""; // No debug info provided with unloaded modules |
| 3838 | } |
| 3839 | |
| 3840 | string MinidumpUnloadedModule::debug_identifier() const { |
| 3841 | return ""; // No debug info provided with unloaded modules |
| 3842 | } |
| 3843 | |
| 3844 | string MinidumpUnloadedModule::version() const { |
| 3845 | return ""; // No version info provided with unloaded modules |
| 3846 | } |
| 3847 | |
| 3848 | CodeModule* MinidumpUnloadedModule::Copy() const { |
| 3849 | return new BasicCodeModule(this); |
| 3850 | } |
| 3851 | |
| 3852 | uint64_t MinidumpUnloadedModule::shrink_down_delta() const { |
| 3853 | return 0; |
| 3854 | } |
| 3855 | |
| 3856 | void MinidumpUnloadedModule::SetShrinkDownDelta(uint64_t shrink_down_delta) { |
| 3857 | // Not implemented |
| 3858 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
| 3859 | } |
| 3860 | |
| 3861 | bool MinidumpUnloadedModule::Read(uint32_t expected_size) { |
| 3862 | |
| 3863 | delete name_; |
| 3864 | valid_ = false; |
| 3865 | |
| 3866 | if (expected_size < sizeof(unloaded_module_)) { |
| 3867 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3867)) << "MinidumpUnloadedModule expected size is less than size " |
| 3868 | << "of struct " << expected_size << " < " |
| 3869 | << sizeof(unloaded_module_); |
| 3870 | return false; |
| 3871 | } |
| 3872 | |
| 3873 | if (!minidump_->ReadBytes(&unloaded_module_, sizeof(unloaded_module_))) { |
| 3874 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3874)) << "MinidumpUnloadedModule cannot read module"; |
| 3875 | return false; |
| 3876 | } |
| 3877 | |
| 3878 | if (expected_size > sizeof(unloaded_module_)) { |
| 3879 | uint32_t module_bytes_remaining = expected_size - sizeof(unloaded_module_); |
| 3880 | off_t pos = minidump_->Tell(); |
| 3881 | if (!minidump_->SeekSet(pos + module_bytes_remaining)) { |
| 3882 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3882)) << "MinidumpUnloadedModule unable to seek to end of module"; |
| 3883 | return false; |
| 3884 | } |
| 3885 | } |
| 3886 | |
| 3887 | if (minidump_->swap()) { |
| 3888 | Swap(&unloaded_module_.base_of_image); |
| 3889 | Swap(&unloaded_module_.size_of_image); |
| 3890 | Swap(&unloaded_module_.checksum); |
| 3891 | Swap(&unloaded_module_.time_date_stamp); |
| 3892 | Swap(&unloaded_module_.module_name_rva); |
| 3893 | } |
| 3894 | |
| 3895 | // Check for base + size overflow or undersize. |
| 3896 | if (unloaded_module_.size_of_image == 0 || |
| 3897 | unloaded_module_.size_of_image > |
| 3898 | numeric_limits<uint64_t>::max() - unloaded_module_.base_of_image) { |
| 3899 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3899)) << "MinidumpUnloadedModule has a module problem, " << |
| 3900 | HexString(unloaded_module_.base_of_image) << "+" << |
| 3901 | HexString(unloaded_module_.size_of_image); |
| 3902 | return false; |
| 3903 | } |
| 3904 | |
| 3905 | |
| 3906 | module_valid_ = true; |
| 3907 | return true; |
| 3908 | } |
| 3909 | |
| 3910 | bool MinidumpUnloadedModule::ReadAuxiliaryData() { |
| 3911 | if (!module_valid_) { |
| 3912 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3912)) << "Invalid MinidumpUnloadedModule for ReadAuxiliaryData"; |
| 3913 | return false; |
| 3914 | } |
| 3915 | |
| 3916 | // Each module must have a name. |
| 3917 | name_ = minidump_->ReadString(unloaded_module_.module_name_rva); |
| 3918 | if (!name_) { |
| 3919 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3919)) << "MinidumpUnloadedModule could not read name"; |
| 3920 | return false; |
| 3921 | } |
| 3922 | |
| 3923 | // At this point, we have enough info for the module to be valid. |
| 3924 | valid_ = true; |
| 3925 | return true; |
| 3926 | } |
| 3927 | |
| 3928 | // |
| 3929 | // MinidumpUnloadedModuleList |
| 3930 | // |
| 3931 | |
| 3932 | |
| 3933 | uint32_t MinidumpUnloadedModuleList::max_modules_ = 2048; |
| 3934 | |
| 3935 | |
| 3936 | MinidumpUnloadedModuleList::MinidumpUnloadedModuleList(Minidump* minidump) |
| 3937 | : MinidumpStream(minidump), |
| 3938 | range_map_(new RangeMap<uint64_t, unsigned int>()), |
| 3939 | unloaded_modules_(NULL__null), |
| 3940 | module_count_(0) { |
| 3941 | range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower); |
| 3942 | } |
| 3943 | |
| 3944 | MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() { |
| 3945 | delete range_map_; |
| 3946 | delete unloaded_modules_; |
| 3947 | } |
| 3948 | |
| 3949 | void MinidumpUnloadedModuleList::Print() { |
| 3950 | if (!valid_) { |
| 3951 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3951)) << "MinidumpUnloadedModuleList cannot print invalid data"; |
| 3952 | return; |
| 3953 | } |
| 3954 | |
| 3955 | printf("MinidumpUnloadedModuleList\n"); |
| 3956 | printf(" module_count = %d\n", module_count_); |
| 3957 | printf("\n"); |
| 3958 | |
| 3959 | for (unsigned int module_index = 0; |
| 3960 | module_index < module_count_; |
| 3961 | ++module_index) { |
| 3962 | printf("module[%d]\n", module_index); |
| 3963 | |
| 3964 | (*unloaded_modules_)[module_index].Print(); |
| 3965 | } |
| 3966 | } |
| 3967 | |
| 3968 | bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) { |
| 3969 | range_map_->Clear(); |
| 3970 | delete unloaded_modules_; |
| 3971 | unloaded_modules_ = NULL__null; |
| 3972 | module_count_ = 0; |
| 3973 | |
| 3974 | valid_ = false; |
| 3975 | |
| 3976 | uint32_t size_of_header; |
| 3977 | if (!minidump_->ReadBytes(&size_of_header, sizeof(size_of_header))) { |
| 3978 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3978)) << "MinidumpUnloadedModuleList could not read header size"; |
| 3979 | return false; |
| 3980 | } |
| 3981 | |
| 3982 | uint32_t size_of_entry; |
| 3983 | if (!minidump_->ReadBytes(&size_of_entry, sizeof(size_of_entry))) { |
| 3984 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3984)) << "MinidumpUnloadedModuleList could not read entry size"; |
| 3985 | return false; |
| 3986 | } |
| 3987 | |
| 3988 | uint32_t number_of_entries; |
| 3989 | if (!minidump_->ReadBytes(&number_of_entries, sizeof(number_of_entries))) { |
| 3990 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 3990)) << |
| 3991 | "MinidumpUnloadedModuleList could not read number of entries"; |
| 3992 | return false; |
| 3993 | } |
| 3994 | |
| 3995 | if (minidump_->swap()) { |
| 3996 | Swap(&size_of_header); |
| 3997 | Swap(&size_of_entry); |
| 3998 | Swap(&number_of_entries); |
| 3999 | } |
| 4000 | |
| 4001 | uint32_t header_bytes_remaining = size_of_header - sizeof(size_of_header) - |
| 4002 | sizeof(size_of_entry) - sizeof(number_of_entries); |
| 4003 | if (header_bytes_remaining) { |
| 4004 | off_t pos = minidump_->Tell(); |
| 4005 | if (!minidump_->SeekSet(pos + header_bytes_remaining)) { |
| 4006 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4006)) << "MinidumpUnloadedModuleList could not read header sized " |
| 4007 | << size_of_header; |
| 4008 | return false; |
| 4009 | } |
| 4010 | } |
| 4011 | |
| 4012 | if (expected_size != size_of_header + (size_of_entry * number_of_entries)) { |
| 4013 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4013)) << "MinidumpUnloadedModuleList expected_size mismatch " << |
| 4014 | expected_size << " != " << size_of_header << " + (" << |
| 4015 | size_of_entry << " * " << number_of_entries << ")"; |
| 4016 | return false; |
| 4017 | } |
| 4018 | |
| 4019 | if (number_of_entries > max_modules_) { |
| 4020 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4020)) << "MinidumpUnloadedModuleList count " << |
| 4021 | number_of_entries << " exceeds maximum " << max_modules_; |
| 4022 | return false; |
| 4023 | } |
| 4024 | |
| 4025 | if (number_of_entries != 0) { |
| 4026 | scoped_ptr<MinidumpUnloadedModules> modules( |
| 4027 | new MinidumpUnloadedModules(number_of_entries, |
| 4028 | MinidumpUnloadedModule(minidump_))); |
| 4029 | |
| 4030 | for (unsigned int module_index = 0; |
| 4031 | module_index < number_of_entries; |
| 4032 | ++module_index) { |
| 4033 | MinidumpUnloadedModule* module = &(*modules)[module_index]; |
| 4034 | |
| 4035 | if (!module->Read(size_of_entry)) { |
| 4036 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4036)) << "MinidumpUnloadedModuleList could not read module " << |
| 4037 | module_index << "/" << number_of_entries; |
| 4038 | return false; |
| 4039 | } |
| 4040 | } |
| 4041 | |
| 4042 | for (unsigned int module_index = 0; |
| 4043 | module_index < number_of_entries; |
| 4044 | ++module_index) { |
| 4045 | MinidumpUnloadedModule* module = &(*modules)[module_index]; |
| 4046 | |
| 4047 | if (!module->ReadAuxiliaryData()) { |
| 4048 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4048)) << "MinidumpUnloadedModuleList could not read required " |
| 4049 | "module auxiliary data for module " << |
| 4050 | module_index << "/" << number_of_entries; |
| 4051 | return false; |
| 4052 | } |
| 4053 | |
| 4054 | uint64_t base_address = module->base_address(); |
| 4055 | uint64_t module_size = module->size(); |
| 4056 | |
| 4057 | // Ignore any failures for conflicting address ranges |
| 4058 | range_map_->StoreRange(base_address, module_size, module_index); |
| 4059 | |
| 4060 | } |
| 4061 | unloaded_modules_ = modules.release(); |
| 4062 | } |
| 4063 | |
| 4064 | module_count_ = number_of_entries; |
| 4065 | valid_ = true; |
| 4066 | return true; |
| 4067 | } |
| 4068 | |
| 4069 | const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetModuleForAddress( |
| 4070 | uint64_t address) const { |
| 4071 | if (!valid_) { |
| 4072 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4072)) |
| 4073 | << "Invalid MinidumpUnloadedModuleList for GetModuleForAddress"; |
| 4074 | return NULL__null; |
| 4075 | } |
| 4076 | |
| 4077 | unsigned int module_index; |
| 4078 | if (!range_map_->RetrieveRange(address, &module_index, NULL__null /* base */, |
| 4079 | NULL__null /* delta */, NULL__null /* size */)) { |
| 4080 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4080)) << "MinidumpUnloadedModuleList has no module at " |
| 4081 | << HexString(address); |
| 4082 | return NULL__null; |
| 4083 | } |
| 4084 | |
| 4085 | return GetModuleAtIndex(module_index); |
| 4086 | } |
| 4087 | |
| 4088 | const MinidumpUnloadedModule* |
| 4089 | MinidumpUnloadedModuleList::GetMainModule() const { |
| 4090 | return NULL__null; |
| 4091 | } |
| 4092 | |
| 4093 | const MinidumpUnloadedModule* |
| 4094 | MinidumpUnloadedModuleList::GetModuleAtSequence(unsigned int sequence) const { |
| 4095 | if (!valid_) { |
| 4096 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4096)) |
| 4097 | << "Invalid MinidumpUnloadedModuleList for GetModuleAtSequence"; |
| 4098 | return NULL__null; |
| 4099 | } |
| 4100 | |
| 4101 | if (sequence >= module_count_) { |
| 4102 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4102)) << "MinidumpUnloadedModuleList sequence out of range: " |
| 4103 | << sequence << "/" << module_count_; |
| 4104 | return NULL__null; |
| 4105 | } |
| 4106 | |
| 4107 | unsigned int module_index; |
| 4108 | if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, |
| 4109 | NULL__null /* base */, NULL__null /* delta */, |
| 4110 | NULL__null /* size */)) { |
| 4111 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4111)) << "MinidumpUnloadedModuleList has no module at sequence " |
| 4112 | << sequence; |
| 4113 | return NULL__null; |
| 4114 | } |
| 4115 | |
| 4116 | return GetModuleAtIndex(module_index); |
| 4117 | } |
| 4118 | |
| 4119 | const MinidumpUnloadedModule* |
| 4120 | MinidumpUnloadedModuleList::GetModuleAtIndex( |
| 4121 | unsigned int index) const { |
| 4122 | if (!valid_) { |
| 4123 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4123)) << "Invalid MinidumpUnloadedModuleList for GetModuleAtIndex"; |
| 4124 | return NULL__null; |
| 4125 | } |
| 4126 | |
| 4127 | if (index >= module_count_) { |
| 4128 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4128)) << "MinidumpUnloadedModuleList index out of range: " |
| 4129 | << index << "/" << module_count_; |
| 4130 | return NULL__null; |
| 4131 | } |
| 4132 | |
| 4133 | return &(*unloaded_modules_)[index]; |
| 4134 | } |
| 4135 | |
| 4136 | const CodeModules* MinidumpUnloadedModuleList::Copy() const { |
| 4137 | return new BasicCodeModules(this, range_map_->GetMergeStrategy()); |
| 4138 | } |
| 4139 | |
| 4140 | vector<linked_ptr<const CodeModule>> |
| 4141 | MinidumpUnloadedModuleList::GetShrunkRangeModules() const { |
| 4142 | return vector<linked_ptr<const CodeModule> >(); |
| 4143 | } |
| 4144 | |
| 4145 | |
| 4146 | // |
| 4147 | // MinidumpMiscInfo |
| 4148 | // |
| 4149 | |
| 4150 | |
| 4151 | MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump) |
| 4152 | : MinidumpStream(minidump), |
| 4153 | misc_info_() { |
| 4154 | } |
| 4155 | |
| 4156 | |
| 4157 | bool MinidumpMiscInfo::Read(uint32_t expected_size) { |
| 4158 | valid_ = false; |
| 4159 | |
| 4160 | size_t padding = 0; |
| 4161 | if (expected_size != MD_MISCINFO_SIZE && |
| 4162 | expected_size != MD_MISCINFO2_SIZE && |
| 4163 | expected_size != MD_MISCINFO3_SIZE && |
| 4164 | expected_size != MD_MISCINFO4_SIZE && |
| 4165 | expected_size != MD_MISCINFO5_SIZE) { |
| 4166 | if (expected_size > MD_MISCINFO5_SIZE) { |
| 4167 | // Only read the part of the misc info structure we know how to handle |
| 4168 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4168)) << "MinidumpMiscInfo size larger than expected " |
| 4169 | << expected_size << ", skipping over the unknown part"; |
| 4170 | padding = expected_size - MD_MISCINFO5_SIZE; |
| 4171 | expected_size = MD_MISCINFO5_SIZE; |
| 4172 | } else { |
| 4173 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4173)) << "MinidumpMiscInfo size mismatch, " << expected_size |
| 4174 | << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE |
| 4175 | << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE |
| 4176 | << ", " << MD_MISCINFO5_SIZE << ")"; |
| 4177 | return false; |
| 4178 | } |
| 4179 | } |
| 4180 | |
| 4181 | if (!minidump_->ReadBytes(&misc_info_, expected_size)) { |
| 4182 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4182)) << "MinidumpMiscInfo cannot read miscellaneous info"; |
| 4183 | return false; |
| 4184 | } |
| 4185 | |
| 4186 | if (padding != 0) { |
| 4187 | off_t saved_position = minidump_->Tell(); |
| 4188 | if (saved_position == -1) { |
| 4189 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4189)) << "MinidumpMiscInfo could not tell the current position"; |
| 4190 | return false; |
| 4191 | } |
| 4192 | |
| 4193 | if (!minidump_->SeekSet(saved_position + static_cast<off_t>(padding))) { |
| 4194 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4194)) << "MinidumpMiscInfo could not seek past the miscellaneous " |
| 4195 | << "info structure"; |
| 4196 | return false; |
| 4197 | } |
| 4198 | } |
| 4199 | |
| 4200 | if (minidump_->swap()) { |
| 4201 | // Swap version 1 fields |
| 4202 | Swap(&misc_info_.size_of_info); |
| 4203 | Swap(&misc_info_.flags1); |
| 4204 | Swap(&misc_info_.process_id); |
| 4205 | Swap(&misc_info_.process_create_time); |
| 4206 | Swap(&misc_info_.process_user_time); |
| 4207 | Swap(&misc_info_.process_kernel_time); |
| 4208 | if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { |
| 4209 | // Swap version 2 fields |
| 4210 | Swap(&misc_info_.processor_max_mhz); |
| 4211 | Swap(&misc_info_.processor_current_mhz); |
| 4212 | Swap(&misc_info_.processor_mhz_limit); |
| 4213 | Swap(&misc_info_.processor_max_idle_state); |
| 4214 | Swap(&misc_info_.processor_current_idle_state); |
| 4215 | } |
| 4216 | if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { |
| 4217 | // Swap version 3 fields |
| 4218 | Swap(&misc_info_.process_integrity_level); |
| 4219 | Swap(&misc_info_.process_execute_flags); |
| 4220 | Swap(&misc_info_.protected_process); |
| 4221 | Swap(&misc_info_.time_zone_id); |
| 4222 | Swap(&misc_info_.time_zone); |
| 4223 | } |
| 4224 | if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { |
| 4225 | // Swap version 4 fields. |
| 4226 | // Do not swap UTF-16 strings. The swap is done as part of the |
| 4227 | // conversion to UTF-8 (code follows below). |
| 4228 | } |
| 4229 | if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { |
| 4230 | // Swap version 5 fields |
| 4231 | Swap(&misc_info_.xstate_data); |
| 4232 | Swap(&misc_info_.process_cookie); |
| 4233 | } |
| 4234 | } |
| 4235 | |
| 4236 | if (expected_size + padding != misc_info_.size_of_info) { |
| 4237 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4237)) << "MinidumpMiscInfo size mismatch, " << |
| 4238 | expected_size << " != " << misc_info_.size_of_info; |
| 4239 | return false; |
| 4240 | } |
| 4241 | |
| 4242 | // Convert UTF-16 strings |
| 4243 | if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { |
| 4244 | // Convert UTF-16 strings in version 3 fields |
| 4245 | ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name, |
| 4246 | sizeof(misc_info_.time_zone.standard_name), |
| 4247 | &standard_name_, minidump_->swap()); |
| 4248 | ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name, |
| 4249 | sizeof(misc_info_.time_zone.daylight_name), |
| 4250 | &daylight_name_, minidump_->swap()); |
| 4251 | } |
| 4252 | if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { |
| 4253 | // Convert UTF-16 strings in version 4 fields |
| 4254 | ConvertUTF16BufferToUTF8String(misc_info_.build_string, |
| 4255 | sizeof(misc_info_.build_string), |
| 4256 | &build_string_, minidump_->swap()); |
| 4257 | ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str, |
| 4258 | sizeof(misc_info_.dbg_bld_str), |
| 4259 | &dbg_bld_str_, minidump_->swap()); |
| 4260 | } |
| 4261 | |
| 4262 | valid_ = true; |
| 4263 | return true; |
| 4264 | } |
| 4265 | |
| 4266 | |
| 4267 | void MinidumpMiscInfo::Print() { |
| 4268 | if (!valid_) { |
| 4269 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4269)) << "MinidumpMiscInfo cannot print invalid data"; |
| 4270 | return; |
| 4271 | } |
| 4272 | |
| 4273 | printf("MDRawMiscInfo\n"); |
| 4274 | // Print version 1 fields |
| 4275 | printf(" size_of_info = %d\n", misc_info_.size_of_info); |
| 4276 | printf(" flags1 = 0x%x\n", misc_info_.flags1); |
| 4277 | printf(" process_id = "); |
| 4278 | PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID, |
| 4279 | kNumberFormatDecimal, misc_info_.process_id); |
| 4280 | if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) { |
| 4281 | printf(" process_create_time = 0x%x %s\n", |
| 4282 | misc_info_.process_create_time, |
| 4283 | TimeTToUTCString(misc_info_.process_create_time).c_str()); |
| 4284 | } else { |
| 4285 | printf(" process_create_time = (invalid)\n"); |
| 4286 | } |
| 4287 | printf(" process_user_time = "); |
| 4288 | PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, |
| 4289 | kNumberFormatDecimal, misc_info_.process_user_time); |
| 4290 | printf(" process_kernel_time = "); |
| 4291 | PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, |
| 4292 | kNumberFormatDecimal, misc_info_.process_kernel_time); |
| 4293 | if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { |
| 4294 | // Print version 2 fields |
| 4295 | printf(" processor_max_mhz = "); |
| 4296 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4297 | MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, |
| 4298 | kNumberFormatDecimal, misc_info_.processor_max_mhz); |
| 4299 | printf(" processor_current_mhz = "); |
| 4300 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4301 | MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, |
| 4302 | kNumberFormatDecimal, misc_info_.processor_current_mhz); |
| 4303 | printf(" processor_mhz_limit = "); |
| 4304 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4305 | MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, |
| 4306 | kNumberFormatDecimal, misc_info_.processor_mhz_limit); |
| 4307 | printf(" processor_max_idle_state = "); |
| 4308 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4309 | MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, |
| 4310 | kNumberFormatDecimal, |
| 4311 | misc_info_.processor_max_idle_state); |
| 4312 | printf(" processor_current_idle_state = "); |
| 4313 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4314 | MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, |
| 4315 | kNumberFormatDecimal, |
| 4316 | misc_info_.processor_current_idle_state); |
| 4317 | } |
| 4318 | if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { |
| 4319 | // Print version 3 fields |
| 4320 | printf(" process_integrity_level = "); |
| 4321 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4322 | MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY, |
| 4323 | kNumberFormatHexadecimal, |
| 4324 | misc_info_.process_integrity_level); |
| 4325 | printf(" process_execute_flags = "); |
| 4326 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4327 | MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS, |
| 4328 | kNumberFormatHexadecimal, |
| 4329 | misc_info_.process_execute_flags); |
| 4330 | printf(" protected_process = "); |
| 4331 | PrintValueOrInvalid(misc_info_.flags1 & |
| 4332 | MD_MISCINFO_FLAGS1_PROTECTED_PROCESS, |
| 4333 | kNumberFormatDecimal, misc_info_.protected_process); |
| 4334 | printf(" time_zone_id = "); |
| 4335 | PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE, |
| 4336 | kNumberFormatDecimal, misc_info_.time_zone_id); |
| 4337 | if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) { |
| 4338 | printf(" time_zone.bias = %d\n", |
| 4339 | misc_info_.time_zone.bias); |
| 4340 | printf(" time_zone.standard_name = %s\n", standard_name_.c_str()); |
| 4341 | printf(" time_zone.standard_date = " |
| 4342 | "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", |
| 4343 | misc_info_.time_zone.standard_date.year, |
| 4344 | misc_info_.time_zone.standard_date.month, |
| 4345 | misc_info_.time_zone.standard_date.day, |
| 4346 | misc_info_.time_zone.standard_date.day_of_week, |
| 4347 | misc_info_.time_zone.standard_date.hour, |
| 4348 | misc_info_.time_zone.standard_date.minute, |
| 4349 | misc_info_.time_zone.standard_date.second, |
| 4350 | misc_info_.time_zone.standard_date.milliseconds); |
| 4351 | printf(" time_zone.standard_bias = %d\n", |
| 4352 | misc_info_.time_zone.standard_bias); |
| 4353 | printf(" time_zone.daylight_name = %s\n", daylight_name_.c_str()); |
| 4354 | printf(" time_zone.daylight_date = " |
| 4355 | "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", |
| 4356 | misc_info_.time_zone.daylight_date.year, |
| 4357 | misc_info_.time_zone.daylight_date.month, |
| 4358 | misc_info_.time_zone.daylight_date.day, |
| 4359 | misc_info_.time_zone.daylight_date.day_of_week, |
| 4360 | misc_info_.time_zone.daylight_date.hour, |
| 4361 | misc_info_.time_zone.daylight_date.minute, |
| 4362 | misc_info_.time_zone.daylight_date.second, |
| 4363 | misc_info_.time_zone.daylight_date.milliseconds); |
| 4364 | printf(" time_zone.daylight_bias = %d\n", |
| 4365 | misc_info_.time_zone.daylight_bias); |
| 4366 | } else { |
| 4367 | printf(" time_zone.bias = (invalid)\n"); |
| 4368 | printf(" time_zone.standard_name = (invalid)\n"); |
| 4369 | printf(" time_zone.standard_date = (invalid)\n"); |
| 4370 | printf(" time_zone.standard_bias = (invalid)\n"); |
| 4371 | printf(" time_zone.daylight_name = (invalid)\n"); |
| 4372 | printf(" time_zone.daylight_date = (invalid)\n"); |
| 4373 | printf(" time_zone.daylight_bias = (invalid)\n"); |
| 4374 | } |
| 4375 | } |
| 4376 | if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { |
| 4377 | // Print version 4 fields |
| 4378 | if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) { |
| 4379 | printf(" build_string = %s\n", build_string_.c_str()); |
| 4380 | printf(" dbg_bld_str = %s\n", dbg_bld_str_.c_str()); |
| 4381 | } else { |
| 4382 | printf(" build_string = (invalid)\n"); |
| 4383 | printf(" dbg_bld_str = (invalid)\n"); |
| 4384 | } |
| 4385 | } |
| 4386 | if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { |
| 4387 | // Print version 5 fields |
| 4388 | if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_COOKIE) { |
| 4389 | printf(" xstate_data.size_of_info = %d\n", |
| 4390 | misc_info_.xstate_data.size_of_info); |
| 4391 | printf(" xstate_data.context_size = %d\n", |
| 4392 | misc_info_.xstate_data.context_size); |
| 4393 | printf(" xstate_data.enabled_features = 0x%" PRIx64"l" "x" "\n", |
| 4394 | misc_info_.xstate_data.enabled_features); |
| 4395 | for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES64; i++) { |
| 4396 | if ((misc_info_.xstate_data.enabled_features >> i) & 1) { |
| 4397 | printf(" xstate_data.features[%02zu] = { %d, %d }\n", i, |
| 4398 | misc_info_.xstate_data.features[i].offset, |
| 4399 | misc_info_.xstate_data.features[i].size); |
| 4400 | } |
| 4401 | } |
| 4402 | if (misc_info_.xstate_data.enabled_features == 0) { |
| 4403 | printf(" xstate_data.features[] = (empty)\n"); |
| 4404 | } |
| 4405 | printf(" process_cookie = %d\n", |
| 4406 | misc_info_.process_cookie); |
| 4407 | } else { |
| 4408 | printf(" xstate_data.size_of_info = (invalid)\n"); |
| 4409 | printf(" xstate_data.context_size = (invalid)\n"); |
| 4410 | printf(" xstate_data.enabled_features = (invalid)\n"); |
| 4411 | printf(" xstate_data.features[] = (invalid)\n"); |
| 4412 | printf(" process_cookie = (invalid)\n"); |
| 4413 | } |
| 4414 | } |
| 4415 | printf("\n"); |
| 4416 | } |
| 4417 | |
| 4418 | |
| 4419 | // |
| 4420 | // MinidumpBreakpadInfo |
| 4421 | // |
| 4422 | |
| 4423 | |
| 4424 | MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump) |
| 4425 | : MinidumpStream(minidump), |
| 4426 | breakpad_info_() { |
| 4427 | } |
| 4428 | |
| 4429 | |
| 4430 | bool MinidumpBreakpadInfo::Read(uint32_t expected_size) { |
| 4431 | valid_ = false; |
| 4432 | |
| 4433 | if (expected_size != sizeof(breakpad_info_)) { |
| 4434 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4434)) << "MinidumpBreakpadInfo size mismatch, " << expected_size << |
| 4435 | " != " << sizeof(breakpad_info_); |
| 4436 | return false; |
| 4437 | } |
| 4438 | |
| 4439 | if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) { |
| 4440 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4440)) << "MinidumpBreakpadInfo cannot read Breakpad info"; |
| 4441 | return false; |
| 4442 | } |
| 4443 | |
| 4444 | if (minidump_->swap()) { |
| 4445 | Swap(&breakpad_info_.validity); |
| 4446 | Swap(&breakpad_info_.dump_thread_id); |
| 4447 | Swap(&breakpad_info_.requesting_thread_id); |
| 4448 | } |
| 4449 | |
| 4450 | valid_ = true; |
| 4451 | return true; |
| 4452 | } |
| 4453 | |
| 4454 | |
| 4455 | bool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const { |
| 4456 | BPLOG_IF(ERROR, !thread_id)!(((!thread_id) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4456)) << "MinidumpBreakpadInfo::GetDumpThreadID " |
| 4457 | "requires |thread_id|"; |
| 4458 | assert(thread_id)(static_cast <bool> (thread_id) ? void (0) : __assert_fail ("thread_id", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 4459 | *thread_id = 0; |
| 4460 | |
| 4461 | if (!valid_) { |
| 4462 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4462)) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID"; |
| 4463 | return false; |
| 4464 | } |
| 4465 | |
| 4466 | if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) { |
| 4467 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4467)) << "MinidumpBreakpadInfo has no dump thread"; |
| 4468 | return false; |
| 4469 | } |
| 4470 | |
| 4471 | *thread_id = breakpad_info_.dump_thread_id; |
| 4472 | return true; |
| 4473 | } |
| 4474 | |
| 4475 | |
| 4476 | bool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id) |
| 4477 | const { |
| 4478 | BPLOG_IF(ERROR, !thread_id)!(((!thread_id) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4478)) << "MinidumpBreakpadInfo::GetRequestingThreadID " |
| 4479 | "requires |thread_id|"; |
| 4480 | assert(thread_id)(static_cast <bool> (thread_id) ? void (0) : __assert_fail ("thread_id", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 4481 | *thread_id = 0; |
| 4482 | |
| 4483 | if (!thread_id || !valid_) { |
| 4484 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4484)) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID"; |
| 4485 | return false; |
| 4486 | } |
| 4487 | |
| 4488 | if (!(breakpad_info_.validity & |
| 4489 | MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) { |
| 4490 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4490)) << "MinidumpBreakpadInfo has no requesting thread"; |
| 4491 | return false; |
| 4492 | } |
| 4493 | |
| 4494 | *thread_id = breakpad_info_.requesting_thread_id; |
| 4495 | return true; |
| 4496 | } |
| 4497 | |
| 4498 | |
| 4499 | void MinidumpBreakpadInfo::Print() { |
| 4500 | if (!valid_) { |
| 4501 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4501)) << "MinidumpBreakpadInfo cannot print invalid data"; |
| 4502 | return; |
| 4503 | } |
| 4504 | |
| 4505 | printf("MDRawBreakpadInfo\n"); |
| 4506 | printf(" validity = 0x%x\n", breakpad_info_.validity); |
| 4507 | printf(" dump_thread_id = "); |
| 4508 | PrintValueOrInvalid(breakpad_info_.validity & |
| 4509 | MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID, |
| 4510 | kNumberFormatHexadecimal, breakpad_info_.dump_thread_id); |
| 4511 | printf(" requesting_thread_id = "); |
| 4512 | PrintValueOrInvalid(breakpad_info_.validity & |
| 4513 | MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID, |
| 4514 | kNumberFormatHexadecimal, |
| 4515 | breakpad_info_.requesting_thread_id); |
| 4516 | |
| 4517 | printf("\n"); |
| 4518 | } |
| 4519 | |
| 4520 | |
| 4521 | // |
| 4522 | // MinidumpMemoryInfo |
| 4523 | // |
| 4524 | |
| 4525 | |
| 4526 | MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump) |
| 4527 | : MinidumpObject(minidump), |
| 4528 | memory_info_() { |
| 4529 | } |
| 4530 | |
| 4531 | |
| 4532 | bool MinidumpMemoryInfo::IsExecutable() const { |
| 4533 | uint32_t protection = |
| 4534 | memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; |
| 4535 | return protection == MD_MEMORY_PROTECT_EXECUTE || |
| 4536 | protection == MD_MEMORY_PROTECT_EXECUTE_READ || |
| 4537 | protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE; |
| 4538 | } |
| 4539 | |
| 4540 | |
| 4541 | bool MinidumpMemoryInfo::IsWritable() const { |
| 4542 | uint32_t protection = |
| 4543 | memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; |
| 4544 | return protection == MD_MEMORY_PROTECT_READWRITE || |
| 4545 | protection == MD_MEMORY_PROTECT_WRITECOPY || |
| 4546 | protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE || |
| 4547 | protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY; |
| 4548 | } |
| 4549 | |
| 4550 | |
| 4551 | bool MinidumpMemoryInfo::Read() { |
| 4552 | valid_ = false; |
| 4553 | |
| 4554 | if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) { |
| 4555 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4555)) << "MinidumpMemoryInfo cannot read memory info"; |
| 4556 | return false; |
| 4557 | } |
| 4558 | |
| 4559 | if (minidump_->swap()) { |
| 4560 | Swap(&memory_info_.base_address); |
| 4561 | Swap(&memory_info_.allocation_base); |
| 4562 | Swap(&memory_info_.allocation_protection); |
| 4563 | Swap(&memory_info_.region_size); |
| 4564 | Swap(&memory_info_.state); |
| 4565 | Swap(&memory_info_.protection); |
| 4566 | Swap(&memory_info_.type); |
| 4567 | } |
| 4568 | |
| 4569 | // Check for base + size overflow or undersize. |
| 4570 | if (memory_info_.region_size == 0 || |
| 4571 | memory_info_.region_size > numeric_limits<uint64_t>::max() - |
| 4572 | memory_info_.base_address) { |
| 4573 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4573)) << "MinidumpMemoryInfo has a memory region problem, " << |
| 4574 | HexString(memory_info_.base_address) << "+" << |
| 4575 | HexString(memory_info_.region_size); |
| 4576 | return false; |
| 4577 | } |
| 4578 | |
| 4579 | valid_ = true; |
| 4580 | return true; |
| 4581 | } |
| 4582 | |
| 4583 | |
| 4584 | void MinidumpMemoryInfo::Print() { |
| 4585 | if (!valid_) { |
| 4586 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4586)) << "MinidumpMemoryInfo cannot print invalid data"; |
| 4587 | return; |
| 4588 | } |
| 4589 | |
| 4590 | printf("MDRawMemoryInfo\n"); |
| 4591 | printf(" base_address = 0x%" PRIx64"l" "x" "\n", |
| 4592 | memory_info_.base_address); |
| 4593 | printf(" allocation_base = 0x%" PRIx64"l" "x" "\n", |
| 4594 | memory_info_.allocation_base); |
| 4595 | printf(" allocation_protection = 0x%x\n", |
| 4596 | memory_info_.allocation_protection); |
| 4597 | printf(" region_size = 0x%" PRIx64"l" "x" "\n", memory_info_.region_size); |
| 4598 | printf(" state = 0x%x\n", memory_info_.state); |
| 4599 | printf(" protection = 0x%x\n", memory_info_.protection); |
| 4600 | printf(" type = 0x%x\n", memory_info_.type); |
| 4601 | } |
| 4602 | |
| 4603 | |
| 4604 | // |
| 4605 | // MinidumpMemoryInfoList |
| 4606 | // |
| 4607 | |
| 4608 | |
| 4609 | MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump) |
| 4610 | : MinidumpStream(minidump), |
| 4611 | range_map_(new RangeMap<uint64_t, unsigned int>()), |
| 4612 | infos_(NULL__null), |
| 4613 | info_count_(0) { |
| 4614 | } |
| 4615 | |
| 4616 | |
| 4617 | MinidumpMemoryInfoList::~MinidumpMemoryInfoList() { |
| 4618 | delete range_map_; |
| 4619 | delete infos_; |
| 4620 | } |
| 4621 | |
| 4622 | |
| 4623 | bool MinidumpMemoryInfoList::Read(uint32_t expected_size) { |
| 4624 | // Invalidate cached data. |
| 4625 | delete infos_; |
| 4626 | infos_ = NULL__null; |
| 4627 | range_map_->Clear(); |
| 4628 | info_count_ = 0; |
| 4629 | |
| 4630 | valid_ = false; |
| 4631 | |
| 4632 | MDRawMemoryInfoList header; |
| 4633 | if (expected_size < sizeof(MDRawMemoryInfoList)) { |
| 4634 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4634)) << "MinidumpMemoryInfoList header size mismatch, " << |
| 4635 | expected_size << " < " << sizeof(MDRawMemoryInfoList); |
| 4636 | return false; |
| 4637 | } |
| 4638 | if (!minidump_->ReadBytes(&header, sizeof(header))) { |
| 4639 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4639)) << "MinidumpMemoryInfoList could not read header"; |
| 4640 | return false; |
| 4641 | } |
| 4642 | |
| 4643 | if (minidump_->swap()) { |
| 4644 | Swap(&header.size_of_header); |
| 4645 | Swap(&header.size_of_entry); |
| 4646 | Swap(&header.number_of_entries); |
| 4647 | } |
| 4648 | |
| 4649 | // Sanity check that the header is the expected size. |
| 4650 | // TODO(ted): could possibly handle this more gracefully, assuming |
| 4651 | // that future versions of the structs would be backwards-compatible. |
| 4652 | if (header.size_of_header != sizeof(MDRawMemoryInfoList)) { |
| 4653 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4653)) << "MinidumpMemoryInfoList header size mismatch, " << |
| 4654 | header.size_of_header << " != " << |
| 4655 | sizeof(MDRawMemoryInfoList); |
| 4656 | return false; |
| 4657 | } |
| 4658 | |
| 4659 | // Sanity check that the entries are the expected size. |
| 4660 | if (header.size_of_entry != sizeof(MDRawMemoryInfo)) { |
| 4661 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4661)) << "MinidumpMemoryInfoList entry size mismatch, " << |
| 4662 | header.size_of_entry << " != " << |
| 4663 | sizeof(MDRawMemoryInfo); |
| 4664 | return false; |
| 4665 | } |
| 4666 | |
| 4667 | if (header.number_of_entries > |
| 4668 | numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) { |
| 4669 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4669)) << "MinidumpMemoryInfoList info count " << |
| 4670 | header.number_of_entries << |
| 4671 | " would cause multiplication overflow"; |
| 4672 | return false; |
| 4673 | } |
| 4674 | |
| 4675 | if (expected_size != sizeof(MDRawMemoryInfoList) + |
| 4676 | header.number_of_entries * sizeof(MDRawMemoryInfo)) { |
| 4677 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4677)) << "MinidumpMemoryInfoList size mismatch, " << expected_size << |
| 4678 | " != " << sizeof(MDRawMemoryInfoList) + |
| 4679 | header.number_of_entries * sizeof(MDRawMemoryInfo); |
| 4680 | return false; |
| 4681 | } |
| 4682 | |
| 4683 | // Check for data loss when converting header.number_of_entries from |
| 4684 | // uint64_t into MinidumpMemoryInfos::size_type (uint32_t) |
| 4685 | MinidumpMemoryInfos::size_type header_number_of_entries = |
| 4686 | static_cast<unsigned int>(header.number_of_entries); |
| 4687 | if (static_cast<uint64_t>(header_number_of_entries) != |
| 4688 | header.number_of_entries) { |
| 4689 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4689)) << "Data loss detected when converting " |
| 4690 | "the header's number_of_entries"; |
| 4691 | return false; |
| 4692 | } |
| 4693 | |
| 4694 | if (header.number_of_entries != 0) { |
| 4695 | scoped_ptr<MinidumpMemoryInfos> infos( |
| 4696 | new MinidumpMemoryInfos(header_number_of_entries, |
| 4697 | MinidumpMemoryInfo(minidump_))); |
| 4698 | |
| 4699 | for (unsigned int index = 0; |
| 4700 | index < header.number_of_entries; |
| 4701 | ++index) { |
| 4702 | MinidumpMemoryInfo* info = &(*infos)[index]; |
| 4703 | |
| 4704 | // Assume that the file offset is correct after the last read. |
| 4705 | if (!info->Read()) { |
| 4706 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4706)) << "MinidumpMemoryInfoList cannot read info " << |
| 4707 | index << "/" << header.number_of_entries; |
| 4708 | return false; |
| 4709 | } |
| 4710 | |
| 4711 | uint64_t base_address = info->GetBase(); |
| 4712 | uint64_t region_size = info->GetSize(); |
| 4713 | |
| 4714 | if (!range_map_->StoreRange(base_address, region_size, index)) { |
| 4715 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4715)) << "MinidumpMemoryInfoList could not store" |
| 4716 | " memory region " << |
| 4717 | index << "/" << header.number_of_entries << ", " << |
| 4718 | HexString(base_address) << "+" << |
| 4719 | HexString(region_size); |
| 4720 | return false; |
| 4721 | } |
| 4722 | } |
| 4723 | |
| 4724 | infos_ = infos.release(); |
| 4725 | } |
| 4726 | |
| 4727 | info_count_ = static_cast<uint32_t>(header_number_of_entries); |
| 4728 | |
| 4729 | valid_ = true; |
| 4730 | return true; |
| 4731 | } |
| 4732 | |
| 4733 | |
| 4734 | const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex( |
| 4735 | unsigned int index) const { |
| 4736 | if (!valid_) { |
| 4737 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4737)) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex"; |
| 4738 | return NULL__null; |
| 4739 | } |
| 4740 | |
| 4741 | if (index >= info_count_) { |
| 4742 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4742)) << "MinidumpMemoryInfoList index out of range: " << |
| 4743 | index << "/" << info_count_; |
| 4744 | return NULL__null; |
| 4745 | } |
| 4746 | |
| 4747 | return &(*infos_)[index]; |
| 4748 | } |
| 4749 | |
| 4750 | |
| 4751 | const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress( |
| 4752 | uint64_t address) const { |
| 4753 | if (!valid_) { |
| 4754 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4754)) << "Invalid MinidumpMemoryInfoList for" |
| 4755 | " GetMemoryInfoForAddress"; |
| 4756 | return NULL__null; |
| 4757 | } |
| 4758 | |
| 4759 | unsigned int info_index; |
| 4760 | if (!range_map_->RetrieveRange(address, &info_index, NULL__null /* base */, |
| 4761 | NULL__null /* delta */, NULL__null /* size */)) { |
| 4762 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4762)) << "MinidumpMemoryInfoList has no memory info at " << |
| 4763 | HexString(address); |
| 4764 | return NULL__null; |
| 4765 | } |
| 4766 | |
| 4767 | return GetMemoryInfoAtIndex(info_index); |
| 4768 | } |
| 4769 | |
| 4770 | |
| 4771 | void MinidumpMemoryInfoList::Print() { |
| 4772 | if (!valid_) { |
| 4773 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4773)) << "MinidumpMemoryInfoList cannot print invalid data"; |
| 4774 | return; |
| 4775 | } |
| 4776 | |
| 4777 | printf("MinidumpMemoryInfoList\n"); |
| 4778 | printf(" info_count = %d\n", info_count_); |
| 4779 | printf("\n"); |
| 4780 | |
| 4781 | for (unsigned int info_index = 0; |
| 4782 | info_index < info_count_; |
| 4783 | ++info_index) { |
| 4784 | printf("info[%d]\n", info_index); |
| 4785 | (*infos_)[info_index].Print(); |
| 4786 | printf("\n"); |
| 4787 | } |
| 4788 | } |
| 4789 | |
| 4790 | // |
| 4791 | // MinidumpLinuxMaps |
| 4792 | // |
| 4793 | |
| 4794 | MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump) |
| 4795 | : MinidumpObject(minidump) { |
| 4796 | } |
| 4797 | |
| 4798 | void MinidumpLinuxMaps::Print() const { |
| 4799 | if (!valid_) { |
| 4800 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4800)) << "MinidumpLinuxMaps cannot print invalid data"; |
| 4801 | return; |
| 4802 | } |
| 4803 | std::cout << region_.line << std::endl; |
| 4804 | } |
| 4805 | |
| 4806 | // |
| 4807 | // MinidumpLinuxMapsList |
| 4808 | // |
| 4809 | |
| 4810 | MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump) |
| 4811 | : MinidumpStream(minidump), |
| 4812 | maps_(NULL__null), |
| 4813 | maps_count_(0) { |
| 4814 | } |
| 4815 | |
| 4816 | MinidumpLinuxMapsList::~MinidumpLinuxMapsList() { |
| 4817 | if (maps_) { |
| 4818 | for (unsigned int i = 0; i < maps_->size(); i++) { |
| 4819 | delete (*maps_)[i]; |
| 4820 | } |
| 4821 | delete maps_; |
| 4822 | } |
| 4823 | } |
| 4824 | |
| 4825 | const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress( |
| 4826 | uint64_t address) const { |
| 4827 | if (!valid_ || (maps_ == NULL__null)) { |
| 4828 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4828)) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress"; |
| 4829 | return NULL__null; |
| 4830 | } |
| 4831 | |
| 4832 | // Search every memory mapping. |
| 4833 | for (unsigned int index = 0; index < maps_count_; index++) { |
| 4834 | // Check if address is within bounds of the current memory region. |
| 4835 | if ((*maps_)[index]->GetBase() <= address && |
| 4836 | (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) { |
| 4837 | return (*maps_)[index]; |
| 4838 | } |
| 4839 | } |
| 4840 | |
| 4841 | // No mapping encloses the memory address. |
| 4842 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4842)) << "MinidumpLinuxMapsList has no mapping at " |
| 4843 | << HexString(address); |
| 4844 | return NULL__null; |
| 4845 | } |
| 4846 | |
| 4847 | const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex( |
| 4848 | unsigned int index) const { |
| 4849 | if (!valid_ || (maps_ == NULL__null)) { |
| 4850 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4850)) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex"; |
| 4851 | return NULL__null; |
| 4852 | } |
| 4853 | |
| 4854 | // Index out of bounds. |
| 4855 | if (index >= maps_count_ || (maps_ == NULL__null)) { |
| 4856 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4856)) << "MinidumpLinuxMapsList index of out range: " |
| 4857 | << index |
| 4858 | << "/" |
| 4859 | << maps_count_; |
| 4860 | return NULL__null; |
| 4861 | } |
| 4862 | return (*maps_)[index]; |
| 4863 | } |
| 4864 | |
| 4865 | bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { |
| 4866 | // Invalidate cached data. |
| 4867 | if (maps_) { |
| 4868 | for (unsigned int i = 0; i < maps_->size(); i++) { |
| 4869 | delete (*maps_)[i]; |
| 4870 | } |
| 4871 | delete maps_; |
| 4872 | } |
| 4873 | maps_ = NULL__null; |
| 4874 | maps_count_ = 0; |
| 4875 | |
| 4876 | valid_ = false; |
| 4877 | |
| 4878 | // Load and check expected stream length. |
| 4879 | uint32_t length = 0; |
| 4880 | if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) { |
| 4881 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4881)) << "MinidumpLinuxMapsList stream type not found"; |
| 4882 | return false; |
| 4883 | } |
| 4884 | if (expected_size != length) { |
| 4885 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4885)) << "MinidumpLinuxMapsList size mismatch: " |
| 4886 | << expected_size |
| 4887 | << " != " |
| 4888 | << length; |
| 4889 | return false; |
| 4890 | } |
| 4891 | |
| 4892 | // Create a vector to read stream data. The vector needs to have |
| 4893 | // at least enough capacity to read all the data. |
| 4894 | vector<char> mapping_bytes(length); |
| 4895 | if (!minidump_->ReadBytes(&mapping_bytes[0], length)) { |
| 4896 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4896)) << "MinidumpLinuxMapsList failed to read bytes"; |
| 4897 | return false; |
| 4898 | } |
| 4899 | string map_string(mapping_bytes.begin(), mapping_bytes.end()); |
| 4900 | vector<MappedMemoryRegion> all_regions; |
| 4901 | |
| 4902 | // Parse string into mapping data. |
| 4903 | if (!ParseProcMaps(map_string, &all_regions)) { |
| 4904 | return false; |
| 4905 | } |
| 4906 | |
| 4907 | scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings()); |
| 4908 | |
| 4909 | // Push mapping data into wrapper classes. |
| 4910 | for (size_t i = 0; i < all_regions.size(); i++) { |
| 4911 | scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_)); |
| 4912 | ele->region_ = all_regions[i]; |
| 4913 | ele->valid_ = true; |
| 4914 | maps->push_back(ele.release()); |
| 4915 | } |
| 4916 | |
| 4917 | // Set instance variables. |
| 4918 | maps_ = maps.release(); |
| 4919 | maps_count_ = static_cast<uint32_t>(maps_->size()); |
| 4920 | valid_ = true; |
| 4921 | return true; |
| 4922 | } |
| 4923 | |
| 4924 | void MinidumpLinuxMapsList::Print() const { |
| 4925 | if (!valid_ || (maps_ == NULL__null)) { |
| 4926 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4926)) << "MinidumpLinuxMapsList cannot print valid data"; |
| 4927 | return; |
| 4928 | } |
| 4929 | for (size_t i = 0; i < maps_->size(); i++) { |
| 4930 | (*maps_)[i]->Print(); |
| 4931 | } |
| 4932 | } |
| 4933 | |
| 4934 | // |
| 4935 | // MinidumpCrashpadInfo |
| 4936 | // |
| 4937 | |
| 4938 | |
| 4939 | MinidumpCrashpadInfo::MinidumpCrashpadInfo(Minidump* minidump) |
| 4940 | : MinidumpStream(minidump), |
| 4941 | crashpad_info_(), |
| 4942 | module_crashpad_info_links_(), |
| 4943 | module_crashpad_info_(), |
| 4944 | module_crashpad_info_list_annotations_(), |
| 4945 | module_crashpad_info_simple_annotations_(), |
| 4946 | simple_annotations_() { |
| 4947 | } |
| 4948 | |
| 4949 | |
| 4950 | bool MinidumpCrashpadInfo::Read(uint32_t expected_size) { |
| 4951 | valid_ = false; |
| 4952 | |
| 4953 | if (expected_size != sizeof(crashpad_info_)) { |
| 4954 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4954)) << "MinidumpCrashpadInfo size mismatch, " << expected_size << |
| 4955 | " != " << sizeof(crashpad_info_); |
| 4956 | return false; |
| 4957 | } |
| 4958 | |
| 4959 | if (!minidump_->ReadBytes(&crashpad_info_, sizeof(crashpad_info_))) { |
| 4960 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4960)) << "MinidumpCrashpadInfo cannot read Crashpad info"; |
| 4961 | return false; |
| 4962 | } |
| 4963 | |
| 4964 | if (minidump_->swap()) { |
| 4965 | Swap(&crashpad_info_.version); |
| 4966 | Swap(&crashpad_info_.report_id); |
| 4967 | Swap(&crashpad_info_.client_id); |
| 4968 | Swap(&crashpad_info_.simple_annotations); |
| 4969 | Swap(&crashpad_info_.module_list); |
| 4970 | } |
| 4971 | |
| 4972 | if (crashpad_info_.simple_annotations.data_size) { |
| 4973 | if (!minidump_->ReadSimpleStringDictionary( |
| 4974 | crashpad_info_.simple_annotations.rva, |
| 4975 | &simple_annotations_)) { |
| 4976 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4976)) << "MinidumpCrashpadInfo cannot read simple_annotations"; |
| 4977 | return false; |
| 4978 | } |
| 4979 | } |
| 4980 | |
| 4981 | if (crashpad_info_.module_list.data_size) { |
| 4982 | if (!minidump_->SeekSet(crashpad_info_.module_list.rva)) { |
| 4983 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4983)) << "MinidumpCrashpadInfo cannot seek to module_list"; |
| 4984 | return false; |
| 4985 | } |
| 4986 | |
| 4987 | uint32_t count; |
| 4988 | if (!minidump_->ReadBytes(&count, sizeof(count))) { |
| 4989 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 4989)) << "MinidumpCrashpadInfo cannot read module_list count"; |
| 4990 | return false; |
| 4991 | } |
| 4992 | |
| 4993 | if (minidump_->swap()) { |
| 4994 | Swap(&count); |
| 4995 | } |
| 4996 | |
| 4997 | scoped_array<MDRawModuleCrashpadInfoLink> module_crashpad_info_links( |
| 4998 | new MDRawModuleCrashpadInfoLink[count]); |
| 4999 | |
| 5000 | // Read the entire array in one fell swoop, instead of reading one entry |
| 5001 | // at a time in the loop. |
| 5002 | if (!minidump_->ReadBytes( |
| 5003 | &module_crashpad_info_links[0], |
| 5004 | sizeof(MDRawModuleCrashpadInfoLink) * count)) { |
| 5005 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5005)) |
| 5006 | << "MinidumpCrashpadInfo could not read Crashpad module links"; |
| 5007 | return false; |
| 5008 | } |
| 5009 | |
| 5010 | for (uint32_t index = 0; index < count; ++index) { |
| 5011 | if (minidump_->swap()) { |
| 5012 | Swap(&module_crashpad_info_links[index].minidump_module_list_index); |
| 5013 | Swap(&module_crashpad_info_links[index].location); |
| 5014 | } |
| 5015 | |
| 5016 | if (!minidump_->SeekSet(module_crashpad_info_links[index].location.rva)) { |
| 5017 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5017)) |
| 5018 | << "MinidumpCrashpadInfo cannot seek to Crashpad module info"; |
| 5019 | return false; |
| 5020 | } |
| 5021 | |
| 5022 | MDRawModuleCrashpadInfo module_crashpad_info; |
| 5023 | if (!minidump_->ReadBytes(&module_crashpad_info, |
| 5024 | sizeof(module_crashpad_info))) { |
| 5025 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5025)) << "MinidumpCrashpadInfo cannot read Crashpad module info"; |
| 5026 | return false; |
| 5027 | } |
| 5028 | |
| 5029 | if (minidump_->swap()) { |
| 5030 | Swap(&module_crashpad_info.version); |
| 5031 | Swap(&module_crashpad_info.list_annotations); |
| 5032 | Swap(&module_crashpad_info.simple_annotations); |
| 5033 | } |
| 5034 | |
| 5035 | std::vector<std::string> list_annotations; |
| 5036 | if (module_crashpad_info.list_annotations.data_size) { |
| 5037 | if (!minidump_->ReadStringList( |
| 5038 | module_crashpad_info.list_annotations.rva, |
| 5039 | &list_annotations)) { |
| 5040 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5040)) << "MinidumpCrashpadInfo cannot read Crashpad module " |
| 5041 | "info list annotations"; |
| 5042 | return false; |
| 5043 | } |
| 5044 | } |
| 5045 | |
| 5046 | std::map<std::string, std::string> simple_annotations; |
| 5047 | if (module_crashpad_info.simple_annotations.data_size) { |
| 5048 | if (!minidump_->ReadSimpleStringDictionary( |
| 5049 | module_crashpad_info.simple_annotations.rva, |
| 5050 | &simple_annotations)) { |
| 5051 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5051)) << "MinidumpCrashpadInfo cannot read Crashpad module " |
| 5052 | "info simple annotations"; |
| 5053 | return false; |
| 5054 | } |
| 5055 | } |
| 5056 | |
| 5057 | module_crashpad_info_links_.push_back( |
| 5058 | module_crashpad_info_links[index].minidump_module_list_index); |
| 5059 | module_crashpad_info_.push_back(module_crashpad_info); |
| 5060 | module_crashpad_info_list_annotations_.push_back(list_annotations); |
| 5061 | module_crashpad_info_simple_annotations_.push_back(simple_annotations); |
| 5062 | } |
| 5063 | } |
| 5064 | |
| 5065 | valid_ = true; |
| 5066 | return true; |
| 5067 | } |
| 5068 | |
| 5069 | |
| 5070 | void MinidumpCrashpadInfo::Print() { |
| 5071 | if (!valid_) { |
| 5072 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5072)) << "MinidumpCrashpadInfo cannot print invalid data"; |
| 5073 | return; |
| 5074 | } |
| 5075 | |
| 5076 | printf("MDRawCrashpadInfo\n"); |
| 5077 | printf(" version = %d\n", crashpad_info_.version); |
| 5078 | printf(" report_id = %s\n", |
| 5079 | MDGUIDToString(crashpad_info_.report_id).c_str()); |
| 5080 | printf(" client_id = %s\n", |
| 5081 | MDGUIDToString(crashpad_info_.client_id).c_str()); |
| 5082 | for (std::map<std::string, std::string>::const_iterator iterator = |
| 5083 | simple_annotations_.begin(); |
| 5084 | iterator != simple_annotations_.end(); |
| 5085 | ++iterator) { |
| 5086 | printf(" simple_annotations[\"%s\"] = %s\n", |
| 5087 | iterator->first.c_str(), iterator->second.c_str()); |
| 5088 | } |
| 5089 | for (uint32_t module_index = 0; |
| 5090 | module_index < module_crashpad_info_links_.size(); |
| 5091 | ++module_index) { |
| 5092 | printf(" module_list[%d].minidump_module_list_index = %d\n", |
| 5093 | module_index, module_crashpad_info_links_[module_index]); |
| 5094 | printf(" module_list[%d].version = %d\n", |
| 5095 | module_index, module_crashpad_info_[module_index].version); |
| 5096 | for (uint32_t annotation_index = 0; |
| 5097 | annotation_index < |
| 5098 | module_crashpad_info_list_annotations_[module_index].size(); |
| 5099 | ++annotation_index) { |
| 5100 | printf(" module_list[%d].list_annotations[%d] = %s\n", |
| 5101 | module_index, |
| 5102 | annotation_index, |
| 5103 | module_crashpad_info_list_annotations_ |
| 5104 | [module_index][annotation_index].c_str()); |
| 5105 | } |
| 5106 | for (std::map<std::string, std::string>::const_iterator iterator = |
| 5107 | module_crashpad_info_simple_annotations_[module_index].begin(); |
| 5108 | iterator != |
| 5109 | module_crashpad_info_simple_annotations_[module_index].end(); |
| 5110 | ++iterator) { |
| 5111 | printf(" module_list[%d].simple_annotations[\"%s\"] = %s\n", |
| 5112 | module_index, iterator->first.c_str(), iterator->second.c_str()); |
| 5113 | } |
| 5114 | } |
| 5115 | |
| 5116 | printf("\n"); |
| 5117 | } |
| 5118 | |
| 5119 | // |
| 5120 | // MinidumpMacCrashInfo |
| 5121 | // |
| 5122 | |
| 5123 | MinidumpMacCrashInfo::MinidumpMacCrashInfo(Minidump* minidump) |
| 5124 | : MinidumpStream(minidump), |
| 5125 | description_(), |
| 5126 | records_() { |
| 5127 | } |
| 5128 | |
| 5129 | bool MinidumpMacCrashInfo::ReadCrashInfoRecord(MDLocationDescriptor location, |
| 5130 | uint32_t record_start_size) { |
| 5131 | if (!minidump_->SeekSet(location.rva)) { |
| 5132 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5132)) << "ReadCrashInfoRecord could not seek to record"; |
| 5133 | return false; |
| 5134 | } |
| 5135 | |
| 5136 | // We may be reading a minidump 1) created by (newer) code that defines more |
| 5137 | // fields than we do in the fixed-size part of MDRawMacCrashInfoRecord |
| 5138 | // (before 'data'), or 2) created by (older) code that defines fewer fields. |
| 5139 | // In the first case we read in the newer fields but ignore them. In the |
| 5140 | // second case we read in only the older fields, and leave the newer fields |
| 5141 | // (in 'raw_record_start') set to zero. |
| 5142 | uint32_t raw_record_size = sizeof(MDRawMacCrashInfoRecord); |
| 5143 | if (record_start_size > raw_record_size) { |
| 5144 | raw_record_size = record_start_size; |
| 5145 | } |
| 5146 | scoped_ptr< vector<uint8_t> > raw_record( |
| 5147 | new vector<uint8_t>(raw_record_size)); |
| 5148 | if (!minidump_->ReadBytes(&(*raw_record)[0], record_start_size)) { |
| 5149 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5149)) << "ReadCrashInfoRecord could not read " << |
| 5150 | record_start_size << " bytes of record"; |
| 5151 | return false; |
| 5152 | } |
| 5153 | MDRawMacCrashInfoRecord* raw_record_start = |
| 5154 | (MDRawMacCrashInfoRecord*) &(*raw_record)[0]; |
| 5155 | |
| 5156 | if (minidump_->swap()) { |
| 5157 | Swap(&raw_record_start->stream_type); |
| 5158 | Swap(&raw_record_start->version); |
| 5159 | Swap(&raw_record_start->thread); |
| 5160 | Swap(&raw_record_start->dialog_mode); |
| 5161 | Swap(&raw_record_start->abort_cause); |
| 5162 | } |
| 5163 | |
| 5164 | if (raw_record_start->stream_type != MOZ_MACOS_CRASH_INFO_STREAM) { |
| 5165 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5165)) << "ReadCrashInfoRecord stream type mismatch, " << |
| 5166 | raw_record_start->stream_type << " != " << |
| 5167 | MOZ_MACOS_CRASH_INFO_STREAM; |
| 5168 | return false; |
| 5169 | } |
| 5170 | |
| 5171 | uint32_t string_data_size = location.data_size - record_start_size; |
| 5172 | scoped_ptr< vector<uint8_t> > data(new vector<uint8_t>(string_data_size)); |
| 5173 | if (!minidump_->ReadBytes(&(*data)[0], string_data_size)) { |
| 5174 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5174)) << "ReadCrashInfoRecord could not read " << |
| 5175 | string_data_size << " bytes of record data"; |
| 5176 | return false; |
| 5177 | } |
| 5178 | |
| 5179 | crash_info_record_t record; |
| 5180 | |
| 5181 | record.version = (unsigned long) raw_record_start->version; |
| 5182 | record.thread = (unsigned long long) raw_record_start->thread; |
| 5183 | record.dialog_mode = (unsigned int) raw_record_start->dialog_mode; |
| 5184 | record.abort_cause = (long long) raw_record_start->abort_cause; |
| 5185 | |
| 5186 | // Once again, we may be reading a minidump created by newer code that |
| 5187 | // stores more strings than we expect in (MDRawMacCrashInfoRecord).data, |
| 5188 | // or one created by older code that contains fewer strings than we |
| 5189 | // expect. In the first case we ignore the "extra" strings. To deal with |
| 5190 | // the second case we bail when 'offset >= string_data_size'. |
| 5191 | const char* string_data = (const char*) &(*data)[0]; |
| 5192 | size_t offset = 0; |
| 5193 | for (int i = 1; i <= 5; ++i) { |
| 5194 | switch (i) { |
| 5195 | case 1: |
| 5196 | record.module_path.append(string_data); |
| 5197 | break; |
| 5198 | case 2: |
| 5199 | record.message.append(string_data); |
| 5200 | break; |
| 5201 | case 3: |
| 5202 | record.signature_string.append(string_data); |
| 5203 | break; |
| 5204 | case 4: |
| 5205 | record.backtrace.append(string_data); |
| 5206 | break; |
| 5207 | case 5: |
| 5208 | record.message2.append(string_data); |
| 5209 | break; |
| 5210 | } |
| 5211 | size_t char_array_size = strlen(string_data) + 1; |
| 5212 | offset += char_array_size; |
| 5213 | if (offset >= string_data_size) { |
| 5214 | break; |
| 5215 | } |
| 5216 | string_data += char_array_size; |
| 5217 | } |
| 5218 | |
| 5219 | records_.push_back(record); |
| 5220 | |
| 5221 | description_.append(" Module \""); |
| 5222 | description_.append(record.module_path); |
| 5223 | description_.append("\":\n"); |
| 5224 | |
| 5225 | int num_fields = 6; |
| 5226 | if (record.version > 4) { |
| 5227 | num_fields = 7; |
| 5228 | } |
| 5229 | for (int i = 1; i <= num_fields; ++i) { |
| 5230 | switch (i) { |
| 5231 | case 1: |
| 5232 | if (!record.message.empty()) { |
| 5233 | description_.append(" message: \""); |
| 5234 | description_.append(record.message); |
| 5235 | description_.append("\"\n"); |
| 5236 | } |
| 5237 | break; |
| 5238 | case 2: |
| 5239 | if (!record.signature_string.empty()) { |
| 5240 | description_.append(" signature_string: \""); |
| 5241 | description_.append(record.signature_string); |
| 5242 | description_.append("\"\n"); |
| 5243 | } |
| 5244 | break; |
| 5245 | case 3: |
| 5246 | if (!record.backtrace.empty()) { |
| 5247 | description_.append(" backtrace: \""); |
| 5248 | description_.append(record.backtrace); |
| 5249 | description_.append("\"\n"); |
| 5250 | } |
| 5251 | break; |
| 5252 | case 4: |
| 5253 | if (!record.message2.empty()) { |
| 5254 | description_.append(" message2: \""); |
| 5255 | description_.append(record.message2); |
| 5256 | description_.append("\"\n"); |
| 5257 | } |
| 5258 | break; |
| 5259 | case 5: |
| 5260 | if (record.thread) { |
| 5261 | char thread[128]; |
| 5262 | snprintf(thread, sizeof(thread), " thread: 0x%llx\n", |
| 5263 | record.thread); |
| 5264 | description_.append(thread); |
| 5265 | } |
| 5266 | break; |
| 5267 | case 6: |
| 5268 | if (record.dialog_mode) { |
| 5269 | char dialog_mode[128]; |
| 5270 | snprintf(dialog_mode, sizeof(dialog_mode), " dialog_mode: 0x%x\n", |
| 5271 | record.dialog_mode); |
| 5272 | description_.append(dialog_mode); |
| 5273 | } |
| 5274 | break; |
| 5275 | case 7: |
| 5276 | if (record.abort_cause) { |
| 5277 | char abort_cause[128]; |
| 5278 | snprintf(abort_cause, sizeof(abort_cause), " abort_cause: %lld\n", |
| 5279 | record.abort_cause); |
| 5280 | description_.append(abort_cause); |
| 5281 | } |
| 5282 | break; |
| 5283 | default: |
| 5284 | break; |
| 5285 | } |
| 5286 | } |
| 5287 | |
| 5288 | return true; |
| 5289 | } |
| 5290 | |
| 5291 | bool MinidumpMacCrashInfo::Read(uint32_t expected_size) { |
| 5292 | description_.clear(); |
| 5293 | records_.clear(); |
| 5294 | valid_ = false; |
| 5295 | |
| 5296 | MDRawMacCrashInfo crash_info; |
| 5297 | if (expected_size != sizeof(crash_info)) { |
| 5298 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5298)) << "MinidumpMacCrashInfo size mismatch, " << |
| 5299 | expected_size << " != " << sizeof(crash_info); |
| 5300 | return false; |
| 5301 | } |
| 5302 | if (!minidump_->ReadBytes(&crash_info, sizeof(crash_info))) { |
| 5303 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5303)) << "MinidumpMacCrashInfo could not read " << |
| 5304 | sizeof(crash_info) << " bytes"; |
| 5305 | return false; |
| 5306 | } |
| 5307 | if (minidump_->swap()) { |
| 5308 | Swap(&crash_info.stream_type); |
| 5309 | Swap(&crash_info.record_count); |
| 5310 | Swap(&crash_info.record_start_size); |
| 5311 | for (uint32_t i = 0; i < crash_info.record_count; ++i) { |
| 5312 | Swap(&crash_info.records[i].data_size); |
| 5313 | Swap(&crash_info.records[i].rva); |
| 5314 | } |
| 5315 | } |
| 5316 | if (crash_info.stream_type != MOZ_MACOS_CRASH_INFO_STREAM) { |
| 5317 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5317)) << "MinidumpMacCrashInfo stream type mismatch, " << |
| 5318 | crash_info.stream_type << " != " << |
| 5319 | MOZ_MACOS_CRASH_INFO_STREAM; |
| 5320 | return false; |
| 5321 | } |
| 5322 | |
| 5323 | for (uint32_t i = 0; i < crash_info.record_count; ++i) { |
| 5324 | if (!ReadCrashInfoRecord(crash_info.records[i], |
| 5325 | crash_info.record_start_size)) { |
| 5326 | return false; |
| 5327 | } |
| 5328 | } |
| 5329 | |
| 5330 | valid_ = true; |
| 5331 | return true; |
| 5332 | } |
| 5333 | |
| 5334 | void MinidumpMacCrashInfo::Print() { |
| 5335 | if (!valid_) { |
| 5336 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5336)) << "MinidumpMacCrashInfo cannot print invalid data"; |
| 5337 | return; |
| 5338 | } |
| 5339 | |
| 5340 | printf("MinidumpMacCrashInfo:\n\n"); |
| 5341 | printf("%s", description_.c_str()); |
| 5342 | } |
| 5343 | |
| 5344 | // |
| 5345 | // Minidump |
| 5346 | // |
| 5347 | |
| 5348 | |
| 5349 | uint32_t Minidump::max_streams_ = 128; |
| 5350 | unsigned int Minidump::max_string_length_ = 1024; |
| 5351 | |
| 5352 | |
| 5353 | Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width) |
| 5354 | : header_(), |
| 5355 | directory_(NULL__null), |
| 5356 | stream_map_(new MinidumpStreamMap()), |
| 5357 | path_(path), |
| 5358 | stream_(NULL__null), |
| 5359 | swap_(false), |
| 5360 | is_big_endian_(false), |
| 5361 | valid_(false), |
| 5362 | hexdump_(hexdump), |
| 5363 | hexdump_width_(hexdump_width) { |
| 5364 | } |
| 5365 | |
| 5366 | Minidump::Minidump(istream& stream) |
| 5367 | : header_(), |
| 5368 | directory_(NULL__null), |
| 5369 | stream_map_(new MinidumpStreamMap()), |
| 5370 | path_(), |
| 5371 | stream_(&stream), |
| 5372 | swap_(false), |
| 5373 | is_big_endian_(false), |
| 5374 | valid_(false), |
| 5375 | hexdump_(false), |
| 5376 | hexdump_width_(0) { |
| 5377 | } |
| 5378 | |
| 5379 | Minidump::~Minidump() { |
| 5380 | if (stream_) { |
| 5381 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5381)) << "Minidump closing minidump"; |
| 5382 | } |
| 5383 | if (!path_.empty()) { |
| 5384 | delete stream_; |
| 5385 | } |
| 5386 | delete directory_; |
| 5387 | delete stream_map_; |
| 5388 | } |
| 5389 | |
| 5390 | |
| 5391 | bool Minidump::Open() { |
| 5392 | if (stream_ != NULL__null) { |
| 5393 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5393)) << "Minidump reopening minidump " << path_; |
| 5394 | |
| 5395 | // The file is already open. Seek to the beginning, which is the position |
| 5396 | // the file would be at if it were opened anew. |
| 5397 | return SeekSet(0); |
| 5398 | } |
| 5399 | |
| 5400 | stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary); |
| 5401 | if (!stream_ || !stream_->good()) { |
| 5402 | string error_string; |
| 5403 | int error_code = ErrnoString(&error_string); |
| 5404 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5404)) << "Minidump could not open minidump " << path_ << |
| 5405 | ", error " << error_code << ": " << error_string; |
| 5406 | return false; |
| 5407 | } |
| 5408 | |
| 5409 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5409)) << "Minidump opened minidump " << path_; |
| 5410 | return true; |
| 5411 | } |
| 5412 | |
| 5413 | bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) { |
| 5414 | // Initialize output parameters |
| 5415 | *context_cpu_flags = 0; |
| 5416 | |
| 5417 | // Save the current stream position |
| 5418 | off_t saved_position = Tell(); |
| 5419 | if (saved_position == -1) { |
| 5420 | // Failed to save the current stream position. |
| 5421 | // Returns true because the current position of the stream is preserved. |
| 5422 | return true; |
| 5423 | } |
| 5424 | |
| 5425 | const MDRawSystemInfo* system_info = |
| 5426 | GetSystemInfo() ? GetSystemInfo()->system_info() : NULL__null; |
| 5427 | |
| 5428 | if (system_info != NULL__null) { |
| 5429 | switch (system_info->processor_architecture) { |
| 5430 | case MD_CPU_ARCHITECTURE_X86: |
| 5431 | *context_cpu_flags = MD_CONTEXT_X860x00010000; |
| 5432 | break; |
| 5433 | case MD_CPU_ARCHITECTURE_MIPS: |
| 5434 | *context_cpu_flags = MD_CONTEXT_MIPS0x00040000; |
| 5435 | break; |
| 5436 | case MD_CPU_ARCHITECTURE_MIPS64: |
| 5437 | *context_cpu_flags = MD_CONTEXT_MIPS640x00080000; |
| 5438 | break; |
| 5439 | case MD_CPU_ARCHITECTURE_ALPHA: |
| 5440 | *context_cpu_flags = MD_CONTEXT_ALPHA0x00020000; |
| 5441 | break; |
| 5442 | case MD_CPU_ARCHITECTURE_PPC: |
| 5443 | *context_cpu_flags = MD_CONTEXT_PPC0x20000000; |
| 5444 | break; |
| 5445 | case MD_CPU_ARCHITECTURE_PPC64: |
| 5446 | *context_cpu_flags = MD_CONTEXT_PPC640x01000000; |
| 5447 | break; |
| 5448 | case MD_CPU_ARCHITECTURE_SHX: |
| 5449 | *context_cpu_flags = MD_CONTEXT_SHX0x000000c0; |
| 5450 | break; |
| 5451 | case MD_CPU_ARCHITECTURE_ARM: |
| 5452 | *context_cpu_flags = MD_CONTEXT_ARM0x40000000; |
| 5453 | break; |
| 5454 | case MD_CPU_ARCHITECTURE_ARM64: |
| 5455 | *context_cpu_flags = MD_CONTEXT_ARM640x00400000; |
| 5456 | break; |
| 5457 | case MD_CPU_ARCHITECTURE_ARM64_OLD: |
| 5458 | *context_cpu_flags = MD_CONTEXT_ARM64_OLD0x80000000; |
| 5459 | break; |
| 5460 | case MD_CPU_ARCHITECTURE_IA64: |
| 5461 | *context_cpu_flags = MD_CONTEXT_IA640x00080000; |
| 5462 | break; |
| 5463 | case MD_CPU_ARCHITECTURE_ALPHA64: |
| 5464 | *context_cpu_flags = 0; |
| 5465 | break; |
| 5466 | case MD_CPU_ARCHITECTURE_MSIL: |
| 5467 | *context_cpu_flags = 0; |
| 5468 | break; |
| 5469 | case MD_CPU_ARCHITECTURE_AMD64: |
| 5470 | *context_cpu_flags = MD_CONTEXT_AMD640x00100000; |
| 5471 | break; |
| 5472 | case MD_CPU_ARCHITECTURE_X86_WIN64: |
| 5473 | *context_cpu_flags = 0; |
| 5474 | break; |
| 5475 | case MD_CPU_ARCHITECTURE_SPARC: |
| 5476 | *context_cpu_flags = MD_CONTEXT_SPARC0x10000000; |
| 5477 | break; |
| 5478 | case MD_CPU_ARCHITECTURE_UNKNOWN: |
| 5479 | *context_cpu_flags = 0; |
| 5480 | break; |
| 5481 | default: |
| 5482 | *context_cpu_flags = 0; |
| 5483 | break; |
| 5484 | } |
| 5485 | } |
| 5486 | |
| 5487 | // Restore position and return |
| 5488 | return SeekSet(saved_position); |
| 5489 | } |
| 5490 | |
| 5491 | |
| 5492 | bool Minidump::Read() { |
| 5493 | // Invalidate cached data. |
| 5494 | delete directory_; |
| 5495 | directory_ = NULL__null; |
| 5496 | stream_map_->clear(); |
| 5497 | |
| 5498 | valid_ = false; |
| 5499 | |
| 5500 | if (!Open()) { |
| 5501 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5501)) << "Minidump cannot open minidump"; |
| 5502 | return false; |
| 5503 | } |
| 5504 | |
| 5505 | if (!ReadBytes(&header_, sizeof(MDRawHeader))) { |
| 5506 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5506)) << "Minidump cannot read header"; |
| 5507 | return false; |
| 5508 | } |
| 5509 | |
| 5510 | if (header_.signature != MD_HEADER_SIGNATURE0x504d444d) { |
| 5511 | // The file may be byte-swapped. Under the present architecture, these |
| 5512 | // classes don't know or need to know what CPU (or endianness) the |
| 5513 | // minidump was produced on in order to parse it. Use the signature as |
| 5514 | // a byte order marker. |
| 5515 | uint32_t signature_swapped = header_.signature; |
| 5516 | Swap(&signature_swapped); |
| 5517 | if (signature_swapped != MD_HEADER_SIGNATURE0x504d444d) { |
| 5518 | // This isn't a minidump or a byte-swapped minidump. |
| 5519 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5519)) << "Minidump header signature mismatch: (" << |
| 5520 | HexString(header_.signature) << ", " << |
| 5521 | HexString(signature_swapped) << ") != " << |
| 5522 | HexString(MD_HEADER_SIGNATURE0x504d444d); |
| 5523 | return false; |
| 5524 | } |
| 5525 | swap_ = true; |
| 5526 | } else { |
| 5527 | // The file is not byte-swapped. Set swap_ false (it may have been true |
| 5528 | // if the object is being reused?) |
| 5529 | swap_ = false; |
| 5530 | } |
| 5531 | |
| 5532 | #if defined(__BIG_ENDIAN__) || \ |
| 5533 | (defined(__BYTE_ORDER__1234) && __BYTE_ORDER__1234 == __ORDER_BIG_ENDIAN__4321) |
| 5534 | is_big_endian_ = !swap_; |
| 5535 | #else |
| 5536 | is_big_endian_ = swap_; |
| 5537 | #endif |
| 5538 | |
| 5539 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5539)) << "Minidump " << (swap_ ? "" : "not ") << |
| 5540 | "byte-swapping minidump"; |
| 5541 | |
| 5542 | if (swap_) { |
| 5543 | Swap(&header_.signature); |
| 5544 | Swap(&header_.version); |
| 5545 | Swap(&header_.stream_count); |
| 5546 | Swap(&header_.stream_directory_rva); |
| 5547 | Swap(&header_.checksum); |
| 5548 | Swap(&header_.time_date_stamp); |
| 5549 | Swap(&header_.flags); |
| 5550 | } |
| 5551 | |
| 5552 | // Version check. The high 16 bits of header_.version contain something |
| 5553 | // else "implementation specific." |
| 5554 | if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION0x0000a793) { |
| 5555 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5555)) << "Minidump version mismatch: " << |
| 5556 | HexString(header_.version & 0x0000ffff) << " != " << |
| 5557 | HexString(MD_HEADER_VERSION0x0000a793); |
| 5558 | return false; |
| 5559 | } |
| 5560 | |
| 5561 | if (!SeekSet(header_.stream_directory_rva)) { |
| 5562 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5562)) << "Minidump cannot seek to stream directory"; |
| 5563 | return false; |
| 5564 | } |
| 5565 | |
| 5566 | if (header_.stream_count > max_streams_) { |
| 5567 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5567)) << "Minidump stream count " << header_.stream_count << |
| 5568 | " exceeds maximum " << max_streams_; |
| 5569 | return false; |
| 5570 | } |
| 5571 | |
| 5572 | if (header_.stream_count != 0) { |
| 5573 | scoped_ptr<MinidumpDirectoryEntries> directory( |
| 5574 | new MinidumpDirectoryEntries(header_.stream_count)); |
| 5575 | |
| 5576 | // Read the entire array in one fell swoop, instead of reading one entry |
| 5577 | // at a time in the loop. |
| 5578 | if (!ReadBytes(&(*directory)[0], |
| 5579 | sizeof(MDRawDirectory) * header_.stream_count)) { |
| 5580 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5580)) << "Minidump cannot read stream directory"; |
| 5581 | return false; |
| 5582 | } |
| 5583 | |
| 5584 | for (unsigned int stream_index = 0; |
| 5585 | stream_index < header_.stream_count; |
| 5586 | ++stream_index) { |
| 5587 | MDRawDirectory* directory_entry = &(*directory)[stream_index]; |
| 5588 | |
| 5589 | if (swap_) { |
| 5590 | Swap(&directory_entry->stream_type); |
| 5591 | Swap(&directory_entry->location); |
| 5592 | } |
| 5593 | |
| 5594 | // Initialize the stream_map_ map, which speeds locating a stream by |
| 5595 | // type. |
| 5596 | unsigned int stream_type = directory_entry->stream_type; |
| 5597 | switch (stream_type) { |
| 5598 | case MD_THREAD_LIST_STREAM: |
| 5599 | case MD_MODULE_LIST_STREAM: |
| 5600 | case MD_MEMORY_LIST_STREAM: |
| 5601 | case MD_EXCEPTION_STREAM: |
| 5602 | case MD_SYSTEM_INFO_STREAM: |
| 5603 | case MD_MISC_INFO_STREAM: |
| 5604 | case MD_BREAKPAD_INFO_STREAM: |
| 5605 | case MD_CRASHPAD_INFO_STREAM: |
| 5606 | case MOZ_MACOS_CRASH_INFO_STREAM: { |
| 5607 | if (stream_map_->find(stream_type) != stream_map_->end()) { |
| 5608 | // Another stream with this type was already found. A minidump |
| 5609 | // file should contain at most one of each of these stream types. |
| 5610 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5610)) << "Minidump found multiple streams of type " << |
| 5611 | stream_type << ", but can only deal with one"; |
| 5612 | return false; |
| 5613 | } |
| 5614 | BP_FALLTHROUGH[[clang::fallthrough]]; |
| 5615 | } |
| 5616 | |
| 5617 | default: { |
| 5618 | // Overwrites for stream types other than those above, but it's |
| 5619 | // expected to be the user's burden in that case. |
| 5620 | (*stream_map_)[stream_type].stream_index = stream_index; |
| 5621 | } |
| 5622 | } |
| 5623 | } |
| 5624 | |
| 5625 | directory_ = directory.release(); |
| 5626 | } |
| 5627 | |
| 5628 | valid_ = true; |
| 5629 | return true; |
| 5630 | } |
| 5631 | |
| 5632 | |
| 5633 | MinidumpThreadList* Minidump::GetThreadList() { |
| 5634 | MinidumpThreadList* thread_list; |
| 5635 | return GetStream(&thread_list); |
| 5636 | } |
| 5637 | |
| 5638 | |
| 5639 | MinidumpModuleList* Minidump::GetModuleList() { |
| 5640 | MinidumpModuleList* module_list; |
| 5641 | return GetStream(&module_list); |
| 5642 | } |
| 5643 | |
| 5644 | |
| 5645 | MinidumpMemoryList* Minidump::GetMemoryList() { |
| 5646 | MinidumpMemoryList* memory_list; |
| 5647 | return GetStream(&memory_list); |
| 5648 | } |
| 5649 | |
| 5650 | |
| 5651 | MinidumpException* Minidump::GetException() { |
| 5652 | MinidumpException* exception; |
| 5653 | return GetStream(&exception); |
| 5654 | } |
| 5655 | |
| 5656 | MinidumpAssertion* Minidump::GetAssertion() { |
| 5657 | MinidumpAssertion* assertion; |
| 5658 | return GetStream(&assertion); |
| 5659 | } |
| 5660 | |
| 5661 | |
| 5662 | MinidumpSystemInfo* Minidump::GetSystemInfo() { |
| 5663 | MinidumpSystemInfo* system_info; |
| 5664 | return GetStream(&system_info); |
| 5665 | } |
| 5666 | |
| 5667 | |
| 5668 | MinidumpUnloadedModuleList* Minidump::GetUnloadedModuleList() { |
| 5669 | MinidumpUnloadedModuleList* unloaded_module_list; |
| 5670 | return GetStream(&unloaded_module_list); |
| 5671 | } |
| 5672 | |
| 5673 | |
| 5674 | MinidumpMiscInfo* Minidump::GetMiscInfo() { |
| 5675 | MinidumpMiscInfo* misc_info; |
| 5676 | return GetStream(&misc_info); |
| 5677 | } |
| 5678 | |
| 5679 | |
| 5680 | MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() { |
| 5681 | MinidumpBreakpadInfo* breakpad_info; |
| 5682 | return GetStream(&breakpad_info); |
| 5683 | } |
| 5684 | |
| 5685 | MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() { |
| 5686 | MinidumpMemoryInfoList* memory_info_list; |
| 5687 | return GetStream(&memory_info_list); |
| 5688 | } |
| 5689 | |
| 5690 | MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() { |
| 5691 | MinidumpLinuxMapsList *linux_maps_list; |
| 5692 | return GetStream(&linux_maps_list); |
| 5693 | } |
| 5694 | |
| 5695 | bool Minidump::IsAndroid() { |
| 5696 | MDOSPlatform platform; |
| 5697 | return GetPlatform(&platform) && platform == MD_OS_ANDROID; |
| 5698 | } |
| 5699 | |
| 5700 | bool Minidump::GetPlatform(MDOSPlatform* platform) { |
| 5701 | // Save the current stream position |
| 5702 | off_t saved_position = Tell(); |
| 5703 | if (saved_position == -1) { |
| 5704 | return false; |
| 5705 | } |
| 5706 | const MDRawSystemInfo* system_info = |
| 5707 | GetSystemInfo() ? GetSystemInfo()->system_info() : NULL__null; |
| 5708 | |
| 5709 | // Restore position and return |
| 5710 | if (!SeekSet(saved_position)) { |
| 5711 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5711)) << "Couldn't seek back to saved position"; |
| 5712 | return false; |
| 5713 | } |
| 5714 | |
| 5715 | if (!system_info) { |
| 5716 | return false; |
| 5717 | } |
| 5718 | *platform = static_cast<MDOSPlatform>(system_info->platform_id); |
| 5719 | return true; |
| 5720 | } |
| 5721 | |
| 5722 | MinidumpCrashpadInfo* Minidump::GetCrashpadInfo() { |
| 5723 | MinidumpCrashpadInfo* crashpad_info; |
| 5724 | return GetStream(&crashpad_info); |
| 5725 | } |
| 5726 | |
| 5727 | MinidumpMacCrashInfo* Minidump::GetMacCrashInfo() { |
| 5728 | MinidumpMacCrashInfo* mac_crash_info; |
| 5729 | return GetStream(&mac_crash_info); |
| 5730 | } |
| 5731 | |
| 5732 | MinidumpThreadNamesList* Minidump::GetThreadNamesList() { |
| 5733 | MinidumpThreadNamesList* thread_names_list; |
| 5734 | return GetStream(&thread_names_list); |
| 5735 | } |
| 5736 | |
| 5737 | // |
| 5738 | // MinidumpThreadName |
| 5739 | // |
| 5740 | |
| 5741 | |
| 5742 | MinidumpThreadName::MinidumpThreadName(Minidump* minidump) |
| 5743 | : MinidumpObject(minidump), |
| 5744 | valid_(false), |
| 5745 | thread_name_(), |
| 5746 | name_(NULL__null) { |
| 5747 | |
| 5748 | } |
| 5749 | |
| 5750 | MinidumpThreadName::~MinidumpThreadName() { |
| 5751 | ; |
| 5752 | } |
| 5753 | |
| 5754 | void MinidumpThreadName::Print() { |
| 5755 | if (!valid_) { |
| 5756 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5756)) << "MinidumpThreadName cannot print invalid data"; |
| 5757 | return; |
| 5758 | } |
| 5759 | |
| 5760 | printf("MDRawThreadName\n"); |
| 5761 | printf(" thread_id = 0x%x\n", |
| 5762 | thread_name_.thread_id); |
| 5763 | printf(" rva_of_thread_name = 0x%" PRIx64"l" "x" "\n", |
| 5764 | thread_name_.rva_of_thread_name); |
| 5765 | |
| 5766 | printf(" (name) = \"%s\"\n", name().c_str()); |
| 5767 | printf("\n"); |
| 5768 | } |
| 5769 | |
| 5770 | string MinidumpThreadName::name() const { |
| 5771 | if (!valid_) { |
| 5772 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5772)) << "Invalid MinidumpThreadName for name"; |
| 5773 | return ""; |
| 5774 | } |
| 5775 | |
| 5776 | return *name_; |
| 5777 | } |
| 5778 | |
| 5779 | bool MinidumpThreadName::Read(uint32_t expected_size) { |
| 5780 | |
| 5781 | delete name_; |
| 5782 | |
| 5783 | if (expected_size < sizeof(thread_name_)) { |
| 5784 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5784)) << "MinidumpThreadName expected size is less than size " |
| 5785 | << "of struct " << expected_size << " < " |
| 5786 | << sizeof(thread_name_); |
| 5787 | return false; |
| 5788 | } |
| 5789 | |
| 5790 | if (!minidump_->ReadBytes(&thread_name_, sizeof(thread_name_))) { |
| 5791 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5791)) << "MinidumpThreadName cannot read name"; |
| 5792 | return false; |
| 5793 | } |
| 5794 | |
| 5795 | if (expected_size > sizeof(thread_name_)) { |
| 5796 | uint32_t thread_name_bytes_remaining = expected_size - sizeof(thread_name_); |
| 5797 | off_t pos = minidump_->Tell(); |
| 5798 | if (!minidump_->SeekSet(pos + thread_name_bytes_remaining)) { |
| 5799 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5799)) << "MinidumpThreadName unable to seek to end of name"; |
| 5800 | return false; |
| 5801 | } |
| 5802 | } |
| 5803 | |
| 5804 | if (minidump_->swap()) { |
| 5805 | Swap(&thread_name_.thread_id); |
| 5806 | uint64_t rva_of_thread_name; |
| 5807 | memcpy(&rva_of_thread_name, &thread_name_.rva_of_thread_name, sizeof(uint64_t)); |
| 5808 | Swap(&rva_of_thread_name); |
| 5809 | memcpy(&thread_name_.rva_of_thread_name, &rva_of_thread_name, sizeof(uint64_t)); |
| 5810 | } |
| 5811 | |
| 5812 | return true; |
| 5813 | } |
| 5814 | |
| 5815 | bool MinidumpThreadName::ReadAuxiliaryData() { |
| 5816 | // Each thread must have a name string. |
| 5817 | name_ = minidump_->ReadString(thread_name_.rva_of_thread_name); |
| 5818 | if (!name_) { |
| 5819 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5819)) << "MinidumpThreadName could not read name"; |
| 5820 | valid_ = false; |
| 5821 | return false; |
| 5822 | } |
| 5823 | |
| 5824 | // At this point, we have enough info for the name to be valid. |
| 5825 | valid_ = true; |
| 5826 | return true; |
| 5827 | } |
| 5828 | |
| 5829 | // |
| 5830 | // MinidumpThreadNamesList |
| 5831 | // |
| 5832 | |
| 5833 | |
| 5834 | MinidumpThreadNamesList::MinidumpThreadNamesList(Minidump* minidump) |
| 5835 | : MinidumpStream(minidump), |
| 5836 | thread_names_(NULL__null), |
| 5837 | name_count_(0), |
| 5838 | valid_(false) { |
| 5839 | ; |
| 5840 | } |
| 5841 | |
| 5842 | MinidumpThreadNamesList::~MinidumpThreadNamesList() { |
| 5843 | delete thread_names_; |
| 5844 | } |
| 5845 | |
| 5846 | const string MinidumpThreadNamesList::GetNameForThreadId(uint32_t thread_id) const { |
| 5847 | if (valid_) { |
| 5848 | for (unsigned int name_index = 0; |
| 5849 | name_index < name_count_; |
| 5850 | ++name_index) { |
| 5851 | const MinidumpThreadName& thread_name = (*thread_names_)[name_index]; |
| 5852 | if (thread_name.thread_id() == thread_id) { |
| 5853 | return thread_name.name(); |
| 5854 | } |
| 5855 | } |
| 5856 | } |
| 5857 | |
| 5858 | return ""; |
| 5859 | } |
| 5860 | |
| 5861 | void MinidumpThreadNamesList::Print() { |
| 5862 | if (!valid_) { |
| 5863 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5863)) << "MinidumpThreadNamesList cannot print invalid data"; |
| 5864 | return; |
| 5865 | } |
| 5866 | |
| 5867 | printf("MinidumpThreadNamesList\n"); |
| 5868 | printf(" name_count = %d\n", name_count_); |
| 5869 | printf("\n"); |
| 5870 | |
| 5871 | for (unsigned int name_index = 0; |
| 5872 | name_index < name_count_; |
| 5873 | ++name_index) { |
| 5874 | printf("thread_name[%d]\n", name_index); |
| 5875 | |
| 5876 | (*thread_names_)[name_index].Print(); |
| 5877 | } |
| 5878 | } |
| 5879 | |
| 5880 | bool MinidumpThreadNamesList::Read(uint32_t expected_size) { |
| 5881 | delete thread_names_; |
| 5882 | thread_names_ = NULL__null; |
| 5883 | name_count_ = 0; |
| 5884 | |
| 5885 | valid_ = false; |
| 5886 | |
| 5887 | uint32_t number_of_thread_names; |
| 5888 | if (!minidump_->ReadBytes(&number_of_thread_names, sizeof(number_of_thread_names))) { |
| 5889 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5889)) << "MinidumpThreadNamesList could not read the number of thread names"; |
| 5890 | return false; |
| 5891 | } |
| 5892 | |
| 5893 | if (minidump_->swap()) { |
| 5894 | Swap(&number_of_thread_names); |
| 5895 | } |
| 5896 | |
| 5897 | if (expected_size != |
| 5898 | sizeof(number_of_thread_names) + (sizeof(MDRawThreadName) * number_of_thread_names)) { |
| 5899 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5899)) << "MinidumpThreadNamesList expected_size mismatch " << |
| 5900 | expected_size << " != " << sizeof(number_of_thread_names) << " + (" << |
| 5901 | sizeof(MDRawThreadName) << " * " << number_of_thread_names << ")"; |
| 5902 | return false; |
| 5903 | } |
| 5904 | |
| 5905 | if (number_of_thread_names != 0) { |
| 5906 | scoped_ptr<MinidumpThreadNames> thread_names( |
| 5907 | new MinidumpThreadNames(number_of_thread_names, |
| 5908 | MinidumpThreadName(minidump_))); |
| 5909 | |
| 5910 | for (unsigned int name_index = 0; |
| 5911 | name_index < number_of_thread_names; |
| 5912 | ++name_index) { |
| 5913 | MinidumpThreadName* thread_name = &(*thread_names)[name_index]; |
| 5914 | |
| 5915 | if (!thread_name->Read(sizeof(MDRawThreadName))) { |
| 5916 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5916)) << "MinidumpThreadNamesList could not read name " << |
| 5917 | name_index << "/" << number_of_thread_names; |
| 5918 | return false; |
| 5919 | } |
| 5920 | } |
| 5921 | |
| 5922 | for (unsigned int name_index = 0; |
| 5923 | name_index < number_of_thread_names; |
| 5924 | ++name_index) { |
| 5925 | MinidumpThreadName* thread_name = &(*thread_names)[name_index]; |
| 5926 | |
| 5927 | if (!thread_name->ReadAuxiliaryData()) { |
| 5928 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 5928)) << "MinidumpThreadNamesList could not read required " |
| 5929 | "auxiliary data for thread name " << |
| 5930 | name_index << "/" << number_of_thread_names; |
| 5931 | return false; |
| 5932 | } |
| 5933 | } |
| 5934 | thread_names_ = thread_names.release(); |
| 5935 | } |
| 5936 | |
| 5937 | name_count_ = number_of_thread_names; |
| 5938 | valid_ = true; |
| 5939 | return true; |
| 5940 | } |
| 5941 | |
| 5942 | static const char* get_stream_name(uint32_t stream_type) { |
| 5943 | switch (stream_type) { |
| 5944 | case MD_UNUSED_STREAM: |
| 5945 | return "MD_UNUSED_STREAM"; |
| 5946 | case MD_RESERVED_STREAM_0: |
| 5947 | return "MD_RESERVED_STREAM_0"; |
| 5948 | case MD_RESERVED_STREAM_1: |
| 5949 | return "MD_RESERVED_STREAM_1"; |
| 5950 | case MD_THREAD_LIST_STREAM: |
| 5951 | return "MD_THREAD_LIST_STREAM"; |
| 5952 | case MD_MODULE_LIST_STREAM: |
| 5953 | return "MD_MODULE_LIST_STREAM"; |
| 5954 | case MD_MEMORY_LIST_STREAM: |
| 5955 | return "MD_MEMORY_LIST_STREAM"; |
| 5956 | case MD_EXCEPTION_STREAM: |
| 5957 | return "MD_EXCEPTION_STREAM"; |
| 5958 | case MD_SYSTEM_INFO_STREAM: |
| 5959 | return "MD_SYSTEM_INFO_STREAM"; |
| 5960 | case MD_THREAD_EX_LIST_STREAM: |
| 5961 | return "MD_THREAD_EX_LIST_STREAM"; |
| 5962 | case MD_MEMORY_64_LIST_STREAM: |
| 5963 | return "MD_MEMORY_64_LIST_STREAM"; |
| 5964 | case MD_COMMENT_STREAM_A: |
| 5965 | return "MD_COMMENT_STREAM_A"; |
| 5966 | case MD_COMMENT_STREAM_W: |
| 5967 | return "MD_COMMENT_STREAM_W"; |
| 5968 | case MD_HANDLE_DATA_STREAM: |
| 5969 | return "MD_HANDLE_DATA_STREAM"; |
| 5970 | case MD_FUNCTION_TABLE_STREAM: |
| 5971 | return "MD_FUNCTION_TABLE_STREAM"; |
| 5972 | case MD_UNLOADED_MODULE_LIST_STREAM: |
| 5973 | return "MD_UNLOADED_MODULE_LIST_STREAM"; |
| 5974 | case MD_MISC_INFO_STREAM: |
| 5975 | return "MD_MISC_INFO_STREAM"; |
| 5976 | case MD_MEMORY_INFO_LIST_STREAM: |
| 5977 | return "MD_MEMORY_INFO_LIST_STREAM"; |
| 5978 | case MD_THREAD_INFO_LIST_STREAM: |
| 5979 | return "MD_THREAD_INFO_LIST_STREAM"; |
| 5980 | case MD_HANDLE_OPERATION_LIST_STREAM: |
| 5981 | return "MD_HANDLE_OPERATION_LIST_STREAM"; |
| 5982 | case MD_TOKEN_STREAM: |
| 5983 | return "MD_TOKEN_STREAM"; |
| 5984 | case MD_JAVASCRIPT_DATA_STREAM: |
| 5985 | return "MD_JAVASCRIPT_DATA_STREAM"; |
| 5986 | case MD_SYSTEM_MEMORY_INFO_STREAM: |
| 5987 | return "MD_SYSTEM_MEMORY_INFO_STREAM"; |
| 5988 | case MD_PROCESS_VM_COUNTERS_STREAM: |
| 5989 | return "MD_PROCESS_VM_COUNTERS_STREAM"; |
| 5990 | case MD_IPT_TRACE_STREAM: |
| 5991 | return "MD_IPT_TRACE_STREAM"; |
| 5992 | case MD_THREAD_NAMES_STREAM: |
| 5993 | return "MD_THREAD_NAMES_STREAM"; |
| 5994 | case MD_LAST_RESERVED_STREAM: |
| 5995 | return "MD_LAST_RESERVED_STREAM"; |
| 5996 | case MD_BREAKPAD_INFO_STREAM: |
| 5997 | return "MD_BREAKPAD_INFO_STREAM"; |
| 5998 | case MD_ASSERTION_INFO_STREAM: |
| 5999 | return "MD_ASSERTION_INFO_STREAM"; |
| 6000 | case MD_LINUX_CPU_INFO: |
| 6001 | return "MD_LINUX_CPU_INFO"; |
| 6002 | case MD_LINUX_PROC_STATUS: |
| 6003 | return "MD_LINUX_PROC_STATUS"; |
| 6004 | case MD_LINUX_LSB_RELEASE: |
| 6005 | return "MD_LINUX_LSB_RELEASE"; |
| 6006 | case MD_LINUX_CMD_LINE: |
| 6007 | return "MD_LINUX_CMD_LINE"; |
| 6008 | case MD_LINUX_ENVIRON: |
| 6009 | return "MD_LINUX_ENVIRON"; |
| 6010 | case MD_LINUX_AUXV: |
| 6011 | return "MD_LINUX_AUXV"; |
| 6012 | case MD_LINUX_MAPS: |
| 6013 | return "MD_LINUX_MAPS"; |
| 6014 | case MD_LINUX_DSO_DEBUG: |
| 6015 | return "MD_LINUX_DSO_DEBUG"; |
| 6016 | case MD_CRASHPAD_INFO_STREAM: |
| 6017 | return "MD_CRASHPAD_INFO_STREAM"; |
| 6018 | case MOZ_MACOS_CRASH_INFO_STREAM: |
| 6019 | return "MOZ_MACOS_CRASH_INFO_STREAM"; |
| 6020 | default: |
| 6021 | return "unknown"; |
| 6022 | } |
| 6023 | } |
| 6024 | |
| 6025 | void Minidump::Print() { |
| 6026 | if (!valid_) { |
| 6027 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6027)) << "Minidump cannot print invalid data"; |
| 6028 | return; |
| 6029 | } |
| 6030 | |
| 6031 | printf("MDRawHeader\n"); |
| 6032 | printf(" signature = 0x%x\n", header_.signature); |
| 6033 | printf(" version = 0x%x\n", header_.version); |
| 6034 | printf(" stream_count = %d\n", header_.stream_count); |
| 6035 | printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); |
| 6036 | printf(" checksum = 0x%x\n", header_.checksum); |
| 6037 | printf(" time_date_stamp = 0x%x %s\n", |
| 6038 | header_.time_date_stamp, |
| 6039 | TimeTToUTCString(header_.time_date_stamp).c_str()); |
| 6040 | printf(" flags = 0x%" PRIx64"l" "x" "\n", header_.flags); |
| 6041 | printf("\n"); |
| 6042 | |
| 6043 | for (unsigned int stream_index = 0; |
| 6044 | stream_index < header_.stream_count; |
| 6045 | ++stream_index) { |
| 6046 | MDRawDirectory* directory_entry = &(*directory_)[stream_index]; |
| 6047 | |
| 6048 | printf("mDirectory[%d]\n", stream_index); |
| 6049 | printf("MDRawDirectory\n"); |
| 6050 | printf(" stream_type = 0x%x (%s)\n", directory_entry->stream_type, |
| 6051 | get_stream_name(directory_entry->stream_type)); |
| 6052 | printf(" location.data_size = %d\n", |
| 6053 | directory_entry->location.data_size); |
| 6054 | printf(" location.rva = 0x%x\n", directory_entry->location.rva); |
| 6055 | printf("\n"); |
| 6056 | } |
| 6057 | |
| 6058 | printf("Streams:\n"); |
| 6059 | for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin(); |
| 6060 | iterator != stream_map_->end(); |
| 6061 | ++iterator) { |
| 6062 | uint32_t stream_type = iterator->first; |
| 6063 | const MinidumpStreamInfo& info = iterator->second; |
| 6064 | printf(" stream type 0x%x (%s) at index %d\n", stream_type, |
| 6065 | get_stream_name(stream_type), |
| 6066 | info.stream_index); |
| 6067 | } |
| 6068 | printf("\n"); |
| 6069 | } |
| 6070 | |
| 6071 | |
| 6072 | const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index) |
| 6073 | const { |
| 6074 | if (!valid_) { |
| 6075 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6075)) << "Invalid Minidump for GetDirectoryEntryAtIndex"; |
| 6076 | return NULL__null; |
| 6077 | } |
| 6078 | |
| 6079 | if (index >= header_.stream_count) { |
| 6080 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6080)) << "Minidump stream directory index out of range: " << |
| 6081 | index << "/" << header_.stream_count; |
| 6082 | return NULL__null; |
| 6083 | } |
| 6084 | |
| 6085 | return &(*directory_)[index]; |
| 6086 | } |
| 6087 | |
| 6088 | |
| 6089 | bool Minidump::ReadBytes(void* bytes, size_t count) { |
| 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_->read(static_cast<char*>(bytes), count); |
| 6096 | std::streamsize bytes_read = stream_->gcount(); |
| 6097 | if (bytes_read == -1) { |
| 6098 | string error_string; |
| 6099 | int error_code = ErrnoString(&error_string); |
| 6100 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6100)) << "ReadBytes: error " << error_code << ": " << error_string; |
| 6101 | return false; |
| 6102 | } |
| 6103 | |
| 6104 | // Convert to size_t and check for data loss |
| 6105 | size_t bytes_read_converted = static_cast<size_t>(bytes_read); |
| 6106 | if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) { |
| 6107 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6107)) << "ReadBytes: conversion data loss detected when converting " |
| 6108 | << bytes_read << " to " << bytes_read_converted; |
| 6109 | return false; |
| 6110 | } |
| 6111 | |
| 6112 | if (bytes_read_converted != count) { |
| 6113 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6113)) << "ReadBytes: read " << bytes_read_converted << "/" << count; |
| 6114 | return false; |
| 6115 | } |
| 6116 | |
| 6117 | return true; |
| 6118 | } |
| 6119 | |
| 6120 | |
| 6121 | bool Minidump::SeekSet(off_t offset) { |
| 6122 | // Can't check valid_ because Read needs to call this method before |
| 6123 | // validity can be determined. |
| 6124 | if (!stream_) { |
| 6125 | return false; |
| 6126 | } |
| 6127 | stream_->seekg(offset, std::ios_base::beg); |
| 6128 | if (!stream_->good()) { |
| 6129 | string error_string; |
| 6130 | int error_code = ErrnoString(&error_string); |
| 6131 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6131)) << "SeekSet: error " << error_code << ": " << error_string; |
| 6132 | return false; |
| 6133 | } |
| 6134 | return true; |
| 6135 | } |
| 6136 | |
| 6137 | off_t Minidump::Tell() { |
| 6138 | if (!valid_ || !stream_) { |
| 6139 | return (off_t)-1; |
| 6140 | } |
| 6141 | |
| 6142 | // Check for conversion data loss |
| 6143 | std::streamoff std_streamoff = stream_->tellg(); |
| 6144 | off_t rv = static_cast<off_t>(std_streamoff); |
| 6145 | if (static_cast<std::streamoff>(rv) == std_streamoff) { |
| 6146 | return rv; |
| 6147 | } else { |
| 6148 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6148)) << "Data loss detected"; |
| 6149 | return (off_t)-1; |
| 6150 | } |
| 6151 | } |
| 6152 | |
| 6153 | |
| 6154 | string* Minidump::ReadString(off_t offset) { |
| 6155 | if (!valid_) { |
| 6156 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6156)) << "Invalid Minidump for ReadString"; |
| 6157 | return NULL__null; |
| 6158 | } |
| 6159 | if (!SeekSet(offset)) { |
| 6160 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6160)) << "ReadString could not seek to string at offset " << offset; |
| 6161 | return NULL__null; |
| 6162 | } |
| 6163 | |
| 6164 | uint32_t bytes; |
| 6165 | if (!ReadBytes(&bytes, sizeof(bytes))) { |
| 6166 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6166)) << "ReadString could not read string size at offset " << |
| 6167 | offset; |
| 6168 | return NULL__null; |
| 6169 | } |
| 6170 | if (swap_) |
| 6171 | Swap(&bytes); |
| 6172 | |
| 6173 | if (bytes % 2 != 0) { |
| 6174 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6174)) << "ReadString found odd-sized " << bytes << |
| 6175 | "-byte string at offset " << offset; |
| 6176 | return NULL__null; |
| 6177 | } |
| 6178 | unsigned int utf16_words = bytes / 2; |
| 6179 | |
| 6180 | if (utf16_words > max_string_length_) { |
| 6181 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6181)) << "ReadString string length " << utf16_words << |
| 6182 | " exceeds maximum " << max_string_length_ << |
| 6183 | " at offset " << offset; |
| 6184 | return NULL__null; |
| 6185 | } |
| 6186 | |
| 6187 | vector<uint16_t> string_utf16(utf16_words); |
| 6188 | |
| 6189 | if (utf16_words) { |
| 6190 | if (!ReadBytes(&string_utf16[0], bytes)) { |
| 6191 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6191)) << "ReadString could not read " << bytes << |
| 6192 | "-byte string at offset " << offset; |
| 6193 | return NULL__null; |
| 6194 | } |
| 6195 | } |
| 6196 | |
| 6197 | return UTF16ToUTF8(string_utf16, swap_); |
| 6198 | } |
| 6199 | |
| 6200 | |
| 6201 | bool Minidump::ReadUTF8String(off_t offset, string* string_utf8) { |
| 6202 | if (!valid_) { |
| 6203 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6203)) << "Invalid Minidump for ReadString"; |
| 6204 | return false; |
| 6205 | } |
| 6206 | if (!SeekSet(offset)) { |
| 6207 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6207)) << "ReadUTF8String could not seek to string at offset " |
| 6208 | << offset; |
| 6209 | return false; |
| 6210 | } |
| 6211 | |
| 6212 | uint32_t bytes; |
| 6213 | if (!ReadBytes(&bytes, sizeof(bytes))) { |
| 6214 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6214)) << "ReadUTF8String could not read string size at offset " << |
| 6215 | offset; |
| 6216 | return false; |
| 6217 | } |
| 6218 | |
| 6219 | if (swap_) { |
| 6220 | Swap(&bytes); |
| 6221 | } |
| 6222 | |
| 6223 | if (bytes > max_string_length_) { |
| 6224 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6224)) << "ReadUTF8String string length " << bytes << |
| 6225 | " exceeds maximum " << max_string_length_ << |
| 6226 | " at offset " << offset; |
| 6227 | return false; |
| 6228 | } |
| 6229 | |
| 6230 | string_utf8->resize(bytes); |
| 6231 | |
| 6232 | if (!ReadBytes(&(*string_utf8)[0], bytes)) { |
| 6233 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6233)) << "ReadUTF8String could not read " << bytes << |
| 6234 | "-byte string at offset " << offset; |
| 6235 | return false; |
| 6236 | } |
| 6237 | |
| 6238 | return true; |
| 6239 | } |
| 6240 | |
| 6241 | |
| 6242 | bool Minidump::ReadStringList( |
| 6243 | off_t offset, |
| 6244 | std::vector<std::string>* string_list) { |
| 6245 | string_list->clear(); |
| 6246 | |
| 6247 | if (!SeekSet(offset)) { |
| 6248 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6248)) << "Minidump cannot seek to string_list"; |
| 6249 | return false; |
| 6250 | } |
| 6251 | |
| 6252 | uint32_t count; |
| 6253 | if (!ReadBytes(&count, sizeof(count))) { |
| 6254 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6254)) << "Minidump cannot read string_list count"; |
| 6255 | return false; |
| 6256 | } |
| 6257 | |
| 6258 | if (swap_) { |
| 6259 | Swap(&count); |
| 6260 | } |
| 6261 | |
| 6262 | scoped_array<MDRVA> rvas(new MDRVA[count]); |
| 6263 | |
| 6264 | // Read the entire array in one fell swoop, instead of reading one entry |
| 6265 | // at a time in the loop. |
| 6266 | if (!ReadBytes(&rvas[0], sizeof(MDRVA) * count)) { |
| 6267 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6267)) << "Minidump could not read string_list"; |
| 6268 | return false; |
| 6269 | } |
| 6270 | |
| 6271 | for (uint32_t index = 0; index < count; ++index) { |
| 6272 | if (swap()) { |
| 6273 | Swap(&rvas[index]); |
| 6274 | } |
| 6275 | |
| 6276 | string entry; |
| 6277 | if (!ReadUTF8String(rvas[index], &entry)) { |
| 6278 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6278)) << "Minidump could not read string_list entry"; |
| 6279 | return false; |
| 6280 | } |
| 6281 | |
| 6282 | string_list->push_back(entry); |
| 6283 | } |
| 6284 | |
| 6285 | return true; |
| 6286 | } |
| 6287 | |
| 6288 | |
| 6289 | bool Minidump::ReadSimpleStringDictionary( |
| 6290 | off_t offset, |
| 6291 | std::map<std::string, std::string>* simple_string_dictionary) { |
| 6292 | simple_string_dictionary->clear(); |
| 6293 | |
| 6294 | if (!SeekSet(offset)) { |
| 6295 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6295)) << "Minidump cannot seek to simple_string_dictionary"; |
| 6296 | return false; |
| 6297 | } |
| 6298 | |
| 6299 | uint32_t count; |
| 6300 | if (!ReadBytes(&count, sizeof(count))) { |
| 6301 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6301)) |
| 6302 | << "Minidump cannot read simple_string_dictionary count"; |
| 6303 | return false; |
| 6304 | } |
| 6305 | |
| 6306 | if (swap()) { |
| 6307 | Swap(&count); |
| 6308 | } |
| 6309 | |
| 6310 | scoped_array<MDRawSimpleStringDictionaryEntry> entries( |
| 6311 | new MDRawSimpleStringDictionaryEntry[count]); |
| 6312 | |
| 6313 | // Read the entire array in one fell swoop, instead of reading one entry |
| 6314 | // at a time in the loop. |
| 6315 | if (!ReadBytes( |
| 6316 | &entries[0], |
| 6317 | sizeof(MDRawSimpleStringDictionaryEntry) * count)) { |
| 6318 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6318)) << "Minidump could not read simple_string_dictionary"; |
| 6319 | return false; |
| 6320 | } |
| 6321 | |
| 6322 | for (uint32_t index = 0; index < count; ++index) { |
| 6323 | if (swap()) { |
| 6324 | Swap(&entries[index]); |
| 6325 | } |
| 6326 | |
| 6327 | string key; |
| 6328 | if (!ReadUTF8String(entries[index].key, &key)) { |
| 6329 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6329)) << "Minidump could not read simple_string_dictionary key"; |
| 6330 | return false; |
| 6331 | } |
| 6332 | |
| 6333 | string value; |
| 6334 | if (!ReadUTF8String(entries[index].value, &value)) { |
| 6335 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6335)) << "Minidump could not read simple_string_dictionary value"; |
| 6336 | return false; |
| 6337 | } |
| 6338 | |
| 6339 | if (simple_string_dictionary->find(key) != |
| 6340 | simple_string_dictionary->end()) { |
| 6341 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6341)) |
| 6342 | << "Minidump: discarding duplicate simple_string_dictionary value " |
| 6343 | << value << " for key " << key; |
| 6344 | } else { |
| 6345 | simple_string_dictionary->insert(std::make_pair(key, value)); |
| 6346 | } |
| 6347 | } |
| 6348 | |
| 6349 | return true; |
| 6350 | } |
| 6351 | |
| 6352 | |
| 6353 | bool Minidump::SeekToStreamType(uint32_t stream_type, |
| 6354 | uint32_t* stream_length) { |
| 6355 | BPLOG_IF(ERROR, !stream_length)!(((!stream_length) && ((google_breakpad::LogStream:: SEVERITY_ERROR) >= (google_breakpad::LogStream::SEVERITY_CRITICAL )))) ? (void) 0 : google_breakpad::LogMessageVoidify() & ( google_breakpad::LogStream(std::cerr, google_breakpad::LogStream ::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6355)) << "Minidump::SeekToStreamType requires " |
| 6356 | "|stream_length|"; |
| 6357 | assert(stream_length)(static_cast <bool> (stream_length) ? void (0) : __assert_fail ("stream_length", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 6358 | *stream_length = 0; |
| 6359 | |
| 6360 | if (!valid_) { |
| 6361 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6361)) << "Invalid Mindump for SeekToStreamType"; |
| 6362 | return false; |
| 6363 | } |
| 6364 | |
| 6365 | MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type); |
| 6366 | if (iterator == stream_map_->end()) { |
| 6367 | // This stream type didn't exist in the directory. |
| 6368 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6368)) << "SeekToStreamType: type " << stream_type << " not present"; |
| 6369 | return false; |
| 6370 | } |
| 6371 | |
| 6372 | const MinidumpStreamInfo& info = iterator->second; |
| 6373 | if (info.stream_index >= header_.stream_count) { |
| 6374 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6374)) << "SeekToStreamType: type " << stream_type << |
| 6375 | " out of range: " << |
| 6376 | info.stream_index << "/" << header_.stream_count; |
| 6377 | return false; |
| 6378 | } |
| 6379 | |
| 6380 | MDRawDirectory* directory_entry = &(*directory_)[info.stream_index]; |
| 6381 | if (!SeekSet(directory_entry->location.rva)) { |
| 6382 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6382)) << "SeekToStreamType could not seek to stream type " << |
| 6383 | stream_type; |
| 6384 | return false; |
| 6385 | } |
| 6386 | |
| 6387 | *stream_length = directory_entry->location.data_size; |
| 6388 | |
| 6389 | return true; |
| 6390 | } |
| 6391 | |
| 6392 | |
| 6393 | template<typename T> |
| 6394 | T* Minidump::GetStream(T** stream) { |
| 6395 | // stream is a garbage parameter that's present only to account for C++'s |
| 6396 | // inability to overload a method based solely on its return type. |
| 6397 | |
| 6398 | const uint32_t stream_type = T::kStreamType; |
| 6399 | |
| 6400 | BPLOG_IF(ERROR, !stream)!(((!stream) && ((google_breakpad::LogStream::SEVERITY_ERROR ) >= (google_breakpad::LogStream::SEVERITY_CRITICAL)))) ? ( void) 0 : google_breakpad::LogMessageVoidify() & (google_breakpad ::LogStream(std::cerr, google_breakpad::LogStream::SEVERITY_ERROR , "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6400)) << "Minidump::GetStream type " << stream_type << |
| 6401 | " requires |stream|"; |
| 6402 | assert(stream)(static_cast <bool> (stream) ? void (0) : __assert_fail ("stream", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
| 6403 | *stream = NULL__null; |
| 6404 | |
| 6405 | if (!valid_) { |
| 6406 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6406)) << "Invalid Minidump for GetStream type " << stream_type; |
| 6407 | return NULL__null; |
| 6408 | } |
| 6409 | |
| 6410 | MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type); |
| 6411 | if (iterator == stream_map_->end()) { |
| 6412 | // This stream type didn't exist in the directory. |
| 6413 | BPLOG(INFO)!(((google_breakpad::LogStream::SEVERITY_INFO) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: clog, google_breakpad::LogStream::SEVERITY_INFO, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6413)) << "GetStream: type " << stream_type << " not present"; |
| 6414 | return NULL__null; |
| 6415 | } |
| 6416 | |
| 6417 | // Get a pointer so that the stored stream field can be altered. |
| 6418 | MinidumpStreamInfo* info = &iterator->second; |
| 6419 | |
| 6420 | if (info->stream) { |
| 6421 | // This cast is safe because info.stream is only populated by this |
| 6422 | // method, and there is a direct correlation between T and stream_type. |
| 6423 | *stream = static_cast<T*>(info->stream); |
| 6424 | return *stream; |
| 6425 | } |
| 6426 | |
| 6427 | uint32_t stream_length; |
| 6428 | if (!SeekToStreamType(stream_type, &stream_length)) { |
| 6429 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6429)) << "GetStream could not seek to stream type " << stream_type; |
| 6430 | return NULL__null; |
| 6431 | } |
| 6432 | |
| 6433 | scoped_ptr<T> new_stream(new T(this)); |
| 6434 | |
| 6435 | if (!new_stream->Read(stream_length)) { |
| 6436 | BPLOG(ERROR)!(((google_breakpad::LogStream::SEVERITY_ERROR) >= (google_breakpad ::LogStream::SEVERITY_CRITICAL))) ? (void) 0 : google_breakpad ::LogMessageVoidify() & (google_breakpad::LogStream(std:: cerr, google_breakpad::LogStream::SEVERITY_ERROR, "./../../../../../../toolkit/crashreporter/google-breakpad/src/processor/minidump.cc" , 6436)) << "GetStream could not read stream type " << stream_type; |
| 6437 | return NULL__null; |
| 6438 | } |
| 6439 | |
| 6440 | *stream = new_stream.release(); |
| 6441 | info->stream = *stream; |
| 6442 | return *stream; |
| 6443 | } |
| 6444 | |
| 6445 | } // namespace google_breakpad |