toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006, Google Inc.
     2 // All rights reserved.
     3 //
     4 // Redistribution and use in source and binary forms, with or without
     5 // modification, are permitted provided that the following conditions are
     6 // met:
     7 //
     8 //     * Redistributions of source code must retain the above copyright
     9 // notice, this list of conditions and the following disclaimer.
    10 //     * Redistributions in binary form must reproduce the above
    11 // copyright notice, this list of conditions and the following disclaimer
    12 // in the documentation and/or other materials provided with the
    13 // distribution.
    14 //     * Neither the name of Google Inc. nor the names of its
    15 // contributors may be used to endorse or promote products derived from
    16 // this software without specific prior written permission.
    17 //
    18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    30 #include "google_breakpad/processor/minidump_processor.h"
    32 #include <assert.h>
    33 #include <stdio.h>
    35 #include "common/scoped_ptr.h"
    36 #include "google_breakpad/processor/call_stack.h"
    37 #include "google_breakpad/processor/minidump.h"
    38 #include "google_breakpad/processor/process_state.h"
    39 #include "google_breakpad/processor/exploitability.h"
    40 #include "google_breakpad/processor/stack_frame_symbolizer.h"
    41 #include "processor/logging.h"
    42 #include "processor/stackwalker_x86.h"
    44 namespace google_breakpad {
    46 MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
    47                                      SourceLineResolverInterface *resolver)
    48     : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
    49       own_frame_symbolizer_(true),
    50       enable_exploitability_(false) {
    51 }
    53 MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
    54                                      SourceLineResolverInterface *resolver,
    55                                      bool enable_exploitability)
    56     : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
    57       own_frame_symbolizer_(true),
    58       enable_exploitability_(enable_exploitability) {
    59 }
    61 MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer,
    62                                      bool enable_exploitability)
    63     : frame_symbolizer_(frame_symbolizer),
    64       own_frame_symbolizer_(false),
    65       enable_exploitability_(enable_exploitability) {
    66   assert(frame_symbolizer_);
    67 }
    69 MinidumpProcessor::~MinidumpProcessor() {
    70   if (own_frame_symbolizer_) delete frame_symbolizer_;
    71 }
    73 ProcessResult MinidumpProcessor::Process(
    74     Minidump *dump, ProcessState *process_state) {
    75   assert(dump);
    76   assert(process_state);
    78   process_state->Clear();
    80   const MDRawHeader *header = dump->header();
    81   if (!header) {
    82     BPLOG(ERROR) << "Minidump " << dump->path() << " has no header";
    83     return PROCESS_ERROR_NO_MINIDUMP_HEADER;
    84   }
    85   process_state->time_date_stamp_ = header->time_date_stamp;
    87   bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
    88   bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
    90   uint32_t dump_thread_id = 0;
    91   bool has_dump_thread = false;
    92   uint32_t requesting_thread_id = 0;
    93   bool has_requesting_thread = false;
    95   MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo();
    96   if (breakpad_info) {
    97     has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id);
    98     has_requesting_thread =
    99         breakpad_info->GetRequestingThreadID(&requesting_thread_id);
   100   }
   102   MinidumpException *exception = dump->GetException();
   103   if (exception) {
   104     process_state->crashed_ = true;
   105     has_requesting_thread = exception->GetThreadID(&requesting_thread_id);
   107     process_state->crash_reason_ = GetCrashReason(
   108         dump, &process_state->crash_address_);
   109   }
   111   // This will just return an empty string if it doesn't exist.
   112   process_state->assertion_ = GetAssertion(dump);
   114   MinidumpModuleList *module_list = dump->GetModuleList();
   116   // Put a copy of the module list into ProcessState object.  This is not
   117   // necessarily a MinidumpModuleList, but it adheres to the CodeModules
   118   // interface, which is all that ProcessState needs to expose.
   119   if (module_list)
   120     process_state->modules_ = module_list->Copy();
   122   MinidumpThreadList *threads = dump->GetThreadList();
   123   if (!threads) {
   124     BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list";
   125     return PROCESS_ERROR_NO_THREAD_LIST;
   126   }
   128   BPLOG(INFO) << "Minidump " << dump->path() << " has " <<
   129       (has_cpu_info           ? "" : "no ") << "CPU info, " <<
   130       (has_os_info            ? "" : "no ") << "OS info, " <<
   131       (breakpad_info != NULL  ? "" : "no ") << "Breakpad info, " <<
   132       (exception != NULL      ? "" : "no ") << "exception, " <<
   133       (module_list != NULL    ? "" : "no ") << "module list, " <<
   134       (threads != NULL        ? "" : "no ") << "thread list, " <<
   135       (has_dump_thread        ? "" : "no ") << "dump thread, and " <<
   136       (has_requesting_thread  ? "" : "no ") << "requesting thread";
   138   bool interrupted = false;
   139   bool found_requesting_thread = false;
   140   unsigned int thread_count = threads->thread_count();
   142   // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump.
   143   frame_symbolizer_->Reset();
   145   for (unsigned int thread_index = 0;
   146        thread_index < thread_count;
   147        ++thread_index) {
   148     char thread_string_buffer[64];
   149     snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d",
   150              thread_index, thread_count);
   151     string thread_string = dump->path() + ":" + thread_string_buffer;
   153     MinidumpThread *thread = threads->GetThreadAtIndex(thread_index);
   154     if (!thread) {
   155       BPLOG(ERROR) << "Could not get thread for " << thread_string;
   156       return PROCESS_ERROR_GETTING_THREAD;
   157     }
   159     uint32_t thread_id;
   160     if (!thread->GetThreadID(&thread_id)) {
   161       BPLOG(ERROR) << "Could not get thread ID for " << thread_string;
   162       return PROCESS_ERROR_GETTING_THREAD_ID;
   163     }
   165     thread_string += " id " + HexString(thread_id);
   166     BPLOG(INFO) << "Looking at thread " << thread_string;
   168     // If this thread is the thread that produced the minidump, don't process
   169     // it.  Because of the problems associated with a thread producing a
   170     // dump of itself (when both its context and its stack are in flux),
   171     // processing that stack wouldn't provide much useful data.
   172     if (has_dump_thread && thread_id == dump_thread_id) {
   173       continue;
   174     }
   176     MinidumpContext *context = thread->GetContext();
   178     if (has_requesting_thread && thread_id == requesting_thread_id) {
   179       if (found_requesting_thread) {
   180         // There can't be more than one requesting thread.
   181         BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string;
   182         return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS;
   183       }
   185       // Use processed_state->threads_.size() instead of thread_index.
   186       // thread_index points to the thread index in the minidump, which
   187       // might be greater than the thread index in the threads vector if
   188       // any of the minidump's threads are skipped and not placed into the
   189       // processed threads vector.  The thread vector's current size will
   190       // be the index of the current thread when it's pushed into the
   191       // vector.
   192       process_state->requesting_thread_ = process_state->threads_.size();
   194       found_requesting_thread = true;
   196       if (process_state->crashed_) {
   197         // Use the exception record's context for the crashed thread, instead
   198         // of the thread's own context.  For the crashed thread, the thread's
   199         // own context is the state inside the exception handler.  Using it
   200         // would not result in the expected stack trace from the time of the
   201         // crash. If the exception context is invalid, however, we fall back
   202         // on the thread context.
   203         MinidumpContext *ctx = exception->GetContext();
   204         context = ctx ? ctx : thread->GetContext();
   205       }
   206     }
   208     MinidumpMemoryRegion *thread_memory = thread->GetMemory();
   209     if (!thread_memory) {
   210       BPLOG(ERROR) << "No memory region for " << thread_string;
   211     }
   213     // Use process_state->modules_ instead of module_list, because the
   214     // |modules| argument will be used to populate the |module| fields in
   215     // the returned StackFrame objects, which will be placed into the
   216     // returned ProcessState object.  module_list's lifetime is only as
   217     // long as the Minidump object: it will be deleted when this function
   218     // returns.  process_state->modules_ is owned by the ProcessState object
   219     // (just like the StackFrame objects), and is much more suitable for this
   220     // task.
   221     scoped_ptr<Stackwalker> stackwalker(
   222         Stackwalker::StackwalkerForCPU(process_state->system_info(),
   223                                        context,
   224                                        thread_memory,
   225                                        process_state->modules_,
   226                                        frame_symbolizer_));
   228     scoped_ptr<CallStack> stack(new CallStack());
   229     if (stackwalker.get()) {
   230       if (!stackwalker->Walk(stack.get(),
   231                              &process_state->modules_without_symbols_)) {
   232         BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
   233                     << thread_string;
   234         interrupted = true;
   235       }
   236     } else {
   237       // Threads with missing CPU contexts will hit this, but
   238       // don't abort processing the rest of the dump just for
   239       // one bad thread.
   240       BPLOG(ERROR) << "No stackwalker for " << thread_string;
   241     }
   242     process_state->threads_.push_back(stack.release());
   243     process_state->thread_memory_regions_.push_back(thread_memory);
   244   }
   246   if (interrupted) {
   247     BPLOG(INFO) << "Processing interrupted for " << dump->path();
   248     return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
   249   }
   251   // If a requesting thread was indicated, it must be present.
   252   if (has_requesting_thread && !found_requesting_thread) {
   253     // Don't mark as an error, but invalidate the requesting thread
   254     BPLOG(ERROR) << "Minidump indicated requesting thread " <<
   255         HexString(requesting_thread_id) << ", not found in " <<
   256         dump->path();
   257     process_state->requesting_thread_ = -1;
   258   }
   260   // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED
   261   process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED;
   263   // If an exploitability run was requested we perform the platform specific
   264   // rating.
   265   if (enable_exploitability_) {
   266     scoped_ptr<Exploitability> exploitability(
   267         Exploitability::ExploitabilityForPlatform(dump, process_state));
   268     // The engine will be null if the platform is not supported
   269     if (exploitability != NULL) {
   270       process_state->exploitability_ = exploitability->CheckExploitability();
   271     } else {
   272       process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE;
   273     }
   274   }
   276   BPLOG(INFO) << "Processed " << dump->path();
   277   return PROCESS_OK;
   278 }
   280 ProcessResult MinidumpProcessor::Process(
   281     const string &minidump_file, ProcessState *process_state) {
   282   BPLOG(INFO) << "Processing minidump in file " << minidump_file;
   284   Minidump dump(minidump_file);
   285   if (!dump.Read()) {
   286      BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
   287      return PROCESS_ERROR_MINIDUMP_NOT_FOUND;
   288   }
   290   return Process(&dump, process_state);
   291 }
   293 // Returns the MDRawSystemInfo from a minidump, or NULL if system info is
   294 // not available from the minidump.  If system_info is non-NULL, it is used
   295 // to pass back the MinidumpSystemInfo object.
   296 static const MDRawSystemInfo* GetSystemInfo(Minidump *dump,
   297                                             MinidumpSystemInfo **system_info) {
   298   MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo();
   299   if (!minidump_system_info)
   300     return NULL;
   302   if (system_info)
   303     *system_info = minidump_system_info;
   305   return minidump_system_info->system_info();
   306 }
   308 // static
   309 bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) {
   310   assert(dump);
   311   assert(info);
   313   info->cpu.clear();
   314   info->cpu_info.clear();
   316   MinidumpSystemInfo *system_info;
   317   const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
   318   if (!raw_system_info)
   319     return false;
   321   switch (raw_system_info->processor_architecture) {
   322     case MD_CPU_ARCHITECTURE_X86:
   323     case MD_CPU_ARCHITECTURE_AMD64: {
   324       if (raw_system_info->processor_architecture ==
   325           MD_CPU_ARCHITECTURE_X86)
   326         info->cpu = "x86";
   327       else
   328         info->cpu = "amd64";
   330       const string *cpu_vendor = system_info->GetCPUVendor();
   331       if (cpu_vendor) {
   332         info->cpu_info = *cpu_vendor;
   333         info->cpu_info.append(" ");
   334       }
   336       char x86_info[36];
   337       snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u",
   338                raw_system_info->processor_level,
   339                raw_system_info->processor_revision >> 8,
   340                raw_system_info->processor_revision & 0xff);
   341       info->cpu_info.append(x86_info);
   342       break;
   343     }
   345     case MD_CPU_ARCHITECTURE_PPC: {
   346       info->cpu = "ppc";
   347       break;
   348     }
   350     case MD_CPU_ARCHITECTURE_SPARC: {
   351       info->cpu = "sparc";
   352       break;
   353     }
   355     case MD_CPU_ARCHITECTURE_ARM: {
   356       info->cpu = "arm";
   357       break;
   358     }
   360     default: {
   361       // Assign the numeric architecture ID into the CPU string.
   362       char cpu_string[7];
   363       snprintf(cpu_string, sizeof(cpu_string), "0x%04x",
   364                raw_system_info->processor_architecture);
   365       info->cpu = cpu_string;
   366       break;
   367     }
   368   }
   370   info->cpu_count = raw_system_info->number_of_processors;
   372   return true;
   373 }
   375 // static
   376 bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) {
   377   assert(dump);
   378   assert(info);
   380   info->os.clear();
   381   info->os_short.clear();
   382   info->os_version.clear();
   384   MinidumpSystemInfo *system_info;
   385   const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
   386   if (!raw_system_info)
   387     return false;
   389   info->os_short = system_info->GetOS();
   391   switch (raw_system_info->platform_id) {
   392     case MD_OS_WIN32_NT: {
   393       info->os = "Windows NT";
   394       break;
   395     }
   397     case MD_OS_WIN32_WINDOWS: {
   398       info->os = "Windows";
   399       break;
   400     }
   402     case MD_OS_MAC_OS_X: {
   403       info->os = "Mac OS X";
   404       break;
   405     }
   407     case MD_OS_IOS: {
   408       info->os = "iOS";
   409       break;
   410     }
   412     case MD_OS_LINUX: {
   413       info->os = "Linux";
   414       break;
   415     }
   417     case MD_OS_SOLARIS: {
   418       info->os = "Solaris";
   419       break;
   420     }
   422     case MD_OS_ANDROID: {
   423       info->os = "Android";
   424       break;
   425     }
   427     default: {
   428       // Assign the numeric platform ID into the OS string.
   429       char os_string[11];
   430       snprintf(os_string, sizeof(os_string), "0x%08x",
   431                raw_system_info->platform_id);
   432       info->os = os_string;
   433       break;
   434     }
   435   }
   437   char os_version_string[33];
   438   snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u",
   439            raw_system_info->major_version,
   440            raw_system_info->minor_version,
   441            raw_system_info->build_number);
   442   info->os_version = os_version_string;
   444   const string *csd_version = system_info->GetCSDVersion();
   445   if (csd_version) {
   446     info->os_version.append(" ");
   447     info->os_version.append(*csd_version);
   448   }
   450   return true;
   451 }
   453 // static
   454 string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
   455   MinidumpException *exception = dump->GetException();
   456   if (!exception)
   457     return "";
   459   const MDRawExceptionStream *raw_exception = exception->exception();
   460   if (!raw_exception)
   461     return "";
   463   if (address)
   464     *address = raw_exception->exception_record.exception_address;
   466   // The reason value is OS-specific and possibly CPU-specific.  Set up
   467   // sensible numeric defaults for the reason string in case we can't
   468   // map the codes to a string (because there's no system info, or because
   469   // it's an unrecognized platform, or because it's an unrecognized code.)
   470   char reason_string[24];
   471   uint32_t exception_code = raw_exception->exception_record.exception_code;
   472   uint32_t exception_flags = raw_exception->exception_record.exception_flags;
   473   snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x",
   474            exception_code, exception_flags);
   475   string reason = reason_string;
   477   const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL);
   478   if (!raw_system_info)
   479     return reason;
   481   switch (raw_system_info->platform_id) {
   482     case MD_OS_MAC_OS_X:
   483     case MD_OS_IOS: {
   484       char flags_string[11];
   485       snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags);
   486       switch (exception_code) {
   487         case MD_EXCEPTION_MAC_BAD_ACCESS:
   488           reason = "EXC_BAD_ACCESS / ";
   489           switch (exception_flags) {
   490             case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS:
   491               reason.append("KERN_INVALID_ADDRESS");
   492               break;
   493             case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE:
   494               reason.append("KERN_PROTECTION_FAILURE");
   495               break;
   496             case MD_EXCEPTION_CODE_MAC_NO_ACCESS:
   497               reason.append("KERN_NO_ACCESS");
   498               break;
   499             case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE:
   500               reason.append("KERN_MEMORY_FAILURE");
   501               break;
   502             case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR:
   503               reason.append("KERN_MEMORY_ERROR");
   504               break;
   505             default:
   506               // arm and ppc overlap
   507               if (raw_system_info->processor_architecture ==
   508                   MD_CPU_ARCHITECTURE_ARM) {
   509                 switch (exception_flags) {
   510                   case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
   511                     reason.append("EXC_ARM_DA_ALIGN");
   512                     break;
   513                   case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
   514                     reason.append("EXC_ARM_DA_DEBUG");
   515                     break;
   516                   default:
   517                     reason.append(flags_string);
   518                     BPLOG(INFO) << "Unknown exception reason " << reason;
   519                     break;
   520                 }
   521               } else if (raw_system_info->processor_architecture ==
   522                          MD_CPU_ARCHITECTURE_PPC) {
   523                 switch (exception_flags) {
   524                   case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
   525                     reason.append("EXC_PPC_VM_PROT_READ");
   526                     break;
   527                   case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
   528                     reason.append("EXC_PPC_BADSPACE");
   529                     break;
   530                   case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
   531                     reason.append("EXC_PPC_UNALIGNED");
   532                     break;
   533                   default:
   534                     reason.append(flags_string);
   535                     BPLOG(INFO) << "Unknown exception reason " << reason;
   536                     break;
   537                 }
   538               } else {
   539                 reason.append(flags_string);
   540                 BPLOG(INFO) << "Unknown exception reason " << reason;
   541               }
   542               break;
   543           }
   544           break;
   545         case MD_EXCEPTION_MAC_BAD_INSTRUCTION:
   546           reason = "EXC_BAD_INSTRUCTION / ";
   547           switch (raw_system_info->processor_architecture) {
   548             case MD_CPU_ARCHITECTURE_ARM: {
   549               switch (exception_flags) {
   550                 case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED:
   551                   reason.append("EXC_ARM_UNDEFINED");
   552                   break;
   553                 default:
   554                   reason.append(flags_string);
   555                   BPLOG(INFO) << "Unknown exception reason " << reason;
   556                   break;
   557               }
   558               break;
   559             }
   560             case MD_CPU_ARCHITECTURE_PPC: {
   561               switch (exception_flags) {
   562                 case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL:
   563                   reason.append("EXC_PPC_INVALID_SYSCALL");
   564                   break;
   565                 case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION:
   566                   reason.append("EXC_PPC_UNIPL_INST");
   567                   break;
   568                 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION:
   569                   reason.append("EXC_PPC_PRIVINST");
   570                   break;
   571                 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER:
   572                   reason.append("EXC_PPC_PRIVREG");
   573                   break;
   574                 case MD_EXCEPTION_CODE_MAC_PPC_TRACE:
   575                   reason.append("EXC_PPC_TRACE");
   576                   break;
   577                 case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR:
   578                   reason.append("EXC_PPC_PERFMON");
   579                   break;
   580                 default:
   581                   reason.append(flags_string);
   582                   BPLOG(INFO) << "Unknown exception reason " << reason;
   583                   break;
   584               }
   585               break;
   586             }
   587             case MD_CPU_ARCHITECTURE_X86: {
   588               switch (exception_flags) {
   589                 case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
   590                   reason.append("EXC_I386_INVOP");
   591                   break;
   592                 case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
   593                   reason.append("EXC_INVTSSFLT");
   594                   break;
   595                 case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
   596                   reason.append("EXC_SEGNPFLT");
   597                   break;
   598                 case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
   599                   reason.append("EXC_STKFLT");
   600                   break;
   601                 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
   602                   reason.append("EXC_GPFLT");
   603                   break;
   604                 case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
   605                   reason.append("EXC_ALIGNFLT");
   606                   break;
   607                 default:
   608                   reason.append(flags_string);
   609                   BPLOG(INFO) << "Unknown exception reason " << reason;
   610                   break;
   611               }
   612               break;
   613             }
   614             default:
   615               reason.append(flags_string);
   616               BPLOG(INFO) << "Unknown exception reason " << reason;
   617               break;
   618           }
   619           break;
   620         case MD_EXCEPTION_MAC_ARITHMETIC:
   621           reason = "EXC_ARITHMETIC / ";
   622           switch (raw_system_info->processor_architecture) {
   623             case MD_CPU_ARCHITECTURE_PPC: {
   624               switch (exception_flags) {
   625                 case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW:
   626                   reason.append("EXC_PPC_OVERFLOW");
   627                   break;
   628                 case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE:
   629                   reason.append("EXC_PPC_ZERO_DIVIDE");
   630                   break;
   631                 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT:
   632                   reason.append("EXC_FLT_INEXACT");
   633                   break;
   634                 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE:
   635                   reason.append("EXC_PPC_FLT_ZERO_DIVIDE");
   636                   break;
   637                 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW:
   638                   reason.append("EXC_PPC_FLT_UNDERFLOW");
   639                   break;
   640                 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW:
   641                   reason.append("EXC_PPC_FLT_OVERFLOW");
   642                   break;
   643                 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER:
   644                   reason.append("EXC_PPC_FLT_NOT_A_NUMBER");
   645                   break;
   646                 case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION:
   647                   reason.append("EXC_PPC_NOEMULATION");
   648                   break;
   649                 case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST:
   650                   reason.append("EXC_PPC_ALTIVECASSIST");
   651                 default:
   652                   reason.append(flags_string);
   653                   BPLOG(INFO) << "Unknown exception reason " << reason;
   654                   break;
   655               }
   656               break;
   657             }
   658             case MD_CPU_ARCHITECTURE_X86: {
   659               switch (exception_flags) {
   660                 case MD_EXCEPTION_CODE_MAC_X86_DIV:
   661                   reason.append("EXC_I386_DIV");
   662                   break;
   663                 case MD_EXCEPTION_CODE_MAC_X86_INTO:
   664                   reason.append("EXC_I386_INTO");
   665                   break;
   666                 case MD_EXCEPTION_CODE_MAC_X86_NOEXT:
   667                   reason.append("EXC_I386_NOEXT");
   668                   break;
   669                 case MD_EXCEPTION_CODE_MAC_X86_EXTOVR:
   670                   reason.append("EXC_I386_EXTOVR");
   671                   break;
   672                 case MD_EXCEPTION_CODE_MAC_X86_EXTERR:
   673                   reason.append("EXC_I386_EXTERR");
   674                   break;
   675                 case MD_EXCEPTION_CODE_MAC_X86_EMERR:
   676                   reason.append("EXC_I386_EMERR");
   677                   break;
   678                 case MD_EXCEPTION_CODE_MAC_X86_BOUND:
   679                   reason.append("EXC_I386_BOUND");
   680                   break;
   681                 case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR:
   682                   reason.append("EXC_I386_SSEEXTERR");
   683                   break;
   684                 default:
   685                   reason.append(flags_string);
   686                   BPLOG(INFO) << "Unknown exception reason " << reason;
   687                   break;
   688               }
   689               break;
   690             }
   691             default:
   692               reason.append(flags_string);
   693               BPLOG(INFO) << "Unknown exception reason " << reason;
   694               break;
   695           }
   696           break;
   697         case MD_EXCEPTION_MAC_EMULATION:
   698           reason = "EXC_EMULATION / ";
   699           reason.append(flags_string);
   700           break;
   701         case MD_EXCEPTION_MAC_SOFTWARE:
   702           reason = "EXC_SOFTWARE / ";
   703           switch (exception_flags) {
   704             case MD_EXCEPTION_CODE_MAC_ABORT:
   705               reason.append("SIGABRT");
   706               break;
   707             case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION:
   708               reason.append("UNCAUGHT_NS_EXCEPTION");
   709               break;
   710             // These are ppc only but shouldn't be a problem as they're
   711             // unused on x86
   712             case MD_EXCEPTION_CODE_MAC_PPC_TRAP:
   713               reason.append("EXC_PPC_TRAP");
   714               break;
   715             case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE:
   716               reason.append("EXC_PPC_MIGRATE");
   717               break;
   718             default:
   719               reason.append(flags_string);
   720               BPLOG(INFO) << "Unknown exception reason " << reason;
   721               break;
   722           }
   723           break;
   724         case MD_EXCEPTION_MAC_BREAKPOINT:
   725           reason = "EXC_BREAKPOINT / ";
   726           switch (raw_system_info->processor_architecture) {
   727             case MD_CPU_ARCHITECTURE_ARM: {
   728               switch (exception_flags) {
   729                 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
   730                   reason.append("EXC_ARM_DA_ALIGN");
   731                   break;
   732                 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
   733                   reason.append("EXC_ARM_DA_DEBUG");
   734                   break;
   735                 case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT:
   736                   reason.append("EXC_ARM_BREAKPOINT");
   737                   break;
   738                 default:
   739                   reason.append(flags_string);
   740                   BPLOG(INFO) << "Unknown exception reason " << reason;
   741                   break;
   742               }
   743               break;
   744             }
   745             case MD_CPU_ARCHITECTURE_PPC: {
   746               switch (exception_flags) {
   747                 case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT:
   748                   reason.append("EXC_PPC_BREAKPOINT");
   749                   break;
   750                 default:
   751                   reason.append(flags_string);
   752                   BPLOG(INFO) << "Unknown exception reason " << reason;
   753                   break;
   754               }
   755               break;
   756             }
   757             case MD_CPU_ARCHITECTURE_X86: {
   758               switch (exception_flags) {
   759                 case MD_EXCEPTION_CODE_MAC_X86_SGL:
   760                   reason.append("EXC_I386_SGL");
   761                   break;
   762                 case MD_EXCEPTION_CODE_MAC_X86_BPT:
   763                   reason.append("EXC_I386_BPT");
   764                   break;
   765                 default:
   766                   reason.append(flags_string);
   767                   BPLOG(INFO) << "Unknown exception reason " << reason;
   768                   break;
   769               }
   770               break;
   771             }
   772             default:
   773               reason.append(flags_string);
   774               BPLOG(INFO) << "Unknown exception reason " << reason;
   775               break;
   776           }
   777           break;
   778         case MD_EXCEPTION_MAC_SYSCALL:
   779           reason = "EXC_SYSCALL / ";
   780           reason.append(flags_string);
   781           break;
   782         case MD_EXCEPTION_MAC_MACH_SYSCALL:
   783           reason = "EXC_MACH_SYSCALL / ";
   784           reason.append(flags_string);
   785           break;
   786         case MD_EXCEPTION_MAC_RPC_ALERT:
   787           reason = "EXC_RPC_ALERT / ";
   788           reason.append(flags_string);
   789           break;
   790       }
   791       break;
   792     }
   794     case MD_OS_WIN32_NT:
   795     case MD_OS_WIN32_WINDOWS: {
   796       switch (exception_code) {
   797         case MD_EXCEPTION_CODE_WIN_CONTROL_C:
   798           reason = "DBG_CONTROL_C";
   799           break;
   800         case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
   801           reason = "EXCEPTION_GUARD_PAGE";
   802           break;
   803         case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT:
   804           reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
   805           break;
   806         case MD_EXCEPTION_CODE_WIN_BREAKPOINT:
   807           reason = "EXCEPTION_BREAKPOINT";
   808           break;
   809         case MD_EXCEPTION_CODE_WIN_SINGLE_STEP:
   810           reason = "EXCEPTION_SINGLE_STEP";
   811           break;
   812         case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
   813           // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that
   814           // caused the fault in exception_information[1].
   815           // exception_information[0] is 0 if the violation was caused by
   816           // an attempt to read data and 1 if it was an attempt to write
   817           // data.
   818           // This information is useful in addition to the code address, which
   819           // will be present in the crash thread's instruction field anyway.
   820           if (raw_exception->exception_record.number_parameters >= 1) {
   821             MDAccessViolationTypeWin av_type =
   822                 static_cast<MDAccessViolationTypeWin>
   823                 (raw_exception->exception_record.exception_information[0]);
   824             switch (av_type) {
   825               case MD_ACCESS_VIOLATION_WIN_READ:
   826                 reason = "EXCEPTION_ACCESS_VIOLATION_READ";
   827                 break;
   828               case MD_ACCESS_VIOLATION_WIN_WRITE:
   829                 reason = "EXCEPTION_ACCESS_VIOLATION_WRITE";
   830                 break;
   831               case MD_ACCESS_VIOLATION_WIN_EXEC:
   832                 reason = "EXCEPTION_ACCESS_VIOLATION_EXEC";
   833                 break;
   834               default:
   835                 reason = "EXCEPTION_ACCESS_VIOLATION";
   836                 break;
   837             }
   838           } else {
   839             reason = "EXCEPTION_ACCESS_VIOLATION";
   840           }
   841           if (address &&
   842               raw_exception->exception_record.number_parameters >= 2) {
   843             *address =
   844                 raw_exception->exception_record.exception_information[1];
   845           }
   846           break;
   847         case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
   848           reason = "EXCEPTION_IN_PAGE_ERROR";
   849           break;
   850         case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE:
   851           reason = "EXCEPTION_INVALID_HANDLE";
   852           break;
   853         case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
   854           reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
   855           break;
   856         case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
   857           reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
   858           break;
   859         case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
   860           reason = "EXCEPTION_INVALID_DISPOSITION";
   861           break;
   862         case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED:
   863           reason = "EXCEPTION_BOUNDS_EXCEEDED";
   864           break;
   865         case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND:
   866           reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
   867           break;
   868         case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
   869           reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
   870           break;
   871         case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
   872           reason = "EXCEPTION_FLT_INEXACT_RESULT";
   873           break;
   874         case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
   875           reason = "EXCEPTION_FLT_INVALID_OPERATION";
   876           break;
   877         case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
   878           reason = "EXCEPTION_FLT_OVERFLOW";
   879           break;
   880         case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK:
   881           reason = "EXCEPTION_FLT_STACK_CHECK";
   882           break;
   883         case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
   884           reason = "EXCEPTION_FLT_UNDERFLOW";
   885           break;
   886         case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
   887           reason = "EXCEPTION_INT_DIVIDE_BY_ZERO";
   888           break;
   889         case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
   890           reason = "EXCEPTION_INT_OVERFLOW";
   891           break;
   892         case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
   893           reason = "EXCEPTION_PRIV_INSTRUCTION";
   894           break;
   895         case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
   896           reason = "EXCEPTION_STACK_OVERFLOW";
   897           break;
   898         case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
   899           reason = "EXCEPTION_POSSIBLE_DEADLOCK";
   900           break;
   901         case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
   902           reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
   903           break;
   904         case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
   905           reason = "EXCEPTION_HEAP_CORRUPTION";
   906           break;
   907         case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
   908           reason = "Unhandled C++ Exception";
   909           break;
   910         default:
   911           BPLOG(INFO) << "Unknown exception reason " << reason;
   912           break;
   913       }
   914       break;
   915     }
   917     case MD_OS_ANDROID:
   918     case MD_OS_LINUX: {
   919       switch (exception_code) {
   920         case MD_EXCEPTION_CODE_LIN_SIGHUP:
   921           reason = "SIGHUP";
   922           break;
   923         case MD_EXCEPTION_CODE_LIN_SIGINT:
   924           reason = "SIGINT";
   925           break;
   926         case MD_EXCEPTION_CODE_LIN_SIGQUIT:
   927           reason = "SIGQUIT";
   928           break;
   929         case MD_EXCEPTION_CODE_LIN_SIGILL:
   930           reason = "SIGILL";
   931           break;
   932         case MD_EXCEPTION_CODE_LIN_SIGTRAP:
   933           reason = "SIGTRAP";
   934           break;
   935         case MD_EXCEPTION_CODE_LIN_SIGABRT:
   936           reason = "SIGABRT";
   937           break;
   938         case MD_EXCEPTION_CODE_LIN_SIGBUS:
   939           reason = "SIGBUS";
   940           break;
   941         case MD_EXCEPTION_CODE_LIN_SIGFPE:
   942           reason = "SIGFPE";
   943           break;
   944         case MD_EXCEPTION_CODE_LIN_SIGKILL:
   945           reason = "SIGKILL";
   946           break;
   947         case MD_EXCEPTION_CODE_LIN_SIGUSR1:
   948           reason = "SIGUSR1";
   949           break;
   950         case MD_EXCEPTION_CODE_LIN_SIGSEGV:
   951           reason = "SIGSEGV";
   952           break;
   953         case MD_EXCEPTION_CODE_LIN_SIGUSR2:
   954           reason = "SIGUSR2";
   955           break;
   956         case MD_EXCEPTION_CODE_LIN_SIGPIPE:
   957           reason = "SIGPIPE";
   958           break;
   959         case MD_EXCEPTION_CODE_LIN_SIGALRM:
   960           reason = "SIGALRM";
   961           break;
   962         case MD_EXCEPTION_CODE_LIN_SIGTERM:
   963           reason = "SIGTERM";
   964           break;
   965         case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
   966           reason = "SIGSTKFLT";
   967           break;
   968         case MD_EXCEPTION_CODE_LIN_SIGCHLD:
   969           reason = "SIGCHLD";
   970           break;
   971         case MD_EXCEPTION_CODE_LIN_SIGCONT:
   972           reason = "SIGCONT";
   973           break;
   974         case MD_EXCEPTION_CODE_LIN_SIGSTOP:
   975           reason = "SIGSTOP";
   976           break;
   977         case MD_EXCEPTION_CODE_LIN_SIGTSTP:
   978           reason = "SIGTSTP";
   979           break;
   980         case MD_EXCEPTION_CODE_LIN_SIGTTIN:
   981           reason = "SIGTTIN";
   982           break;
   983         case MD_EXCEPTION_CODE_LIN_SIGTTOU:
   984           reason = "SIGTTOU";
   985           break;
   986         case MD_EXCEPTION_CODE_LIN_SIGURG:
   987           reason = "SIGURG";
   988           break;
   989         case MD_EXCEPTION_CODE_LIN_SIGXCPU:
   990           reason = "SIGXCPU";
   991           break;
   992         case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
   993           reason = "SIGXFSZ";
   994           break;
   995         case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
   996           reason = "SIGVTALRM";
   997           break;
   998         case MD_EXCEPTION_CODE_LIN_SIGPROF:
   999           reason = "SIGPROF";
  1000           break;
  1001         case MD_EXCEPTION_CODE_LIN_SIGWINCH:
  1002           reason = "SIGWINCH";
  1003           break;
  1004         case MD_EXCEPTION_CODE_LIN_SIGIO:
  1005           reason = "SIGIO";
  1006           break;
  1007         case MD_EXCEPTION_CODE_LIN_SIGPWR:
  1008           reason = "SIGPWR";
  1009           break;
  1010         case MD_EXCEPTION_CODE_LIN_SIGSYS:
  1011           reason = "SIGSYS";
  1012           break;
  1013       case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
  1014           reason = "DUMP_REQUESTED";
  1015           break;
  1016         default:
  1017           BPLOG(INFO) << "Unknown exception reason " << reason;
  1018           break;
  1020       break;
  1023     case MD_OS_SOLARIS: {
  1024       switch (exception_code) {
  1025         case MD_EXCEPTION_CODE_SOL_SIGHUP:
  1026           reason = "SIGHUP";
  1027           break;
  1028         case MD_EXCEPTION_CODE_SOL_SIGINT:
  1029           reason = "SIGINT";
  1030           break;
  1031         case MD_EXCEPTION_CODE_SOL_SIGQUIT:
  1032           reason = "SIGQUIT";
  1033           break;
  1034         case MD_EXCEPTION_CODE_SOL_SIGILL:
  1035           reason = "SIGILL";
  1036           break;
  1037         case MD_EXCEPTION_CODE_SOL_SIGTRAP:
  1038           reason = "SIGTRAP";
  1039           break;
  1040         case MD_EXCEPTION_CODE_SOL_SIGIOT:
  1041           reason = "SIGIOT | SIGABRT";
  1042           break;
  1043         case MD_EXCEPTION_CODE_SOL_SIGEMT:
  1044           reason = "SIGEMT";
  1045           break;
  1046         case MD_EXCEPTION_CODE_SOL_SIGFPE:
  1047           reason = "SIGFPE";
  1048           break;
  1049         case MD_EXCEPTION_CODE_SOL_SIGKILL:
  1050           reason = "SIGKILL";
  1051           break;
  1052         case MD_EXCEPTION_CODE_SOL_SIGBUS:
  1053           reason = "SIGBUS";
  1054           break;
  1055         case MD_EXCEPTION_CODE_SOL_SIGSEGV:
  1056           reason = "SIGSEGV";
  1057           break;
  1058         case MD_EXCEPTION_CODE_SOL_SIGSYS:
  1059           reason = "SIGSYS";
  1060           break;
  1061         case MD_EXCEPTION_CODE_SOL_SIGPIPE:
  1062           reason = "SIGPIPE";
  1063           break;
  1064         case MD_EXCEPTION_CODE_SOL_SIGALRM:
  1065           reason = "SIGALRM";
  1066           break;
  1067         case MD_EXCEPTION_CODE_SOL_SIGTERM:
  1068           reason = "SIGTERM";
  1069           break;
  1070         case MD_EXCEPTION_CODE_SOL_SIGUSR1:
  1071           reason = "SIGUSR1";
  1072           break;
  1073         case MD_EXCEPTION_CODE_SOL_SIGUSR2:
  1074           reason = "SIGUSR2";
  1075           break;
  1076         case MD_EXCEPTION_CODE_SOL_SIGCLD:
  1077           reason = "SIGCLD | SIGCHLD";
  1078           break;
  1079         case MD_EXCEPTION_CODE_SOL_SIGPWR:
  1080           reason = "SIGPWR";
  1081           break;
  1082         case MD_EXCEPTION_CODE_SOL_SIGWINCH:
  1083           reason = "SIGWINCH";
  1084           break;
  1085         case MD_EXCEPTION_CODE_SOL_SIGURG:
  1086           reason = "SIGURG";
  1087           break;
  1088         case MD_EXCEPTION_CODE_SOL_SIGPOLL:
  1089           reason = "SIGPOLL | SIGIO";
  1090           break;
  1091         case MD_EXCEPTION_CODE_SOL_SIGSTOP:
  1092           reason = "SIGSTOP";
  1093           break;
  1094         case MD_EXCEPTION_CODE_SOL_SIGTSTP:
  1095           reason = "SIGTSTP";
  1096           break;
  1097         case MD_EXCEPTION_CODE_SOL_SIGCONT:
  1098           reason = "SIGCONT";
  1099           break;
  1100         case MD_EXCEPTION_CODE_SOL_SIGTTIN:
  1101           reason = "SIGTTIN";
  1102           break;
  1103         case MD_EXCEPTION_CODE_SOL_SIGTTOU:
  1104           reason = "SIGTTOU";
  1105           break;
  1106         case MD_EXCEPTION_CODE_SOL_SIGVTALRM:
  1107           reason = "SIGVTALRM";
  1108           break;
  1109         case MD_EXCEPTION_CODE_SOL_SIGPROF:
  1110           reason = "SIGPROF";
  1111           break;
  1112         case MD_EXCEPTION_CODE_SOL_SIGXCPU:
  1113           reason = "SIGXCPU";
  1114           break;
  1115         case MD_EXCEPTION_CODE_SOL_SIGXFSZ:
  1116           reason = "SIGXFSZ";
  1117           break;
  1118         case MD_EXCEPTION_CODE_SOL_SIGWAITING:
  1119           reason = "SIGWAITING";
  1120           break;
  1121         case MD_EXCEPTION_CODE_SOL_SIGLWP:
  1122           reason = "SIGLWP";
  1123           break;
  1124         case MD_EXCEPTION_CODE_SOL_SIGFREEZE:
  1125           reason = "SIGFREEZE";
  1126           break;
  1127         case MD_EXCEPTION_CODE_SOL_SIGTHAW:
  1128           reason = "SIGTHAW";
  1129           break;
  1130         case MD_EXCEPTION_CODE_SOL_SIGCANCEL:
  1131           reason = "SIGCANCEL";
  1132           break;
  1133         case MD_EXCEPTION_CODE_SOL_SIGLOST:
  1134           reason = "SIGLOST";
  1135           break;
  1136         case MD_EXCEPTION_CODE_SOL_SIGXRES:
  1137           reason = "SIGXRES";
  1138           break;
  1139         case MD_EXCEPTION_CODE_SOL_SIGJVM1:
  1140           reason = "SIGJVM1";
  1141           break;
  1142         case MD_EXCEPTION_CODE_SOL_SIGJVM2:
  1143           reason = "SIGJVM2";
  1144           break;
  1145         default:
  1146           BPLOG(INFO) << "Unknown exception reason " << reason;
  1147           break;
  1149       break;
  1152     default: {
  1153       BPLOG(INFO) << "Unknown exception reason " << reason;
  1154       break;
  1158   return reason;
  1161 // static
  1162 string MinidumpProcessor::GetAssertion(Minidump *dump) {
  1163   MinidumpAssertion *assertion = dump->GetAssertion();
  1164   if (!assertion)
  1165     return "";
  1167   const MDRawAssertionInfo *raw_assertion = assertion->assertion();
  1168   if (!raw_assertion)
  1169     return "";
  1171   string assertion_string;
  1172   switch (raw_assertion->type) {
  1173   case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER:
  1174     assertion_string = "Invalid parameter passed to library function";
  1175     break;
  1176   case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL:
  1177     assertion_string = "Pure virtual function called";
  1178     break;
  1179   default: {
  1180     char assertion_type[32];
  1181     snprintf(assertion_type, sizeof(assertion_type),
  1182              "0x%08x", raw_assertion->type);
  1183     assertion_string = "Unknown assertion type ";
  1184     assertion_string += assertion_type;
  1185     break;
  1189   string expression = assertion->expression();
  1190   if (!expression.empty()) {
  1191     assertion_string.append(" " + expression);
  1194   string function = assertion->function();
  1195   if (!function.empty()) {
  1196     assertion_string.append(" in function " + function);
  1199   string file = assertion->file();
  1200   if (!file.empty()) {
  1201     assertion_string.append(", in file " + file);
  1204   if (raw_assertion->line != 0) {
  1205     char assertion_line[32];
  1206     snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line);
  1207     assertion_string.append(" at line ");
  1208     assertion_string.append(assertion_line);
  1211   return assertion_string;
  1214 }  // namespace google_breakpad

mercurial