//===-- StopInfoMachException.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "StopInfoMachException.h"

#include "lldb/lldb-forward.h"

#if defined(__APPLE__)
// Needed for the EXC_RESOURCE interpretation macros
#include <kern/exc_resource.h>
#endif

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;

/// Information about a pointer-authentication related instruction.
struct PtrauthInstructionInfo {
  bool IsAuthenticated;
  bool IsLoad;
  bool DoesBranch;
};

/// Get any pointer-authentication related information about the instruction
/// at address \p at_addr.
static std::optional<PtrauthInstructionInfo>
GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch,
                          const Address &at_addr) {
  const char *plugin_name = nullptr;
  const char *flavor = nullptr;
  const char *cpu = nullptr;
  const char *features = nullptr;
  AddressRange range_bounds(at_addr, 4);
  const bool prefer_file_cache = true;
  DisassemblerSP disassembler_sp =
      Disassembler::DisassembleRange(arch, plugin_name, flavor, cpu, features,
                                     target, range_bounds, prefer_file_cache);
  if (!disassembler_sp)
    return std::nullopt;

  InstructionList &insn_list = disassembler_sp->GetInstructionList();
  InstructionSP insn = insn_list.GetInstructionAtIndex(0);
  if (!insn)
    return std::nullopt;

  return PtrauthInstructionInfo{insn->IsAuthenticated(), insn->IsLoad(),
                                insn->DoesBranch()};
}

/// Describe the load address of \p addr using the format filename:line:col.
static void DescribeAddressBriefly(Stream &strm, const Address &addr,
                                   Target &target) {
  strm.Printf("at address=0x%" PRIx64, addr.GetLoadAddress(&target));
  StreamString s;
  if (addr.GetDescription(s, target, eDescriptionLevelBrief))
    strm.Printf(" %s", s.GetString().data());
  strm.Printf(".\n");
}

std::optional<addr_t> StopInfoMachException::GetTagFaultAddress() const {
  const bool bad_access =
      (m_value == 1 || m_value == 12);          // EXC_BAD_ACCESS or EXC_GUARD
  const bool tag_fault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
  // Whether the subcode (m_exc_subcode) holds the fault address.
  const bool has_fault_addr = (m_exc_data_count >= 2);

  if (bad_access && tag_fault && has_fault_addr)
    return m_exc_subcode; // The subcode is the fault address.

  return std::nullopt;
}

static constexpr uint8_t g_mte_tag_shift = 64 - 8;
static constexpr addr_t g_mte_tag_mask = (addr_t)0x0f << g_mte_tag_shift;

bool StopInfoMachException::DetermineTagMismatch() {
  std::optional<addr_t> fault_address = GetTagFaultAddress();
  if (!fault_address)
    return false;

  const uint64_t bad_address = *fault_address;

  StreamString strm;
  strm.Printf("EXC_ARM_MTE_TAG_FAULT (code=%" PRIu64 ", address=0x%" PRIx64
              ")\n",
              m_exc_code, bad_address);

  const uint8_t tag = (bad_address & g_mte_tag_mask) >> g_mte_tag_shift;
  const addr_t canonical_addr = bad_address & ~g_mte_tag_mask;
  strm.Printf(
      "Note: MTE tag mismatch detected: pointer tag=%d, address=0x%" PRIx64,
      tag, canonical_addr);
  m_description = std::string(strm.GetString());

  return true;
}

bool StopInfoMachException::DeterminePtrauthFailure(ExecutionContext &exe_ctx) {
  bool IsBreakpoint = m_value == 6; // EXC_BREAKPOINT
  bool IsBadAccess = m_value == 1;  // EXC_BAD_ACCESS
  if (!IsBreakpoint && !IsBadAccess)
    return false;

  // Check that we have a live process.
  if (!exe_ctx.HasProcessScope() || !exe_ctx.HasThreadScope() ||
      !exe_ctx.HasTargetScope())
    return false;

  Thread &thread = *exe_ctx.GetThreadPtr();
  StackFrameSP current_frame = thread.GetStackFrameAtIndex(0);
  if (!current_frame)
    return false;

  Target &target = *exe_ctx.GetTargetPtr();
  Process &process = *exe_ctx.GetProcessPtr();
  const ArchSpec &arch = target.GetArchitecture();

  // Check for a ptrauth-enabled target.
  const bool ptrauth_enabled_target =
      arch.GetCore() == ArchSpec::eCore_arm_arm64e;
  if (!ptrauth_enabled_target)
    return false;

  // Set up a stream we can write a diagnostic into.
  StreamString strm;
  auto emit_ptrauth_prologue = [&](uint64_t at_address) {
    strm.Printf("EXC_BAD_ACCESS (code=%" PRIu64 ", address=0x%" PRIx64 ")\n",
                m_exc_code, at_address);
    strm.Printf("Note: Possible pointer authentication failure detected.\n");
  };

  ABISP abi_sp = process.GetABI();
  assert(abi_sp && "Missing ABI info");

  // Check if we have a "brk 0xc47x" trap, where the value that failed to
  // authenticate is in x16.
  Address current_address = current_frame->GetFrameCodeAddress();
  if (IsBreakpoint) {
    RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
    if (!reg_ctx)
      return false;

    const RegisterInfo *X16Info = reg_ctx->GetRegisterInfoByName("x16");
    RegisterValue X16Val;
    if (!reg_ctx->ReadRegister(X16Info, X16Val))
      return false;
    uint64_t bad_address = X16Val.GetAsUInt64();

    uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
    Address brk_address;
    if (!target.ResolveLoadAddress(fixed_bad_address, brk_address))
      return false;

    auto brk_ptrauth_info =
        GetPtrauthInstructionInfo(target, arch, current_address);
    if (brk_ptrauth_info && brk_ptrauth_info->IsAuthenticated) {
      emit_ptrauth_prologue(bad_address);
      strm.Printf("Found value that failed to authenticate ");
      DescribeAddressBriefly(strm, brk_address, target);
      m_description = std::string(strm.GetString());
      return true;
    }
    return false;
  }

  assert(IsBadAccess && "Handle EXC_BAD_ACCESS only after this point");

  // Check that we have the "bad address" from an EXC_BAD_ACCESS.
  if (m_exc_data_count < 2)
    return false;

  // Ok, we know the Target is valid and that it describes a ptrauth-enabled
  // device. Now, we need to determine whether this exception was caused by a
  // ptrauth failure.

  uint64_t bad_address = m_exc_subcode;
  uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
  uint64_t current_pc = current_address.GetLoadAddress(&target);

  // Detect: LDRAA, LDRAB (Load Register, with pointer authentication).
  //
  // If an authenticated load results in an exception, the instruction at the
  // current PC should be one of LDRAx.
  if (bad_address != current_pc && fixed_bad_address != current_pc) {
    auto ptrauth_info =
        GetPtrauthInstructionInfo(target, arch, current_address);
    if (ptrauth_info && ptrauth_info->IsAuthenticated && ptrauth_info->IsLoad) {
      emit_ptrauth_prologue(bad_address);
      strm.Printf("Found authenticated load instruction ");
      DescribeAddressBriefly(strm, current_address, target);
      m_description = std::string(strm.GetString());
      return true;
    }
  }

  // Detect: BLRAA, BLRAAZ, BLRAB, BLRABZ (Branch with Link to Register, with
  // pointer authentication).
  //
  // TODO: Detect: BRAA, BRAAZ, BRAB, BRABZ (Branch to Register, with pointer
  // authentication). At a minimum, this requires call site info support for
  // indirect calls.
  //
  // If an authenticated call or tail call results in an exception, stripping
  // the bad address should give the current PC, which points to the address
  // we tried to branch to.
  if (bad_address != current_pc && fixed_bad_address == current_pc) {
    if (StackFrameSP parent_frame = thread.GetStackFrameAtIndex(1)) {
      addr_t return_pc =
          parent_frame->GetFrameCodeAddress().GetLoadAddress(&target);
      Address blr_address;
      if (!target.ResolveLoadAddress(return_pc - 4, blr_address))
        return false;

      auto blr_ptrauth_info =
          GetPtrauthInstructionInfo(target, arch, blr_address);
      if (blr_ptrauth_info && blr_ptrauth_info->IsAuthenticated &&
          blr_ptrauth_info->DoesBranch) {
        emit_ptrauth_prologue(bad_address);
        strm.Printf("Found authenticated indirect branch ");
        DescribeAddressBriefly(strm, blr_address, target);
        m_description = std::string(strm.GetString());
        return true;
      }
    }
  }

  // TODO: Detect: RETAA, RETAB (Return from subroutine, with pointer
  // authentication).
  //
  // Is there a motivating, non-malicious code snippet that corrupts LR?

  return false;
}

const char *StopInfoMachException::GetDescription() {
  if (!m_description.empty())
    return m_description.c_str();
  if (GetValue() == eStopReasonInvalid)
    return "invalid stop reason!";

  ExecutionContext exe_ctx(m_thread_wp.lock());
  Target *target = exe_ctx.GetTargetPtr();
  const llvm::Triple::ArchType cpu =
      target ? target->GetArchitecture().GetMachine()
             : llvm::Triple::UnknownArch;

  const char *exc_desc = nullptr;
  const char *code_label = "code";
  const char *code_desc = nullptr;
  const char *subcode_label = "subcode";
  const char *subcode_desc = nullptr;

#if defined(__APPLE__)
  char code_desc_buf[32];
  char subcode_desc_buf[32];
#endif

  switch (m_value) {
  case 1: // EXC_BAD_ACCESS
    exc_desc = "EXC_BAD_ACCESS";
    subcode_label = "address";
    switch (cpu) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      switch (m_exc_code) {
      case 0xd:
        code_desc = "EXC_I386_GPFLT";
        m_exc_data_count = 1;
        break;
      }
      break;
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      switch (m_exc_code) {
      case 0x101:
        code_desc = "EXC_ARM_DA_ALIGN";
        break;
      case 0x102:
        code_desc = "EXC_ARM_DA_DEBUG";
        break;
      }
      break;

    case llvm::Triple::aarch64:
      if (DeterminePtrauthFailure(exe_ctx))
        return m_description.c_str();
      if (DetermineTagMismatch())
        return m_description.c_str();
      break;

    default:
      break;
    }
    break;

  case 2: // EXC_BAD_INSTRUCTION
    exc_desc = "EXC_BAD_INSTRUCTION";
    switch (cpu) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      if (m_exc_code == 1)
        code_desc = "EXC_I386_INVOP";
      break;

    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      if (m_exc_code == 1)
        code_desc = "EXC_ARM_UNDEFINED";
      break;

    default:
      break;
    }
    break;

  case 3: // EXC_ARITHMETIC
    exc_desc = "EXC_ARITHMETIC";
    switch (cpu) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      switch (m_exc_code) {
      case 1:
        code_desc = "EXC_I386_DIV";
        break;
      case 2:
        code_desc = "EXC_I386_INTO";
        break;
      case 3:
        code_desc = "EXC_I386_NOEXT";
        break;
      case 4:
        code_desc = "EXC_I386_EXTOVR";
        break;
      case 5:
        code_desc = "EXC_I386_EXTERR";
        break;
      case 6:
        code_desc = "EXC_I386_EMERR";
        break;
      case 7:
        code_desc = "EXC_I386_BOUND";
        break;
      case 8:
        code_desc = "EXC_I386_SSEEXTERR";
        break;
      }
      break;

    default:
      break;
    }
    break;

  case 4: // EXC_EMULATION
    exc_desc = "EXC_EMULATION";
    break;

  case 5: // EXC_SOFTWARE
    exc_desc = "EXC_SOFTWARE";
    if (m_exc_code == 0x10003) {
      subcode_desc = "EXC_SOFT_SIGNAL";
      subcode_label = "signo";
    }
    break;

  case 6: // EXC_BREAKPOINT
  {
    exc_desc = "EXC_BREAKPOINT";
    switch (cpu) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      switch (m_exc_code) {
      case 1:
        code_desc = "EXC_I386_SGL";
        break;
      case 2:
        code_desc = "EXC_I386_BPT";
        break;
      }
      break;

    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      switch (m_exc_code) {
      case 0x101:
        code_desc = "EXC_ARM_DA_ALIGN";
        break;
      case 0x102:
        code_desc = "EXC_ARM_DA_DEBUG";
        break;
      case 1:
        code_desc = "EXC_ARM_BREAKPOINT";
        break;
      // FIXME temporary workaround, exc_code 0 does not really mean
      // EXC_ARM_BREAKPOINT
      case 0:
        code_desc = "EXC_ARM_BREAKPOINT";
        break;
      }
      break;

    case llvm::Triple::aarch64:
      if (DeterminePtrauthFailure(exe_ctx))
        return m_description.c_str();
      break;

    default:
      break;
    }
  } break;

  case 7:
    exc_desc = "EXC_SYSCALL";
    break;

  case 8:
    exc_desc = "EXC_MACH_SYSCALL";
    break;

  case 9:
    exc_desc = "EXC_RPC_ALERT";
    break;

  case 10:
    exc_desc = "EXC_CRASH";
    break;
  case 11:
    exc_desc = "EXC_RESOURCE";
#if defined(__APPLE__)
    {
      int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code);

      code_label = "limit";
      code_desc = code_desc_buf;
      subcode_label = "observed";
      subcode_desc = subcode_desc_buf;

      switch (resource_type) {
      case RESOURCE_TYPE_CPU:
        exc_desc =
            "EXC_RESOURCE (RESOURCE_TYPE_CPU: CPU usage monitor tripped)";
        snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
                 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
        snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
                 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(
                     m_exc_subcode));
        break;
      case RESOURCE_TYPE_WAKEUPS:
        exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_WAKEUPS: idle wakeups monitor "
                   "tripped)";
        snprintf(
            code_desc_buf, sizeof(code_desc_buf), "%d w/s",
            (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
        snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
                 (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(
                     m_exc_subcode));
        break;
      case RESOURCE_TYPE_MEMORY:
        exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_MEMORY: high watermark memory "
                   "limit exceeded)";
        snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
                 (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
        subcode_desc = nullptr;
        subcode_label = nullptr;
        break;
#if defined(RESOURCE_TYPE_IO)
      // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12.
      case RESOURCE_TYPE_IO:
        exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
        snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
                 (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
        snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
                 (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));
        ;
        break;
#endif
      }
    }
#endif
    break;
  case 12:
    if (DetermineTagMismatch())
      return m_description.c_str();
    exc_desc = "EXC_GUARD";
    break;
  }

  StreamString strm;

  if (exc_desc)
    strm.PutCString(exc_desc);
  else
    strm.Printf("EXC_??? (%" PRIu64 ")", m_value);

  if (m_exc_data_count >= 1) {
    if (code_desc)
      strm.Printf(" (%s=%s", code_label, code_desc);
    else
      strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
  }

  if (m_exc_data_count >= 2) {
    if (subcode_label && subcode_desc)
      strm.Printf(", %s=%s", subcode_label, subcode_desc);
    else if (subcode_label)
      strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
  }

  if (m_exc_data_count > 0)
    strm.PutChar(')');

  m_description = std::string(strm.GetString());
  return m_description.c_str();
}

#if defined(__APPLE__)
const char *
StopInfoMachException::MachException::Name(exception_type_t exc_type) {
  switch (exc_type) {
  case EXC_BAD_ACCESS:
    return "EXC_BAD_ACCESS";
  case EXC_BAD_INSTRUCTION:
    return "EXC_BAD_INSTRUCTION";
  case EXC_ARITHMETIC:
    return "EXC_ARITHMETIC";
  case EXC_EMULATION:
    return "EXC_EMULATION";
  case EXC_SOFTWARE:
    return "EXC_SOFTWARE";
  case EXC_BREAKPOINT:
    return "EXC_BREAKPOINT";
  case EXC_SYSCALL:
    return "EXC_SYSCALL";
  case EXC_MACH_SYSCALL:
    return "EXC_MACH_SYSCALL";
  case EXC_RPC_ALERT:
    return "EXC_RPC_ALERT";
#ifdef EXC_CRASH
  case EXC_CRASH:
    return "EXC_CRASH";
#endif
  case EXC_RESOURCE:
    return "EXC_RESOURCE";
#ifdef EXC_GUARD
  case EXC_GUARD:
    return "EXC_GUARD";
#endif
#ifdef EXC_CORPSE_NOTIFY
  case EXC_CORPSE_NOTIFY:
    return "EXC_CORPSE_NOTIFY";
#endif
#ifdef EXC_CORPSE_VARIANT_BIT
  case EXC_CORPSE_VARIANT_BIT:
    return "EXC_CORPSE_VARIANT_BIT";
#endif
  default:
    break;
  }
  return NULL;
}

std::optional<exception_type_t>
StopInfoMachException::MachException::ExceptionCode(const char *name) {
  return llvm::StringSwitch<std::optional<exception_type_t>>(name)
      .Case("EXC_BAD_ACCESS", EXC_BAD_ACCESS)
      .Case("EXC_BAD_INSTRUCTION", EXC_BAD_INSTRUCTION)
      .Case("EXC_ARITHMETIC", EXC_ARITHMETIC)
      .Case("EXC_EMULATION", EXC_EMULATION)
      .Case("EXC_SOFTWARE", EXC_SOFTWARE)
      .Case("EXC_BREAKPOINT", EXC_BREAKPOINT)
      .Case("EXC_SYSCALL", EXC_SYSCALL)
      .Case("EXC_MACH_SYSCALL", EXC_MACH_SYSCALL)
      .Case("EXC_RPC_ALERT", EXC_RPC_ALERT)
#ifdef EXC_CRASH
      .Case("EXC_CRASH", EXC_CRASH)
#endif
      .Case("EXC_RESOURCE", EXC_RESOURCE)
#ifdef EXC_GUARD
      .Case("EXC_GUARD", EXC_GUARD)
#endif
#ifdef EXC_CORPSE_NOTIFY
      .Case("EXC_CORPSE_NOTIFY", EXC_CORPSE_NOTIFY)
#endif
      .Default(std::nullopt);
}
#endif

StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
    Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
    uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
    bool pc_already_adjusted, bool adjust_pc_if_needed) {
  if (exc_type == 0)
    return StopInfoSP();

  bool not_stepping_but_got_singlestep_exception = false;
  uint32_t pc_decrement = 0;
  ExecutionContext exe_ctx(thread.shared_from_this());
  Target *target = exe_ctx.GetTargetPtr();
  const llvm::Triple::ArchType cpu =
      target ? target->GetArchitecture().GetMachine()
             : llvm::Triple::UnknownArch;

  ProcessSP process_sp(thread.GetProcess());
  RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
  // Caveat: with x86 KDP if we've hit a breakpoint, the pc we
  // receive is past the breakpoint instruction.
  // If we have a breakpoints at 0x100 and 0x101, we hit the
  // 0x100 breakpoint and the pc is reported at 0x101.
  // We will initially mark this thread as being stopped at an
  // unexecuted breakpoint at 0x101. Later when we see that
  // we stopped for a Breakpoint reason, we will decrement the
  // pc, and update the thread to record that we hit the
  // breakpoint at 0x100.
  // The fact that the pc may be off by one at this point
  // (for an x86 KDP breakpoint hit) is not a problem.
  addr_t pc = reg_ctx_sp->GetPC();
  BreakpointSiteSP bp_site_sp =
      process_sp->GetBreakpointSiteList().FindByAddress(pc);
  if (bp_site_sp && process_sp->IsBreakpointSitePhysicallyEnabled(*bp_site_sp))
    thread.SetThreadStoppedAtUnexecutedBP(pc);

  switch (exc_type) {
  case 1: // EXC_BAD_ACCESS
  case 2: // EXC_BAD_INSTRUCTION
  case 3: // EXC_ARITHMETIC
  case 4: // EXC_EMULATION
    break;

  case 5:                    // EXC_SOFTWARE
    if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
    {
      if (exc_sub_code == 5) {
        // On MacOSX, a SIGTRAP can signify that a process has called exec,
        // so we should check with our dynamic loader to verify.
        ProcessSP process_sp(thread.GetProcess());
        if (process_sp) {
          DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
          if (dynamic_loader && dynamic_loader->ProcessDidExec()) {
            // The program was re-exec'ed
            return StopInfo::CreateStopReasonWithExec(thread);
          }
        }
      }
      return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
    }
    break;

    // A mach exception comes with 2-4 pieces of data.
    // The sub-codes are only provided for certain types
    // of mach exceptions.
    // [exc_type, exc_code, exc_sub_code, exc_sub_sub_code]
    //
    // Here are all of the EXC_BREAKPOINT, exc_type==6,
    // exceptions we can receive.
    //
    // Instruction step:
    //   [6, 1, 0]
    //   Intel KDP [6, 3, ??]
    //   armv7 [6, 0x102, <stop-pc>]  Same as software breakpoint!
    //
    // Software breakpoint:
    //   x86 [6, 2, 0]
    //   Intel KDP [6, 2, <bp-addr + 1>]
    //   arm64 [6, 1, <bp-addr>]
    //   armv7 [6, 0x102, <bp-addr>]  Same as instruction step!
    //
    // Hardware breakpoint:
    //   x86 [6, 1, <bp-addr>, 0]
    //   x86/Rosetta not implemented, see software breakpoint
    //   arm64 [6, 1, <bp-addr>]
    //   armv7 not implemented, see software breakpoint
    //
    // Hardware watchpoint:
    //   x86 [6, 1, <accessed-addr>, 0] (both Intel hw and Rosetta)
    //   arm64 [6, 0x102, <accessed-addr>, 0]
    //   armv7 [6, 0x102, <accessed-addr>, 0]
    //
    // arm64 BRK instruction (imm arg not reflected in the ME)
    //   [ 6, 1, <addr-of-BRK-insn>]
    //
    // In order of codes mach exceptions:
    //   [6, 1, 0] - instruction step
    //   [6, 1, <bp-addr>] - hardware breakpoint or watchpoint
    //
    //   [6, 2, 0] - software breakpoint
    //   [6, 2, <bp-addr + 1>] - software breakpoint
    //
    //   [6, 3] - instruction step
    //
    //   [6, 0x102, <stop-pc>] armv7 instruction step
    //   [6, 0x102, <bp-addr>] armv7 software breakpoint
    //   [6, 0x102, <accessed-addr>, 0] arm64/armv7 watchpoint

  case 6: // EXC_BREAKPOINT
  {
    bool stopped_by_hitting_breakpoint = false;
    bool stopped_by_completing_stepi = false;
    bool stopped_watchpoint = false;
    std::optional<addr_t> address;

    // exc_code 1
    if (exc_code == 1) {
      if (exc_sub_code == 0) {
        stopped_by_completing_stepi = true;
      } else {
        // Ambiguous: could be signalling a
        // breakpoint or watchpoint hit.
        stopped_by_hitting_breakpoint = true;
        stopped_watchpoint = true;
        address = exc_sub_code;
      }
    }

    // exc_code 2
    if (exc_code == 2) {
      if (exc_sub_code == 0)
        stopped_by_hitting_breakpoint = true;
      else {
        stopped_by_hitting_breakpoint = true;
        // Intel KDP software breakpoint
        if (!pc_already_adjusted)
          pc_decrement = 1;
      }
    }

    // exc_code 3
    if (exc_code == 3)
      stopped_by_completing_stepi = true;

    // exc_code 0x102
    if (exc_code == 0x102 && exc_sub_code != 0) {
      if (cpu == llvm::Triple::arm || cpu == llvm::Triple::thumb) {
        stopped_by_hitting_breakpoint = true;
        stopped_by_completing_stepi = true;
      }
      stopped_watchpoint = true;
      address = exc_sub_code;
    }

    // The Mach Exception may have been ambiguous --
    // e.g. we stopped either because of a breakpoint
    // or a watchpoint.  We'll disambiguate which it
    // really was.

    if (stopped_by_hitting_breakpoint) {
      addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;

      if (address)
        bp_site_sp =
            process_sp->GetBreakpointSiteList().FindByAddress(*address);
      if (!bp_site_sp && reg_ctx_sp) {
        bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
      }
      if (bp_site_sp &&
          process_sp->IsBreakpointSitePhysicallyEnabled(*bp_site_sp)) {
        // We've hit this breakpoint, whether it was intended for this thread
        // or not.  Clear this in the Tread object so we step past it on resume.
        thread.SetThreadHitBreakpointSite();

        if (bp_site_sp->ValidForThisThread(thread)) {
          // Update the PC if we were asked to do so, but only do so if we find
          // a breakpoint that we know about because this could be a trap
          // instruction in the code.
          if (pc_decrement > 0 && adjust_pc_if_needed && reg_ctx_sp)
            reg_ctx_sp->SetPC(pc);

          return StopInfo::CreateStopReasonWithBreakpointSiteID(
              thread, bp_site_sp->GetID());
        } else {
          return StopInfoSP();
        }
      }
    }

    // Breakpoint-hit events are handled.
    // Now handle watchpoints.

    if (stopped_watchpoint && address) {
      WatchpointResourceSP wp_rsrc_sp =
          target->GetProcessSP()->GetWatchpointResourceList().FindByAddress(
              *address);
      if (wp_rsrc_sp && wp_rsrc_sp->GetNumberOfConstituents() > 0) {
        return StopInfo::CreateStopReasonWithWatchpointID(
            thread, wp_rsrc_sp->GetConstituentAtIndex(0)->GetID());
      }
    }

    // Finally, handle instruction step.

    if (stopped_by_completing_stepi) {
      if (thread.GetTemporaryResumeState() != eStateStepping)
        not_stepping_but_got_singlestep_exception = true;
      else
        return StopInfo::CreateStopReasonToTrace(thread);
    }

  } break;

  case 7:  // EXC_SYSCALL
  case 8:  // EXC_MACH_SYSCALL
  case 9:  // EXC_RPC_ALERT
  case 10: // EXC_CRASH
    break;
  }

  return std::make_shared<StopInfoMachException>(
      thread, exc_type, exc_data_count, exc_code, exc_sub_code,
      not_stepping_but_got_singlestep_exception);
}

// Detect an unusual situation on Darwin where:
//
//   0. We did an instruction-step before this.
//   1. We have a hardware breakpoint or watchpoint set.
//   2. We resumed the process, but not with an instruction-step.
//   3. The thread gets an "instruction-step completed" mach exception.
//   4. The pc has not advanced - it is the same as before.
//
// This method returns true for that combination of events.
bool StopInfoMachException::WasContinueInterrupted(Thread &thread) {
  Log *log = GetLog(LLDBLog::Step);

  // We got an instruction-step completed mach exception but we were not
  // doing an instruction step on this thread.
  if (!m_not_stepping_but_got_singlestep_exception)
    return false;

  RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
  std::optional<addr_t> prev_pc = thread.GetPreviousFrameZeroPC();
  if (!reg_ctx_sp || !prev_pc)
    return false;

  // The previous pc value and current pc value are the same.
  if (*prev_pc != reg_ctx_sp->GetPC())
    return false;

  // We have a watchpoint -- this is the kernel bug.
  ProcessSP process_sp = thread.GetProcess();
  if (process_sp->GetWatchpointResourceList().GetSize()) {
    LLDB_LOGF(log,
              "Thread stopped with insn-step completed mach exception but "
              "thread was not stepping; there is a hardware watchpoint set.");
    return true;
  }

  // We have a hardware breakpoint -- this is the kernel bug.
  auto &bp_site_list = process_sp->GetBreakpointSiteList();
  for (auto &site : bp_site_list.Sites()) {
    if (site->IsHardware() &&
        process_sp->IsBreakpointSitePhysicallyEnabled(*site)) {
      LLDB_LOGF(log,
                "Thread stopped with insn-step completed mach exception but "
                "thread was not stepping; there is a hardware breakpoint set.");
      return true;
    }
  }

  return false;
}
