// 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/protocol.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/register_value.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"
#include "src/lib/unwinder/error.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::IsDebugLoggingActive())
    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::IsDebugLoggingActive())
    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)
    : thread_handle_(std::move(handle)),
      debug_agent_(debug_agent),
      process_(process),
      weak_factory_(this) {}

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.
    LOGS(Warn) << "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 = exception_handle_->GetRecord();
  exception.timestamp = GetNowTimestamp();

  // TODO(https://fxbug.dev/42086129) clean up the single-step queue here (currently only handled in
  // the HandleSingleStep() function to advance the single-step queue when the stepped-over
  // instruction crashes rather than issues a single-step exception.

  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();
      // It's possible that the software breakpoint we see is newly installed, e.g., when a user
      // uninstall and reinstall a breakpoint at the same location. We shouldn't skip the breakpoint
      // instruction in this case.
      if (regs && process_->FindSoftwareBreakpoint(regs->ip()) == nullptr &&
          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_) {
    // TODO(https://fxbug.dev/42086129) this single-step cleanup needs to be unconditionally
    // executed for any exception on the thread (not just here in the "single step" handler) because
    // the thread could crash on the instruction being stepped over and then the step over queue
    // will never be cleaned up.

    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 occurred 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;
  }

  // When stepping with a count, automatically continue if step_count_ > 1.
  if (run_mode_ == debug_ipc::ResumeRequest::How::kStepInstruction && step_count_ > 1) {
    DEBUG_LOG(Thread) << ThreadPreamble(this) << "Stepping with count. Continuing.";
    step_count_ -= 1;
    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()) {
    LOGS(Warn) << "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()) {
      LOGS(Warn) << "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::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_agent_->SendNotification(*exception);
}

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

  run_mode_ = request.how;
  step_count_ = request.count;
  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();

  // When we're stopped on an exception that doesn't correspond to one of our breakpoints or us
  // single stepping, we forward the exception instead of handling it. This is very important to
  // expectations about "continuing" while stopped on a crash for example. Here's a pretty common
  // situation:
  //  1. User sets a breakpoint on a function call somewhere.
  //  2. User steps over function
  //  3. Something in the function caused a crash.
  //  4. User types "next" or "step over" in VSCode (possibly many times).
  //  5. The same crashing exception is raised over and over again because we cannot single step
  //     over it, the program never continues or proceeds to the system crash handler.
  //
  // What we want to happen, however, is more like this:
  //  1..4 same as above
  //  5. Crashing exception is reported again if left unhandled as a second chance exception.
  //  6. User types "next" or clicks "step over" again.
  //  7. Exception is released, process actually crashes and is lost to the debugger.
  //
  // This is closer to the experience in GDB, but with second-chance exceptions which is more
  // Windows-like. It is up to the client to properly display the second-chance notification to the
  // user so they can take some action if they want before the process actually crashes.
  if (run_mode_ == debug_ipc::ResumeRequest::How::kForwardAndContinue ||
      (debug_ipc::ResumeRequest::MakesStep(run_mode_) &&
       !debug_ipc::IsDebug(exception_handle_->GetType(thread_handle())))) {
    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;

      auto err = UnwindStack(process_->process_handle(), process_->module_list(), thread_handle(),
                             *regs, max_stack_depth, &record.frames);
      if (err.has_err()) {
        DEBUG_LOG(Thread) << ThreadPreamble(this) << "Unwinder aborted: " << err.msg();
      }
    }
  } 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) {
  // If we're updating the instruction pointer to a new value 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);

  auto ip = std::find_if(regs.begin(), regs.end(),
                         [rip_id](const debug::RegisterValue& rv) { return rv.id == rip_id; });

  if (ip != regs.end()) {
    auto current_registers = thread_handle_->GetGeneralRegisters();
    if (current_registers && ip->GetValue() != current_registers->ip()) {
      rip_change = true;
    }
  }

  if (rip_change)
    current_breakpoint_ = nullptr;

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

  return written;
}

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

  debug_agent_->SendNotification(notify);
}

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)) {
#if defined(__linux__)
    // OnLinux, the loader breakpoint is a software breakpoint we inserted. Special-case this.
    if (found_bp->IsInternalLdSoBreakpoint()) {
      if (process_->HandleLoaderBreakpoint(breakpoint_address)) {
        // |HandleLoaderBreakpoint| may suspend the task and it's safe for us to always resume.
        DEBUG_LOG(Thread) << ThreadPreamble(this)
                          << "Hardcoded loader breakpoint, internally resuming.";
        current_breakpoint_ = found_bp;
        return OnStop::kResume;
      }
      return OnStop::kNotify;
    }
#endif
    LogHitBreakpoint(FROM_HERE, this, found_bp, breakpoint_address);

    // 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.

    if (process_->HandleLoaderBreakpoint(breakpoint_address)) {
      // |HandleLoaderBreakpoint| may suspend the task and it's safe for us to always resume.
      DEBUG_LOG(Thread) << ThreadPreamble(this)
                        << "Hardcoded loader breakpoint, internally resuming.";
      return OnStop::kResume;
    }
  } 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;

    // 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
