// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/debug_agent/debugged_thread.h"

#include <inttypes.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/exception.h>

#include <memory>

#include "src/developer/debug/debug_agent/arch.h"
#include "src/developer/debug/debug_agent/arch_types.h"
#include "src/developer/debug/debug_agent/debug_agent.h"
#include "src/developer/debug/debug_agent/debugged_process.h"
#include "src/developer/debug/debug_agent/hardware_breakpoint.h"
#include "src/developer/debug/debug_agent/process_breakpoint.h"
#include "src/developer/debug/debug_agent/software_breakpoint.h"
#include "src/developer/debug/debug_agent/time.h"
#include "src/developer/debug/debug_agent/unwind.h"
#include "src/developer/debug/debug_agent/watchpoint.h"
#include "src/developer/debug/ipc/agent_protocol.h"
#include "src/developer/debug/ipc/message_reader.h"
#include "src/developer/debug/ipc/message_writer.h"
#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/developer/debug/shared/stream_buffer.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace debug_agent {

namespace {

// Used to have better context upon reading the debug logs.
std::string ThreadPreamble(const DebuggedThread* thread) {
  return fxl::StringPrintf("[Pr: %lu (%s), T: %lu] ", thread->process()->koid(),
                           thread->process()->process_handle().GetName().c_str(), thread->koid());
}

void LogHitBreakpoint(debug::FileLineFunction location, const DebuggedThread* thread,
                      ProcessBreakpoint* process_breakpoint, uint64_t address) {
  if (!debug::IsDebugModeActive())
    return;

  std::stringstream ss;
  ss << ThreadPreamble(thread) << "Hit SW breakpoint on 0x" << std::hex << address << " for: ";
  for (Breakpoint* breakpoint : process_breakpoint->breakpoints()) {
    ss << breakpoint->settings().name << ", ";
  }

  DEBUG_LOG_WITH_LOCATION(Thread, location) << ss.str();
}

void LogExceptionNotification(debug::FileLineFunction location, const DebuggedThread* thread,
                              const debug_ipc::NotifyException& exception) {
  if (!debug::IsDebugModeActive())
    return;

  std::stringstream ss;
  ss << ThreadPreamble(thread) << "Notifying exception "
     << debug_ipc::ExceptionTypeToString(exception.type) << ". ";
  ss << "Breakpoints hit: ";
  int count = 0;
  for (auto& bp : exception.hit_breakpoints) {
    if (count > 0)
      ss << ", ";

    ss << bp.id;
    if (bp.should_delete)
      ss << " (delete)";
  }

  DEBUG_LOG_WITH_LOCATION(Thread, location) << ss.str();
}

}  // namespace

DebuggedThread::DebuggedThread(DebugAgent* debug_agent, DebuggedProcess* process,
                               std::unique_ptr<ThreadHandle> handle,
                               ThreadCreationOption creation_option,
                               std::unique_ptr<ExceptionHandle> exception)
    : thread_handle_(std::move(handle)),
      debug_agent_(debug_agent),
      process_(process),
      exception_handle_(std::move(exception)),
      weak_factory_(this) {
  switch (creation_option) {
    case ThreadCreationOption::kRunningKeepRunning:
      // do nothing
      break;
    case ThreadCreationOption::kSuspendedKeepSuspended:
      break;
    case ThreadCreationOption::kSuspendedShouldRun:
      InternalResumeException();
      break;
  }
}

DebuggedThread::~DebuggedThread() = default;

fxl::WeakPtr<DebuggedThread> DebuggedThread::GetWeakPtr() { return weak_factory_.GetWeakPtr(); }

void DebuggedThread::OnException(std::unique_ptr<ExceptionHandle> exception_handle) {
  exception_handle_ = std::move(exception_handle);

  debug_ipc::ExceptionType type = exception_handle_->GetType(*thread_handle_);

  std::optional<GeneralRegisters> regs = thread_handle_->GetGeneralRegisters();
  if (!regs) {
    // This can happen, for example, if the thread was killed during the time the exception message
    // was waiting to be delivered to us.
    FX_LOGS(WARNING) << "Could not read registers from thread.";
    return;
  }

  DEBUG_LOG(Thread) << ThreadPreamble(this) << "Exception @ 0x" << std::hex << regs->ip()
                    << std::dec << ": " << debug_ipc::ExceptionTypeToString(type);

  debug_ipc::NotifyException exception{};
  exception.type = type;
  exception.exception = thread_handle_->GetExceptionRecord();
  exception.timestamp = GetNowTimestamp();

  switch (type) {
    case debug_ipc::ExceptionType::kSingleStep:
      return HandleSingleStep(&exception, *regs);
    case debug_ipc::ExceptionType::kSoftwareBreakpoint:
      return HandleSoftwareBreakpoint(&exception, *regs);
    case debug_ipc::ExceptionType::kHardwareBreakpoint:
      return HandleHardwareBreakpoint(&exception, *regs);
    case debug_ipc::ExceptionType::kWatchpoint:
      return HandleWatchpoint(&exception, *regs);
    case debug_ipc::ExceptionType::kNone:
    case debug_ipc::ExceptionType::kLast:
      break;
    // TODO(donosoc): Should synthetic be general or invalid?
    case debug_ipc::ExceptionType::kSynthetic:
    default:
      return HandleGeneralException(&exception, *regs);
  }

  FX_NOTREACHED() << "Invalid exception notification type: "
                  << debug_ipc::ExceptionTypeToString(type);

  // The exception was unhandled, so we close it so that the system can run its course. The
  // destructor would've done it anyway, but being explicit helps readability.
  exception_handle_ = nullptr;
}

void DebuggedThread::ResumeFromException() {
  if (in_exception() && current_breakpoint_) {
    // Resuming from a breakpoint hit. Going over a breakpoint requires removing the breakpoint,
    // single-stepping the thread, and putting the breakpoint back.
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Stepping over breakpoint: 0x" << std::hex
                      << current_breakpoint_->address();

    // BeginStepOver() will takes responsibility for resuming the exception at the proper time.
    current_breakpoint_->BeginStepOver(this);
  } else {
    // Check whether we're resuming from a hardcoded breakpoint exception. If it is, continue from
    // the following instruction since the breakpoint instruction will never go away.
    if (in_exception() && exception_handle_->GetType(*thread_handle_) ==
                              debug_ipc::ExceptionType::kSoftwareBreakpoint) {
      auto regs = thread_handle_->GetGeneralRegisters();
      if (regs && IsBreakpointInstructionAtAddress(regs->ip())) {
        regs->set_ip(regs->ip() + arch::kBreakInstructionSize);
        thread_handle_->SetGeneralRegisters(*regs);
      }
    }

    // Normal exception resumption.
    InternalResumeException();
  }
}

void DebuggedThread::HandleSingleStep(debug_ipc::NotifyException* exception,
                                      const GeneralRegisters& regs) {
  if (current_breakpoint_) {
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Ending single stepped over 0x" << std::hex
                      << current_breakpoint_->address();
    // Getting here means that the thread is done stepping over a breakpoint.
    // Depending on whether others threads are stepping over the breakpoints, this thread might be
    // suspended (waiting for other threads to step over).
    // This means that we cannot resume from suspension here, as the breakpoint is owning the
    // thread "run-lifetime".
    //
    // We can, though, resume from the exception, as effectively we already handled the single-step
    // exception, so there is no more need to keep the thread in an excepted state. The suspend
    // handle will take care of keeping the thread stopped.
    //
    // NOTE: It's important to resume the exception *after* telling the breakpoint we are done going
    //       over it. This is because in the case that there are no other threads queued (the normal
    //       case), it produces a window between resuming the exception and suspending the thread
    //       to reinstall the breakpointer, which could make the thread miss the exception. By
    //       keeping the exception until *after* the breakpoint has been told to step over, we
    //       ensure that any installs have already occured and thus the thread won't miss any
    //       breakpoints.
    current_breakpoint_->EndStepOver(this);
    current_breakpoint_ = nullptr;

    InternalResumeException();
    return;
  }

  if (!debug_ipc::ResumeRequest::MakesStep(run_mode_)) {
    // This could be due to a race where the user was previously single stepping and then requested
    // a continue or forward before the single stepping completed. It could also be a breakpoint
    // that was deleted while in the process of single-stepping over it. In both cases, the least
    // confusing thing is to resume automatically (since forwarding the single step exception to the
    // debugged program makes no sense).
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Single step without breakpoint. Continuing.";
    ResumeFromException();
    return;
  }

  // When stepping in a range, automatically continue as long as we're still in range.
  if (run_mode_ == debug_ipc::ResumeRequest::How::kStepInRange &&
      regs.ip() >= step_in_range_begin_ && regs.ip() < step_in_range_end_) {
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Stepping in range. Continuing.";
    ResumeFromException();
    return;
  }

  DEBUG_LOG(Thread) << ThreadPreamble(this) << "Expected single step. Notifying.";
  SendExceptionNotification(exception, regs);
}

void DebuggedThread::HandleGeneralException(debug_ipc::NotifyException* exception,
                                            const GeneralRegisters& regs) {
  auto strategy = exception_handle_->GetStrategy();
  if (strategy.is_error()) {
    FX_LOGS(WARNING) << "Failed to determine current exception strategy: "
                     << strategy.error_value().message();
    return;
  }

  debug_ipc::ExceptionStrategy applied = strategy.value();
  bool handle_now = true;

  // If the strategy is first-chance, then this is the first that we've seen this exception.
  // Further, if the applied strategy for this type is second-chance, update and handle it
  // accordingly.
  auto applicable_strategy = debug_agent_->GetExceptionStrategy(exception->type);
  if (strategy.value() == debug_ipc::ExceptionStrategy::kFirstChance &&
      applicable_strategy == debug_ipc::ExceptionStrategy::kSecondChance) {
    if (auto status = exception_handle_->SetStrategy(applicable_strategy); status.has_error()) {
      FX_LOGS(WARNING) << "Failed to apply default exception strategy: " << status.message();
      return;
    }
    applied = applicable_strategy;
    handle_now = false;
  }

  DEBUG_LOG(Thread) << ThreadPreamble(this)
                    << "Exception strategy: " << debug_ipc::ExceptionStrategyToString(applied);

  if (handle_now) {
    exception->exception.strategy = applied;
    SendExceptionNotification(exception, regs);
  } else {
    // Reset and close the handle to "forward" the exception back to the
    // program to resolve.
    exception_handle_.reset();
  }
}

void DebuggedThread::HandleSoftwareBreakpoint(debug_ipc::NotifyException* exception,
                                              GeneralRegisters& regs) {
  switch (UpdateForSoftwareBreakpoint(regs, exception->hit_breakpoints,
                                      exception->other_affected_threads)) {
    case OnStop::kIgnore:
      return;
    case OnStop::kNotify:
      SendExceptionNotification(exception, regs);
      return;
    case OnStop::kResume: {
      ResumeFromException();
      return;
    }
  }

  FX_NOTREACHED() << "Invalid OnStop.";
}

void DebuggedThread::HandleHardwareBreakpoint(debug_ipc::NotifyException* exception,
                                              GeneralRegisters& regs) {
  uint64_t breakpoint_address = arch::BreakpointInstructionForHardwareExceptionAddress(regs.ip());
  if (HardwareBreakpoint* found_bp = process_->FindHardwareBreakpoint(breakpoint_address)) {
    UpdateForHitProcessBreakpoint(debug_ipc::BreakpointType::kHardware, found_bp,
                                  exception->hit_breakpoints, exception->other_affected_threads);
    // Note: may have deleted found_bp.
  } else {
    // Hit a hw debug exception that doesn't belong to any ProcessBreakpoint. This is probably a
    // race between the removal and the exception handler.
    regs.set_ip(breakpoint_address);
  }
  SendExceptionNotification(exception, regs);
}

void DebuggedThread::HandleWatchpoint(debug_ipc::NotifyException* exception,
                                      const GeneralRegisters& regs) {
  std::optional<DebugRegisters> debug_regs = thread_handle_->GetDebugRegisters();
  if (!debug_regs) {
    DEBUG_LOG(Thread) << "Could not load debug registers to handle watchpoint.";
    return;
  }

  std::optional<WatchpointInfo> hit = debug_regs->DecodeHitWatchpoint();
  if (!hit) {
    // When no watchpoint matches this watchpoint, send the exception notification and let the
    // debugger frontend handle the exception.
    DEBUG_LOG(Thread) << "Could not find watchpoint.";
    SendExceptionNotification(exception, regs);
    return;
  }

  DEBUG_LOG(Thread) << "Found watchpoint hit at 0x" << std::hex << hit->range.ToString()
                    << " on slot " << std::dec << hit->slot;

  // Comparison is by the base of the address range.
  Watchpoint* watchpoint = process_->FindWatchpoint(hit->range);
  if (!watchpoint) {
    DEBUG_LOG(Thread) << "Could not find watchpoint for range " << hit->range.ToString();
    SendExceptionNotification(exception, regs);
    return;
  }

  // TODO(donosoc): Plumb in R/RW types.
  UpdateForHitProcessBreakpoint(watchpoint->Type(), watchpoint, exception->hit_breakpoints,
                                exception->other_affected_threads);
  // The ProcessBreakpoint could'be been deleted, so we cannot use it anymore.
  watchpoint = nullptr;
  SendExceptionNotification(exception, regs);
}

void DebuggedThread::SendExceptionNotification(debug_ipc::NotifyException* exception,
                                               const GeneralRegisters& regs) {
  exception->thread = GetThreadRecord(debug_ipc::ThreadRecord::StackAmount::kMinimal, regs);

  // Keep the thread suspended for the client.

  // TODO(brettw) suspend other threads in the process and other debugged processes as desired.

  // The debug agent is able to automatically retrieve memory blocks when a breakpoint is reached
  // based on a list of instructions.
  // Calls the automation handler which computes the memory blocks and adds them to the exception.
  automation_handler_.OnException(exception, regs, process_->process_handle(),
                                  debug_agent_->breakpoints());

  LogExceptionNotification(FROM_HERE, this, *exception);
  // Send notification.
  debug_ipc::MessageWriter writer;
  debug_ipc::WriteNotifyException(*exception, &writer);
  debug_agent_->stream()->Write(writer.MessageComplete());
}

void DebuggedThread::ClientResume(const debug_ipc::ResumeRequest& request) {
  DEBUG_LOG(Thread) << ThreadPreamble(this)
                    << "Resuming. Run mode: " << debug_ipc::ResumeRequest::HowToString(request.how)
                    << ", Range: [" << request.range_begin << ", " << request.range_end << ").";

  run_mode_ = request.how;
  step_in_range_begin_ = request.range_begin;
  step_in_range_end_ = request.range_end;

  ResumeFromException();
  if (client_suspend_handle_) {
    // Normally the single-step flat is set by the exception resumption code, but if we're resuming
    // from a pause that will do nothing so set here.
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Resuming from client suspend.";
    SetSingleStepForRunMode();
    client_suspend_handle_.reset();
  }
}

void DebuggedThread::InternalResumeException() {
  if (!in_exception()) {
    DEBUG_LOG(Thread) << ThreadPreamble(this)
                      << "Resuming from exception but there is no exception.";
    return;
  }

  SetSingleStepForRunMode();

  if (run_mode_ == debug_ipc::ResumeRequest::How::kForwardAndContinue) {
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Resuming from exception (second chance).";
    if (auto status = exception_handle_->SetStrategy(debug_ipc::ExceptionStrategy::kSecondChance);
        status.has_error()) {
      DEBUG_LOG(Thread) << ThreadPreamble(this)
                        << "Failed to set exception as second-chance: " << status.message();
    }
  } else {
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Resuming from exception (handled).";
    if (auto status = exception_handle_->SetResolution(ExceptionHandle::Resolution::kHandled);
        status.has_error()) {
      DEBUG_LOG(Thread) << ThreadPreamble(this)
                        << "Failed to set exception as handled: " << status.message();
    }
  }
  exception_handle_ = nullptr;
}

void DebuggedThread::ClientSuspend(bool synchronous) {
  if (!client_suspend_handle_)
    client_suspend_handle_ = thread_handle_->Suspend();

  // Even if there was already a client_suspend, the previous suspend could have been asynchronous
  // and still pending. When a synchronous suspend is requested make sure we honor that the thread
  // is suspended before returning. WaitForSuspension() should be relatively inexpensive if the
  // thread is already suspended.
  if (synchronous)
    thread_handle_->WaitForSuspension(DefaultSuspendDeadline());
}

std::unique_ptr<SuspendHandle> DebuggedThread::InternalSuspend(bool synchronous) {
  auto suspend_handle = thread_handle_->Suspend();
  if (synchronous)
    thread_handle_->WaitForSuspension(DefaultSuspendDeadline());
  return suspend_handle;
}

TickTimePoint DebuggedThread::DefaultSuspendDeadline() {
  // Various events and environments can cause suspensions to take a long time, so this needs to
  // be a relatively long time. We don't generally expect error cases that take infinitely long so
  // there isn't much downside of a long timeout.
  return std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
}

// Note that everything in this function is racy because the thread state can change at any time,
// even while processing an exception (an external program can kill it out from under us).
debug_ipc::ThreadRecord DebuggedThread::GetThreadRecord(
    debug_ipc::ThreadRecord::StackAmount stack_amount, std::optional<GeneralRegisters> regs) const {
  debug_ipc::ThreadRecord record = thread_handle_->GetThreadRecord(process_->koid());

  // Unwind the stack if requested. This requires the registers which are available when suspended
  // or blocked in an exception.
  if ((record.state == debug_ipc::ThreadRecord::State::kSuspended ||
       (record.state == debug_ipc::ThreadRecord::State::kBlocked &&
        record.blocked_reason == debug_ipc::ThreadRecord::BlockedReason::kException)) &&
      stack_amount != debug_ipc::ThreadRecord::StackAmount::kNone) {
    // Only record this when we actually attempt to query the stack.
    record.stack_amount = stack_amount;

    // The registers are required, fetch them if the caller didn't provide.
    if (!regs)
      regs = thread_handle_->GetGeneralRegisters();  // Note this could still fail.

    if (regs) {
      // Minimal stacks are 2 (current frame and calling one). Full stacks max out at 256 to prevent
      // edge cases, especially around corrupted stacks.
      uint32_t max_stack_depth =
          stack_amount == debug_ipc::ThreadRecord::StackAmount::kMinimal ? 2 : 256;

      UnwindStack(process_->process_handle(), process_->module_list(), thread_handle(), *regs,
                  max_stack_depth, &record.frames);
    }
  } else {
    // Didn't bother querying the stack.
    record.stack_amount = debug_ipc::ThreadRecord::StackAmount::kNone;
  }
  return record;
}

std::vector<debug::RegisterValue> DebuggedThread::ReadRegisters(
    const std::vector<debug::RegisterCategory>& cats_to_get) const {
  return thread_handle_->ReadRegisters(cats_to_get);
}

std::vector<debug::RegisterValue> DebuggedThread::WriteRegisters(
    const std::vector<debug::RegisterValue>& regs) {
  std::vector<debug::RegisterValue> written = thread_handle_->WriteRegisters(regs);

  // If we're updating the instruction pointer directly, current state is no longer valid.
  // Specifically, if we're currently on a breakpoint, we have to now know the fact that we're no
  // longer in a breakpoint.
  //
  // This is necessary to avoid the single-stepping logic that the thread does when resuming from
  // a breakpoint.
  bool rip_change = false;
  debug::RegisterID rip_id =
      GetSpecialRegisterID(arch::GetCurrentArch(), debug::SpecialRegisterType::kIP);
  for (const debug::RegisterValue& reg : regs) {
    if (reg.id == rip_id) {
      rip_change = true;
      break;
    }
  }
  if (rip_change)
    current_breakpoint_ = nullptr;

  return written;
}

void DebuggedThread::SendThreadNotification() const {
  DEBUG_LOG(Thread) << ThreadPreamble(this) << "Sending starting notification.";
  debug_ipc::NotifyThread notify;
  notify.record = GetThreadRecord(debug_ipc::ThreadRecord::StackAmount::kMinimal);
  notify.timestamp = GetNowTimestamp();

  debug_ipc::MessageWriter writer;
  debug_ipc::WriteNotifyThread(debug_ipc::MsgHeader::Type::kNotifyThreadStarting, notify, &writer);
  debug_agent_->stream()->Write(writer.MessageComplete());
}

void DebuggedThread::WillDeleteProcessBreakpoint(ProcessBreakpoint* bp) {
  if (current_breakpoint_ == bp)
    current_breakpoint_ = nullptr;
}

DebuggedThread::OnStop DebuggedThread::UpdateForSoftwareBreakpoint(
    GeneralRegisters& regs, std::vector<debug_ipc::BreakpointStats>& hit_breakpoints,
    std::vector<debug_ipc::ThreadRecord>& other_affected_threads) {
  // Get the correct address where the CPU is after hitting a breakpoint (this is
  // architecture-specific).
  uint64_t breakpoint_address = regs.ip() - arch::kExceptionOffsetForSoftwareBreakpoint;

  // When the program hits a software breakpoint, set the IP back to the exact address that
  // triggered the breakpoint, so that
  //  1) the backtrace is from the breakpoint instruction.
  //  2) if it's a breakpoint that we installed, we need to evaluate the original instruction on
  //     this address.
  if (breakpoint_address != regs.ip()) {
    regs.set_ip(breakpoint_address);
    thread_handle_->SetGeneralRegisters(regs);
  }

  if (SoftwareBreakpoint* found_bp = process_->FindSoftwareBreakpoint(breakpoint_address)) {
    LogHitBreakpoint(FROM_HERE, this, found_bp, breakpoint_address);

    switch (process_->HandleSpecialBreakpoint(found_bp)) {
      case DebuggedProcess::SpecialBreakpointResult::kContinue: {
        DEBUG_LOG(Thread) << ThreadPreamble(this) << "Loader breakpoint, internally resuming.";
        current_breakpoint_ = found_bp;
        return OnStop::kResume;
      }
      case DebuggedProcess::SpecialBreakpointResult::kKeepSuspended: {
        DEBUG_LOG(Thread) << ThreadPreamble(this) << "Loader breakpoint, keeping stopped.";
        current_breakpoint_ = found_bp;
        return OnStop::kIgnore;
      }
      case DebuggedProcess::SpecialBreakpointResult::kNotSpecial:
        break;
    }

    // When hitting a breakpoint, we need to check if indeed this exception should apply to this
    // thread or not.
    if (!found_bp->ShouldHitThread(koid())) {
      DEBUG_LOG(Thread) << ThreadPreamble(this) << "SW Breakpoint not for me. Ignoring.";
      // The way to go over is to step over the breakpoint as one would over a resume.
      current_breakpoint_ = found_bp;
      return OnStop::kResume;
    }

    UpdateForHitProcessBreakpoint(debug_ipc::BreakpointType::kSoftware, found_bp, hit_breakpoints,
                                  other_affected_threads);
    // Note: may have deleted found_bp!
  } else if (IsBreakpointInstructionAtAddress(breakpoint_address)) {
    // Hit a software breakpoint that doesn't correspond to any current breakpoint.

    switch (process_->HandleSpecialBreakpoint(nullptr)) {
      case DebuggedProcess::SpecialBreakpointResult::kContinue: {
        DEBUG_LOG(Thread) << ThreadPreamble(this)
                          << "Hardcoded loader breakpoint, internally resuming.";
        return OnStop::kResume;
      }
      case DebuggedProcess::SpecialBreakpointResult::kKeepSuspended: {
        DEBUG_LOG(Thread) << ThreadPreamble(this)
                          << "Hardcoded loader breakpoint, keeping stopped.";
        current_breakpoint_ = nullptr;
        return OnStop::kIgnore;
      }
      case DebuggedProcess::SpecialBreakpointResult::kNotSpecial:
        break;
    }
  } else {
    // Not a breakpoint instruction. Probably the breakpoint instruction used to be ours but its
    // removal raced with the exception handler. Resume from the instruction that used to be the
    // breakpoint.
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Hit non debugger SW breakpoint on 0x" << std::hex
                      << breakpoint_address;
    regs.set_ip(breakpoint_address);

    // Don't automatically continue execution here. A race for this should be unusual and maybe
    // something weird happened that caused an exception we're not set up to handle. Err on the
    // side of telling the user about the exception.
  }

  return OnStop::kNotify;
}

void DebuggedThread::UpdateForHitProcessBreakpoint(
    debug_ipc::BreakpointType exception_type, ProcessBreakpoint* process_breakpoint,
    std::vector<debug_ipc::BreakpointStats>& hit_breakpoints,
    std::vector<debug_ipc::ThreadRecord>& other_affected_threads) {
  current_breakpoint_ = process_breakpoint;

  process_breakpoint->OnHit(this, exception_type, hit_breakpoints, other_affected_threads);

  // Delete any one-shot breakpoints. Since there can be multiple Breakpoints (some one-shot, some
  // not) referring to the current ProcessBreakpoint, this operation could delete the
  // ProcessBreakpoint or it could not. If it does, our observer will be told and
  // current_breakpoint_ will be cleared.
  for (const auto& stats : hit_breakpoints) {
    if (stats.should_delete)
      process_->debug_agent()->RemoveBreakpoint(stats.id);
  }
}

bool DebuggedThread::IsBreakpointInstructionAtAddress(uint64_t address) const {
  arch::BreakInstructionType instruction = 0;
  size_t bytes_read = 0;
  if (process_->process_handle()
          .ReadMemory(address, &instruction, sizeof(instruction), &bytes_read)
          .has_error() ||
      bytes_read != sizeof(instruction))
    return false;
  return arch::IsBreakpointInstruction(instruction);
}

void DebuggedThread::SetSingleStepForRunMode() {
  // When we're single-stepping over a breakpoint, that overrides the user run mode.
  thread_handle_->SetSingleStep(stepping_over_breakpoint_ ||
                                debug_ipc::ResumeRequest::MakesStep(run_mode_));
}

}  // namespace debug_agent
