minidump_processor.cc
1 // Copyright 2006 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #ifdef HAVE_CONFIG_H 30 #include <config.h> // Must come first 31 #endif 32 33 #include "google_breakpad/processor/minidump_processor.h" 34 35 #include <assert.h> 36 37 #include <algorithm> 38 #include <limits> 39 #include <map> 40 #include <string> 41 #include <utility> 42 43 #include "common/scoped_ptr.h" 44 #include "common/stdio_wrapper.h" 45 #include "common/using_std_string.h" 46 #include "google_breakpad/processor/call_stack.h" 47 #include "google_breakpad/processor/minidump.h" 48 #include "google_breakpad/processor/process_state.h" 49 #include "google_breakpad/processor/exploitability.h" 50 #include "google_breakpad/processor/stack_frame_symbolizer.h" 51 #include "processor/logging.h" 52 #include "processor/stackwalker_x86.h" 53 #include "processor/symbolic_constants_win.h" 54 55 #ifdef __linux__ 56 #include "processor/disassembler_objdump.h" 57 #endif 58 59 namespace google_breakpad { 60 61 MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, 62 SourceLineResolverInterface* resolver) 63 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), 64 own_frame_symbolizer_(true), 65 enable_exploitability_(false), 66 enable_objdump_(false), 67 enable_objdump_for_exploitability_(false) { 68 } 69 70 MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, 71 SourceLineResolverInterface* resolver, 72 bool enable_exploitability) 73 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), 74 own_frame_symbolizer_(true), 75 enable_exploitability_(enable_exploitability), 76 enable_objdump_(false), 77 enable_objdump_for_exploitability_(false) { 78 } 79 80 MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer* frame_symbolizer, 81 bool enable_exploitability) 82 : frame_symbolizer_(frame_symbolizer), 83 own_frame_symbolizer_(false), 84 enable_exploitability_(enable_exploitability), 85 enable_objdump_(false), 86 enable_objdump_for_exploitability_(false) { 87 assert(frame_symbolizer_); 88 } 89 90 MinidumpProcessor::~MinidumpProcessor() { 91 if (own_frame_symbolizer_) delete frame_symbolizer_; 92 } 93 94 ProcessResult MinidumpProcessor::Process( 95 Minidump* dump, ProcessState* process_state) { 96 assert(dump); 97 assert(process_state); 98 99 process_state->Clear(); 100 101 const MDRawHeader* header = dump->header(); 102 if (!header) { 103 BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; 104 return PROCESS_ERROR_NO_MINIDUMP_HEADER; 105 } 106 process_state->time_date_stamp_ = header->time_date_stamp; 107 108 bool has_process_create_time = 109 GetProcessCreateTime(dump, &process_state->process_create_time_); 110 111 bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_); 112 bool has_os_info = GetOSInfo(dump, &process_state->system_info_); 113 114 uint32_t dump_thread_id = 0; 115 bool has_dump_thread = false; 116 uint32_t requesting_thread_id = 0; 117 bool has_requesting_thread = false; 118 119 MinidumpBreakpadInfo* breakpad_info = dump->GetBreakpadInfo(); 120 if (breakpad_info) { 121 has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); 122 has_requesting_thread = 123 breakpad_info->GetRequestingThreadID(&requesting_thread_id); 124 } 125 126 MinidumpException* exception = dump->GetException(); 127 if (exception) { 128 process_state->crashed_ = true; 129 has_requesting_thread = exception->GetThreadID(&requesting_thread_id); 130 131 process_state->crash_reason_ = GetCrashReason( 132 dump, &process_state->crash_address_, enable_objdump_); 133 134 process_state->exception_record_.set_code( 135 exception->exception()->exception_record.exception_code, 136 // TODO(ivanpe): Populate description. 137 /* description = */ ""); 138 process_state->exception_record_.set_flags( 139 exception->exception()->exception_record.exception_flags, 140 // TODO(ivanpe): Populate description. 141 /* description = */ ""); 142 process_state->exception_record_.set_nested_exception_record_address( 143 exception->exception()->exception_record.exception_record); 144 process_state->exception_record_.set_address(process_state->crash_address_); 145 const uint32_t num_parameters = 146 std::min(exception->exception()->exception_record.number_parameters, 147 MD_EXCEPTION_MAXIMUM_PARAMETERS); 148 for (uint32_t i = 0; i < num_parameters; ++i) { 149 process_state->exception_record_.add_parameter( 150 exception->exception()->exception_record.exception_information[i], 151 // TODO(ivanpe): Populate description. 152 /* description = */ ""); 153 } 154 } 155 156 // This will just return an empty string if it doesn't exist. 157 process_state->assertion_ = GetAssertion(dump); 158 159 MinidumpModuleList* module_list = dump->GetModuleList(); 160 161 // Put a copy of the module list into ProcessState object. This is not 162 // necessarily a MinidumpModuleList, but it adheres to the CodeModules 163 // interface, which is all that ProcessState needs to expose. 164 if (module_list) { 165 process_state->modules_ = module_list->Copy(); 166 process_state->shrunk_range_modules_ = 167 process_state->modules_->GetShrunkRangeModules(); 168 for (unsigned int i = 0; 169 i < process_state->shrunk_range_modules_.size(); 170 i++) { 171 linked_ptr<const CodeModule> module = 172 process_state->shrunk_range_modules_[i]; 173 BPLOG(INFO) << "The range for module " << module->code_file() 174 << " was shrunk down by " << HexString( 175 module->shrink_down_delta()) << " bytes. "; 176 } 177 } 178 179 MinidumpUnloadedModuleList* unloaded_module_list = 180 dump->GetUnloadedModuleList(); 181 if (unloaded_module_list) { 182 process_state->unloaded_modules_ = unloaded_module_list->Copy(); 183 } 184 185 MinidumpMemoryList* memory_list = dump->GetMemoryList(); 186 if (memory_list) { 187 BPLOG(INFO) << "Found " << memory_list->region_count() 188 << " memory regions."; 189 } 190 191 MinidumpThreadList* threads = dump->GetThreadList(); 192 if (!threads) { 193 BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; 194 return PROCESS_ERROR_NO_THREAD_LIST; 195 } 196 197 BPLOG(INFO) << "Minidump " << dump->path() << " has " << 198 (has_cpu_info ? "" : "no ") << "CPU info, " << 199 (has_os_info ? "" : "no ") << "OS info, " << 200 (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << 201 (exception != NULL ? "" : "no ") << "exception, " << 202 (module_list != NULL ? "" : "no ") << "module list, " << 203 (threads != NULL ? "" : "no ") << "thread list, " << 204 (has_dump_thread ? "" : "no ") << "dump thread, " << 205 (has_requesting_thread ? "" : "no ") << "requesting thread, and " << 206 (has_process_create_time ? "" : "no ") << "process create time"; 207 208 bool interrupted = false; 209 bool found_requesting_thread = false; 210 unsigned int thread_count = threads->thread_count(); 211 212 // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. 213 frame_symbolizer_->Reset(); 214 215 216 MinidumpThreadNameList* thread_names = dump->GetThreadNameList(); 217 std::map<uint32_t, string> thread_id_to_name; 218 if (thread_names) { 219 const unsigned int thread_name_count = thread_names->thread_name_count(); 220 for (unsigned int thread_name_index = 0; 221 thread_name_index < thread_name_count; 222 ++thread_name_index) { 223 MinidumpThreadName* thread_name = thread_names->GetThreadNameAtIndex(thread_name_index); 224 if (!thread_name) { 225 BPLOG(ERROR) << "Could not get thread name for thread at index " << thread_name_index; 226 return PROCESS_ERROR_GETTING_THREAD_NAME; 227 } 228 uint32_t thread_id; 229 if (!thread_name->GetThreadID(&thread_id)) { 230 BPLOG(ERROR) << "Could not get thread ID for thread at index " << thread_name_index; 231 return PROCESS_ERROR_GETTING_THREAD_NAME; 232 } 233 thread_id_to_name.insert(std::make_pair(thread_id, thread_name->GetThreadName())); 234 } 235 } 236 237 for (unsigned int thread_index = 0; 238 thread_index < thread_count; 239 ++thread_index) { 240 char thread_string_buffer[64]; 241 snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", 242 thread_index, thread_count); 243 string thread_string = dump->path() + ":" + thread_string_buffer; 244 245 MinidumpThread* thread = threads->GetThreadAtIndex(thread_index); 246 if (!thread) { 247 BPLOG(ERROR) << "Could not get thread for " << thread_string; 248 return PROCESS_ERROR_GETTING_THREAD; 249 } 250 251 uint32_t thread_id; 252 if (!thread->GetThreadID(&thread_id)) { 253 BPLOG(ERROR) << "Could not get thread ID for " << thread_string; 254 return PROCESS_ERROR_GETTING_THREAD_ID; 255 } 256 257 thread_string += " id " + HexString(thread_id); 258 auto thread_name_iter = thread_id_to_name.find(thread_id); 259 string thread_name; 260 if (thread_name_iter != thread_id_to_name.end()) { 261 thread_name = thread_name_iter->second; 262 } 263 if (!thread_name.empty()) { 264 thread_string += " name [" + thread_name + "]"; 265 } 266 BPLOG(INFO) << "Looking at thread " << thread_string; 267 268 // If this thread is the thread that produced the minidump, don't process 269 // it. Because of the problems associated with a thread producing a 270 // dump of itself (when both its context and its stack are in flux), 271 // processing that stack wouldn't provide much useful data. 272 if (has_dump_thread && thread_id == dump_thread_id) { 273 continue; 274 } 275 276 MinidumpContext* context = thread->GetContext(); 277 278 if (has_requesting_thread && thread_id == requesting_thread_id) { 279 if (found_requesting_thread) { 280 // There can't be more than one requesting thread. 281 BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; 282 return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS; 283 } 284 285 // Use processed_state->threads_.size() instead of thread_index. 286 // thread_index points to the thread index in the minidump, which 287 // might be greater than the thread index in the threads vector if 288 // any of the minidump's threads are skipped and not placed into the 289 // processed threads vector. The thread vector's current size will 290 // be the index of the current thread when it's pushed into the 291 // vector. 292 process_state->requesting_thread_ = process_state->threads_.size(); 293 294 found_requesting_thread = true; 295 296 if (process_state->crashed_) { 297 // Use the exception record's context for the crashed thread, instead 298 // of the thread's own context. For the crashed thread, the thread's 299 // own context is the state inside the exception handler. Using it 300 // would not result in the expected stack trace from the time of the 301 // crash. If the exception context is invalid, however, we fall back 302 // on the thread context. 303 MinidumpContext* ctx = exception->GetContext(); 304 context = ctx ? ctx : thread->GetContext(); 305 } 306 } 307 308 // If the memory region for the stack cannot be read using the RVA stored 309 // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use 310 // a memory region (containing the stack) from the minidump memory list. 311 MinidumpMemoryRegion* thread_memory = thread->GetMemory(); 312 if (!thread_memory && memory_list) { 313 uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange(); 314 if (start_stack_memory_range) { 315 thread_memory = memory_list->GetMemoryRegionForAddress( 316 start_stack_memory_range); 317 } 318 } 319 if (!thread_memory) { 320 BPLOG(ERROR) << "No memory region for " << thread_string; 321 } 322 323 // Use process_state->modules_ instead of module_list, because the 324 // |modules| argument will be used to populate the |module| fields in 325 // the returned StackFrame objects, which will be placed into the 326 // returned ProcessState object. module_list's lifetime is only as 327 // long as the Minidump object: it will be deleted when this function 328 // returns. process_state->modules_ is owned by the ProcessState object 329 // (just like the StackFrame objects), and is much more suitable for this 330 // task. 331 scoped_ptr<Stackwalker> stackwalker( 332 Stackwalker::StackwalkerForCPU(process_state->system_info(), 333 context, 334 thread_memory, 335 process_state->modules_, 336 process_state->unloaded_modules_, 337 frame_symbolizer_)); 338 339 scoped_ptr<CallStack> stack(new CallStack()); 340 if (stackwalker.get()) { 341 if (!stackwalker->Walk(stack.get(), 342 &process_state->modules_without_symbols_, 343 &process_state->modules_with_corrupt_symbols_)) { 344 BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " 345 << thread_string; 346 interrupted = true; 347 } 348 } else { 349 // Threads with missing CPU contexts will hit this, but 350 // don't abort processing the rest of the dump just for 351 // one bad thread. 352 BPLOG(ERROR) << "No stackwalker for " << thread_string; 353 } 354 stack->set_tid(thread_id); 355 process_state->threads_.push_back(stack.release()); 356 process_state->thread_memory_regions_.push_back(thread_memory); 357 process_state->thread_names_.push_back(thread_name); 358 } 359 360 if (interrupted) { 361 BPLOG(INFO) << "Processing interrupted for " << dump->path(); 362 return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; 363 } 364 365 // If a requesting thread was indicated, it must be present. 366 if (has_requesting_thread && !found_requesting_thread) { 367 // Don't mark as an error, but invalidate the requesting thread 368 BPLOG(ERROR) << "Minidump indicated requesting thread " << 369 HexString(requesting_thread_id) << ", not found in " << 370 dump->path(); 371 process_state->requesting_thread_ = -1; 372 } 373 374 // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED 375 process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED; 376 377 // If an exploitability run was requested we perform the platform specific 378 // rating. 379 if (enable_exploitability_) { 380 scoped_ptr<Exploitability> exploitability( 381 Exploitability::ExploitabilityForPlatform( 382 dump, process_state, enable_objdump_for_exploitability_)); 383 // The engine will be null if the platform is not supported 384 if (exploitability != NULL) { 385 process_state->exploitability_ = exploitability->CheckExploitability(); 386 } else { 387 process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE; 388 } 389 } 390 391 BPLOG(INFO) << "Processed " << dump->path(); 392 return PROCESS_OK; 393 } 394 395 ProcessResult MinidumpProcessor::Process( 396 const string& minidump_file, ProcessState* process_state) { 397 BPLOG(INFO) << "Processing minidump in file " << minidump_file; 398 399 Minidump dump(minidump_file); 400 if (!dump.Read()) { 401 BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; 402 return PROCESS_ERROR_MINIDUMP_NOT_FOUND; 403 } 404 405 return Process(&dump, process_state); 406 } 407 408 // Returns the MDRawSystemInfo from a minidump, or NULL if system info is 409 // not available from the minidump. If system_info is non-NULL, it is used 410 // to pass back the MinidumpSystemInfo object. 411 static const MDRawSystemInfo* GetSystemInfo(Minidump* dump, 412 MinidumpSystemInfo** system_info) { 413 MinidumpSystemInfo* minidump_system_info = dump->GetSystemInfo(); 414 if (!minidump_system_info) 415 return NULL; 416 417 if (system_info) 418 *system_info = minidump_system_info; 419 420 return minidump_system_info->system_info(); 421 } 422 423 static uint64_t GetAddressForArchitecture(const MDCPUArchitecture architecture, 424 size_t raw_address) 425 { 426 switch (architecture) { 427 case MD_CPU_ARCHITECTURE_X86: 428 case MD_CPU_ARCHITECTURE_MIPS: 429 case MD_CPU_ARCHITECTURE_PPC: 430 case MD_CPU_ARCHITECTURE_SHX: 431 case MD_CPU_ARCHITECTURE_ARM: 432 case MD_CPU_ARCHITECTURE_X86_WIN64: 433 // 32-bit architectures, mask the upper bits. 434 return raw_address & 0xffffffffULL; 435 436 default: 437 // All other architectures either have 64-bit pointers or it's impossible 438 // to tell from the minidump (e.g. MSIL or SPARC) so use 64-bits anyway. 439 return raw_address; 440 } 441 } 442 443 // Extract CPU info string from ARM-specific MDRawSystemInfo structure. 444 // raw_info: pointer to source MDRawSystemInfo. 445 // cpu_info: address of target string, cpu info text will be appended to it. 446 static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, 447 string* cpu_info) { 448 assert(raw_info != NULL && cpu_info != NULL); 449 450 // Write ARM architecture version. 451 char cpu_string[32]; 452 snprintf(cpu_string, sizeof(cpu_string), "ARMv%d", 453 raw_info->processor_level); 454 cpu_info->append(cpu_string); 455 456 // There is no good list of implementer id values, but the following 457 // pages provide some help: 458 // http://comments.gmane.org/gmane.linux.linaro.devel/6903 459 // http://forum.xda-developers.com/archive/index.php/t-480226.html 460 const struct { 461 uint32_t id; 462 const char* name; 463 } vendors[] = { 464 { 0x41, "ARM" }, 465 { 0x51, "Qualcomm" }, 466 { 0x56, "Marvell" }, 467 { 0x69, "Intel/Marvell" }, 468 }; 469 const struct { 470 uint32_t id; 471 const char* name; 472 } parts[] = { 473 { 0x4100c050, "Cortex-A5" }, 474 { 0x4100c080, "Cortex-A8" }, 475 { 0x4100c090, "Cortex-A9" }, 476 { 0x4100c0f0, "Cortex-A15" }, 477 { 0x4100c140, "Cortex-R4" }, 478 { 0x4100c150, "Cortex-R5" }, 479 { 0x4100b360, "ARM1136" }, 480 { 0x4100b560, "ARM1156" }, 481 { 0x4100b760, "ARM1176" }, 482 { 0x4100b020, "ARM11-MPCore" }, 483 { 0x41009260, "ARM926" }, 484 { 0x41009460, "ARM946" }, 485 { 0x41009660, "ARM966" }, 486 { 0x510006f0, "Krait" }, 487 { 0x510000f0, "Scorpion" }, 488 }; 489 490 const struct { 491 uint32_t hwcap; 492 const char* name; 493 } features[] = { 494 { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" }, 495 { MD_CPU_ARM_ELF_HWCAP_HALF, "half" }, 496 { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" }, 497 { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" }, 498 { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" }, 499 { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" }, 500 { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" }, 501 { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" }, 502 { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" }, 503 { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" }, 504 { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" }, 505 { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" }, 506 { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" }, 507 { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" }, 508 { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" }, 509 { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" }, 510 { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" }, 511 { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" }, 512 { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" }, 513 }; 514 515 uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; 516 if (cpuid != 0) { 517 // Extract vendor name from CPUID 518 const char* vendor = NULL; 519 uint32_t vendor_id = (cpuid >> 24) & 0xff; 520 for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { 521 if (vendors[i].id == vendor_id) { 522 vendor = vendors[i].name; 523 break; 524 } 525 } 526 cpu_info->append(" "); 527 if (vendor) { 528 cpu_info->append(vendor); 529 } else { 530 snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id); 531 cpu_info->append(cpu_string); 532 } 533 534 // Extract part name from CPUID 535 uint32_t part_id = (cpuid & 0xff00fff0); 536 const char* part = NULL; 537 for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { 538 if (parts[i].id == part_id) { 539 part = parts[i].name; 540 break; 541 } 542 } 543 cpu_info->append(" "); 544 if (part != NULL) { 545 cpu_info->append(part); 546 } else { 547 snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); 548 cpu_info->append(cpu_string); 549 } 550 } 551 uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps; 552 if (elf_hwcaps != 0) { 553 cpu_info->append(" features: "); 554 const char* comma = ""; 555 for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) { 556 if (elf_hwcaps & features[i].hwcap) { 557 cpu_info->append(comma); 558 cpu_info->append(features[i].name); 559 comma = ","; 560 } 561 } 562 } 563 } 564 565 // static 566 bool MinidumpProcessor::GetCPUInfo(Minidump* dump, SystemInfo* info) { 567 assert(dump); 568 assert(info); 569 570 info->cpu.clear(); 571 info->cpu_info.clear(); 572 573 MinidumpSystemInfo* system_info; 574 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info); 575 if (!raw_system_info) 576 return false; 577 578 switch (raw_system_info->processor_architecture) { 579 case MD_CPU_ARCHITECTURE_X86: 580 case MD_CPU_ARCHITECTURE_AMD64: { 581 if (raw_system_info->processor_architecture == 582 MD_CPU_ARCHITECTURE_X86) 583 info->cpu = "x86"; 584 else 585 info->cpu = "amd64"; 586 587 const string* cpu_vendor = system_info->GetCPUVendor(); 588 if (cpu_vendor) { 589 info->cpu_info = *cpu_vendor; 590 info->cpu_info.append(" "); 591 } 592 593 char x86_info[36]; 594 snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", 595 raw_system_info->processor_level, 596 raw_system_info->processor_revision >> 8, 597 raw_system_info->processor_revision & 0xff); 598 info->cpu_info.append(x86_info); 599 break; 600 } 601 602 case MD_CPU_ARCHITECTURE_PPC: { 603 info->cpu = "ppc"; 604 break; 605 } 606 607 case MD_CPU_ARCHITECTURE_PPC64: { 608 info->cpu = "ppc64"; 609 break; 610 } 611 612 case MD_CPU_ARCHITECTURE_SPARC: { 613 info->cpu = "sparc"; 614 break; 615 } 616 617 case MD_CPU_ARCHITECTURE_ARM: { 618 info->cpu = "arm"; 619 GetARMCpuInfo(raw_system_info, &info->cpu_info); 620 break; 621 } 622 623 case MD_CPU_ARCHITECTURE_ARM64: 624 case MD_CPU_ARCHITECTURE_ARM64_OLD: { 625 info->cpu = "arm64"; 626 break; 627 } 628 629 case MD_CPU_ARCHITECTURE_MIPS: { 630 info->cpu = "mips"; 631 break; 632 } 633 case MD_CPU_ARCHITECTURE_MIPS64: { 634 info->cpu = "mips64"; 635 break; 636 } 637 638 case MD_CPU_ARCHITECTURE_RISCV: { 639 info->cpu = "riscv"; 640 break; 641 } 642 643 case MD_CPU_ARCHITECTURE_RISCV64: { 644 info->cpu = "riscv64"; 645 break; 646 } 647 648 default: { 649 // Assign the numeric architecture ID into the CPU string. 650 char cpu_string[7]; 651 snprintf(cpu_string, sizeof(cpu_string), "0x%04x", 652 raw_system_info->processor_architecture); 653 info->cpu = cpu_string; 654 break; 655 } 656 } 657 658 info->cpu_count = raw_system_info->number_of_processors; 659 660 return true; 661 } 662 663 // static 664 bool MinidumpProcessor::GetOSInfo(Minidump* dump, SystemInfo* info) { 665 assert(dump); 666 assert(info); 667 668 info->os.clear(); 669 info->os_short.clear(); 670 info->os_version.clear(); 671 672 MinidumpSystemInfo* system_info; 673 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info); 674 if (!raw_system_info) 675 return false; 676 677 info->os_short = system_info->GetOS(); 678 679 switch (raw_system_info->platform_id) { 680 case MD_OS_WIN32_NT: { 681 info->os = "Windows NT"; 682 break; 683 } 684 685 case MD_OS_WIN32_WINDOWS: { 686 info->os = "Windows"; 687 break; 688 } 689 690 case MD_OS_MAC_OS_X: { 691 info->os = "Mac OS X"; 692 break; 693 } 694 695 case MD_OS_IOS: { 696 info->os = "iOS"; 697 break; 698 } 699 700 case MD_OS_LINUX: { 701 info->os = "Linux"; 702 break; 703 } 704 705 case MD_OS_SOLARIS: { 706 info->os = "Solaris"; 707 break; 708 } 709 710 case MD_OS_ANDROID: { 711 info->os = "Android"; 712 break; 713 } 714 715 case MD_OS_PS3: { 716 info->os = "PS3"; 717 break; 718 } 719 720 case MD_OS_NACL: { 721 info->os = "NaCl"; 722 break; 723 } 724 725 case MD_OS_FUCHSIA: { 726 info->os = "Fuchsia"; 727 break; 728 } 729 730 default: { 731 // Assign the numeric platform ID into the OS string. 732 char os_string[11]; 733 snprintf(os_string, sizeof(os_string), "0x%08x", 734 raw_system_info->platform_id); 735 info->os = os_string; 736 break; 737 } 738 } 739 740 char os_version_string[33]; 741 snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", 742 raw_system_info->major_version, 743 raw_system_info->minor_version, 744 raw_system_info->build_number); 745 info->os_version = os_version_string; 746 747 const string* csd_version = system_info->GetCSDVersion(); 748 if (csd_version) { 749 info->os_version.append(" "); 750 info->os_version.append(*csd_version); 751 } 752 753 return true; 754 } 755 756 // static 757 bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump, 758 uint32_t* process_create_time) { 759 assert(dump); 760 assert(process_create_time); 761 762 *process_create_time = 0; 763 764 MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo(); 765 if (!minidump_misc_info) { 766 return false; 767 } 768 769 const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info(); 770 if (!md_raw_misc_info) { 771 return false; 772 } 773 774 if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) { 775 return false; 776 } 777 778 *process_create_time = md_raw_misc_info->process_create_time; 779 return true; 780 } 781 782 #ifdef __linux__ 783 784 static bool IsCanonicalAddress(uint64_t address) { 785 uint64_t sign_bit = (address >> 63) & 1; 786 for (int shift = 48; shift < 63; ++shift) { 787 if (sign_bit != ((address >> shift) & 1)) { 788 return false; 789 } 790 } 791 return true; 792 } 793 794 static void CalculateFaultAddressFromInstruction(Minidump* dump, 795 uint64_t* address) { 796 MinidumpException* exception = dump->GetException(); 797 if (exception == NULL) { 798 BPLOG(INFO) << "Failed to get exception."; 799 return; 800 } 801 802 MinidumpContext* context = exception->GetContext(); 803 if (context == NULL) { 804 BPLOG(INFO) << "Failed to get exception context."; 805 return; 806 } 807 808 uint64_t instruction_ptr = 0; 809 if (!context->GetInstructionPointer(&instruction_ptr)) { 810 BPLOG(INFO) << "Failed to get instruction pointer."; 811 return; 812 } 813 814 // Get memory region containing instruction pointer. 815 MinidumpMemoryList* memory_list = dump->GetMemoryList(); 816 MinidumpMemoryRegion* memory_region = 817 memory_list ? 818 memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; 819 if (!memory_region) { 820 BPLOG(INFO) << "No memory region around instruction pointer."; 821 return; 822 } 823 824 DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region, 825 instruction_ptr); 826 fprintf(stderr, "%s %s %s\n", disassembler.operation().c_str(), 827 disassembler.src().c_str(), disassembler.dest().c_str()); 828 if (!disassembler.IsValid()) { 829 BPLOG(INFO) << "Disassembling fault instruction failed."; 830 return; 831 } 832 833 // It's possible that we reach here when the faulting address is already 834 // correct, so we only update it if we find that at least one of the src/dest 835 // addresses is non-canonical. If both are non-canonical, we arbitrarily set 836 // it to the larger of the two, as this is more likely to be a known poison 837 // value. 838 839 bool valid_read, valid_write; 840 uint64_t read_address, write_address; 841 842 valid_read = disassembler.CalculateSrcAddress(*context, read_address); 843 valid_read &= !IsCanonicalAddress(read_address); 844 845 valid_write = disassembler.CalculateDestAddress(*context, write_address); 846 valid_write &= !IsCanonicalAddress(write_address); 847 848 if (valid_read && valid_write) { 849 *address = read_address > write_address ? read_address : write_address; 850 } else if (valid_read) { 851 *address = read_address; 852 } else if (valid_write) { 853 *address = write_address; 854 } 855 } 856 #endif // __linux__ 857 858 // static 859 string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address, 860 bool enable_objdump) { 861 MinidumpException* exception = dump->GetException(); 862 if (!exception) 863 return ""; 864 865 const MDRawExceptionStream* raw_exception = exception->exception(); 866 if (!raw_exception) 867 return ""; 868 869 if (address) 870 *address = raw_exception->exception_record.exception_address; 871 872 // The reason value is OS-specific and possibly CPU-specific. Set up 873 // sensible numeric defaults for the reason string in case we can't 874 // map the codes to a string (because there's no system info, or because 875 // it's an unrecognized platform, or because it's an unrecognized code.) 876 char reason_string[24]; 877 char flags_string[11]; 878 uint32_t exception_code = raw_exception->exception_record.exception_code; 879 uint32_t exception_flags = raw_exception->exception_record.exception_flags; 880 snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags); 881 snprintf(reason_string, sizeof(reason_string), "0x%08x / %s", exception_code, 882 flags_string); 883 string reason = reason_string; 884 885 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, NULL); 886 if (!raw_system_info) 887 return reason; 888 889 switch (raw_system_info->platform_id) { 890 case MD_OS_FUCHSIA: { 891 switch (exception_code) { 892 case MD_EXCEPTION_CODE_FUCHSIA_GENERAL: 893 reason = "GENERAL / "; 894 reason.append(flags_string); 895 break; 896 case MD_EXCEPTION_CODE_FUCHSIA_FATAL_PAGE_FAULT: 897 reason = "FATAL_PAGE_FAULT / "; 898 reason.append(flags_string); 899 break; 900 case MD_EXCEPTION_CODE_FUCHSIA_UNDEFINED_INSTRUCTION: 901 reason = "UNDEFINED_INSTRUCTION / "; 902 reason.append(flags_string); 903 break; 904 case MD_EXCEPTION_CODE_FUCHSIA_SW_BREAKPOINT: 905 reason = "SW_BREAKPOINT / "; 906 reason.append(flags_string); 907 break; 908 case MD_EXCEPTION_CODE_FUCHSIA_HW_BREAKPOINT: 909 reason = "HW_BREAKPOINT / "; 910 reason.append(flags_string); 911 break; 912 case MD_EXCEPTION_CODE_FUCHSIA_UNALIGNED_ACCESS: 913 reason = "UNALIGNED_ACCESS / "; 914 reason.append(flags_string); 915 break; 916 case MD_EXCEPTION_CODE_FUCHSIA_THREAD_STARTING: 917 reason = "THREAD_STARTING / "; 918 reason.append(flags_string); 919 break; 920 case MD_EXCEPTION_CODE_FUCHSIA_THREAD_EXITING: 921 reason = "THREAD_EXITING / "; 922 reason.append(flags_string); 923 break; 924 case MD_EXCEPTION_CODE_FUCHSIA_POLICY_ERROR: 925 reason = "POLICY_ERROR / "; 926 reason.append(flags_string); 927 break; 928 case MD_EXCEPTION_CODE_FUCHSIA_PROCESS_STARTING: 929 reason = "PROCESS_STARTING / "; 930 reason.append(flags_string); 931 break; 932 default: 933 BPLOG(INFO) << "Unknown exception reason " << reason; 934 } 935 break; 936 } 937 938 case MD_OS_MAC_OS_X: 939 case MD_OS_IOS: { 940 switch (exception_code) { 941 case MD_EXCEPTION_MAC_BAD_ACCESS: 942 reason = "EXC_BAD_ACCESS / "; 943 switch (exception_flags) { 944 case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS: 945 reason.append("KERN_INVALID_ADDRESS"); 946 break; 947 case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE: 948 reason.append("KERN_PROTECTION_FAILURE"); 949 break; 950 case MD_EXCEPTION_CODE_MAC_NO_ACCESS: 951 reason.append("KERN_NO_ACCESS"); 952 break; 953 case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE: 954 reason.append("KERN_MEMORY_FAILURE"); 955 break; 956 case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR: 957 reason.append("KERN_MEMORY_ERROR"); 958 break; 959 case MD_EXCEPTION_CODE_MAC_CODESIGN_ERROR: 960 reason.append("KERN_CODESIGN_ERROR"); 961 break; 962 default: 963 // arm and ppc overlap 964 if (raw_system_info->processor_architecture == 965 MD_CPU_ARCHITECTURE_ARM || 966 raw_system_info->processor_architecture == 967 MD_CPU_ARCHITECTURE_ARM64_OLD) { 968 switch (exception_flags) { 969 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: 970 reason.append("EXC_ARM_DA_ALIGN"); 971 break; 972 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: 973 reason.append("EXC_ARM_DA_DEBUG"); 974 break; 975 default: 976 reason.append(flags_string); 977 BPLOG(INFO) << "Unknown exception reason " << reason; 978 break; 979 } 980 } else if (raw_system_info->processor_architecture == 981 MD_CPU_ARCHITECTURE_PPC) { 982 switch (exception_flags) { 983 case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ: 984 reason.append("EXC_PPC_VM_PROT_READ"); 985 break; 986 case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE: 987 reason.append("EXC_PPC_BADSPACE"); 988 break; 989 case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED: 990 reason.append("EXC_PPC_UNALIGNED"); 991 break; 992 default: 993 reason.append(flags_string); 994 BPLOG(INFO) << "Unknown exception reason " << reason; 995 break; 996 } 997 } else if (raw_system_info->processor_architecture == 998 MD_CPU_ARCHITECTURE_X86 || 999 raw_system_info->processor_architecture == 1000 MD_CPU_ARCHITECTURE_AMD64) { 1001 switch (exception_flags) { 1002 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: 1003 reason.append("EXC_I386_GPFLT"); 1004 break; 1005 default: 1006 reason.append(flags_string); 1007 BPLOG(INFO) << "Unknown exception reason " << reason; 1008 break; 1009 } 1010 } else { 1011 reason.append(flags_string); 1012 BPLOG(INFO) << "Unknown exception reason " << reason; 1013 } 1014 break; 1015 } 1016 break; 1017 case MD_EXCEPTION_MAC_BAD_INSTRUCTION: 1018 reason = "EXC_BAD_INSTRUCTION / "; 1019 switch (raw_system_info->processor_architecture) { 1020 case MD_CPU_ARCHITECTURE_ARM: 1021 case MD_CPU_ARCHITECTURE_ARM64_OLD: { 1022 switch (exception_flags) { 1023 case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED: 1024 reason.append("EXC_ARM_UNDEFINED"); 1025 break; 1026 default: 1027 reason.append(flags_string); 1028 BPLOG(INFO) << "Unknown exception reason " << reason; 1029 break; 1030 } 1031 break; 1032 } 1033 case MD_CPU_ARCHITECTURE_PPC: { 1034 switch (exception_flags) { 1035 case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL: 1036 reason.append("EXC_PPC_INVALID_SYSCALL"); 1037 break; 1038 case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION: 1039 reason.append("EXC_PPC_UNIPL_INST"); 1040 break; 1041 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION: 1042 reason.append("EXC_PPC_PRIVINST"); 1043 break; 1044 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER: 1045 reason.append("EXC_PPC_PRIVREG"); 1046 break; 1047 case MD_EXCEPTION_CODE_MAC_PPC_TRACE: 1048 reason.append("EXC_PPC_TRACE"); 1049 break; 1050 case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR: 1051 reason.append("EXC_PPC_PERFMON"); 1052 break; 1053 default: 1054 reason.append(flags_string); 1055 BPLOG(INFO) << "Unknown exception reason " << reason; 1056 break; 1057 } 1058 break; 1059 } 1060 case MD_CPU_ARCHITECTURE_AMD64: 1061 case MD_CPU_ARCHITECTURE_X86: { 1062 switch (exception_flags) { 1063 case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION: 1064 reason.append("EXC_I386_INVOP"); 1065 break; 1066 case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT: 1067 reason.append("EXC_I386_INVTSSFLT"); 1068 break; 1069 case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT: 1070 reason.append("EXC_I386_SEGNPFLT"); 1071 break; 1072 case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT: 1073 reason.append("EXC_I386_STKFLT"); 1074 break; 1075 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: 1076 reason.append("EXC_I386_GPFLT"); 1077 break; 1078 case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT: 1079 reason.append("EXC_I386_ALIGNFLT"); 1080 break; 1081 default: 1082 reason.append(flags_string); 1083 BPLOG(INFO) << "Unknown exception reason " << reason; 1084 break; 1085 } 1086 break; 1087 } 1088 default: 1089 reason.append(flags_string); 1090 BPLOG(INFO) << "Unknown exception reason " << reason; 1091 break; 1092 } 1093 break; 1094 case MD_EXCEPTION_MAC_ARITHMETIC: 1095 reason = "EXC_ARITHMETIC / "; 1096 switch (raw_system_info->processor_architecture) { 1097 case MD_CPU_ARCHITECTURE_PPC: { 1098 switch (exception_flags) { 1099 case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW: 1100 reason.append("EXC_PPC_OVERFLOW"); 1101 break; 1102 case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE: 1103 reason.append("EXC_PPC_ZERO_DIVIDE"); 1104 break; 1105 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT: 1106 reason.append("EXC_FLT_INEXACT"); 1107 break; 1108 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE: 1109 reason.append("EXC_PPC_FLT_ZERO_DIVIDE"); 1110 break; 1111 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW: 1112 reason.append("EXC_PPC_FLT_UNDERFLOW"); 1113 break; 1114 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW: 1115 reason.append("EXC_PPC_FLT_OVERFLOW"); 1116 break; 1117 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER: 1118 reason.append("EXC_PPC_FLT_NOT_A_NUMBER"); 1119 break; 1120 case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION: 1121 reason.append("EXC_PPC_NOEMULATION"); 1122 break; 1123 case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST: 1124 reason.append("EXC_PPC_ALTIVECASSIST"); 1125 break; 1126 default: 1127 reason.append(flags_string); 1128 BPLOG(INFO) << "Unknown exception reason " << reason; 1129 break; 1130 } 1131 break; 1132 } 1133 case MD_CPU_ARCHITECTURE_AMD64: 1134 case MD_CPU_ARCHITECTURE_X86: { 1135 switch (exception_flags) { 1136 case MD_EXCEPTION_CODE_MAC_X86_DIV: 1137 reason.append("EXC_I386_DIV"); 1138 break; 1139 case MD_EXCEPTION_CODE_MAC_X86_INTO: 1140 reason.append("EXC_I386_INTO"); 1141 break; 1142 case MD_EXCEPTION_CODE_MAC_X86_NOEXT: 1143 reason.append("EXC_I386_NOEXT"); 1144 break; 1145 case MD_EXCEPTION_CODE_MAC_X86_EXTOVR: 1146 reason.append("EXC_I386_EXTOVR"); 1147 break; 1148 case MD_EXCEPTION_CODE_MAC_X86_EXTERR: 1149 reason.append("EXC_I386_EXTERR"); 1150 break; 1151 case MD_EXCEPTION_CODE_MAC_X86_EMERR: 1152 reason.append("EXC_I386_EMERR"); 1153 break; 1154 case MD_EXCEPTION_CODE_MAC_X86_BOUND: 1155 reason.append("EXC_I386_BOUND"); 1156 break; 1157 case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR: 1158 reason.append("EXC_I386_SSEEXTERR"); 1159 break; 1160 default: 1161 reason.append(flags_string); 1162 BPLOG(INFO) << "Unknown exception reason " << reason; 1163 break; 1164 } 1165 break; 1166 } 1167 default: 1168 reason.append(flags_string); 1169 BPLOG(INFO) << "Unknown exception reason " << reason; 1170 break; 1171 } 1172 break; 1173 case MD_EXCEPTION_MAC_EMULATION: 1174 reason = "EXC_EMULATION / "; 1175 reason.append(flags_string); 1176 break; 1177 case MD_EXCEPTION_MAC_SOFTWARE: 1178 reason = "EXC_SOFTWARE / "; 1179 switch (exception_flags) { 1180 case MD_EXCEPTION_CODE_MAC_ABORT: 1181 reason.append("SIGABRT"); 1182 break; 1183 case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION: 1184 reason.append("UNCAUGHT_NS_EXCEPTION"); 1185 break; 1186 // These are ppc only but shouldn't be a problem as they're 1187 // unused on x86 1188 case MD_EXCEPTION_CODE_MAC_PPC_TRAP: 1189 reason.append("EXC_PPC_TRAP"); 1190 break; 1191 case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE: 1192 reason.append("EXC_PPC_MIGRATE"); 1193 break; 1194 default: 1195 reason.append(flags_string); 1196 BPLOG(INFO) << "Unknown exception reason " << reason; 1197 break; 1198 } 1199 break; 1200 case MD_EXCEPTION_MAC_BREAKPOINT: 1201 reason = "EXC_BREAKPOINT / "; 1202 switch (raw_system_info->processor_architecture) { 1203 case MD_CPU_ARCHITECTURE_ARM: 1204 case MD_CPU_ARCHITECTURE_ARM64_OLD: { 1205 switch (exception_flags) { 1206 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: 1207 reason.append("EXC_ARM_DA_ALIGN"); 1208 break; 1209 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: 1210 reason.append("EXC_ARM_DA_DEBUG"); 1211 break; 1212 case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT: 1213 reason.append("EXC_ARM_BREAKPOINT"); 1214 break; 1215 default: 1216 reason.append(flags_string); 1217 BPLOG(INFO) << "Unknown exception reason " << reason; 1218 break; 1219 } 1220 break; 1221 } 1222 case MD_CPU_ARCHITECTURE_PPC: { 1223 switch (exception_flags) { 1224 case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT: 1225 reason.append("EXC_PPC_BREAKPOINT"); 1226 break; 1227 default: 1228 reason.append(flags_string); 1229 BPLOG(INFO) << "Unknown exception reason " << reason; 1230 break; 1231 } 1232 break; 1233 } 1234 case MD_CPU_ARCHITECTURE_AMD64: 1235 case MD_CPU_ARCHITECTURE_X86: { 1236 switch (exception_flags) { 1237 case MD_EXCEPTION_CODE_MAC_X86_SGL: 1238 reason.append("EXC_I386_SGL"); 1239 break; 1240 case MD_EXCEPTION_CODE_MAC_X86_BPT: 1241 reason.append("EXC_I386_BPT"); 1242 break; 1243 default: 1244 reason.append(flags_string); 1245 BPLOG(INFO) << "Unknown exception reason " << reason; 1246 break; 1247 } 1248 break; 1249 } 1250 default: 1251 reason.append(flags_string); 1252 BPLOG(INFO) << "Unknown exception reason " << reason; 1253 break; 1254 } 1255 break; 1256 case MD_EXCEPTION_MAC_SYSCALL: 1257 reason = "EXC_SYSCALL / "; 1258 reason.append(flags_string); 1259 break; 1260 case MD_EXCEPTION_MAC_MACH_SYSCALL: 1261 reason = "EXC_MACH_SYSCALL / "; 1262 reason.append(flags_string); 1263 break; 1264 case MD_EXCEPTION_MAC_RPC_ALERT: 1265 reason = "EXC_RPC_ALERT / "; 1266 reason.append(flags_string); 1267 break; 1268 case MD_EXCEPTION_MAC_RESOURCE: 1269 reason = "EXC_RESOURCE / "; 1270 reason.append(flags_string); 1271 break; 1272 case MD_EXCEPTION_MAC_GUARD: 1273 reason = "EXC_GUARD / "; 1274 reason.append(flags_string); 1275 break; 1276 case MD_EXCEPTION_MAC_SIMULATED: 1277 reason = "Simulated Exception"; 1278 break; 1279 case MD_NS_EXCEPTION_SIMULATED: 1280 reason = "Uncaught NSException"; 1281 break; 1282 } 1283 break; 1284 } 1285 1286 case MD_OS_WIN32_NT: 1287 case MD_OS_WIN32_WINDOWS: { 1288 switch (exception_code) { 1289 case MD_EXCEPTION_CODE_WIN_CONTROL_C: 1290 reason = "DBG_CONTROL_C"; 1291 break; 1292 case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: 1293 reason = "EXCEPTION_GUARD_PAGE"; 1294 break; 1295 case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT: 1296 reason = "EXCEPTION_DATATYPE_MISALIGNMENT"; 1297 break; 1298 case MD_EXCEPTION_CODE_WIN_BREAKPOINT: 1299 reason = "EXCEPTION_BREAKPOINT"; 1300 break; 1301 case MD_EXCEPTION_CODE_WIN_SINGLE_STEP: 1302 reason = "EXCEPTION_SINGLE_STEP"; 1303 break; 1304 case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: 1305 // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that 1306 // caused the fault in exception_information[1]. 1307 // exception_information[0] is 0 if the violation was caused by 1308 // an attempt to read data, 1 if it was an attempt to write data, 1309 // and 8 if this was a data execution violation. 1310 // This information is useful in addition to the code address, which 1311 // will be present in the crash thread's instruction field anyway. 1312 if (raw_exception->exception_record.number_parameters >= 1) { 1313 MDAccessViolationTypeWin av_type = 1314 static_cast<MDAccessViolationTypeWin> 1315 (raw_exception->exception_record.exception_information[0]); 1316 switch (av_type) { 1317 case MD_ACCESS_VIOLATION_WIN_READ: 1318 reason = "EXCEPTION_ACCESS_VIOLATION_READ"; 1319 break; 1320 case MD_ACCESS_VIOLATION_WIN_WRITE: 1321 reason = "EXCEPTION_ACCESS_VIOLATION_WRITE"; 1322 break; 1323 case MD_ACCESS_VIOLATION_WIN_EXEC: 1324 reason = "EXCEPTION_ACCESS_VIOLATION_EXEC"; 1325 break; 1326 default: 1327 reason = "EXCEPTION_ACCESS_VIOLATION"; 1328 break; 1329 } 1330 } else { 1331 reason = "EXCEPTION_ACCESS_VIOLATION"; 1332 } 1333 if (address && 1334 raw_exception->exception_record.number_parameters >= 2) { 1335 *address = 1336 raw_exception->exception_record.exception_information[1]; 1337 } 1338 break; 1339 case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: 1340 // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that 1341 // caused the fault in exception_information[1]. 1342 // exception_information[0] is 0 if the violation was caused by 1343 // an attempt to read data, 1 if it was an attempt to write data, 1344 // and 8 if this was a data execution violation. 1345 // exception_information[2] contains the underlying NTSTATUS code, 1346 // which is the explanation for why this error occured. 1347 // This information is useful in addition to the code address, which 1348 // will be present in the crash thread's instruction field anyway. 1349 if (raw_exception->exception_record.number_parameters >= 1) { 1350 MDInPageErrorTypeWin av_type = 1351 static_cast<MDInPageErrorTypeWin> 1352 (raw_exception->exception_record.exception_information[0]); 1353 switch (av_type) { 1354 case MD_IN_PAGE_ERROR_WIN_READ: 1355 reason = "EXCEPTION_IN_PAGE_ERROR_READ"; 1356 break; 1357 case MD_IN_PAGE_ERROR_WIN_WRITE: 1358 reason = "EXCEPTION_IN_PAGE_ERROR_WRITE"; 1359 break; 1360 case MD_IN_PAGE_ERROR_WIN_EXEC: 1361 reason = "EXCEPTION_IN_PAGE_ERROR_EXEC"; 1362 break; 1363 default: 1364 reason = "EXCEPTION_IN_PAGE_ERROR"; 1365 break; 1366 } 1367 } else { 1368 reason = "EXCEPTION_IN_PAGE_ERROR"; 1369 } 1370 if (address && 1371 raw_exception->exception_record.number_parameters >= 2) { 1372 *address = 1373 raw_exception->exception_record.exception_information[1]; 1374 } 1375 if (raw_exception->exception_record.number_parameters >= 3) { 1376 uint32_t ntstatus = 1377 static_cast<uint32_t> 1378 (raw_exception->exception_record.exception_information[2]); 1379 reason.append(" / "); 1380 reason.append(NTStatusToString(ntstatus)); 1381 } 1382 break; 1383 case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE: 1384 reason = "EXCEPTION_INVALID_HANDLE"; 1385 break; 1386 case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: 1387 reason = "EXCEPTION_ILLEGAL_INSTRUCTION"; 1388 break; 1389 case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: 1390 reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; 1391 break; 1392 case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: 1393 reason = "EXCEPTION_INVALID_DISPOSITION"; 1394 break; 1395 case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED: 1396 reason = "EXCEPTION_BOUNDS_EXCEEDED"; 1397 break; 1398 case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND: 1399 reason = "EXCEPTION_FLT_DENORMAL_OPERAND"; 1400 break; 1401 case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: 1402 reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO"; 1403 break; 1404 case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: 1405 reason = "EXCEPTION_FLT_INEXACT_RESULT"; 1406 break; 1407 case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: 1408 reason = "EXCEPTION_FLT_INVALID_OPERATION"; 1409 break; 1410 case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: 1411 reason = "EXCEPTION_FLT_OVERFLOW"; 1412 break; 1413 case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK: 1414 reason = "EXCEPTION_FLT_STACK_CHECK"; 1415 break; 1416 case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: 1417 reason = "EXCEPTION_FLT_UNDERFLOW"; 1418 break; 1419 case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: 1420 reason = "EXCEPTION_INT_DIVIDE_BY_ZERO"; 1421 break; 1422 case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: 1423 reason = "EXCEPTION_INT_OVERFLOW"; 1424 break; 1425 case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: 1426 reason = "EXCEPTION_PRIV_INSTRUCTION"; 1427 break; 1428 case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: 1429 reason = "EXCEPTION_STACK_OVERFLOW"; 1430 break; 1431 case MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE: 1432 reason = "EXCEPTION_BAD_FUNCTION_TABLE"; 1433 break; 1434 case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: 1435 reason = "EXCEPTION_POSSIBLE_DEADLOCK"; 1436 break; 1437 case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: 1438 if (raw_exception->exception_record.number_parameters >= 1) { 1439 MDFastFailSubcodeTypeWin subcode = 1440 static_cast<MDFastFailSubcodeTypeWin>( 1441 raw_exception->exception_record.exception_information[0]); 1442 switch (subcode) { 1443 // Note - we skip the '0'/GS case as it exists for legacy reasons. 1444 case MD_FAST_FAIL_VTGUARD_CHECK_FAILURE: 1445 reason = "FAST_FAIL_VTGUARD_CHECK_FAILURE"; 1446 break; 1447 case MD_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE: 1448 reason = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE"; 1449 break; 1450 case MD_FAST_FAIL_CORRUPT_LIST_ENTRY: 1451 reason = "FAST_FAIL_CORRUPT_LIST_ENTRY"; 1452 break; 1453 case MD_FAST_FAIL_INCORRECT_STACK: 1454 reason = "FAST_FAIL_INCORRECT_STACK"; 1455 break; 1456 case MD_FAST_FAIL_INVALID_ARG: 1457 reason = "FAST_FAIL_INVALID_ARG"; 1458 break; 1459 case MD_FAST_FAIL_GS_COOKIE_INIT: 1460 reason = "FAST_FAIL_GS_COOKIE_INIT"; 1461 break; 1462 case MD_FAST_FAIL_FATAL_APP_EXIT: 1463 reason = "FAST_FAIL_FATAL_APP_EXIT"; 1464 break; 1465 case MD_FAST_FAIL_RANGE_CHECK_FAILURE: 1466 reason = "FAST_FAIL_RANGE_CHECK_FAILURE"; 1467 break; 1468 case MD_FAST_FAIL_UNSAFE_REGISTRY_ACCESS: 1469 reason = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS"; 1470 break; 1471 case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE: 1472 reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE"; 1473 break; 1474 case MD_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE: 1475 reason = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE"; 1476 break; 1477 case MD_FAST_FAIL_INVALID_FIBER_SWITCH: 1478 reason = "FAST_FAIL_INVALID_FIBER_SWITCH"; 1479 break; 1480 case MD_FAST_FAIL_INVALID_SET_OF_CONTEXT: 1481 reason = "FAST_FAIL_INVALID_SET_OF_CONTEXT"; 1482 break; 1483 case MD_FAST_FAIL_INVALID_REFERENCE_COUNT: 1484 reason = "FAST_FAIL_INVALID_REFERENCE_COUNT"; 1485 break; 1486 case MD_FAST_FAIL_INVALID_JUMP_BUFFER: 1487 reason = "FAST_FAIL_INVALID_JUMP_BUFFER"; 1488 break; 1489 case MD_FAST_FAIL_MRDATA_MODIFIED: 1490 reason = "FAST_FAIL_MRDATA_MODIFIED"; 1491 break; 1492 case MD_FAST_FAIL_CERTIFICATION_FAILURE: 1493 reason = "FAST_FAIL_CERTIFICATION_FAILURE"; 1494 break; 1495 case MD_FAST_FAIL_INVALID_EXCEPTION_CHAIN: 1496 reason = "FAST_FAIL_INVALID_EXCEPTION_CHAIN"; 1497 break; 1498 case MD_FAST_FAIL_CRYPTO_LIBRARY: 1499 reason = "FAST_FAIL_CRYPTO_LIBRARY"; 1500 break; 1501 case MD_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT: 1502 reason = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT"; 1503 break; 1504 case MD_FAST_FAIL_INVALID_IMAGE_BASE: 1505 reason = "FAST_FAIL_INVALID_IMAGE_BASE"; 1506 break; 1507 case MD_FAST_FAIL_DLOAD_PROTECTION_FAILURE: 1508 reason = "FAST_FAIL_DLOAD_PROTECTION_FAILURE"; 1509 break; 1510 case MD_FAST_FAIL_UNSAFE_EXTENSION_CALL: 1511 reason = "FAST_FAIL_UNSAFE_EXTENSION_CALL"; 1512 break; 1513 case MD_FAST_FAIL_DEPRECATED_SERVICE_INVOKED: 1514 reason = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED"; 1515 break; 1516 case MD_FAST_FAIL_INVALID_BUFFER_ACCESS: 1517 reason = "FAST_FAIL_INVALID_BUFFER_ACCESS"; 1518 break; 1519 case MD_FAST_FAIL_INVALID_BALANCED_TREE: 1520 reason = "FAST_FAIL_INVALID_BALANCED_TREE"; 1521 break; 1522 case MD_FAST_FAIL_INVALID_NEXT_THREAD: 1523 reason = "FAST_FAIL_INVALID_NEXT_THREAD"; 1524 break; 1525 case MD_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED: 1526 reason = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED"; 1527 break; 1528 case MD_FAST_FAIL_APCS_DISABLED: 1529 reason = "FAST_FAIL_APCS_DISABLED"; 1530 break; 1531 case MD_FAST_FAIL_INVALID_IDLE_STATE: 1532 reason = "FAST_FAIL_INVALID_IDLE_STATE"; 1533 break; 1534 case MD_FAST_FAIL_MRDATA_PROTECTION_FAILURE: 1535 reason = "FAST_FAIL_MRDATA_PROTECTION_FAILURE"; 1536 break; 1537 case MD_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION: 1538 reason = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION"; 1539 break; 1540 case MD_FAST_FAIL_INVALID_LOCK_STATE: 1541 reason = "FAST_FAIL_INVALID_LOCK_STATE"; 1542 break; 1543 case MD_FAST_FAIL_GUARD_JUMPTABLE: 1544 reason = "FAST_FAIL_GUARD_JUMPTABLE"; 1545 break; 1546 case MD_FAST_FAIL_INVALID_LONGJUMP_TARGET: 1547 reason = "FAST_FAIL_INVALID_LONGJUMP_TARGET"; 1548 break; 1549 case MD_FAST_FAIL_INVALID_DISPATCH_CONTEXT: 1550 reason = "FAST_FAIL_INVALID_DISPATCH_CONTEXT"; 1551 break; 1552 case MD_FAST_FAIL_INVALID_THREAD: 1553 reason = "FAST_FAIL_INVALID_THREAD"; 1554 break; 1555 case MD_FAST_FAIL_INVALID_SYSCALL_NUMBER: 1556 reason = "FAST_FAIL_INVALID_SYSCALL_NUMBER"; 1557 break; 1558 case MD_FAST_FAIL_INVALID_FILE_OPERATION: 1559 reason = "FAST_FAIL_INVALID_FILE_OPERATION"; 1560 break; 1561 case MD_FAST_FAIL_LPAC_ACCESS_DENIED: 1562 reason = "FAST_FAIL_LPAC_ACCESS_DENIED"; 1563 break; 1564 case MD_FAST_FAIL_GUARD_SS_FAILURE: 1565 reason = "FAST_FAIL_GUARD_SS_FAILURE"; 1566 break; 1567 case MD_FAST_FAIL_LOADER_CONTINUITY_FAILURE: 1568 reason = "FAST_FAIL_LOADER_CONTINUITY_FAILURE"; 1569 break; 1570 case MD_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE: 1571 reason = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE"; 1572 break; 1573 case MD_FAST_FAIL_INVALID_CONTROL_STACK: 1574 reason = "FAST_FAIL_INVALID_CONTROL_STACK"; 1575 break; 1576 case MD_FAST_FAIL_SET_CONTEXT_DENIED: 1577 reason = "FAST_FAIL_SET_CONTEXT_DENIED"; 1578 break; 1579 case MD_FAST_FAIL_INVALID_IAT: 1580 reason = "FAST_FAIL_INVALID_IAT"; 1581 break; 1582 case MD_FAST_FAIL_HEAP_METADATA_CORRUPTION: 1583 reason = "FAST_FAIL_HEAP_METADATA_CORRUPTION"; 1584 break; 1585 case MD_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION: 1586 reason = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION"; 1587 break; 1588 case MD_FAST_FAIL_LOW_LABEL_ACCESS_DENIED: 1589 reason = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED"; 1590 break; 1591 case MD_FAST_FAIL_ENCLAVE_CALL_FAILURE: 1592 reason = "FAST_FAIL_ENCLAVE_CALL_FAILURE"; 1593 break; 1594 case MD_FAST_FAIL_UNHANDLED_LSS_EXCEPTON: 1595 reason = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON"; 1596 break; 1597 case MD_FAST_FAIL_ADMINLESS_ACCESS_DENIED: 1598 reason = "FAST_FAIL_ADMINLESS_ACCESS_DENIED"; 1599 break; 1600 case MD_FAST_FAIL_UNEXPECTED_CALL: 1601 reason = "FAST_FAIL_UNEXPECTED_CALL"; 1602 break; 1603 case MD_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS: 1604 reason = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS"; 1605 break; 1606 case MD_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR: 1607 reason = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR"; 1608 break; 1609 case MD_FAST_FAIL_FLAGS_CORRUPTION: 1610 reason = "FAST_FAIL_FLAGS_CORRUPTION"; 1611 break; 1612 case MD_FAST_FAIL_VEH_CORRUPTION: 1613 reason = "FAST_FAIL_VEH_CORRUPTION"; 1614 break; 1615 case MD_FAST_FAIL_ETW_CORRUPTION: 1616 reason = "FAST_FAIL_ETW_CORRUPTION"; 1617 break; 1618 case MD_FAST_FAIL_RIO_ABORT: 1619 reason = "FAST_FAIL_RIO_ABORT"; 1620 break; 1621 case MD_FAST_FAIL_INVALID_PFN: 1622 reason = "FAST_FAIL_INVALID_PFN"; 1623 break; 1624 case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG: 1625 reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG"; 1626 break; 1627 case MD_FAST_FAIL_CAST_GUARD: 1628 reason = "FAST_FAIL_CAST_GUARD"; 1629 break; 1630 case MD_FAST_FAIL_HOST_VISIBILITY_CHANGE: 1631 reason = "FAST_FAIL_HOST_VISIBILITY_CHANGE"; 1632 break; 1633 case MD_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST: 1634 reason = "FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST"; 1635 break; 1636 case MD_FAST_FAIL_PATCH_CALLBACK_FAILED: 1637 reason = "FAST_FAIL_PATCH_CALLBACK_FAILED"; 1638 break; 1639 case MD_FAST_FAIL_NTDLL_PATCH_FAILED: 1640 reason = "FAST_FAIL_NTDLL_PATCH_FAILED"; 1641 break; 1642 case MD_FAST_FAIL_INVALID_FLS_DATA: 1643 reason = "FAST_FAIL_INVALID_FLS_DATA"; 1644 break; 1645 default: 1646 reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; 1647 break; 1648 } 1649 } else { 1650 reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; 1651 } 1652 break; 1653 case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: 1654 reason = "EXCEPTION_HEAP_CORRUPTION"; 1655 break; 1656 case MD_EXCEPTION_OUT_OF_MEMORY: 1657 reason = "Out of Memory"; 1658 break; 1659 case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION: 1660 reason = "Unhandled C++ Exception"; 1661 break; 1662 case MD_EXCEPTION_CODE_WIN_SIMULATED: 1663 reason = "Simulated Exception"; 1664 break; 1665 default: 1666 BPLOG(INFO) << "Unknown exception reason " << reason; 1667 break; 1668 } 1669 break; 1670 } 1671 1672 case MD_OS_ANDROID: 1673 case MD_OS_LINUX: { 1674 switch (exception_code) { 1675 case MD_EXCEPTION_CODE_LIN_SIGHUP: 1676 reason = "SIGHUP"; 1677 break; 1678 case MD_EXCEPTION_CODE_LIN_SIGINT: 1679 reason = "SIGINT"; 1680 break; 1681 case MD_EXCEPTION_CODE_LIN_SIGQUIT: 1682 reason = "SIGQUIT"; 1683 break; 1684 case MD_EXCEPTION_CODE_LIN_SIGILL: 1685 reason = "SIGILL / "; 1686 switch (exception_flags) { 1687 case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC: 1688 reason.append("ILL_ILLOPC"); 1689 break; 1690 case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN: 1691 reason.append("ILL_ILLOPN"); 1692 break; 1693 case MD_EXCEPTION_FLAG_LIN_ILL_ILLADR: 1694 reason.append("ILL_ILLADR"); 1695 break; 1696 case MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP: 1697 reason.append("ILL_ILLTRP"); 1698 break; 1699 case MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC: 1700 reason.append("ILL_PRVOPC"); 1701 break; 1702 case MD_EXCEPTION_FLAG_LIN_ILL_PRVREG: 1703 reason.append("ILL_PRVREG"); 1704 break; 1705 case MD_EXCEPTION_FLAG_LIN_ILL_COPROC: 1706 reason.append("ILL_COPROC"); 1707 break; 1708 case MD_EXCEPTION_FLAG_LIN_ILL_BADSTK: 1709 reason.append("ILL_BADSTK"); 1710 break; 1711 default: 1712 reason.append(flags_string); 1713 BPLOG(INFO) << "Unknown exception reason " << reason; 1714 break; 1715 } 1716 break; 1717 case MD_EXCEPTION_CODE_LIN_SIGTRAP: 1718 reason = "SIGTRAP"; 1719 break; 1720 case MD_EXCEPTION_CODE_LIN_SIGABRT: 1721 reason = "SIGABRT"; 1722 break; 1723 case MD_EXCEPTION_CODE_LIN_SIGBUS: 1724 reason = "SIGBUS / "; 1725 switch (exception_flags) { 1726 case MD_EXCEPTION_FLAG_LIN_BUS_ADRALN: 1727 reason.append("BUS_ADRALN"); 1728 break; 1729 case MD_EXCEPTION_FLAG_LIN_BUS_ADRERR: 1730 reason.append("BUS_ADRERR"); 1731 break; 1732 case MD_EXCEPTION_FLAG_LIN_BUS_OBJERR: 1733 reason.append("BUS_OBJERR"); 1734 break; 1735 case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AR: 1736 reason.append("BUS_MCEERR_AR"); 1737 break; 1738 case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AO: 1739 reason.append("BUS_MCEERR_AO"); 1740 break; 1741 default: 1742 reason.append(flags_string); 1743 BPLOG(INFO) << "Unknown exception reason " << reason; 1744 break; 1745 } 1746 break; 1747 case MD_EXCEPTION_CODE_LIN_SIGFPE: 1748 reason = "SIGFPE / "; 1749 switch (exception_flags) { 1750 case MD_EXCEPTION_FLAG_LIN_FPE_INTDIV: 1751 reason.append("FPE_INTDIV"); 1752 break; 1753 case MD_EXCEPTION_FLAG_LIN_FPE_INTOVF: 1754 reason.append("FPE_INTOVF"); 1755 break; 1756 case MD_EXCEPTION_FLAG_LIN_FPE_FLTDIV: 1757 reason.append("FPE_FLTDIV"); 1758 break; 1759 case MD_EXCEPTION_FLAG_LIN_FPE_FLTOVF: 1760 reason.append("FPE_FLTOVF"); 1761 break; 1762 case MD_EXCEPTION_FLAG_LIN_FPE_FLTUND: 1763 reason.append("FPE_FLTUND"); 1764 break; 1765 case MD_EXCEPTION_FLAG_LIN_FPE_FLTRES: 1766 reason.append("FPE_FLTRES"); 1767 break; 1768 case MD_EXCEPTION_FLAG_LIN_FPE_FLTINV: 1769 reason.append("FPE_FLTINV"); 1770 break; 1771 case MD_EXCEPTION_FLAG_LIN_FPE_FLTSUB: 1772 reason.append("FPE_FLTSUB"); 1773 break; 1774 default: 1775 reason.append(flags_string); 1776 BPLOG(INFO) << "Unknown exception reason " << reason; 1777 break; 1778 } 1779 break; 1780 case MD_EXCEPTION_CODE_LIN_SIGKILL: 1781 reason = "SIGKILL"; 1782 break; 1783 case MD_EXCEPTION_CODE_LIN_SIGUSR1: 1784 reason = "SIGUSR1"; 1785 break; 1786 case MD_EXCEPTION_CODE_LIN_SIGSEGV: 1787 reason = "SIGSEGV /"; 1788 switch (exception_flags) { 1789 case MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR: 1790 reason.append("SEGV_MAPERR"); 1791 break; 1792 case MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR: 1793 reason.append("SEGV_ACCERR"); 1794 break; 1795 case MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR: 1796 reason.append("SEGV_BNDERR"); 1797 break; 1798 case MD_EXCEPTION_FLAG_LIN_SEGV_PKUERR: 1799 reason.append("SEGV_PKUERR"); 1800 break; 1801 case MD_EXCEPTION_FLAG_LIN_SEGV_ACCADI: 1802 reason.append("SEGV_ACCADI"); 1803 break; 1804 case MD_EXCEPTION_FLAG_LIN_SEGV_ADIDERR: 1805 reason.append("SEGV_ADIDERR"); 1806 break; 1807 case MD_EXCEPTION_FLAG_LIN_SEGV_ADIPERR: 1808 reason.append("SEGV_ADIPERR"); 1809 break; 1810 case MD_EXCEPTION_FLAG_LIN_SEGV_MTEAERR: 1811 reason.append("SEGV_MTEAERR"); 1812 break; 1813 case MD_EXCEPTION_FLAG_LIN_SEGV_MTESERR: 1814 reason.append("SEGV_MTESERR"); 1815 break; 1816 default: 1817 reason.append(flags_string); 1818 BPLOG(INFO) << "Unknown exception reason " << reason; 1819 break; 1820 } 1821 break; 1822 case MD_EXCEPTION_CODE_LIN_SIGUSR2: 1823 reason = "SIGUSR2"; 1824 break; 1825 case MD_EXCEPTION_CODE_LIN_SIGPIPE: 1826 reason = "SIGPIPE"; 1827 break; 1828 case MD_EXCEPTION_CODE_LIN_SIGALRM: 1829 reason = "SIGALRM"; 1830 break; 1831 case MD_EXCEPTION_CODE_LIN_SIGTERM: 1832 reason = "SIGTERM"; 1833 break; 1834 case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: 1835 reason = "SIGSTKFLT"; 1836 break; 1837 case MD_EXCEPTION_CODE_LIN_SIGCHLD: 1838 reason = "SIGCHLD"; 1839 break; 1840 case MD_EXCEPTION_CODE_LIN_SIGCONT: 1841 reason = "SIGCONT"; 1842 break; 1843 case MD_EXCEPTION_CODE_LIN_SIGSTOP: 1844 reason = "SIGSTOP"; 1845 break; 1846 case MD_EXCEPTION_CODE_LIN_SIGTSTP: 1847 reason = "SIGTSTP"; 1848 break; 1849 case MD_EXCEPTION_CODE_LIN_SIGTTIN: 1850 reason = "SIGTTIN"; 1851 break; 1852 case MD_EXCEPTION_CODE_LIN_SIGTTOU: 1853 reason = "SIGTTOU"; 1854 break; 1855 case MD_EXCEPTION_CODE_LIN_SIGURG: 1856 reason = "SIGURG"; 1857 break; 1858 case MD_EXCEPTION_CODE_LIN_SIGXCPU: 1859 reason = "SIGXCPU"; 1860 break; 1861 case MD_EXCEPTION_CODE_LIN_SIGXFSZ: 1862 reason = "SIGXFSZ"; 1863 break; 1864 case MD_EXCEPTION_CODE_LIN_SIGVTALRM: 1865 reason = "SIGVTALRM"; 1866 break; 1867 case MD_EXCEPTION_CODE_LIN_SIGPROF: 1868 reason = "SIGPROF"; 1869 break; 1870 case MD_EXCEPTION_CODE_LIN_SIGWINCH: 1871 reason = "SIGWINCH"; 1872 break; 1873 case MD_EXCEPTION_CODE_LIN_SIGIO: 1874 reason = "SIGIO"; 1875 break; 1876 case MD_EXCEPTION_CODE_LIN_SIGPWR: 1877 reason = "SIGPWR"; 1878 break; 1879 case MD_EXCEPTION_CODE_LIN_SIGSYS: 1880 reason = "SIGSYS"; 1881 break; 1882 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: 1883 reason = "DUMP_REQUESTED"; 1884 break; 1885 default: 1886 BPLOG(INFO) << "Unknown exception reason " << reason; 1887 break; 1888 } 1889 break; 1890 } 1891 1892 case MD_OS_SOLARIS: { 1893 switch (exception_code) { 1894 case MD_EXCEPTION_CODE_SOL_SIGHUP: 1895 reason = "SIGHUP"; 1896 break; 1897 case MD_EXCEPTION_CODE_SOL_SIGINT: 1898 reason = "SIGINT"; 1899 break; 1900 case MD_EXCEPTION_CODE_SOL_SIGQUIT: 1901 reason = "SIGQUIT"; 1902 break; 1903 case MD_EXCEPTION_CODE_SOL_SIGILL: 1904 reason = "SIGILL"; 1905 break; 1906 case MD_EXCEPTION_CODE_SOL_SIGTRAP: 1907 reason = "SIGTRAP"; 1908 break; 1909 case MD_EXCEPTION_CODE_SOL_SIGIOT: 1910 reason = "SIGIOT | SIGABRT"; 1911 break; 1912 case MD_EXCEPTION_CODE_SOL_SIGEMT: 1913 reason = "SIGEMT"; 1914 break; 1915 case MD_EXCEPTION_CODE_SOL_SIGFPE: 1916 reason = "SIGFPE"; 1917 break; 1918 case MD_EXCEPTION_CODE_SOL_SIGKILL: 1919 reason = "SIGKILL"; 1920 break; 1921 case MD_EXCEPTION_CODE_SOL_SIGBUS: 1922 reason = "SIGBUS"; 1923 break; 1924 case MD_EXCEPTION_CODE_SOL_SIGSEGV: 1925 reason = "SIGSEGV"; 1926 break; 1927 case MD_EXCEPTION_CODE_SOL_SIGSYS: 1928 reason = "SIGSYS"; 1929 break; 1930 case MD_EXCEPTION_CODE_SOL_SIGPIPE: 1931 reason = "SIGPIPE"; 1932 break; 1933 case MD_EXCEPTION_CODE_SOL_SIGALRM: 1934 reason = "SIGALRM"; 1935 break; 1936 case MD_EXCEPTION_CODE_SOL_SIGTERM: 1937 reason = "SIGTERM"; 1938 break; 1939 case MD_EXCEPTION_CODE_SOL_SIGUSR1: 1940 reason = "SIGUSR1"; 1941 break; 1942 case MD_EXCEPTION_CODE_SOL_SIGUSR2: 1943 reason = "SIGUSR2"; 1944 break; 1945 case MD_EXCEPTION_CODE_SOL_SIGCLD: 1946 reason = "SIGCLD | SIGCHLD"; 1947 break; 1948 case MD_EXCEPTION_CODE_SOL_SIGPWR: 1949 reason = "SIGPWR"; 1950 break; 1951 case MD_EXCEPTION_CODE_SOL_SIGWINCH: 1952 reason = "SIGWINCH"; 1953 break; 1954 case MD_EXCEPTION_CODE_SOL_SIGURG: 1955 reason = "SIGURG"; 1956 break; 1957 case MD_EXCEPTION_CODE_SOL_SIGPOLL: 1958 reason = "SIGPOLL | SIGIO"; 1959 break; 1960 case MD_EXCEPTION_CODE_SOL_SIGSTOP: 1961 reason = "SIGSTOP"; 1962 break; 1963 case MD_EXCEPTION_CODE_SOL_SIGTSTP: 1964 reason = "SIGTSTP"; 1965 break; 1966 case MD_EXCEPTION_CODE_SOL_SIGCONT: 1967 reason = "SIGCONT"; 1968 break; 1969 case MD_EXCEPTION_CODE_SOL_SIGTTIN: 1970 reason = "SIGTTIN"; 1971 break; 1972 case MD_EXCEPTION_CODE_SOL_SIGTTOU: 1973 reason = "SIGTTOU"; 1974 break; 1975 case MD_EXCEPTION_CODE_SOL_SIGVTALRM: 1976 reason = "SIGVTALRM"; 1977 break; 1978 case MD_EXCEPTION_CODE_SOL_SIGPROF: 1979 reason = "SIGPROF"; 1980 break; 1981 case MD_EXCEPTION_CODE_SOL_SIGXCPU: 1982 reason = "SIGXCPU"; 1983 break; 1984 case MD_EXCEPTION_CODE_SOL_SIGXFSZ: 1985 reason = "SIGXFSZ"; 1986 break; 1987 case MD_EXCEPTION_CODE_SOL_SIGWAITING: 1988 reason = "SIGWAITING"; 1989 break; 1990 case MD_EXCEPTION_CODE_SOL_SIGLWP: 1991 reason = "SIGLWP"; 1992 break; 1993 case MD_EXCEPTION_CODE_SOL_SIGFREEZE: 1994 reason = "SIGFREEZE"; 1995 break; 1996 case MD_EXCEPTION_CODE_SOL_SIGTHAW: 1997 reason = "SIGTHAW"; 1998 break; 1999 case MD_EXCEPTION_CODE_SOL_SIGCANCEL: 2000 reason = "SIGCANCEL"; 2001 break; 2002 case MD_EXCEPTION_CODE_SOL_SIGLOST: 2003 reason = "SIGLOST"; 2004 break; 2005 case MD_EXCEPTION_CODE_SOL_SIGXRES: 2006 reason = "SIGXRES"; 2007 break; 2008 case MD_EXCEPTION_CODE_SOL_SIGJVM1: 2009 reason = "SIGJVM1"; 2010 break; 2011 case MD_EXCEPTION_CODE_SOL_SIGJVM2: 2012 reason = "SIGJVM2"; 2013 break; 2014 default: 2015 BPLOG(INFO) << "Unknown exception reason " << reason; 2016 break; 2017 } 2018 break; 2019 } 2020 2021 case MD_OS_PS3: { 2022 switch (exception_code) { 2023 case MD_EXCEPTION_CODE_PS3_UNKNOWN: 2024 reason = "UNKNOWN"; 2025 break; 2026 case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP: 2027 reason = "TRAP_EXCEP"; 2028 break; 2029 case MD_EXCEPTION_CODE_PS3_PRIV_INSTR: 2030 reason = "PRIV_INSTR"; 2031 break; 2032 case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR: 2033 reason = "ILLEGAL_INSTR"; 2034 break; 2035 case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE: 2036 reason = "INSTR_STORAGE"; 2037 break; 2038 case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT: 2039 reason = "INSTR_SEGMENT"; 2040 break; 2041 case MD_EXCEPTION_CODE_PS3_DATA_STORAGE: 2042 reason = "DATA_STORAGE"; 2043 break; 2044 case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT: 2045 reason = "DATA_SEGMENT"; 2046 break; 2047 case MD_EXCEPTION_CODE_PS3_FLOAT_POINT: 2048 reason = "FLOAT_POINT"; 2049 break; 2050 case MD_EXCEPTION_CODE_PS3_DABR_MATCH: 2051 reason = "DABR_MATCH"; 2052 break; 2053 case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP: 2054 reason = "ALIGN_EXCEP"; 2055 break; 2056 case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS: 2057 reason = "MEMORY_ACCESS"; 2058 break; 2059 case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN: 2060 reason = "COPRO_ALIGN"; 2061 break; 2062 case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM: 2063 reason = "COPRO_INVALID_COM"; 2064 break; 2065 case MD_EXCEPTION_CODE_PS3_COPRO_ERR: 2066 reason = "COPRO_ERR"; 2067 break; 2068 case MD_EXCEPTION_CODE_PS3_COPRO_FIR: 2069 reason = "COPRO_FIR"; 2070 break; 2071 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT: 2072 reason = "COPRO_DATA_SEGMENT"; 2073 break; 2074 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE: 2075 reason = "COPRO_DATA_STORAGE"; 2076 break; 2077 case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR: 2078 reason = "COPRO_STOP_INSTR"; 2079 break; 2080 case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR: 2081 reason = "COPRO_HALT_INSTR"; 2082 break; 2083 case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN: 2084 reason = "COPRO_HALTINSTR_UNKNOWN"; 2085 break; 2086 case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS: 2087 reason = "COPRO_MEMORY_ACCESS"; 2088 break; 2089 case MD_EXCEPTION_CODE_PS3_GRAPHIC: 2090 reason = "GRAPHIC"; 2091 break; 2092 default: 2093 BPLOG(INFO) << "Unknown exception reason "<< reason; 2094 break; 2095 } 2096 break; 2097 } 2098 2099 default: { 2100 BPLOG(INFO) << "Unknown exception reason " << reason; 2101 break; 2102 } 2103 } 2104 2105 if (address) { 2106 *address = GetAddressForArchitecture( 2107 static_cast<MDCPUArchitecture>(raw_system_info->processor_architecture), 2108 *address); 2109 2110 #ifdef __linux__ 2111 // For invalid accesses to non-canonical addresses, amd64 cpus don't provide 2112 // the fault address, so recover it from the disassembly and register state 2113 // if possible. 2114 if (enable_objdump 2115 && raw_system_info->processor_architecture == MD_CPU_ARCHITECTURE_AMD64 2116 && std::numeric_limits<uint64_t>::max() == *address) { 2117 CalculateFaultAddressFromInstruction(dump, address); 2118 } 2119 #endif // __linux__ 2120 } 2121 2122 return reason; 2123 } 2124 2125 // static 2126 string MinidumpProcessor::GetAssertion(Minidump* dump) { 2127 MinidumpAssertion* assertion = dump->GetAssertion(); 2128 if (!assertion) 2129 return ""; 2130 2131 const MDRawAssertionInfo* raw_assertion = assertion->assertion(); 2132 if (!raw_assertion) 2133 return ""; 2134 2135 string assertion_string; 2136 switch (raw_assertion->type) { 2137 case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER: 2138 assertion_string = "Invalid parameter passed to library function"; 2139 break; 2140 case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL: 2141 assertion_string = "Pure virtual function called"; 2142 break; 2143 default: { 2144 char assertion_type[32]; 2145 snprintf(assertion_type, sizeof(assertion_type), 2146 "0x%08x", raw_assertion->type); 2147 assertion_string = "Unknown assertion type "; 2148 assertion_string += assertion_type; 2149 break; 2150 } 2151 } 2152 2153 string expression = assertion->expression(); 2154 if (!expression.empty()) { 2155 assertion_string.append(" " + expression); 2156 } 2157 2158 string function = assertion->function(); 2159 if (!function.empty()) { 2160 assertion_string.append(" in function " + function); 2161 } 2162 2163 string file = assertion->file(); 2164 if (!file.empty()) { 2165 assertion_string.append(", in file " + file); 2166 } 2167 2168 if (raw_assertion->line != 0) { 2169 char assertion_line[32]; 2170 snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line); 2171 assertion_string.append(" at line "); 2172 assertion_string.append(assertion_line); 2173 } 2174 2175 return assertion_string; 2176 } 2177 2178 } // namespace google_breakpad