1// Copyright (c) 2006, 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#include "google_breakpad/processor/minidump_processor.h" 31 32#include <assert.h> 33#include <stdio.h> 34 35#include <string> 36 37#include "common/scoped_ptr.h" 38#include "common/using_std_string.h" 39#include "google_breakpad/processor/call_stack.h" 40#include "google_breakpad/processor/minidump.h" 41#include "google_breakpad/processor/process_state.h" 42#include "google_breakpad/processor/exploitability.h" 43#include "google_breakpad/processor/stack_frame_symbolizer.h" 44#include "processor/logging.h" 45#include "processor/stackwalker_x86.h" 46#include "processor/symbolic_constants_win.h" 47 48namespace google_breakpad { 49 50MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, 51 SourceLineResolverInterface *resolver) 52 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), 53 own_frame_symbolizer_(true), 54 enable_exploitability_(false) { 55} 56 57MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, 58 SourceLineResolverInterface *resolver, 59 bool enable_exploitability) 60 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), 61 own_frame_symbolizer_(true), 62 enable_exploitability_(enable_exploitability) { 63} 64 65MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer, 66 bool enable_exploitability) 67 : frame_symbolizer_(frame_symbolizer), 68 own_frame_symbolizer_(false), 69 enable_exploitability_(enable_exploitability) { 70 assert(frame_symbolizer_); 71} 72 73MinidumpProcessor::~MinidumpProcessor() { 74 if (own_frame_symbolizer_) delete frame_symbolizer_; 75} 76 77ProcessResult MinidumpProcessor::Process( 78 Minidump *dump, ProcessState *process_state) { 79 assert(dump); 80 assert(process_state); 81 82 process_state->Clear(); 83 84 const MDRawHeader *header = dump->header(); 85 if (!header) { 86 BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; 87 return PROCESS_ERROR_NO_MINIDUMP_HEADER; 88 } 89 process_state->time_date_stamp_ = header->time_date_stamp; 90 91 bool has_process_create_time = 92 GetProcessCreateTime(dump, &process_state->process_create_time_); 93 94 bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_); 95 bool has_os_info = GetOSInfo(dump, &process_state->system_info_); 96 97 uint32_t dump_thread_id = 0; 98 bool has_dump_thread = false; 99 uint32_t requesting_thread_id = 0; 100 bool has_requesting_thread = false; 101 102 MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo(); 103 if (breakpad_info) { 104 has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); 105 has_requesting_thread = 106 breakpad_info->GetRequestingThreadID(&requesting_thread_id); 107 } 108 109 MinidumpException *exception = dump->GetException(); 110 if (exception) { 111 process_state->crashed_ = true; 112 has_requesting_thread = exception->GetThreadID(&requesting_thread_id); 113 114 process_state->crash_reason_ = GetCrashReason( 115 dump, &process_state->crash_address_); 116 } 117 118 // This will just return an empty string if it doesn't exist. 119 process_state->assertion_ = GetAssertion(dump); 120 121 MinidumpModuleList *module_list = dump->GetModuleList(); 122 123 // Put a copy of the module list into ProcessState object. This is not 124 // necessarily a MinidumpModuleList, but it adheres to the CodeModules 125 // interface, which is all that ProcessState needs to expose. 126 if (module_list) 127 process_state->modules_ = module_list->Copy(); 128 129 MinidumpMemoryList *memory_list = dump->GetMemoryList(); 130 if (memory_list) { 131 BPLOG(INFO) << "Found " << memory_list->region_count() 132 << " memory regions."; 133 } 134 135 MinidumpThreadList *threads = dump->GetThreadList(); 136 if (!threads) { 137 BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; 138 return PROCESS_ERROR_NO_THREAD_LIST; 139 } 140 141 BPLOG(INFO) << "Minidump " << dump->path() << " has " << 142 (has_cpu_info ? "" : "no ") << "CPU info, " << 143 (has_os_info ? "" : "no ") << "OS info, " << 144 (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << 145 (exception != NULL ? "" : "no ") << "exception, " << 146 (module_list != NULL ? "" : "no ") << "module list, " << 147 (threads != NULL ? "" : "no ") << "thread list, " << 148 (has_dump_thread ? "" : "no ") << "dump thread, " << 149 (has_requesting_thread ? "" : "no ") << "requesting thread, and " << 150 (has_process_create_time ? "" : "no ") << "process create time"; 151 152 bool interrupted = false; 153 bool found_requesting_thread = false; 154 unsigned int thread_count = threads->thread_count(); 155 156 // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. 157 frame_symbolizer_->Reset(); 158 159 for (unsigned int thread_index = 0; 160 thread_index < thread_count; 161 ++thread_index) { 162 char thread_string_buffer[64]; 163 snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", 164 thread_index, thread_count); 165 string thread_string = dump->path() + ":" + thread_string_buffer; 166 167 MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); 168 if (!thread) { 169 BPLOG(ERROR) << "Could not get thread for " << thread_string; 170 return PROCESS_ERROR_GETTING_THREAD; 171 } 172 173 uint32_t thread_id; 174 if (!thread->GetThreadID(&thread_id)) { 175 BPLOG(ERROR) << "Could not get thread ID for " << thread_string; 176 return PROCESS_ERROR_GETTING_THREAD_ID; 177 } 178 179 thread_string += " id " + HexString(thread_id); 180 BPLOG(INFO) << "Looking at thread " << thread_string; 181 182 // If this thread is the thread that produced the minidump, don't process 183 // it. Because of the problems associated with a thread producing a 184 // dump of itself (when both its context and its stack are in flux), 185 // processing that stack wouldn't provide much useful data. 186 if (has_dump_thread && thread_id == dump_thread_id) { 187 continue; 188 } 189 190 MinidumpContext *context = thread->GetContext(); 191 192 if (has_requesting_thread && thread_id == requesting_thread_id) { 193 if (found_requesting_thread) { 194 // There can't be more than one requesting thread. 195 BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; 196 return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS; 197 } 198 199 // Use processed_state->threads_.size() instead of thread_index. 200 // thread_index points to the thread index in the minidump, which 201 // might be greater than the thread index in the threads vector if 202 // any of the minidump's threads are skipped and not placed into the 203 // processed threads vector. The thread vector's current size will 204 // be the index of the current thread when it's pushed into the 205 // vector. 206 process_state->requesting_thread_ = process_state->threads_.size(); 207 208 found_requesting_thread = true; 209 210 if (process_state->crashed_) { 211 // Use the exception record's context for the crashed thread, instead 212 // of the thread's own context. For the crashed thread, the thread's 213 // own context is the state inside the exception handler. Using it 214 // would not result in the expected stack trace from the time of the 215 // crash. If the exception context is invalid, however, we fall back 216 // on the thread context. 217 MinidumpContext *ctx = exception->GetContext(); 218 context = ctx ? ctx : thread->GetContext(); 219 } 220 } 221 222 // If the memory region for the stack cannot be read using the RVA stored 223 // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use 224 // a memory region (containing the stack) from the minidump memory list. 225 MinidumpMemoryRegion *thread_memory = thread->GetMemory(); 226 if (!thread_memory && memory_list) { 227 uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange(); 228 if (start_stack_memory_range) { 229 thread_memory = memory_list->GetMemoryRegionForAddress( 230 start_stack_memory_range); 231 } 232 } 233 if (!thread_memory) { 234 BPLOG(ERROR) << "No memory region for " << thread_string; 235 } 236 237 // Use process_state->modules_ instead of module_list, because the 238 // |modules| argument will be used to populate the |module| fields in 239 // the returned StackFrame objects, which will be placed into the 240 // returned ProcessState object. module_list's lifetime is only as 241 // long as the Minidump object: it will be deleted when this function 242 // returns. process_state->modules_ is owned by the ProcessState object 243 // (just like the StackFrame objects), and is much more suitable for this 244 // task. 245 scoped_ptr<Stackwalker> stackwalker( 246 Stackwalker::StackwalkerForCPU(process_state->system_info(), 247 context, 248 thread_memory, 249 process_state->modules_, 250 frame_symbolizer_)); 251 252 scoped_ptr<CallStack> stack(new CallStack()); 253 if (stackwalker.get()) { 254 if (!stackwalker->Walk(stack.get(), 255 &process_state->modules_without_symbols_, 256 &process_state->modules_with_corrupt_symbols_)) { 257 BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " 258 << thread_string; 259 interrupted = true; 260 } 261 } else { 262 // Threads with missing CPU contexts will hit this, but 263 // don't abort processing the rest of the dump just for 264 // one bad thread. 265 BPLOG(ERROR) << "No stackwalker for " << thread_string; 266 } 267 process_state->threads_.push_back(stack.release()); 268 process_state->thread_memory_regions_.push_back(thread_memory); 269 } 270 271 if (interrupted) { 272 BPLOG(INFO) << "Processing interrupted for " << dump->path(); 273 return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; 274 } 275 276 // If a requesting thread was indicated, it must be present. 277 if (has_requesting_thread && !found_requesting_thread) { 278 // Don't mark as an error, but invalidate the requesting thread 279 BPLOG(ERROR) << "Minidump indicated requesting thread " << 280 HexString(requesting_thread_id) << ", not found in " << 281 dump->path(); 282 process_state->requesting_thread_ = -1; 283 } 284 285 // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED 286 process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED; 287 288 // If an exploitability run was requested we perform the platform specific 289 // rating. 290 if (enable_exploitability_) { 291 scoped_ptr<Exploitability> exploitability( 292 Exploitability::ExploitabilityForPlatform(dump, process_state)); 293 // The engine will be null if the platform is not supported 294 if (exploitability != NULL) { 295 process_state->exploitability_ = exploitability->CheckExploitability(); 296 } else { 297 process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE; 298 } 299 } 300 301 BPLOG(INFO) << "Processed " << dump->path(); 302 return PROCESS_OK; 303} 304 305ProcessResult MinidumpProcessor::Process( 306 const string &minidump_file, ProcessState *process_state) { 307 BPLOG(INFO) << "Processing minidump in file " << minidump_file; 308 309 Minidump dump(minidump_file); 310 if (!dump.Read()) { 311 BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; 312 return PROCESS_ERROR_MINIDUMP_NOT_FOUND; 313 } 314 315 return Process(&dump, process_state); 316} 317 318// Returns the MDRawSystemInfo from a minidump, or NULL if system info is 319// not available from the minidump. If system_info is non-NULL, it is used 320// to pass back the MinidumpSystemInfo object. 321static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, 322 MinidumpSystemInfo **system_info) { 323 MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); 324 if (!minidump_system_info) 325 return NULL; 326 327 if (system_info) 328 *system_info = minidump_system_info; 329 330 return minidump_system_info->system_info(); 331} 332 333// Extract CPU info string from ARM-specific MDRawSystemInfo structure. 334// raw_info: pointer to source MDRawSystemInfo. 335// cpu_info: address of target string, cpu info text will be appended to it. 336static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, 337 string* cpu_info) { 338 assert(raw_info != NULL && cpu_info != NULL); 339 340 // Write ARM architecture version. 341 char cpu_string[32]; 342 snprintf(cpu_string, sizeof(cpu_string), "ARMv%d", 343 raw_info->processor_level); 344 cpu_info->append(cpu_string); 345 346 // There is no good list of implementer id values, but the following 347 // pages provide some help: 348 // http://comments.gmane.org/gmane.linux.linaro.devel/6903 349 // http://forum.xda-developers.com/archive/index.php/t-480226.html 350 const struct { 351 uint32_t id; 352 const char* name; 353 } vendors[] = { 354 { 0x41, "ARM" }, 355 { 0x51, "Qualcomm" }, 356 { 0x56, "Marvell" }, 357 { 0x69, "Intel/Marvell" }, 358 }; 359 const struct { 360 uint32_t id; 361 const char* name; 362 } parts[] = { 363 { 0x4100c050, "Cortex-A5" }, 364 { 0x4100c080, "Cortex-A8" }, 365 { 0x4100c090, "Cortex-A9" }, 366 { 0x4100c0f0, "Cortex-A15" }, 367 { 0x4100c140, "Cortex-R4" }, 368 { 0x4100c150, "Cortex-R5" }, 369 { 0x4100b360, "ARM1136" }, 370 { 0x4100b560, "ARM1156" }, 371 { 0x4100b760, "ARM1176" }, 372 { 0x4100b020, "ARM11-MPCore" }, 373 { 0x41009260, "ARM926" }, 374 { 0x41009460, "ARM946" }, 375 { 0x41009660, "ARM966" }, 376 { 0x510006f0, "Krait" }, 377 { 0x510000f0, "Scorpion" }, 378 }; 379 380 const struct { 381 uint32_t hwcap; 382 const char* name; 383 } features[] = { 384 { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" }, 385 { MD_CPU_ARM_ELF_HWCAP_HALF, "half" }, 386 { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" }, 387 { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" }, 388 { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" }, 389 { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" }, 390 { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" }, 391 { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" }, 392 { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" }, 393 { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" }, 394 { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" }, 395 { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" }, 396 { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" }, 397 { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" }, 398 { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" }, 399 { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" }, 400 { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" }, 401 { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" }, 402 { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" }, 403 }; 404 405 uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; 406 if (cpuid != 0) { 407 // Extract vendor name from CPUID 408 const char* vendor = NULL; 409 uint32_t vendor_id = (cpuid >> 24) & 0xff; 410 for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { 411 if (vendors[i].id == vendor_id) { 412 vendor = vendors[i].name; 413 break; 414 } 415 } 416 cpu_info->append(" "); 417 if (vendor) { 418 cpu_info->append(vendor); 419 } else { 420 snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id); 421 cpu_info->append(cpu_string); 422 } 423 424 // Extract part name from CPUID 425 uint32_t part_id = (cpuid & 0xff00fff0); 426 const char* part = NULL; 427 for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { 428 if (parts[i].id == part_id) { 429 part = parts[i].name; 430 break; 431 } 432 } 433 cpu_info->append(" "); 434 if (part != NULL) { 435 cpu_info->append(part); 436 } else { 437 snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); 438 cpu_info->append(cpu_string); 439 } 440 } 441 uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps; 442 if (elf_hwcaps != 0) { 443 cpu_info->append(" features: "); 444 const char* comma = ""; 445 for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) { 446 if (elf_hwcaps & features[i].hwcap) { 447 cpu_info->append(comma); 448 cpu_info->append(features[i].name); 449 comma = ","; 450 } 451 } 452 } 453} 454 455// static 456bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { 457 assert(dump); 458 assert(info); 459 460 info->cpu.clear(); 461 info->cpu_info.clear(); 462 463 MinidumpSystemInfo *system_info; 464 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); 465 if (!raw_system_info) 466 return false; 467 468 switch (raw_system_info->processor_architecture) { 469 case MD_CPU_ARCHITECTURE_X86: 470 case MD_CPU_ARCHITECTURE_AMD64: { 471 if (raw_system_info->processor_architecture == 472 MD_CPU_ARCHITECTURE_X86) 473 info->cpu = "x86"; 474 else 475 info->cpu = "amd64"; 476 477 const string *cpu_vendor = system_info->GetCPUVendor(); 478 if (cpu_vendor) { 479 info->cpu_info = *cpu_vendor; 480 info->cpu_info.append(" "); 481 } 482 483 char x86_info[36]; 484 snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", 485 raw_system_info->processor_level, 486 raw_system_info->processor_revision >> 8, 487 raw_system_info->processor_revision & 0xff); 488 info->cpu_info.append(x86_info); 489 break; 490 } 491 492 case MD_CPU_ARCHITECTURE_PPC: { 493 info->cpu = "ppc"; 494 break; 495 } 496 497 case MD_CPU_ARCHITECTURE_PPC64: { 498 info->cpu = "ppc64"; 499 break; 500 } 501 502 case MD_CPU_ARCHITECTURE_SPARC: { 503 info->cpu = "sparc"; 504 break; 505 } 506 507 case MD_CPU_ARCHITECTURE_ARM: { 508 info->cpu = "arm"; 509 GetARMCpuInfo(raw_system_info, &info->cpu_info); 510 break; 511 } 512 513 case MD_CPU_ARCHITECTURE_ARM64: { 514 info->cpu = "arm64"; 515 break; 516 } 517 518 case MD_CPU_ARCHITECTURE_MIPS: { 519 info->cpu = "mips"; 520 break; 521 } 522 523 default: { 524 // Assign the numeric architecture ID into the CPU string. 525 char cpu_string[7]; 526 snprintf(cpu_string, sizeof(cpu_string), "0x%04x", 527 raw_system_info->processor_architecture); 528 info->cpu = cpu_string; 529 break; 530 } 531 } 532 533 info->cpu_count = raw_system_info->number_of_processors; 534 535 return true; 536} 537 538// static 539bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { 540 assert(dump); 541 assert(info); 542 543 info->os.clear(); 544 info->os_short.clear(); 545 info->os_version.clear(); 546 547 MinidumpSystemInfo *system_info; 548 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); 549 if (!raw_system_info) 550 return false; 551 552 info->os_short = system_info->GetOS(); 553 554 switch (raw_system_info->platform_id) { 555 case MD_OS_WIN32_NT: { 556 info->os = "Windows NT"; 557 break; 558 } 559 560 case MD_OS_WIN32_WINDOWS: { 561 info->os = "Windows"; 562 break; 563 } 564 565 case MD_OS_MAC_OS_X: { 566 info->os = "Mac OS X"; 567 break; 568 } 569 570 case MD_OS_IOS: { 571 info->os = "iOS"; 572 break; 573 } 574 575 case MD_OS_LINUX: { 576 info->os = "Linux"; 577 break; 578 } 579 580 case MD_OS_SOLARIS: { 581 info->os = "Solaris"; 582 break; 583 } 584 585 case MD_OS_ANDROID: { 586 info->os = "Android"; 587 break; 588 } 589 590 case MD_OS_PS3: { 591 info->os = "PS3"; 592 break; 593 } 594 595 case MD_OS_NACL: { 596 info->os = "NaCl"; 597 break; 598 } 599 600 default: { 601 // Assign the numeric platform ID into the OS string. 602 char os_string[11]; 603 snprintf(os_string, sizeof(os_string), "0x%08x", 604 raw_system_info->platform_id); 605 info->os = os_string; 606 break; 607 } 608 } 609 610 char os_version_string[33]; 611 snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", 612 raw_system_info->major_version, 613 raw_system_info->minor_version, 614 raw_system_info->build_number); 615 info->os_version = os_version_string; 616 617 const string *csd_version = system_info->GetCSDVersion(); 618 if (csd_version) { 619 info->os_version.append(" "); 620 info->os_version.append(*csd_version); 621 } 622 623 return true; 624} 625 626// static 627bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump, 628 uint32_t* process_create_time) { 629 assert(dump); 630 assert(process_create_time); 631 632 *process_create_time = 0; 633 634 MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo(); 635 if (!minidump_misc_info) { 636 return false; 637 } 638 639 const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info(); 640 if (!md_raw_misc_info) { 641 return false; 642 } 643 644 if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) { 645 return false; 646 } 647 648 *process_create_time = md_raw_misc_info->process_create_time; 649 return true; 650} 651 652// static 653string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { 654 MinidumpException *exception = dump->GetException(); 655 if (!exception) 656 return ""; 657 658 const MDRawExceptionStream *raw_exception = exception->exception(); 659 if (!raw_exception) 660 return ""; 661 662 if (address) 663 *address = raw_exception->exception_record.exception_address; 664 665 // The reason value is OS-specific and possibly CPU-specific. Set up 666 // sensible numeric defaults for the reason string in case we can't 667 // map the codes to a string (because there's no system info, or because 668 // it's an unrecognized platform, or because it's an unrecognized code.) 669 char reason_string[24]; 670 uint32_t exception_code = raw_exception->exception_record.exception_code; 671 uint32_t exception_flags = raw_exception->exception_record.exception_flags; 672 snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x", 673 exception_code, exception_flags); 674 string reason = reason_string; 675 676 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL); 677 if (!raw_system_info) 678 return reason; 679 680 switch (raw_system_info->platform_id) { 681 case MD_OS_MAC_OS_X: 682 case MD_OS_IOS: { 683 char flags_string[11]; 684 snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags); 685 switch (exception_code) { 686 case MD_EXCEPTION_MAC_BAD_ACCESS: 687 reason = "EXC_BAD_ACCESS / "; 688 switch (exception_flags) { 689 case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS: 690 reason.append("KERN_INVALID_ADDRESS"); 691 break; 692 case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE: 693 reason.append("KERN_PROTECTION_FAILURE"); 694 break; 695 case MD_EXCEPTION_CODE_MAC_NO_ACCESS: 696 reason.append("KERN_NO_ACCESS"); 697 break; 698 case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE: 699 reason.append("KERN_MEMORY_FAILURE"); 700 break; 701 case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR: 702 reason.append("KERN_MEMORY_ERROR"); 703 break; 704 default: 705 // arm and ppc overlap 706 if (raw_system_info->processor_architecture == 707 MD_CPU_ARCHITECTURE_ARM || 708 raw_system_info->processor_architecture == 709 MD_CPU_ARCHITECTURE_ARM64) { 710 switch (exception_flags) { 711 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: 712 reason.append("EXC_ARM_DA_ALIGN"); 713 break; 714 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: 715 reason.append("EXC_ARM_DA_DEBUG"); 716 break; 717 default: 718 reason.append(flags_string); 719 BPLOG(INFO) << "Unknown exception reason " << reason; 720 break; 721 } 722 } else if (raw_system_info->processor_architecture == 723 MD_CPU_ARCHITECTURE_PPC) { 724 switch (exception_flags) { 725 case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ: 726 reason.append("EXC_PPC_VM_PROT_READ"); 727 break; 728 case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE: 729 reason.append("EXC_PPC_BADSPACE"); 730 break; 731 case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED: 732 reason.append("EXC_PPC_UNALIGNED"); 733 break; 734 default: 735 reason.append(flags_string); 736 BPLOG(INFO) << "Unknown exception reason " << reason; 737 break; 738 } 739 } else { 740 reason.append(flags_string); 741 BPLOG(INFO) << "Unknown exception reason " << reason; 742 } 743 break; 744 } 745 break; 746 case MD_EXCEPTION_MAC_BAD_INSTRUCTION: 747 reason = "EXC_BAD_INSTRUCTION / "; 748 switch (raw_system_info->processor_architecture) { 749 case MD_CPU_ARCHITECTURE_ARM: 750 case MD_CPU_ARCHITECTURE_ARM64: { 751 switch (exception_flags) { 752 case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED: 753 reason.append("EXC_ARM_UNDEFINED"); 754 break; 755 default: 756 reason.append(flags_string); 757 BPLOG(INFO) << "Unknown exception reason " << reason; 758 break; 759 } 760 break; 761 } 762 case MD_CPU_ARCHITECTURE_PPC: { 763 switch (exception_flags) { 764 case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL: 765 reason.append("EXC_PPC_INVALID_SYSCALL"); 766 break; 767 case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION: 768 reason.append("EXC_PPC_UNIPL_INST"); 769 break; 770 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION: 771 reason.append("EXC_PPC_PRIVINST"); 772 break; 773 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER: 774 reason.append("EXC_PPC_PRIVREG"); 775 break; 776 case MD_EXCEPTION_CODE_MAC_PPC_TRACE: 777 reason.append("EXC_PPC_TRACE"); 778 break; 779 case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR: 780 reason.append("EXC_PPC_PERFMON"); 781 break; 782 default: 783 reason.append(flags_string); 784 BPLOG(INFO) << "Unknown exception reason " << reason; 785 break; 786 } 787 break; 788 } 789 case MD_CPU_ARCHITECTURE_X86: { 790 switch (exception_flags) { 791 case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION: 792 reason.append("EXC_I386_INVOP"); 793 break; 794 case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT: 795 reason.append("EXC_INVTSSFLT"); 796 break; 797 case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT: 798 reason.append("EXC_SEGNPFLT"); 799 break; 800 case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT: 801 reason.append("EXC_STKFLT"); 802 break; 803 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: 804 reason.append("EXC_GPFLT"); 805 break; 806 case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT: 807 reason.append("EXC_ALIGNFLT"); 808 break; 809 default: 810 reason.append(flags_string); 811 BPLOG(INFO) << "Unknown exception reason " << reason; 812 break; 813 } 814 break; 815 } 816 default: 817 reason.append(flags_string); 818 BPLOG(INFO) << "Unknown exception reason " << reason; 819 break; 820 } 821 break; 822 case MD_EXCEPTION_MAC_ARITHMETIC: 823 reason = "EXC_ARITHMETIC / "; 824 switch (raw_system_info->processor_architecture) { 825 case MD_CPU_ARCHITECTURE_PPC: { 826 switch (exception_flags) { 827 case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW: 828 reason.append("EXC_PPC_OVERFLOW"); 829 break; 830 case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE: 831 reason.append("EXC_PPC_ZERO_DIVIDE"); 832 break; 833 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT: 834 reason.append("EXC_FLT_INEXACT"); 835 break; 836 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE: 837 reason.append("EXC_PPC_FLT_ZERO_DIVIDE"); 838 break; 839 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW: 840 reason.append("EXC_PPC_FLT_UNDERFLOW"); 841 break; 842 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW: 843 reason.append("EXC_PPC_FLT_OVERFLOW"); 844 break; 845 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER: 846 reason.append("EXC_PPC_FLT_NOT_A_NUMBER"); 847 break; 848 case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION: 849 reason.append("EXC_PPC_NOEMULATION"); 850 break; 851 case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST: 852 reason.append("EXC_PPC_ALTIVECASSIST"); 853 default: 854 reason.append(flags_string); 855 BPLOG(INFO) << "Unknown exception reason " << reason; 856 break; 857 } 858 break; 859 } 860 case MD_CPU_ARCHITECTURE_X86: { 861 switch (exception_flags) { 862 case MD_EXCEPTION_CODE_MAC_X86_DIV: 863 reason.append("EXC_I386_DIV"); 864 break; 865 case MD_EXCEPTION_CODE_MAC_X86_INTO: 866 reason.append("EXC_I386_INTO"); 867 break; 868 case MD_EXCEPTION_CODE_MAC_X86_NOEXT: 869 reason.append("EXC_I386_NOEXT"); 870 break; 871 case MD_EXCEPTION_CODE_MAC_X86_EXTOVR: 872 reason.append("EXC_I386_EXTOVR"); 873 break; 874 case MD_EXCEPTION_CODE_MAC_X86_EXTERR: 875 reason.append("EXC_I386_EXTERR"); 876 break; 877 case MD_EXCEPTION_CODE_MAC_X86_EMERR: 878 reason.append("EXC_I386_EMERR"); 879 break; 880 case MD_EXCEPTION_CODE_MAC_X86_BOUND: 881 reason.append("EXC_I386_BOUND"); 882 break; 883 case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR: 884 reason.append("EXC_I386_SSEEXTERR"); 885 break; 886 default: 887 reason.append(flags_string); 888 BPLOG(INFO) << "Unknown exception reason " << reason; 889 break; 890 } 891 break; 892 } 893 default: 894 reason.append(flags_string); 895 BPLOG(INFO) << "Unknown exception reason " << reason; 896 break; 897 } 898 break; 899 case MD_EXCEPTION_MAC_EMULATION: 900 reason = "EXC_EMULATION / "; 901 reason.append(flags_string); 902 break; 903 case MD_EXCEPTION_MAC_SOFTWARE: 904 reason = "EXC_SOFTWARE / "; 905 switch (exception_flags) { 906 case MD_EXCEPTION_CODE_MAC_ABORT: 907 reason.append("SIGABRT"); 908 break; 909 case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION: 910 reason.append("UNCAUGHT_NS_EXCEPTION"); 911 break; 912 // These are ppc only but shouldn't be a problem as they're 913 // unused on x86 914 case MD_EXCEPTION_CODE_MAC_PPC_TRAP: 915 reason.append("EXC_PPC_TRAP"); 916 break; 917 case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE: 918 reason.append("EXC_PPC_MIGRATE"); 919 break; 920 default: 921 reason.append(flags_string); 922 BPLOG(INFO) << "Unknown exception reason " << reason; 923 break; 924 } 925 break; 926 case MD_EXCEPTION_MAC_BREAKPOINT: 927 reason = "EXC_BREAKPOINT / "; 928 switch (raw_system_info->processor_architecture) { 929 case MD_CPU_ARCHITECTURE_ARM: 930 case MD_CPU_ARCHITECTURE_ARM64: { 931 switch (exception_flags) { 932 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: 933 reason.append("EXC_ARM_DA_ALIGN"); 934 break; 935 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: 936 reason.append("EXC_ARM_DA_DEBUG"); 937 break; 938 case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT: 939 reason.append("EXC_ARM_BREAKPOINT"); 940 break; 941 default: 942 reason.append(flags_string); 943 BPLOG(INFO) << "Unknown exception reason " << reason; 944 break; 945 } 946 break; 947 } 948 case MD_CPU_ARCHITECTURE_PPC: { 949 switch (exception_flags) { 950 case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT: 951 reason.append("EXC_PPC_BREAKPOINT"); 952 break; 953 default: 954 reason.append(flags_string); 955 BPLOG(INFO) << "Unknown exception reason " << reason; 956 break; 957 } 958 break; 959 } 960 case MD_CPU_ARCHITECTURE_X86: { 961 switch (exception_flags) { 962 case MD_EXCEPTION_CODE_MAC_X86_SGL: 963 reason.append("EXC_I386_SGL"); 964 break; 965 case MD_EXCEPTION_CODE_MAC_X86_BPT: 966 reason.append("EXC_I386_BPT"); 967 break; 968 default: 969 reason.append(flags_string); 970 BPLOG(INFO) << "Unknown exception reason " << reason; 971 break; 972 } 973 break; 974 } 975 default: 976 reason.append(flags_string); 977 BPLOG(INFO) << "Unknown exception reason " << reason; 978 break; 979 } 980 break; 981 case MD_EXCEPTION_MAC_SYSCALL: 982 reason = "EXC_SYSCALL / "; 983 reason.append(flags_string); 984 break; 985 case MD_EXCEPTION_MAC_MACH_SYSCALL: 986 reason = "EXC_MACH_SYSCALL / "; 987 reason.append(flags_string); 988 break; 989 case MD_EXCEPTION_MAC_RPC_ALERT: 990 reason = "EXC_RPC_ALERT / "; 991 reason.append(flags_string); 992 break; 993 } 994 break; 995 } 996 997 case MD_OS_WIN32_NT: 998 case MD_OS_WIN32_WINDOWS: { 999 switch (exception_code) { 1000 case MD_EXCEPTION_CODE_WIN_CONTROL_C: 1001 reason = "DBG_CONTROL_C"; 1002 break; 1003 case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: 1004 reason = "EXCEPTION_GUARD_PAGE"; 1005 break; 1006 case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT: 1007 reason = "EXCEPTION_DATATYPE_MISALIGNMENT"; 1008 break; 1009 case MD_EXCEPTION_CODE_WIN_BREAKPOINT: 1010 reason = "EXCEPTION_BREAKPOINT"; 1011 break; 1012 case MD_EXCEPTION_CODE_WIN_SINGLE_STEP: 1013 reason = "EXCEPTION_SINGLE_STEP"; 1014 break; 1015 case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: 1016 // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that 1017 // caused the fault in exception_information[1]. 1018 // exception_information[0] is 0 if the violation was caused by 1019 // an attempt to read data, 1 if it was an attempt to write data, 1020 // and 8 if this was a data execution violation. 1021 // This information is useful in addition to the code address, which 1022 // will be present in the crash thread's instruction field anyway. 1023 if (raw_exception->exception_record.number_parameters >= 1) { 1024 MDAccessViolationTypeWin av_type = 1025 static_cast<MDAccessViolationTypeWin> 1026 (raw_exception->exception_record.exception_information[0]); 1027 switch (av_type) { 1028 case MD_ACCESS_VIOLATION_WIN_READ: 1029 reason = "EXCEPTION_ACCESS_VIOLATION_READ"; 1030 break; 1031 case MD_ACCESS_VIOLATION_WIN_WRITE: 1032 reason = "EXCEPTION_ACCESS_VIOLATION_WRITE"; 1033 break; 1034 case MD_ACCESS_VIOLATION_WIN_EXEC: 1035 reason = "EXCEPTION_ACCESS_VIOLATION_EXEC"; 1036 break; 1037 default: 1038 reason = "EXCEPTION_ACCESS_VIOLATION"; 1039 break; 1040 } 1041 } else { 1042 reason = "EXCEPTION_ACCESS_VIOLATION"; 1043 } 1044 if (address && 1045 raw_exception->exception_record.number_parameters >= 2) { 1046 *address = 1047 raw_exception->exception_record.exception_information[1]; 1048 } 1049 break; 1050 case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: 1051 // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that 1052 // caused the fault in exception_information[1]. 1053 // exception_information[0] is 0 if the violation was caused by 1054 // an attempt to read data, 1 if it was an attempt to write data, 1055 // and 8 if this was a data execution violation. 1056 // exception_information[2] contains the underlying NTSTATUS code, 1057 // which is the explanation for why this error occured. 1058 // This information is useful in addition to the code address, which 1059 // will be present in the crash thread's instruction field anyway. 1060 if (raw_exception->exception_record.number_parameters >= 1) { 1061 MDInPageErrorTypeWin av_type = 1062 static_cast<MDInPageErrorTypeWin> 1063 (raw_exception->exception_record.exception_information[0]); 1064 switch (av_type) { 1065 case MD_IN_PAGE_ERROR_WIN_READ: 1066 reason = "EXCEPTION_IN_PAGE_ERROR_READ"; 1067 break; 1068 case MD_IN_PAGE_ERROR_WIN_WRITE: 1069 reason = "EXCEPTION_IN_PAGE_ERROR_WRITE"; 1070 break; 1071 case MD_IN_PAGE_ERROR_WIN_EXEC: 1072 reason = "EXCEPTION_IN_PAGE_ERROR_EXEC"; 1073 break; 1074 default: 1075 reason = "EXCEPTION_IN_PAGE_ERROR"; 1076 break; 1077 } 1078 } else { 1079 reason = "EXCEPTION_IN_PAGE_ERROR"; 1080 } 1081 if (address && 1082 raw_exception->exception_record.number_parameters >= 2) { 1083 *address = 1084 raw_exception->exception_record.exception_information[1]; 1085 } 1086 if (raw_exception->exception_record.number_parameters >= 3) { 1087 uint32_t ntstatus = 1088 static_cast<uint32_t> 1089 (raw_exception->exception_record.exception_information[2]); 1090 reason.append(" / "); 1091 reason.append(NTStatusToString(ntstatus)); 1092 } 1093 break; 1094 case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE: 1095 reason = "EXCEPTION_INVALID_HANDLE"; 1096 break; 1097 case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: 1098 reason = "EXCEPTION_ILLEGAL_INSTRUCTION"; 1099 break; 1100 case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: 1101 reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; 1102 break; 1103 case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: 1104 reason = "EXCEPTION_INVALID_DISPOSITION"; 1105 break; 1106 case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED: 1107 reason = "EXCEPTION_BOUNDS_EXCEEDED"; 1108 break; 1109 case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND: 1110 reason = "EXCEPTION_FLT_DENORMAL_OPERAND"; 1111 break; 1112 case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: 1113 reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO"; 1114 break; 1115 case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: 1116 reason = "EXCEPTION_FLT_INEXACT_RESULT"; 1117 break; 1118 case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: 1119 reason = "EXCEPTION_FLT_INVALID_OPERATION"; 1120 break; 1121 case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: 1122 reason = "EXCEPTION_FLT_OVERFLOW"; 1123 break; 1124 case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK: 1125 reason = "EXCEPTION_FLT_STACK_CHECK"; 1126 break; 1127 case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: 1128 reason = "EXCEPTION_FLT_UNDERFLOW"; 1129 break; 1130 case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: 1131 reason = "EXCEPTION_INT_DIVIDE_BY_ZERO"; 1132 break; 1133 case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: 1134 reason = "EXCEPTION_INT_OVERFLOW"; 1135 break; 1136 case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: 1137 reason = "EXCEPTION_PRIV_INSTRUCTION"; 1138 break; 1139 case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: 1140 reason = "EXCEPTION_STACK_OVERFLOW"; 1141 break; 1142 case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: 1143 reason = "EXCEPTION_POSSIBLE_DEADLOCK"; 1144 break; 1145 case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: 1146 reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; 1147 break; 1148 case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: 1149 reason = "EXCEPTION_HEAP_CORRUPTION"; 1150 break; 1151 case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION: 1152 reason = "Unhandled C++ Exception"; 1153 break; 1154 default: 1155 BPLOG(INFO) << "Unknown exception reason " << reason; 1156 break; 1157 } 1158 break; 1159 } 1160 1161 case MD_OS_ANDROID: 1162 case MD_OS_LINUX: { 1163 switch (exception_code) { 1164 case MD_EXCEPTION_CODE_LIN_SIGHUP: 1165 reason = "SIGHUP"; 1166 break; 1167 case MD_EXCEPTION_CODE_LIN_SIGINT: 1168 reason = "SIGINT"; 1169 break; 1170 case MD_EXCEPTION_CODE_LIN_SIGQUIT: 1171 reason = "SIGQUIT"; 1172 break; 1173 case MD_EXCEPTION_CODE_LIN_SIGILL: 1174 reason = "SIGILL"; 1175 break; 1176 case MD_EXCEPTION_CODE_LIN_SIGTRAP: 1177 reason = "SIGTRAP"; 1178 break; 1179 case MD_EXCEPTION_CODE_LIN_SIGABRT: 1180 reason = "SIGABRT"; 1181 break; 1182 case MD_EXCEPTION_CODE_LIN_SIGBUS: 1183 reason = "SIGBUS"; 1184 break; 1185 case MD_EXCEPTION_CODE_LIN_SIGFPE: 1186 reason = "SIGFPE"; 1187 break; 1188 case MD_EXCEPTION_CODE_LIN_SIGKILL: 1189 reason = "SIGKILL"; 1190 break; 1191 case MD_EXCEPTION_CODE_LIN_SIGUSR1: 1192 reason = "SIGUSR1"; 1193 break; 1194 case MD_EXCEPTION_CODE_LIN_SIGSEGV: 1195 reason = "SIGSEGV"; 1196 break; 1197 case MD_EXCEPTION_CODE_LIN_SIGUSR2: 1198 reason = "SIGUSR2"; 1199 break; 1200 case MD_EXCEPTION_CODE_LIN_SIGPIPE: 1201 reason = "SIGPIPE"; 1202 break; 1203 case MD_EXCEPTION_CODE_LIN_SIGALRM: 1204 reason = "SIGALRM"; 1205 break; 1206 case MD_EXCEPTION_CODE_LIN_SIGTERM: 1207 reason = "SIGTERM"; 1208 break; 1209 case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: 1210 reason = "SIGSTKFLT"; 1211 break; 1212 case MD_EXCEPTION_CODE_LIN_SIGCHLD: 1213 reason = "SIGCHLD"; 1214 break; 1215 case MD_EXCEPTION_CODE_LIN_SIGCONT: 1216 reason = "SIGCONT"; 1217 break; 1218 case MD_EXCEPTION_CODE_LIN_SIGSTOP: 1219 reason = "SIGSTOP"; 1220 break; 1221 case MD_EXCEPTION_CODE_LIN_SIGTSTP: 1222 reason = "SIGTSTP"; 1223 break; 1224 case MD_EXCEPTION_CODE_LIN_SIGTTIN: 1225 reason = "SIGTTIN"; 1226 break; 1227 case MD_EXCEPTION_CODE_LIN_SIGTTOU: 1228 reason = "SIGTTOU"; 1229 break; 1230 case MD_EXCEPTION_CODE_LIN_SIGURG: 1231 reason = "SIGURG"; 1232 break; 1233 case MD_EXCEPTION_CODE_LIN_SIGXCPU: 1234 reason = "SIGXCPU"; 1235 break; 1236 case MD_EXCEPTION_CODE_LIN_SIGXFSZ: 1237 reason = "SIGXFSZ"; 1238 break; 1239 case MD_EXCEPTION_CODE_LIN_SIGVTALRM: 1240 reason = "SIGVTALRM"; 1241 break; 1242 case MD_EXCEPTION_CODE_LIN_SIGPROF: 1243 reason = "SIGPROF"; 1244 break; 1245 case MD_EXCEPTION_CODE_LIN_SIGWINCH: 1246 reason = "SIGWINCH"; 1247 break; 1248 case MD_EXCEPTION_CODE_LIN_SIGIO: 1249 reason = "SIGIO"; 1250 break; 1251 case MD_EXCEPTION_CODE_LIN_SIGPWR: 1252 reason = "SIGPWR"; 1253 break; 1254 case MD_EXCEPTION_CODE_LIN_SIGSYS: 1255 reason = "SIGSYS"; 1256 break; 1257 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: 1258 reason = "DUMP_REQUESTED"; 1259 break; 1260 default: 1261 BPLOG(INFO) << "Unknown exception reason " << reason; 1262 break; 1263 } 1264 break; 1265 } 1266 1267 case MD_OS_SOLARIS: { 1268 switch (exception_code) { 1269 case MD_EXCEPTION_CODE_SOL_SIGHUP: 1270 reason = "SIGHUP"; 1271 break; 1272 case MD_EXCEPTION_CODE_SOL_SIGINT: 1273 reason = "SIGINT"; 1274 break; 1275 case MD_EXCEPTION_CODE_SOL_SIGQUIT: 1276 reason = "SIGQUIT"; 1277 break; 1278 case MD_EXCEPTION_CODE_SOL_SIGILL: 1279 reason = "SIGILL"; 1280 break; 1281 case MD_EXCEPTION_CODE_SOL_SIGTRAP: 1282 reason = "SIGTRAP"; 1283 break; 1284 case MD_EXCEPTION_CODE_SOL_SIGIOT: 1285 reason = "SIGIOT | SIGABRT"; 1286 break; 1287 case MD_EXCEPTION_CODE_SOL_SIGEMT: 1288 reason = "SIGEMT"; 1289 break; 1290 case MD_EXCEPTION_CODE_SOL_SIGFPE: 1291 reason = "SIGFPE"; 1292 break; 1293 case MD_EXCEPTION_CODE_SOL_SIGKILL: 1294 reason = "SIGKILL"; 1295 break; 1296 case MD_EXCEPTION_CODE_SOL_SIGBUS: 1297 reason = "SIGBUS"; 1298 break; 1299 case MD_EXCEPTION_CODE_SOL_SIGSEGV: 1300 reason = "SIGSEGV"; 1301 break; 1302 case MD_EXCEPTION_CODE_SOL_SIGSYS: 1303 reason = "SIGSYS"; 1304 break; 1305 case MD_EXCEPTION_CODE_SOL_SIGPIPE: 1306 reason = "SIGPIPE"; 1307 break; 1308 case MD_EXCEPTION_CODE_SOL_SIGALRM: 1309 reason = "SIGALRM"; 1310 break; 1311 case MD_EXCEPTION_CODE_SOL_SIGTERM: 1312 reason = "SIGTERM"; 1313 break; 1314 case MD_EXCEPTION_CODE_SOL_SIGUSR1: 1315 reason = "SIGUSR1"; 1316 break; 1317 case MD_EXCEPTION_CODE_SOL_SIGUSR2: 1318 reason = "SIGUSR2"; 1319 break; 1320 case MD_EXCEPTION_CODE_SOL_SIGCLD: 1321 reason = "SIGCLD | SIGCHLD"; 1322 break; 1323 case MD_EXCEPTION_CODE_SOL_SIGPWR: 1324 reason = "SIGPWR"; 1325 break; 1326 case MD_EXCEPTION_CODE_SOL_SIGWINCH: 1327 reason = "SIGWINCH"; 1328 break; 1329 case MD_EXCEPTION_CODE_SOL_SIGURG: 1330 reason = "SIGURG"; 1331 break; 1332 case MD_EXCEPTION_CODE_SOL_SIGPOLL: 1333 reason = "SIGPOLL | SIGIO"; 1334 break; 1335 case MD_EXCEPTION_CODE_SOL_SIGSTOP: 1336 reason = "SIGSTOP"; 1337 break; 1338 case MD_EXCEPTION_CODE_SOL_SIGTSTP: 1339 reason = "SIGTSTP"; 1340 break; 1341 case MD_EXCEPTION_CODE_SOL_SIGCONT: 1342 reason = "SIGCONT"; 1343 break; 1344 case MD_EXCEPTION_CODE_SOL_SIGTTIN: 1345 reason = "SIGTTIN"; 1346 break; 1347 case MD_EXCEPTION_CODE_SOL_SIGTTOU: 1348 reason = "SIGTTOU"; 1349 break; 1350 case MD_EXCEPTION_CODE_SOL_SIGVTALRM: 1351 reason = "SIGVTALRM"; 1352 break; 1353 case MD_EXCEPTION_CODE_SOL_SIGPROF: 1354 reason = "SIGPROF"; 1355 break; 1356 case MD_EXCEPTION_CODE_SOL_SIGXCPU: 1357 reason = "SIGXCPU"; 1358 break; 1359 case MD_EXCEPTION_CODE_SOL_SIGXFSZ: 1360 reason = "SIGXFSZ"; 1361 break; 1362 case MD_EXCEPTION_CODE_SOL_SIGWAITING: 1363 reason = "SIGWAITING"; 1364 break; 1365 case MD_EXCEPTION_CODE_SOL_SIGLWP: 1366 reason = "SIGLWP"; 1367 break; 1368 case MD_EXCEPTION_CODE_SOL_SIGFREEZE: 1369 reason = "SIGFREEZE"; 1370 break; 1371 case MD_EXCEPTION_CODE_SOL_SIGTHAW: 1372 reason = "SIGTHAW"; 1373 break; 1374 case MD_EXCEPTION_CODE_SOL_SIGCANCEL: 1375 reason = "SIGCANCEL"; 1376 break; 1377 case MD_EXCEPTION_CODE_SOL_SIGLOST: 1378 reason = "SIGLOST"; 1379 break; 1380 case MD_EXCEPTION_CODE_SOL_SIGXRES: 1381 reason = "SIGXRES"; 1382 break; 1383 case MD_EXCEPTION_CODE_SOL_SIGJVM1: 1384 reason = "SIGJVM1"; 1385 break; 1386 case MD_EXCEPTION_CODE_SOL_SIGJVM2: 1387 reason = "SIGJVM2"; 1388 break; 1389 default: 1390 BPLOG(INFO) << "Unknown exception reason " << reason; 1391 break; 1392 } 1393 break; 1394 } 1395 1396 case MD_OS_PS3: { 1397 switch (exception_code) { 1398 case MD_EXCEPTION_CODE_PS3_UNKNOWN: 1399 reason = "UNKNOWN"; 1400 break; 1401 case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP: 1402 reason = "TRAP_EXCEP"; 1403 break; 1404 case MD_EXCEPTION_CODE_PS3_PRIV_INSTR: 1405 reason = "PRIV_INSTR"; 1406 break; 1407 case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR: 1408 reason = "ILLEGAL_INSTR"; 1409 break; 1410 case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE: 1411 reason = "INSTR_STORAGE"; 1412 break; 1413 case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT: 1414 reason = "INSTR_SEGMENT"; 1415 break; 1416 case MD_EXCEPTION_CODE_PS3_DATA_STORAGE: 1417 reason = "DATA_STORAGE"; 1418 break; 1419 case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT: 1420 reason = "DATA_SEGMENT"; 1421 break; 1422 case MD_EXCEPTION_CODE_PS3_FLOAT_POINT: 1423 reason = "FLOAT_POINT"; 1424 break; 1425 case MD_EXCEPTION_CODE_PS3_DABR_MATCH: 1426 reason = "DABR_MATCH"; 1427 break; 1428 case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP: 1429 reason = "ALIGN_EXCEP"; 1430 break; 1431 case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS: 1432 reason = "MEMORY_ACCESS"; 1433 break; 1434 case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN: 1435 reason = "COPRO_ALIGN"; 1436 break; 1437 case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM: 1438 reason = "COPRO_INVALID_COM"; 1439 break; 1440 case MD_EXCEPTION_CODE_PS3_COPRO_ERR: 1441 reason = "COPRO_ERR"; 1442 break; 1443 case MD_EXCEPTION_CODE_PS3_COPRO_FIR: 1444 reason = "COPRO_FIR"; 1445 break; 1446 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT: 1447 reason = "COPRO_DATA_SEGMENT"; 1448 break; 1449 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE: 1450 reason = "COPRO_DATA_STORAGE"; 1451 break; 1452 case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR: 1453 reason = "COPRO_STOP_INSTR"; 1454 break; 1455 case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR: 1456 reason = "COPRO_HALT_INSTR"; 1457 break; 1458 case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN: 1459 reason = "COPRO_HALTINSTR_UNKNOWN"; 1460 break; 1461 case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS: 1462 reason = "COPRO_MEMORY_ACCESS"; 1463 break; 1464 case MD_EXCEPTION_CODE_PS3_GRAPHIC: 1465 reason = "GRAPHIC"; 1466 break; 1467 default: 1468 BPLOG(INFO) << "Unknown exception reason "<< reason; 1469 break; 1470 } 1471 break; 1472 } 1473 1474 default: { 1475 BPLOG(INFO) << "Unknown exception reason " << reason; 1476 break; 1477 } 1478 } 1479 1480 return reason; 1481} 1482 1483// static 1484string MinidumpProcessor::GetAssertion(Minidump *dump) { 1485 MinidumpAssertion *assertion = dump->GetAssertion(); 1486 if (!assertion) 1487 return ""; 1488 1489 const MDRawAssertionInfo *raw_assertion = assertion->assertion(); 1490 if (!raw_assertion) 1491 return ""; 1492 1493 string assertion_string; 1494 switch (raw_assertion->type) { 1495 case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER: 1496 assertion_string = "Invalid parameter passed to library function"; 1497 break; 1498 case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL: 1499 assertion_string = "Pure virtual function called"; 1500 break; 1501 default: { 1502 char assertion_type[32]; 1503 snprintf(assertion_type, sizeof(assertion_type), 1504 "0x%08x", raw_assertion->type); 1505 assertion_string = "Unknown assertion type "; 1506 assertion_string += assertion_type; 1507 break; 1508 } 1509 } 1510 1511 string expression = assertion->expression(); 1512 if (!expression.empty()) { 1513 assertion_string.append(" " + expression); 1514 } 1515 1516 string function = assertion->function(); 1517 if (!function.empty()) { 1518 assertion_string.append(" in function " + function); 1519 } 1520 1521 string file = assertion->file(); 1522 if (!file.empty()) { 1523 assertion_string.append(", in file " + file); 1524 } 1525 1526 if (raw_assertion->line != 0) { 1527 char assertion_line[32]; 1528 snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line); 1529 assertion_string.append(" at line "); 1530 assertion_string.append(assertion_line); 1531 } 1532 1533 return assertion_string; 1534} 1535 1536} // namespace google_breakpad 1537