diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc | 1577 |
1 files changed, 0 insertions, 1577 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc deleted file mode 100644 index 33b4a1284..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc +++ /dev/null @@ -1,1577 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "google_breakpad/processor/minidump_processor.h" - -#include <assert.h> - -#include <string> - -#include "common/scoped_ptr.h" -#include "common/stdio_wrapper.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/exploitability.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "processor/logging.h" -#include "processor/stackwalker_x86.h" -#include "processor/symbolic_constants_win.h" - -namespace google_breakpad { - -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), - own_frame_symbolizer_(true), - enable_exploitability_(false), - enable_objdump_(false) { -} - -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver, - bool enable_exploitability) - : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), - own_frame_symbolizer_(true), - enable_exploitability_(enable_exploitability), - enable_objdump_(false) { -} - -MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer, - bool enable_exploitability) - : frame_symbolizer_(frame_symbolizer), - own_frame_symbolizer_(false), - enable_exploitability_(enable_exploitability), - enable_objdump_(false) { - assert(frame_symbolizer_); -} - -MinidumpProcessor::~MinidumpProcessor() { - if (own_frame_symbolizer_) delete frame_symbolizer_; -} - -ProcessResult MinidumpProcessor::Process( - Minidump *dump, ProcessState *process_state) { - assert(dump); - assert(process_state); - - process_state->Clear(); - - const MDRawHeader *header = dump->header(); - if (!header) { - BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; - return PROCESS_ERROR_NO_MINIDUMP_HEADER; - } - process_state->time_date_stamp_ = header->time_date_stamp; - - bool has_process_create_time = - GetProcessCreateTime(dump, &process_state->process_create_time_); - - bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_); - bool has_os_info = GetOSInfo(dump, &process_state->system_info_); - - uint32_t dump_thread_id = 0; - bool has_dump_thread = false; - uint32_t requesting_thread_id = 0; - bool has_requesting_thread = false; - - MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo(); - if (breakpad_info) { - has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); - has_requesting_thread = - breakpad_info->GetRequestingThreadID(&requesting_thread_id); - } - - MinidumpException *exception = dump->GetException(); - if (exception) { - process_state->crashed_ = true; - has_requesting_thread = exception->GetThreadID(&requesting_thread_id); - - process_state->crash_reason_ = GetCrashReason( - dump, &process_state->crash_address_); - } - - // This will just return an empty string if it doesn't exist. - process_state->assertion_ = GetAssertion(dump); - - MinidumpModuleList *module_list = dump->GetModuleList(); - - // Put a copy of the module list into ProcessState object. This is not - // necessarily a MinidumpModuleList, but it adheres to the CodeModules - // interface, which is all that ProcessState needs to expose. - if (module_list) { - process_state->modules_ = module_list->Copy(); - process_state->shrunk_range_modules_ = - process_state->modules_->GetShrunkRangeModules(); - for (unsigned int i = 0; - i < process_state->shrunk_range_modules_.size(); - i++) { - linked_ptr<const CodeModule> module = - process_state->shrunk_range_modules_[i]; - BPLOG(INFO) << "The range for module " << module->code_file() - << " was shrunk down by " << HexString( - module->shrink_down_delta()) << " bytes. "; - } - } - - MinidumpMemoryList *memory_list = dump->GetMemoryList(); - if (memory_list) { - BPLOG(INFO) << "Found " << memory_list->region_count() - << " memory regions."; - } - - MinidumpThreadList *threads = dump->GetThreadList(); - if (!threads) { - BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; - return PROCESS_ERROR_NO_THREAD_LIST; - } - - BPLOG(INFO) << "Minidump " << dump->path() << " has " << - (has_cpu_info ? "" : "no ") << "CPU info, " << - (has_os_info ? "" : "no ") << "OS info, " << - (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << - (exception != NULL ? "" : "no ") << "exception, " << - (module_list != NULL ? "" : "no ") << "module list, " << - (threads != NULL ? "" : "no ") << "thread list, " << - (has_dump_thread ? "" : "no ") << "dump thread, " << - (has_requesting_thread ? "" : "no ") << "requesting thread, and " << - (has_process_create_time ? "" : "no ") << "process create time"; - - bool interrupted = false; - bool found_requesting_thread = false; - unsigned int thread_count = threads->thread_count(); - - // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. - frame_symbolizer_->Reset(); - - for (unsigned int thread_index = 0; - thread_index < thread_count; - ++thread_index) { - char thread_string_buffer[64]; - snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", - thread_index, thread_count); - string thread_string = dump->path() + ":" + thread_string_buffer; - - MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); - if (!thread) { - BPLOG(ERROR) << "Could not get thread for " << thread_string; - return PROCESS_ERROR_GETTING_THREAD; - } - - uint32_t thread_id; - if (!thread->GetThreadID(&thread_id)) { - BPLOG(ERROR) << "Could not get thread ID for " << thread_string; - return PROCESS_ERROR_GETTING_THREAD_ID; - } - - thread_string += " id " + HexString(thread_id); - BPLOG(INFO) << "Looking at thread " << thread_string; - - // If this thread is the thread that produced the minidump, don't process - // it. Because of the problems associated with a thread producing a - // dump of itself (when both its context and its stack are in flux), - // processing that stack wouldn't provide much useful data. - if (has_dump_thread && thread_id == dump_thread_id) { - continue; - } - - MinidumpContext *context = thread->GetContext(); - - if (has_requesting_thread && thread_id == requesting_thread_id) { - if (found_requesting_thread) { - // There can't be more than one requesting thread. - BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; - return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS; - } - - // Use processed_state->threads_.size() instead of thread_index. - // thread_index points to the thread index in the minidump, which - // might be greater than the thread index in the threads vector if - // any of the minidump's threads are skipped and not placed into the - // processed threads vector. The thread vector's current size will - // be the index of the current thread when it's pushed into the - // vector. - process_state->requesting_thread_ = process_state->threads_.size(); - - found_requesting_thread = true; - - if (process_state->crashed_) { - // Use the exception record's context for the crashed thread, instead - // of the thread's own context. For the crashed thread, the thread's - // own context is the state inside the exception handler. Using it - // would not result in the expected stack trace from the time of the - // crash. If the exception context is invalid, however, we fall back - // on the thread context. - MinidumpContext *ctx = exception->GetContext(); - context = ctx ? ctx : thread->GetContext(); - } - } - - // If the memory region for the stack cannot be read using the RVA stored - // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use - // a memory region (containing the stack) from the minidump memory list. - MinidumpMemoryRegion *thread_memory = thread->GetMemory(); - if (!thread_memory && memory_list) { - uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange(); - if (start_stack_memory_range) { - thread_memory = memory_list->GetMemoryRegionForAddress( - start_stack_memory_range); - } - } - if (!thread_memory) { - BPLOG(ERROR) << "No memory region for " << thread_string; - } - - // Use process_state->modules_ instead of module_list, because the - // |modules| argument will be used to populate the |module| fields in - // the returned StackFrame objects, which will be placed into the - // returned ProcessState object. module_list's lifetime is only as - // long as the Minidump object: it will be deleted when this function - // returns. process_state->modules_ is owned by the ProcessState object - // (just like the StackFrame objects), and is much more suitable for this - // task. - scoped_ptr<Stackwalker> stackwalker( - Stackwalker::StackwalkerForCPU(process_state->system_info(), - context, - thread_memory, - process_state->modules_, - frame_symbolizer_)); - - scoped_ptr<CallStack> stack(new CallStack()); - if (stackwalker.get()) { - if (!stackwalker->Walk(stack.get(), - &process_state->modules_without_symbols_, - &process_state->modules_with_corrupt_symbols_)) { - BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " - << thread_string; - interrupted = true; - } - } else { - // Threads with missing CPU contexts will hit this, but - // don't abort processing the rest of the dump just for - // one bad thread. - BPLOG(ERROR) << "No stackwalker for " << thread_string; - } - stack->set_tid(thread_id); - process_state->threads_.push_back(stack.release()); - process_state->thread_memory_regions_.push_back(thread_memory); - } - - if (interrupted) { - BPLOG(INFO) << "Processing interrupted for " << dump->path(); - return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; - } - - // If a requesting thread was indicated, it must be present. - if (has_requesting_thread && !found_requesting_thread) { - // Don't mark as an error, but invalidate the requesting thread - BPLOG(ERROR) << "Minidump indicated requesting thread " << - HexString(requesting_thread_id) << ", not found in " << - dump->path(); - process_state->requesting_thread_ = -1; - } - - // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED - process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED; - - // If an exploitability run was requested we perform the platform specific - // rating. - if (enable_exploitability_) { - scoped_ptr<Exploitability> exploitability( - Exploitability::ExploitabilityForPlatform(dump, - process_state, - enable_objdump_)); - // The engine will be null if the platform is not supported - if (exploitability != NULL) { - process_state->exploitability_ = exploitability->CheckExploitability(); - } else { - process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE; - } - } - - BPLOG(INFO) << "Processed " << dump->path(); - return PROCESS_OK; -} - -ProcessResult MinidumpProcessor::Process( - const string &minidump_file, ProcessState *process_state) { - BPLOG(INFO) << "Processing minidump in file " << minidump_file; - - Minidump dump(minidump_file); - if (!dump.Read()) { - BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; - return PROCESS_ERROR_MINIDUMP_NOT_FOUND; - } - - return Process(&dump, process_state); -} - -// Returns the MDRawSystemInfo from a minidump, or NULL if system info is -// not available from the minidump. If system_info is non-NULL, it is used -// to pass back the MinidumpSystemInfo object. -static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, - MinidumpSystemInfo **system_info) { - MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); - if (!minidump_system_info) - return NULL; - - if (system_info) - *system_info = minidump_system_info; - - return minidump_system_info->system_info(); -} - -// Extract CPU info string from ARM-specific MDRawSystemInfo structure. -// raw_info: pointer to source MDRawSystemInfo. -// cpu_info: address of target string, cpu info text will be appended to it. -static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, - string* cpu_info) { - assert(raw_info != NULL && cpu_info != NULL); - - // Write ARM architecture version. - char cpu_string[32]; - snprintf(cpu_string, sizeof(cpu_string), "ARMv%d", - raw_info->processor_level); - cpu_info->append(cpu_string); - - // There is no good list of implementer id values, but the following - // pages provide some help: - // http://comments.gmane.org/gmane.linux.linaro.devel/6903 - // http://forum.xda-developers.com/archive/index.php/t-480226.html - const struct { - uint32_t id; - const char* name; - } vendors[] = { - { 0x41, "ARM" }, - { 0x51, "Qualcomm" }, - { 0x56, "Marvell" }, - { 0x69, "Intel/Marvell" }, - }; - const struct { - uint32_t id; - const char* name; - } parts[] = { - { 0x4100c050, "Cortex-A5" }, - { 0x4100c080, "Cortex-A8" }, - { 0x4100c090, "Cortex-A9" }, - { 0x4100c0f0, "Cortex-A15" }, - { 0x4100c140, "Cortex-R4" }, - { 0x4100c150, "Cortex-R5" }, - { 0x4100b360, "ARM1136" }, - { 0x4100b560, "ARM1156" }, - { 0x4100b760, "ARM1176" }, - { 0x4100b020, "ARM11-MPCore" }, - { 0x41009260, "ARM926" }, - { 0x41009460, "ARM946" }, - { 0x41009660, "ARM966" }, - { 0x510006f0, "Krait" }, - { 0x510000f0, "Scorpion" }, - }; - - const struct { - uint32_t hwcap; - const char* name; - } features[] = { - { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" }, - { MD_CPU_ARM_ELF_HWCAP_HALF, "half" }, - { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" }, - { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" }, - { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" }, - { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" }, - { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" }, - { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" }, - { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" }, - { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" }, - { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" }, - { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" }, - { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" }, - { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" }, - { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" }, - { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" }, - }; - - uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; - if (cpuid != 0) { - // Extract vendor name from CPUID - const char* vendor = NULL; - uint32_t vendor_id = (cpuid >> 24) & 0xff; - for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { - if (vendors[i].id == vendor_id) { - vendor = vendors[i].name; - break; - } - } - cpu_info->append(" "); - if (vendor) { - cpu_info->append(vendor); - } else { - snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id); - cpu_info->append(cpu_string); - } - - // Extract part name from CPUID - uint32_t part_id = (cpuid & 0xff00fff0); - const char* part = NULL; - for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { - if (parts[i].id == part_id) { - part = parts[i].name; - break; - } - } - cpu_info->append(" "); - if (part != NULL) { - cpu_info->append(part); - } else { - snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); - cpu_info->append(cpu_string); - } - } - uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps; - if (elf_hwcaps != 0) { - cpu_info->append(" features: "); - const char* comma = ""; - for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) { - if (elf_hwcaps & features[i].hwcap) { - cpu_info->append(comma); - cpu_info->append(features[i].name); - comma = ","; - } - } - } -} - -// static -bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { - assert(dump); - assert(info); - - info->cpu.clear(); - info->cpu_info.clear(); - - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); - if (!raw_system_info) - return false; - - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_X86: - case MD_CPU_ARCHITECTURE_AMD64: { - if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_X86) - info->cpu = "x86"; - else - info->cpu = "amd64"; - - const string *cpu_vendor = system_info->GetCPUVendor(); - if (cpu_vendor) { - info->cpu_info = *cpu_vendor; - info->cpu_info.append(" "); - } - - char x86_info[36]; - snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", - raw_system_info->processor_level, - raw_system_info->processor_revision >> 8, - raw_system_info->processor_revision & 0xff); - info->cpu_info.append(x86_info); - break; - } - - case MD_CPU_ARCHITECTURE_PPC: { - info->cpu = "ppc"; - break; - } - - case MD_CPU_ARCHITECTURE_PPC64: { - info->cpu = "ppc64"; - break; - } - - case MD_CPU_ARCHITECTURE_SPARC: { - info->cpu = "sparc"; - break; - } - - case MD_CPU_ARCHITECTURE_ARM: { - info->cpu = "arm"; - GetARMCpuInfo(raw_system_info, &info->cpu_info); - break; - } - - case MD_CPU_ARCHITECTURE_ARM64: { - info->cpu = "arm64"; - break; - } - - case MD_CPU_ARCHITECTURE_MIPS: { - info->cpu = "mips"; - break; - } - case MD_CPU_ARCHITECTURE_MIPS64: { - info->cpu = "mips64"; - break; - } - - default: { - // Assign the numeric architecture ID into the CPU string. - char cpu_string[7]; - snprintf(cpu_string, sizeof(cpu_string), "0x%04x", - raw_system_info->processor_architecture); - info->cpu = cpu_string; - break; - } - } - - info->cpu_count = raw_system_info->number_of_processors; - - return true; -} - -// static -bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { - assert(dump); - assert(info); - - info->os.clear(); - info->os_short.clear(); - info->os_version.clear(); - - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); - if (!raw_system_info) - return false; - - info->os_short = system_info->GetOS(); - - switch (raw_system_info->platform_id) { - case MD_OS_WIN32_NT: { - info->os = "Windows NT"; - break; - } - - case MD_OS_WIN32_WINDOWS: { - info->os = "Windows"; - break; - } - - case MD_OS_MAC_OS_X: { - info->os = "Mac OS X"; - break; - } - - case MD_OS_IOS: { - info->os = "iOS"; - break; - } - - case MD_OS_LINUX: { - info->os = "Linux"; - break; - } - - case MD_OS_SOLARIS: { - info->os = "Solaris"; - break; - } - - case MD_OS_ANDROID: { - info->os = "Android"; - break; - } - - case MD_OS_PS3: { - info->os = "PS3"; - break; - } - - case MD_OS_NACL: { - info->os = "NaCl"; - break; - } - - default: { - // Assign the numeric platform ID into the OS string. - char os_string[11]; - snprintf(os_string, sizeof(os_string), "0x%08x", - raw_system_info->platform_id); - info->os = os_string; - break; - } - } - - char os_version_string[33]; - snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", - raw_system_info->major_version, - raw_system_info->minor_version, - raw_system_info->build_number); - info->os_version = os_version_string; - - const string *csd_version = system_info->GetCSDVersion(); - if (csd_version) { - info->os_version.append(" "); - info->os_version.append(*csd_version); - } - - return true; -} - -// static -bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump, - uint32_t* process_create_time) { - assert(dump); - assert(process_create_time); - - *process_create_time = 0; - - MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo(); - if (!minidump_misc_info) { - return false; - } - - const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info(); - if (!md_raw_misc_info) { - return false; - } - - if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) { - return false; - } - - *process_create_time = md_raw_misc_info->process_create_time; - return true; -} - -// static -string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { - MinidumpException *exception = dump->GetException(); - if (!exception) - return ""; - - const MDRawExceptionStream *raw_exception = exception->exception(); - if (!raw_exception) - return ""; - - if (address) - *address = raw_exception->exception_record.exception_address; - - // The reason value is OS-specific and possibly CPU-specific. Set up - // sensible numeric defaults for the reason string in case we can't - // map the codes to a string (because there's no system info, or because - // it's an unrecognized platform, or because it's an unrecognized code.) - char reason_string[24]; - uint32_t exception_code = raw_exception->exception_record.exception_code; - uint32_t exception_flags = raw_exception->exception_record.exception_flags; - snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x", - exception_code, exception_flags); - string reason = reason_string; - - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL); - if (!raw_system_info) - return reason; - - switch (raw_system_info->platform_id) { - case MD_OS_MAC_OS_X: - case MD_OS_IOS: { - char flags_string[11]; - snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags); - switch (exception_code) { - case MD_EXCEPTION_MAC_BAD_ACCESS: - reason = "EXC_BAD_ACCESS / "; - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS: - reason.append("KERN_INVALID_ADDRESS"); - break; - case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE: - reason.append("KERN_PROTECTION_FAILURE"); - break; - case MD_EXCEPTION_CODE_MAC_NO_ACCESS: - reason.append("KERN_NO_ACCESS"); - break; - case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE: - reason.append("KERN_MEMORY_FAILURE"); - break; - case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR: - reason.append("KERN_MEMORY_ERROR"); - break; - default: - // arm and ppc overlap - if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_ARM || - raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_ARM64) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: - reason.append("EXC_ARM_DA_ALIGN"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: - reason.append("EXC_ARM_DA_DEBUG"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_PPC) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ: - reason.append("EXC_PPC_VM_PROT_READ"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE: - reason.append("EXC_PPC_BADSPACE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED: - reason.append("EXC_PPC_UNALIGNED"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_X86 || - raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_AMD64) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: - reason.append("EXC_I386_GPFLT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else { - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - } - break; - } - break; - case MD_EXCEPTION_MAC_BAD_INSTRUCTION: - reason = "EXC_BAD_INSTRUCTION / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_ARM: - case MD_CPU_ARCHITECTURE_ARM64: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED: - reason.append("EXC_ARM_UNDEFINED"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL: - reason.append("EXC_PPC_INVALID_SYSCALL"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION: - reason.append("EXC_PPC_UNIPL_INST"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION: - reason.append("EXC_PPC_PRIVINST"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER: - reason.append("EXC_PPC_PRIVREG"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_TRACE: - reason.append("EXC_PPC_TRACE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR: - reason.append("EXC_PPC_PERFMON"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION: - reason.append("EXC_I386_INVOP"); - break; - case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT: - reason.append("EXC_I386_INVTSSFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT: - reason.append("EXC_I386_SEGNPFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT: - reason.append("EXC_I386_STKFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: - reason.append("EXC_I386_GPFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT: - reason.append("EXC_I386_ALIGNFLT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_ARITHMETIC: - reason = "EXC_ARITHMETIC / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW: - reason.append("EXC_PPC_OVERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE: - reason.append("EXC_PPC_ZERO_DIVIDE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT: - reason.append("EXC_FLT_INEXACT"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE: - reason.append("EXC_PPC_FLT_ZERO_DIVIDE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW: - reason.append("EXC_PPC_FLT_UNDERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW: - reason.append("EXC_PPC_FLT_OVERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER: - reason.append("EXC_PPC_FLT_NOT_A_NUMBER"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION: - reason.append("EXC_PPC_NOEMULATION"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST: - reason.append("EXC_PPC_ALTIVECASSIST"); - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_DIV: - reason.append("EXC_I386_DIV"); - break; - case MD_EXCEPTION_CODE_MAC_X86_INTO: - reason.append("EXC_I386_INTO"); - break; - case MD_EXCEPTION_CODE_MAC_X86_NOEXT: - reason.append("EXC_I386_NOEXT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EXTOVR: - reason.append("EXC_I386_EXTOVR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EXTERR: - reason.append("EXC_I386_EXTERR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EMERR: - reason.append("EXC_I386_EMERR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_BOUND: - reason.append("EXC_I386_BOUND"); - break; - case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR: - reason.append("EXC_I386_SSEEXTERR"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_EMULATION: - reason = "EXC_EMULATION / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_SOFTWARE: - reason = "EXC_SOFTWARE / "; - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ABORT: - reason.append("SIGABRT"); - break; - case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION: - reason.append("UNCAUGHT_NS_EXCEPTION"); - break; - // These are ppc only but shouldn't be a problem as they're - // unused on x86 - case MD_EXCEPTION_CODE_MAC_PPC_TRAP: - reason.append("EXC_PPC_TRAP"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE: - reason.append("EXC_PPC_MIGRATE"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_BREAKPOINT: - reason = "EXC_BREAKPOINT / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_ARM: - case MD_CPU_ARCHITECTURE_ARM64: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: - reason.append("EXC_ARM_DA_ALIGN"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: - reason.append("EXC_ARM_DA_DEBUG"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT: - reason.append("EXC_ARM_BREAKPOINT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT: - reason.append("EXC_PPC_BREAKPOINT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_SGL: - reason.append("EXC_I386_SGL"); - break; - case MD_EXCEPTION_CODE_MAC_X86_BPT: - reason.append("EXC_I386_BPT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_SYSCALL: - reason = "EXC_SYSCALL / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_MACH_SYSCALL: - reason = "EXC_MACH_SYSCALL / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_RPC_ALERT: - reason = "EXC_RPC_ALERT / "; - reason.append(flags_string); - break; - } - break; - } - - case MD_OS_WIN32_NT: - case MD_OS_WIN32_WINDOWS: { - switch (exception_code) { - case MD_EXCEPTION_CODE_WIN_CONTROL_C: - reason = "DBG_CONTROL_C"; - break; - case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: - reason = "EXCEPTION_GUARD_PAGE"; - break; - case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT: - reason = "EXCEPTION_DATATYPE_MISALIGNMENT"; - break; - case MD_EXCEPTION_CODE_WIN_BREAKPOINT: - reason = "EXCEPTION_BREAKPOINT"; - break; - case MD_EXCEPTION_CODE_WIN_SINGLE_STEP: - reason = "EXCEPTION_SINGLE_STEP"; - break; - case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: - // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that - // caused the fault in exception_information[1]. - // exception_information[0] is 0 if the violation was caused by - // an attempt to read data, 1 if it was an attempt to write data, - // and 8 if this was a data execution violation. - // This information is useful in addition to the code address, which - // will be present in the crash thread's instruction field anyway. - if (raw_exception->exception_record.number_parameters >= 1) { - MDAccessViolationTypeWin av_type = - static_cast<MDAccessViolationTypeWin> - (raw_exception->exception_record.exception_information[0]); - switch (av_type) { - case MD_ACCESS_VIOLATION_WIN_READ: - reason = "EXCEPTION_ACCESS_VIOLATION_READ"; - break; - case MD_ACCESS_VIOLATION_WIN_WRITE: - reason = "EXCEPTION_ACCESS_VIOLATION_WRITE"; - break; - case MD_ACCESS_VIOLATION_WIN_EXEC: - reason = "EXCEPTION_ACCESS_VIOLATION_EXEC"; - break; - default: - reason = "EXCEPTION_ACCESS_VIOLATION"; - break; - } - } else { - reason = "EXCEPTION_ACCESS_VIOLATION"; - } - if (address && - raw_exception->exception_record.number_parameters >= 2) { - *address = - raw_exception->exception_record.exception_information[1]; - } - break; - case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: - // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that - // caused the fault in exception_information[1]. - // exception_information[0] is 0 if the violation was caused by - // an attempt to read data, 1 if it was an attempt to write data, - // and 8 if this was a data execution violation. - // exception_information[2] contains the underlying NTSTATUS code, - // which is the explanation for why this error occured. - // This information is useful in addition to the code address, which - // will be present in the crash thread's instruction field anyway. - if (raw_exception->exception_record.number_parameters >= 1) { - MDInPageErrorTypeWin av_type = - static_cast<MDInPageErrorTypeWin> - (raw_exception->exception_record.exception_information[0]); - switch (av_type) { - case MD_IN_PAGE_ERROR_WIN_READ: - reason = "EXCEPTION_IN_PAGE_ERROR_READ"; - break; - case MD_IN_PAGE_ERROR_WIN_WRITE: - reason = "EXCEPTION_IN_PAGE_ERROR_WRITE"; - break; - case MD_IN_PAGE_ERROR_WIN_EXEC: - reason = "EXCEPTION_IN_PAGE_ERROR_EXEC"; - break; - default: - reason = "EXCEPTION_IN_PAGE_ERROR"; - break; - } - } else { - reason = "EXCEPTION_IN_PAGE_ERROR"; - } - if (address && - raw_exception->exception_record.number_parameters >= 2) { - *address = - raw_exception->exception_record.exception_information[1]; - } - if (raw_exception->exception_record.number_parameters >= 3) { - uint32_t ntstatus = - static_cast<uint32_t> - (raw_exception->exception_record.exception_information[2]); - reason.append(" / "); - reason.append(NTStatusToString(ntstatus)); - } - break; - case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE: - reason = "EXCEPTION_INVALID_HANDLE"; - break; - case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: - reason = "EXCEPTION_ILLEGAL_INSTRUCTION"; - break; - case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: - reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; - break; - case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: - reason = "EXCEPTION_INVALID_DISPOSITION"; - break; - case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED: - reason = "EXCEPTION_BOUNDS_EXCEEDED"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND: - reason = "EXCEPTION_FLT_DENORMAL_OPERAND"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: - reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: - reason = "EXCEPTION_FLT_INEXACT_RESULT"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: - reason = "EXCEPTION_FLT_INVALID_OPERATION"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: - reason = "EXCEPTION_FLT_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK: - reason = "EXCEPTION_FLT_STACK_CHECK"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: - reason = "EXCEPTION_FLT_UNDERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: - reason = "EXCEPTION_INT_DIVIDE_BY_ZERO"; - break; - case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: - reason = "EXCEPTION_INT_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: - reason = "EXCEPTION_PRIV_INSTRUCTION"; - break; - case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: - reason = "EXCEPTION_STACK_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: - reason = "EXCEPTION_POSSIBLE_DEADLOCK"; - break; - case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: - reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; - break; - case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: - reason = "EXCEPTION_HEAP_CORRUPTION"; - break; - case MD_EXCEPTION_OUT_OF_MEMORY: - reason = "Out of Memory"; - break; - case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION: - reason = "Unhandled C++ Exception"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_ANDROID: - case MD_OS_LINUX: { - switch (exception_code) { - case MD_EXCEPTION_CODE_LIN_SIGHUP: - reason = "SIGHUP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGINT: - reason = "SIGINT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGQUIT: - reason = "SIGQUIT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGILL: - reason = "SIGILL"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTRAP: - reason = "SIGTRAP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGABRT: - reason = "SIGABRT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGBUS: - reason = "SIGBUS"; - break; - case MD_EXCEPTION_CODE_LIN_SIGFPE: - reason = "SIGFPE"; - break; - case MD_EXCEPTION_CODE_LIN_SIGKILL: - reason = "SIGKILL"; - break; - case MD_EXCEPTION_CODE_LIN_SIGUSR1: - reason = "SIGUSR1"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSEGV: - reason = "SIGSEGV"; - break; - case MD_EXCEPTION_CODE_LIN_SIGUSR2: - reason = "SIGUSR2"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPIPE: - reason = "SIGPIPE"; - break; - case MD_EXCEPTION_CODE_LIN_SIGALRM: - reason = "SIGALRM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTERM: - reason = "SIGTERM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: - reason = "SIGSTKFLT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGCHLD: - reason = "SIGCHLD"; - break; - case MD_EXCEPTION_CODE_LIN_SIGCONT: - reason = "SIGCONT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSTOP: - reason = "SIGSTOP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTSTP: - reason = "SIGTSTP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTTIN: - reason = "SIGTTIN"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTTOU: - reason = "SIGTTOU"; - break; - case MD_EXCEPTION_CODE_LIN_SIGURG: - reason = "SIGURG"; - break; - case MD_EXCEPTION_CODE_LIN_SIGXCPU: - reason = "SIGXCPU"; - break; - case MD_EXCEPTION_CODE_LIN_SIGXFSZ: - reason = "SIGXFSZ"; - break; - case MD_EXCEPTION_CODE_LIN_SIGVTALRM: - reason = "SIGVTALRM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPROF: - reason = "SIGPROF"; - break; - case MD_EXCEPTION_CODE_LIN_SIGWINCH: - reason = "SIGWINCH"; - break; - case MD_EXCEPTION_CODE_LIN_SIGIO: - reason = "SIGIO"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPWR: - reason = "SIGPWR"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSYS: - reason = "SIGSYS"; - break; - case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: - reason = "DUMP_REQUESTED"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_SOLARIS: { - switch (exception_code) { - case MD_EXCEPTION_CODE_SOL_SIGHUP: - reason = "SIGHUP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGINT: - reason = "SIGINT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGQUIT: - reason = "SIGQUIT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGILL: - reason = "SIGILL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTRAP: - reason = "SIGTRAP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGIOT: - reason = "SIGIOT | SIGABRT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGEMT: - reason = "SIGEMT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGFPE: - reason = "SIGFPE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGKILL: - reason = "SIGKILL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGBUS: - reason = "SIGBUS"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSEGV: - reason = "SIGSEGV"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSYS: - reason = "SIGSYS"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPIPE: - reason = "SIGPIPE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGALRM: - reason = "SIGALRM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTERM: - reason = "SIGTERM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGUSR1: - reason = "SIGUSR1"; - break; - case MD_EXCEPTION_CODE_SOL_SIGUSR2: - reason = "SIGUSR2"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCLD: - reason = "SIGCLD | SIGCHLD"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPWR: - reason = "SIGPWR"; - break; - case MD_EXCEPTION_CODE_SOL_SIGWINCH: - reason = "SIGWINCH"; - break; - case MD_EXCEPTION_CODE_SOL_SIGURG: - reason = "SIGURG"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPOLL: - reason = "SIGPOLL | SIGIO"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSTOP: - reason = "SIGSTOP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTSTP: - reason = "SIGTSTP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCONT: - reason = "SIGCONT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTTIN: - reason = "SIGTTIN"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTTOU: - reason = "SIGTTOU"; - break; - case MD_EXCEPTION_CODE_SOL_SIGVTALRM: - reason = "SIGVTALRM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPROF: - reason = "SIGPROF"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXCPU: - reason = "SIGXCPU"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXFSZ: - reason = "SIGXFSZ"; - break; - case MD_EXCEPTION_CODE_SOL_SIGWAITING: - reason = "SIGWAITING"; - break; - case MD_EXCEPTION_CODE_SOL_SIGLWP: - reason = "SIGLWP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGFREEZE: - reason = "SIGFREEZE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTHAW: - reason = "SIGTHAW"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCANCEL: - reason = "SIGCANCEL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGLOST: - reason = "SIGLOST"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXRES: - reason = "SIGXRES"; - break; - case MD_EXCEPTION_CODE_SOL_SIGJVM1: - reason = "SIGJVM1"; - break; - case MD_EXCEPTION_CODE_SOL_SIGJVM2: - reason = "SIGJVM2"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_PS3: { - switch (exception_code) { - case MD_EXCEPTION_CODE_PS3_UNKNOWN: - reason = "UNKNOWN"; - break; - case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP: - reason = "TRAP_EXCEP"; - break; - case MD_EXCEPTION_CODE_PS3_PRIV_INSTR: - reason = "PRIV_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR: - reason = "ILLEGAL_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE: - reason = "INSTR_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT: - reason = "INSTR_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_DATA_STORAGE: - reason = "DATA_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT: - reason = "DATA_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_FLOAT_POINT: - reason = "FLOAT_POINT"; - break; - case MD_EXCEPTION_CODE_PS3_DABR_MATCH: - reason = "DABR_MATCH"; - break; - case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP: - reason = "ALIGN_EXCEP"; - break; - case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS: - reason = "MEMORY_ACCESS"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN: - reason = "COPRO_ALIGN"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM: - reason = "COPRO_INVALID_COM"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_ERR: - reason = "COPRO_ERR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_FIR: - reason = "COPRO_FIR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT: - reason = "COPRO_DATA_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE: - reason = "COPRO_DATA_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR: - reason = "COPRO_STOP_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR: - reason = "COPRO_HALT_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN: - reason = "COPRO_HALTINSTR_UNKNOWN"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS: - reason = "COPRO_MEMORY_ACCESS"; - break; - case MD_EXCEPTION_CODE_PS3_GRAPHIC: - reason = "GRAPHIC"; - break; - default: - BPLOG(INFO) << "Unknown exception reason "<< reason; - break; - } - break; - } - - default: { - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } - - return reason; -} - -// static -string MinidumpProcessor::GetAssertion(Minidump *dump) { - MinidumpAssertion *assertion = dump->GetAssertion(); - if (!assertion) - return ""; - - const MDRawAssertionInfo *raw_assertion = assertion->assertion(); - if (!raw_assertion) - return ""; - - string assertion_string; - switch (raw_assertion->type) { - case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER: - assertion_string = "Invalid parameter passed to library function"; - break; - case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL: - assertion_string = "Pure virtual function called"; - break; - default: { - char assertion_type[32]; - snprintf(assertion_type, sizeof(assertion_type), - "0x%08x", raw_assertion->type); - assertion_string = "Unknown assertion type "; - assertion_string += assertion_type; - break; - } - } - - string expression = assertion->expression(); - if (!expression.empty()) { - assertion_string.append(" " + expression); - } - - string function = assertion->function(); - if (!function.empty()) { - assertion_string.append(" in function " + function); - } - - string file = assertion->file(); - if (!file.empty()) { - assertion_string.append(", in file " + file); - } - - if (raw_assertion->line != 0) { - char assertion_line[32]; - snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line); - assertion_string.append(" at line "); - assertion_string.append(assertion_line); - } - - return assertion_string; -} - -} // namespace google_breakpad |