string MinidumpProcessor::GetCrashReason()

in toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc [743:2091]


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];
  char flags_string[11];
  uint32_t exception_code = raw_exception->exception_record.exception_code;
  uint32_t exception_flags = raw_exception->exception_record.exception_flags;
  snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags);
  snprintf(reason_string, sizeof(reason_string), "0x%08x / %s", exception_code,
           flags_string);
  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_FUCHSIA: {
      switch (exception_code) {
        case MD_EXCEPTION_CODE_FUCHSIA_GENERAL:
          reason = "GENERAL / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_FATAL_PAGE_FAULT:
          reason = "FATAL_PAGE_FAULT / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_UNDEFINED_INSTRUCTION:
          reason = "UNDEFINED_INSTRUCTION / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_SW_BREAKPOINT:
          reason = "SW_BREAKPOINT / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_HW_BREAKPOINT:
          reason = "HW_BREAKPOINT / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_UNALIGNED_ACCESS:
          reason = "UNALIGNED_ACCESS / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_THREAD_STARTING:
          reason = "THREAD_STARTING / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_THREAD_EXITING:
          reason = "THREAD_EXITING / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_POLICY_ERROR:
          reason = "POLICY_ERROR / ";
          reason.append(flags_string);
          break;
        case MD_EXCEPTION_CODE_FUCHSIA_PROCESS_STARTING:
          reason = "PROCESS_STARTING / ";
          reason.append(flags_string);
          break;
        default:
          BPLOG(INFO) << "Unknown exception reason " << reason;
      }
      break;
    }

    case MD_OS_MAC_OS_X:
    case MD_OS_IOS: {
      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;
            case MD_EXCEPTION_CODE_MAC_CODESIGN_ERROR:
              reason.append("KERN_CODESIGN_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_OLD) {
                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_OLD: {
              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");
                  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_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_OLD: {
              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;
        case MD_EXCEPTION_MAC_RESOURCE:
          reason = "EXC_RESOURCE / ";
          {
            uint32_t type = (exception_flags >> 29) & 0x7ULL;
            uint32_t flavor = (exception_flags >> 26) & 0x7ULL;
            char flavor_string[6] = {};
            switch (type) {
              case MD_MAC_EXC_RESOURCE_TYPE_CPU:
                reason.append("RESOURCE_TYPE_CPU / ");
                switch (flavor) {
                  case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR:
                    reason.append("FLAVOR_CPU_MONITOR");
                    break;
                  case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR_FATAL:
                    reason.append("FLAVOR_CPU_MONITOR_FATAL");
                    break;
                  default:
                    snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
                    reason.append(flavor_string);
                    break;
                }
                break;
              case MD_MAC_EXC_RESOURCE_TYPE_WAKEUPS:
                reason.append("RESOURCE_TYPE_WAKEUPS / ");
                if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_WAKEUPS_MONITOR) {
                  reason.append("FLAVOR_WAKEUPS_MONITOR");
                } else {
                  snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
                  reason.append(flavor_string);
                }
                break;
              case MD_MAC_EXC_RESOURCE_TYPE_MEMORY:
                reason.append("RESOURCE_TYPE_MEMORY / ");
                if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_HIGH_WATERMARK) {
                  reason.append("FLAVOR_HIGH_WATERMARK");
                } else {
                  snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
                  reason.append(flavor_string);
                }
                break;
              case MD_MAC_EXC_RESOURCE_TYPE_IO:
                reason.append("EXC_RESOURCE_TYPE_IO / ");
                switch (flavor) {
                  case MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES:
                    reason.append("FLAVOR_IO_PHYSICAL_WRITES");
                    break;
                  case MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES:
                    reason.append("FLAVOR_IO_LOGICAL_WRITES");
                    break;
                  default:
                    snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
                    reason.append(flavor_string);
                    break;
                }
                break;
              case MD_MAC_EXC_RESOURCE_TYPE_THREADS:
                reason.append("EXC_RESOURCE_TYPE_THREADS / ");
                if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK) {
                  reason.append("FLAVOR_THREADS_HIGH_WATERMARK");
                } else {
                  snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
                  reason.append(flavor_string);
                }
                break;
              default:
                reason.append(flags_string);
                break;
            }
          }
          break;
        case MD_EXCEPTION_MAC_GUARD:
          reason = "EXC_GUARD / ";
          {
            uint32_t type = (exception_flags >> 29) & 0x7ULL;
            uint32_t flavor = exception_flags & 0x1FFFFFFFULL;
            switch (type) {
              case MD_MAC_EXC_GUARD_TYPE_NONE:
                reason.append("GUARD_TYPE_NONE");
                break;
              case MD_MAC_EXC_GUARD_TYPE_MACH_PORT:
                reason.append("GUARD_TYPE_MACH_PORT");

                if (flavor) {
                  std::vector<std::string> flavors;

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_DESTROY) {
                    flavors.push_back("GUARD_EXC_DESTROY");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS) {
                    flavors.push_back("GUARD_EXC_MOD_REFS");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
                    flavors.push_back("GUARD_EXC_SET_CONTEXT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
                    flavors.push_back("GUARD_EXC_SET_CONTEXT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_UNGUARDED) {
                    flavors.push_back("GUARD_EXC_UNGUARDED");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INCORRECT_GUARD) {
                    flavors.push_back("GUARD_EXC_INCORRECT_GUARD");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE) {
                    flavors.push_back("GUARD_EXC_IMMOVABLE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_STRICT_REPLY) {
                    flavors.push_back("GUARD_EXC_STRICT_REPLY");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MSG_FILTERED) {
                    flavors.push_back("GUARD_EXC_MSG_FILTERED");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_RIGHT) {
                    flavors.push_back("GUARD_EXC_INVALID_RIGHT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_NAME) {
                    flavors.push_back("GUARD_EXC_INVALID_NAME");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_VALUE) {
                    flavors.push_back("GUARD_EXC_INVALID_VALUE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_ARGUMENT) {
                    flavors.push_back("GUARD_EXC_INVALID_ARGUMENT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RIGHT_EXISTS) {
                    flavors.push_back("GUARD_EXC_RIGHT_EXISTS");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_NO_SPACE) {
                    flavors.push_back("GUARD_EXC_KERN_NO_SPACE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_FAILURE) {
                    flavors.push_back("GUARD_EXC_KERN_FAILURE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_RESOURCE) {
                    flavors.push_back("GUARD_EXC_KERN_RESOURCE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_REPLY) {
                    flavors.push_back("GUARD_EXC_SEND_INVALID_REPLY");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_VOUCHER) {
                    flavors.push_back("GUARD_EXC_SEND_INVALID_VOUCHER");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_RIGHT) {
                    flavors.push_back("GUARD_EXC_SEND_INVALID_RIGHT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_INVALID_NAME) {
                    flavors.push_back("GUARD_EXC_RCV_INVALID_NAME");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_GUARDED_DESC) {
                    flavors.push_back("GUARD_EXC_RCV_GUARDED_DESC");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS_NON_FATAL) {
                    flavors.push_back("GUARD_EXC_MOD_REFS_NON_FATAL");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE_NON_FATAL) {
                    flavors.push_back("GUARD_EXC_IMMOVABLE_NON_FATAL");
                  }

                  reason.append(" / ");
                  for (size_t i = 0; i < flavors.size(); i++) {
                    if (i > 0) {
                      reason.append(" | ");
                    }

                    reason.append(flavors[i]);
                  }
                }

                break;
              case MD_MAC_EXC_GUARD_TYPE_FD:
                reason.append("GUARD_TYPE_FD");

                if (flavor) {
                  std::vector<std::string> flavors;

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_CLOSE) {
                    flavors.push_back("GUARD_EXC_CLOSE");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_DUP) {
                    flavors.push_back("GUARD_EXC_DUP");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_NOCLOEXEC) {
                    flavors.push_back("GUARD_EXC_NOCLOEXEC");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_SOCKET_IPC) {
                    flavors.push_back("GUARD_EXC_SOCKET_IPC");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_FILEPORT) {
                    flavors.push_back("GUARD_EXC_FILEPORT");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_MISMATCH) {
                    flavors.push_back("GUARD_EXC_MISMATCH");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE) {
                    flavors.push_back("GUARD_EXC_WRITE");
                  }

                  reason.append(" / ");
                  for (size_t i = 0; i < flavors.size(); i++) {
                    if (i > 0) {
                      reason.append(" | ");
                    }

                    reason.append(flavors[i]);
                  }
                }

                break;
              case MD_MAC_EXC_GUARD_TYPE_USER:
                reason.append("GUARD_TYPE_USER");
                break;
              case MD_MAC_EXC_GUARD_TYPE_VN:
                reason.append("GUARD_TYPE_VN");

                if (flavor) {
                  std::vector<std::string> flavors;

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_TO) {
                    flavors.push_back("GUARD_EXC_RENAME_TO");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_FROM) {
                    flavors.push_back("GUARD_EXC_RENAME_FROM");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_UNLINK) {
                    flavors.push_back("GUARD_EXC_UNLINK");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE_OTHER) {
                    flavors.push_back("GUARD_EXC_WRITE_OTHER");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_TRUNC_OTHER) {
                    flavors.push_back("GUARD_EXC_TRUNC_OTHER");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_LINK) {
                    flavors.push_back("GUARD_EXC_LINK");
                  }

                  if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_EXCHDATA) {
                    flavors.push_back("GUARD_EXC_EXCHDATA");
                  }

                  reason.append(" / ");
                  for (size_t i = 0; i < flavors.size(); i++) {
                    if (i > 0) {
                      reason.append(" | ");
                    }

                    reason.append(flavors[i]);
                  }
                }

                break;
              case MD_MAC_EXC_GUARD_TYPE_VIRT_MEMORY:
                reason.append("GUARD_TYPE_VIRT_MEMORY");

                if (flavor & MD_MAC_EXC_GUARD_VIRT_MEMORY_FLAVOR_GUARD_EXC_DEALLOC_GAP) {
                  reason.append(" / GUARD_EXC_DEALLOC_GAP");
                }

                break;
              default:
                reason.append(flags_string);
                break;
            }
          }
          break;
        case MD_EXCEPTION_MAC_SIMULATED:
          reason = "Simulated Exception";
          break;
      }
      break;
    }

    case MD_OS_WIN32_NT:
    case MD_OS_WIN32_WINDOWS: {
      switch (exception_code) {
        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(" / ");
            const char* ntstatus_str = NTStatusToString(ntstatus);
            if (ntstatus_str) {
              reason.append(ntstatus_str);
            } else {
              snprintf(reason_string, sizeof(reason_string), "%#010x", ntstatus);
              reason.append(reason_string);
            }
          }
          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_ARRAY_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_BAD_FUNCTION_TABLE:
          reason = "EXCEPTION_BAD_FUNCTION_TABLE";
          break;
        case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
          reason = "EXCEPTION_POSSIBLE_DEADLOCK";
          break;
        case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
          reason = "STATUS_STACK_BUFFER_OVERRUN";
            if (raw_exception->exception_record.number_parameters > 0) {
            uint32_t fast_fail_code =
                static_cast<uint32_t>
                (raw_exception->exception_record.exception_information[0]);
            char fast_fail_buff[13] = {};
            const char* fast_fail_string = FastFailToString(fast_fail_code);
            if (!fast_fail_string) {
              snprintf(fast_fail_buff, sizeof(fast_fail_buff), "%#010x",
                       fast_fail_code);
              fast_fail_string = fast_fail_buff;
            }

            reason.append(" / ");
            reason.append(fast_fail_string);
          }

          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;
        case MD_EXCEPTION_CODE_WIN_SIMULATED:
          reason = "Simulated Exception";
          break;
        default:
          fprintf(stderr, "exception_code = %u\n", exception_code);
          const char* exception_str = NTStatusToString(exception_code);
          fprintf(stderr, "exception_str = %s\n", exception_str);
          if (exception_str == nullptr) {
            exception_str = WinErrorToString(exception_code);
          }
          if (exception_str != nullptr) {
            reason = exception_str;
          }
          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 / ";
          switch (exception_flags) {
            case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC:
              reason.append("ILL_ILLOPC");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN:
              reason.append("ILL_ILLOPN");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_ILLADR:
              reason.append("ILL_ILLADR");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP:
              reason.append("ILL_ILLTRP");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC:
              reason.append("ILL_PRVOPC");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_PRVREG:
              reason.append("ILL_PRVREG");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_COPROC:
              reason.append("ILL_COPROC");
              break;
            case MD_EXCEPTION_FLAG_LIN_ILL_BADSTK:
              reason.append("ILL_BADSTK");
              break;
            default:
              reason.append(flags_string);
              BPLOG(INFO) << "Unknown exception reason " << reason;
              break;
          }
          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 / ";
          switch (exception_flags) {
            case MD_EXCEPTION_FLAG_LIN_SI_USER:
              reason.append("SI_USER");
              break;
            case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
              reason.append("SI_KERNEL");
              break;
            case MD_EXCEPTION_FLAG_LIN_BUS_ADRALN:
              reason.append("BUS_ADRALN");
              break;
            case MD_EXCEPTION_FLAG_LIN_BUS_ADRERR:
              reason.append("BUS_ADRERR");
              break;
            case MD_EXCEPTION_FLAG_LIN_BUS_OBJERR:
              reason.append("BUS_OBJERR");
              break;
            case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AR:
              reason.append("BUS_MCEERR_AR");
              break;
            case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AO:
              reason.append("BUS_MCEERR_AO");
              break;
            default:
              reason.append(flags_string);
              BPLOG(INFO) << "Unknown exception reason " << reason;
              break;
          }
          break;
        case MD_EXCEPTION_CODE_LIN_SIGFPE:
          reason = "SIGFPE / ";
          switch (exception_flags) {
            case MD_EXCEPTION_FLAG_LIN_FPE_INTDIV:
              reason.append("FPE_INTDIV");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_INTOVF:
              reason.append("FPE_INTOVF");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTDIV:
              reason.append("FPE_FLTDIV");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTOVF:
              reason.append("FPE_FLTOVF");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTUND:
              reason.append("FPE_FLTUND");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTRES:
              reason.append("FPE_FLTRES");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTINV:
              reason.append("FPE_FLTINV");
              break;
            case MD_EXCEPTION_FLAG_LIN_FPE_FLTSUB:
              reason.append("FPE_FLTSUB");
              break;
            default:
              reason.append(flags_string);
              BPLOG(INFO) << "Unknown exception reason " << reason;
              break;
          }
          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 / ";
          switch (exception_flags) {
            case MD_EXCEPTION_FLAG_LIN_SI_USER:
              reason.append("SI_USER");
              break;
            case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
              reason.append("SI_KERNEL");
              break;
            case MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR:
              reason.append("SEGV_MAPERR");
              break;
            case MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR:
              reason.append("SEGV_ACCERR");
              break;
            case MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR:
              reason.append("SEGV_BNDERR");
              break;
            case MD_EXCEPTION_FLAG_LIN_SEGV_PKUERR:
              reason.append("SEGV_PKUERR");
              break;
            default:
              reason.append(flags_string);
              BPLOG(INFO) << "Unknown exception reason " << reason;
              break;
          }
          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;
    }
  }

  if (address) {
    *address = GetAddressForArchitecture(
      static_cast<MDCPUArchitecture>(raw_system_info->processor_architecture),
      *address);
  }

  return reason;
}