//===-- BreakpointLocation.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 "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObject.h"

using namespace lldb;
using namespace lldb_private;

BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
                                       const Address &addr, lldb::tid_t tid,
                                       bool check_for_resolver)
    : m_should_resolve_indirect_functions(false), m_is_reexported(false),
      m_is_indirect(false), m_address(addr), m_owner(owner),
      m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
  if (check_for_resolver) {
    const Symbol *symbol = m_address.CalculateSymbolContextSymbol();
    if (symbol && symbol->IsIndirect()) {
      SetShouldResolveIndirectFunctions(true);
    }
  }

  SetThreadIDInternal(tid);
}

BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner)
    : m_should_resolve_indirect_functions(false), m_is_reexported(false),
      m_is_indirect(false), m_address(LLDB_INVALID_ADDRESS), m_owner(owner),
      m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
  SetThreadIDInternal(LLDB_INVALID_THREAD_ID);
}

BreakpointLocation::~BreakpointLocation() {
  llvm::consumeError(ClearBreakpointSite());
}

lldb::addr_t BreakpointLocation::GetLoadAddress() const {
  return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
}

const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
    BreakpointOptions::OptionKind kind) const {
  if (m_options_up && m_options_up->IsOptionSet(kind))
    return *m_options_up;
  return m_owner.GetOptions();
}

Address &BreakpointLocation::GetAddress() { return m_address; }

Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }

Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }

bool BreakpointLocation::IsEnabled() const {
  if (!m_owner.IsEnabled())
    return false;
  if (m_options_up != nullptr)
    return m_options_up->IsEnabled();
  return true;
}

llvm::Error BreakpointLocation::SetEnabled(bool enabled) {
  GetLocationOptions().SetEnabled(enabled);
  llvm::Error error = enabled ? ResolveBreakpointSite() : ClearBreakpointSite();
  SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
                                             : eBreakpointEventTypeDisabled);
  return error;
}

bool BreakpointLocation::IsAutoContinue() const {
  if (m_options_up &&
      m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
    return m_options_up->IsAutoContinue();
  return m_owner.IsAutoContinue();
}

void BreakpointLocation::SetAutoContinue(bool auto_continue) {
  GetLocationOptions().SetAutoContinue(auto_continue);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
}

void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
  SetThreadIDInternal(thread_id);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

lldb::tid_t BreakpointLocation::GetThreadID() {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetTID();
  return LLDB_INVALID_THREAD_ID;
}

void BreakpointLocation::SetThreadIndex(uint32_t index) {
  if (index != 0)
    GetLocationOptions().GetThreadSpec()->SetIndex(index);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetIndex(index);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

uint32_t BreakpointLocation::GetThreadIndex() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetIndex();
  return 0;
}

void BreakpointLocation::SetThreadName(const char *thread_name) {
  if (thread_name != nullptr)
    GetLocationOptions().GetThreadSpec()->SetName(thread_name);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetName(thread_name);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

const char *BreakpointLocation::GetThreadName() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetName();
  return nullptr;
}

void BreakpointLocation::SetQueueName(const char *queue_name) {
  if (queue_name != nullptr)
    GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetQueueName(queue_name);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

const char *BreakpointLocation::GetQueueName() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetQueueName();
  return nullptr;
}

bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
  if (m_options_up != nullptr && m_options_up->HasCallback())
    return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
  return m_owner.InvokeCallback(context, GetID());
}

bool BreakpointLocation::IsCallbackSynchronous() {
  if (m_options_up != nullptr && m_options_up->HasCallback())
    return m_options_up->IsCallbackSynchronous();
  return m_owner.GetOptions().IsCallbackSynchronous();
}

void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
                                     void *baton, bool is_synchronous) {
  // The default "Baton" class will keep a copy of "baton" and won't free or
  // delete it when it goes out of scope.
  GetLocationOptions().SetCallback(
      callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}

void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
                                     const BatonSP &baton_sp,
                                     bool is_synchronous) {
  GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}

void BreakpointLocation::ClearCallback() {
  GetLocationOptions().ClearCallback();
}

void BreakpointLocation::SetCondition(StopCondition condition) {
  GetLocationOptions().SetCondition(std::move(condition));
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
}

const StopCondition &BreakpointLocation::GetCondition() const {
  return GetOptionsSpecifyingKind(BreakpointOptions::eCondition).GetCondition();
}

bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
                                           Status &error) {
  Log *log = GetLog(LLDBLog::Breakpoints);

  std::lock_guard<std::mutex> guard(m_condition_mutex);

  StopCondition condition = GetCondition();

  if (!condition) {
    m_user_expression_sp.reset();
    return false;
  }

  error.Clear();

  DiagnosticManager diagnostics;

  if (condition.GetHash() != m_condition_hash || !m_user_expression_sp ||
      !m_user_expression_sp->IsParseCacheable() ||
      !m_user_expression_sp->MatchesContext(exe_ctx)) {
    LanguageType language = condition.GetLanguage();
    if (language == lldb::eLanguageTypeUnknown) {
      // See if we can figure out the language from the frame, otherwise use the
      // default language:
      if (CompileUnit *comp_unit =
              m_address.CalculateSymbolContextCompileUnit())
        language = comp_unit->GetLanguage();
    }

    m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
        condition.GetText(), llvm::StringRef(), SourceLanguage{language},
        Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr,
        error));
    if (error.Fail()) {
      LLDB_LOGF(log, "Error getting condition expression: %s.",
                error.AsCString());
      m_user_expression_sp.reset();
      return true;
    }

    if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
                                     eExecutionPolicyOnlyWhenNeeded, true,
                                     false)) {
      error = Status::FromError(
          diagnostics.GetAsError(lldb::eExpressionParseError,
                                 "Couldn't parse conditional expression:"));

      m_user_expression_sp.reset();
      return true;
    }

    m_condition_hash = condition.GetHash();
  }

  // We need to make sure the user sees any parse errors in their condition, so
  // we'll hook the constructor errors up to the debugger's Async I/O.

  ValueObjectSP result_value_sp;

  EvaluateExpressionOptions options;
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  options.SetTryAllThreads(true);
  options.SetSuppressPersistentResult(
      true); // Don't generate a user variable for condition expressions.

  Status expr_error;

  diagnostics.Clear();

  ExpressionVariableSP result_variable_sp;

  ExpressionResults result_code = m_user_expression_sp->Execute(
      diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);

  bool ret;

  if (result_code == eExpressionCompleted) {
    if (!result_variable_sp) {
      error = Status::FromErrorString("Expression did not return a result");
      return false;
    }

    result_value_sp = result_variable_sp->GetValueObject();

    if (result_value_sp) {
      ret = result_value_sp->IsLogicalTrue(error);
      if (log) {
        if (error.Success()) {
          LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
                    ret ? "true" : "false");
        } else {
          error = Status::FromErrorString(
              "Failed to get an integer result from the expression");
          ret = false;
        }
      }
    } else {
      ret = false;
      error = Status::FromErrorString(
          "Failed to get any result from the expression");
    }
  } else {
    ret = false;
    error = Status::FromError(diagnostics.GetAsError(
        lldb::eExpressionParseError, "Couldn't execute expression:"));
  }

  return ret;
}

uint32_t BreakpointLocation::GetIgnoreCount() const {
  return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
      .GetIgnoreCount();
}

void BreakpointLocation::SetIgnoreCount(uint32_t n) {
  GetLocationOptions().SetIgnoreCount(n);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
}

void BreakpointLocation::DecrementIgnoreCount() {
  if (m_options_up != nullptr) {
    uint32_t loc_ignore = m_options_up->GetIgnoreCount();
    if (loc_ignore != 0)
      m_options_up->SetIgnoreCount(loc_ignore - 1);
  }
}

bool BreakpointLocation::IgnoreCountShouldStop() {
  uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
  uint32_t loc_ignore = 0;
  if (m_options_up != nullptr)
    loc_ignore = m_options_up->GetIgnoreCount();

  if (loc_ignore != 0 || owner_ignore != 0) {
    m_owner.DecrementIgnoreCount();
    DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
                            // since it won't get a chance to.
    return false;
  }
  return true;
}

BreakpointOptions &BreakpointLocation::GetLocationOptions() {
  // If we make the copy we don't copy the callbacks because that is
  // potentially expensive and we don't want to do that for the simple case
  // where someone is just disabling the location.
  if (m_options_up == nullptr)
    m_options_up = std::make_unique<BreakpointOptions>(false);

  return *m_options_up;
}

bool BreakpointLocation::ValidForThisThread(Thread &thread) {
  return thread.MatchesSpec(
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate());
}

BreakpointLocationSP
BreakpointLocation::WasHit(StoppointCallbackContext *context) {
  // Only the BreakpointResolverScripted provides WasHit.
  BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
  BreakpointResolverScripted *scripted =
      llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
  if (!scripted)
    return shared_from_this();

  StackFrameSP frame_sp = context->exe_ctx_ref.GetFrameSP();
  if (!frame_sp)
    return shared_from_this();

  BreakpointLocationSP return_loc_sp =
      scripted->WasHit(frame_sp, shared_from_this());
  // If this is a facade location, then we won't have bumped its hit count
  // while processing the original location hit.  Do so here.  We don't need
  // to bump the breakpoint's hit count, however, since hitting the real
  // location would have already done that.
  // Also we have to check the enabled state here, since we would never have
  // gotten here with a real location...
  if (return_loc_sp && return_loc_sp->IsFacade()) {
    if (return_loc_sp->IsEnabled())
      return_loc_sp->m_hit_counter.Increment();
    else
      return {};
  }
  return return_loc_sp;
}

// RETURNS - true if we should stop at this breakpoint, false if we
// should continue.  Note, we don't check the thread spec for the breakpoint
// here, since if the breakpoint is not for this thread, then the event won't
// even get reported, so the check is redundant.

bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context,
                                    lldb::BreakpointLocationSP &facade_loc_sp) {
  bool should_stop = true;
  Log *log = GetLog(LLDBLog::Breakpoints);

  // Do this first, if a location is disabled, it shouldn't increment its hit
  // count.
  if (!IsEnabled())
    return false;

  // Next check WasHit:
  BreakpointLocationSP loc_hit_sp = WasHit(context);

  if (!loc_hit_sp) {
    // We bump the hit counts in StopInfoBreakpoint::ShouldStopSynchronous,
    // before we call into each location's ShouldStop.  So we need to undo
    // that here.
    UndoBumpHitCount();
    return false;
  }

  // If the location hit was not us, it was a facade location, in which case
  // we should use the facade location's callbacks, etc.  Those will all be
  // run in the asynchronous phase, so for now we just have to record the fact
  // that we should treat this as a facade hit.  This is strictly an out
  // parameter, so clear it if this isn't a facade hit.
  if (loc_hit_sp.get() != this)
    facade_loc_sp = loc_hit_sp;
  else
    facade_loc_sp.reset();

  // We only run synchronous callbacks in ShouldStop:
  context->is_synchronous = true;
  should_stop = InvokeCallback(context);

  if (log) {
    StreamString s;
    GetDescription(&s, lldb::eDescriptionLevelVerbose);
    LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
              should_stop ? "stopping" : "continuing");
    if (facade_loc_sp) {
      s.Clear();
      facade_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
      LLDB_LOGF(log, "Attributing to facade location: %s.\n", s.GetData());
    }
  }

  return should_stop;
}

void BreakpointLocation::BumpHitCount() {
  if (IsEnabled()) {
    // Step our hit count, and also step the hit count of the owner.
    m_hit_counter.Increment();
    m_owner.m_hit_counter.Increment();
  }
}

void BreakpointLocation::UndoBumpHitCount() {
  if (IsEnabled()) {
    // Step our hit count, and also step the hit count of the owner.
    m_hit_counter.Decrement();
    m_owner.m_hit_counter.Decrement();
  }
}

bool BreakpointLocation::IsResolved() const {

  bool has_site = m_bp_site_sp.get() != nullptr;
  // Facade locations are currently always considered resolved.
  return has_site || IsFacade();
}

lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
  return m_bp_site_sp;
}

llvm::Error BreakpointLocation::ResolveBreakpointSite() {
  // This might be a facade location, which doesn't have an address.
  // In that case, don't attempt to make a site.
  if (m_bp_site_sp || IsFacade())
    return llvm::Error::success();

  Process *process = m_owner.GetTarget().GetProcessSP().get();
  if (process == nullptr)
    return llvm::createStringError("no process");

  lldb::break_id_t new_id =
      process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());

  if (new_id == LLDB_INVALID_BREAK_ID)
    return llvm::createStringError(
        llvm::formatv("Failed to add breakpoint site at {0:x}",
                      m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())));

  if (!IsResolved())
    return llvm::createStringError(
        "breakpoint site created but location is still unresolved");

  return llvm::Error::success();
}

bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
  m_bp_site_sp = bp_site_sp;
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
  return true;
}

llvm::Error BreakpointLocation::ClearBreakpointSite() {
  if (!m_bp_site_sp) {
    // This might be a Facade Location, which don't have sites or addresses
    if (IsFacade())
      return llvm::Error::success();
    return llvm::createStringError("no breakpoint site to clear");
  }

  // If the process exists, get it to remove the owner, it will remove the
  // physical implementation of the breakpoint as well if there are no more
  // owners.  Otherwise just remove this owner.
  if (ProcessSP process_sp = m_owner.GetTarget().GetProcessSP())
    process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
                                                    GetID(), m_bp_site_sp);
  else
    m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());

  m_bp_site_sp.reset();
  return llvm::Error::success();
}

void BreakpointLocation::GetDescription(Stream *s,
                                        lldb::DescriptionLevel level) {
  SymbolContext sc;

  // If this is a scripted breakpoint, give it a chance to describe its
  // locations:
  std::optional<std::string> scripted_opt;
  BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
  BreakpointResolverScripted *scripted =
      llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
  if (scripted)
    scripted_opt = scripted->GetLocationDescription(shared_from_this(), level);

  bool is_scripted_desc = scripted_opt.has_value();

  // If the description level is "initial" then the breakpoint is printing out
  // our initial state, and we should let it decide how it wants to print our
  // label.
  if (level != eDescriptionLevelInitial) {
    s->Indent();
    BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
  }

  if (level == lldb::eDescriptionLevelBrief)
    return;

  if (level != eDescriptionLevelInitial)
    s->PutCString(": ");

  if (level == lldb::eDescriptionLevelVerbose)
    s->IndentMore();

  if (is_scripted_desc) {
    s->PutCString(scripted_opt->c_str());
  } else if (m_address.IsSectionOffset()) {
    m_address.CalculateSymbolContext(&sc);

    if (level == lldb::eDescriptionLevelFull ||
        level == eDescriptionLevelInitial) {
      if (IsReExported())
        s->PutCString("re-exported target = ");
      else
        s->PutCString("where = ");

      // If there's a preferred line entry for printing, use that.
      bool show_function_info = true;
      if (auto preferred = GetPreferredLineEntry()) {
        sc.line_entry = *preferred;
        // FIXME: We're going to get the function name wrong when the preferred
        // line entry is not the lowest one.  For now, just leave the function
        // out in this case, but we really should also figure out how to easily
        // fake the function name here.
        show_function_info = false;
      }
      sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
                         false, true, false, show_function_info,
                         show_function_info, show_function_info);
    } else {
      if (sc.module_sp) {
        s->EOL();
        s->Indent("module = ");
        sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
      }

      if (sc.comp_unit != nullptr) {
        s->EOL();
        s->Indent("compile unit = ");
        sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);

        if (sc.function != nullptr) {
          s->EOL();
          s->Indent("function = ");
          s->PutCString(sc.function->GetName().AsCString("<unknown>"));
          if (ConstString mangled_name =
                  sc.function->GetMangled().GetMangledName()) {
            s->EOL();
            s->Indent("mangled function = ");
            s->PutCString(mangled_name.AsCString());
          }
        }

        if (sc.line_entry.line > 0) {
          s->EOL();
          s->Indent("location = ");
          if (auto preferred = GetPreferredLineEntry())
            preferred->DumpStopContext(s, true);
          else
            sc.line_entry.DumpStopContext(s, true);
        }

      } else {
        // If we don't have a comp unit, see if we have a symbol we can print.
        if (sc.symbol) {
          s->EOL();
          if (IsReExported())
            s->Indent("re-exported target = ");
          else
            s->Indent("symbol = ");
          s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
        }
      }
    }
  }

  if (level == lldb::eDescriptionLevelVerbose) {
    s->EOL();
    s->Indent();
  }

  if (!is_scripted_desc) {
    if (m_address.IsSectionOffset() &&
        (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
      s->Printf(", ");
    s->Printf("address = ");

    ExecutionContextScope *exe_scope = nullptr;
    Target *target = &m_owner.GetTarget();
    if (target)
      exe_scope = target->GetProcessSP().get();
    if (exe_scope == nullptr)
      exe_scope = target;

    if (level == eDescriptionLevelInitial)
      m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
                     Address::DumpStyleFileAddress);
    else
      m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
                     Address::DumpStyleModuleWithFileAddress);

    if (IsIndirect() && m_bp_site_sp) {
      Address resolved_address;
      resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
      const Symbol *resolved_symbol =
          resolved_address.CalculateSymbolContextSymbol();
      if (resolved_symbol) {
        if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
          s->Printf(", ");
        else if (level == lldb::eDescriptionLevelVerbose) {
          s->EOL();
          s->Indent();
        }
        s->Printf("indirect target = %s",
                  resolved_symbol->GetName().GetCString());
      }
    }
  }

  // FIXME: scripted breakpoint are currently always resolved.  Does this seem
  // right? If they don't add any scripted locations, we shouldn't consider them
  // resolved.
  bool is_resolved = is_scripted_desc || IsResolved();
  // A scripted breakpoint might be resolved but not have a site.  Be sure to
  // check for that.
  bool is_hardware = !is_scripted_desc && IsResolved() && m_bp_site_sp &&
                     m_bp_site_sp->IsHardware();

  if (level == lldb::eDescriptionLevelVerbose) {
    s->EOL();
    s->Indent();
    s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
    s->Indent();
    s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
    s->Indent();
    s->Printf("hit count = %-4u\n", GetHitCount());

    if (m_options_up) {
      s->Indent();
      m_options_up->GetDescription(s, level);
      s->EOL();
    }
    s->IndentLess();
  } else if (level != eDescriptionLevelInitial) {
    s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
              (is_hardware ? "hardware, " : ""), GetHitCount());
    if (m_options_up) {
      m_options_up->GetDescription(s, level);
    }
  }
}

void BreakpointLocation::Dump(Stream *s) const {
  if (s == nullptr)
    return;

  bool is_resolved = IsResolved();
  bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();

  lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
                        .GetThreadSpecNoCreate()
                        ->GetTID();
  s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
            "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
            "hit_count = %-4u  ignore_count = %-4u",
            GetID(), tid,
            (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
            (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
                ? "enabled "
                : "disabled",
            is_hardware ? "hardware" : "software", GetHitCount(),
            GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
                .GetIgnoreCount());
}

void BreakpointLocation::SendBreakpointLocationChangedEvent(
    lldb::BreakpointEventType eventKind) {
  if (!m_owner.IsInternal()) {
    auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(
        eventKind, m_owner.shared_from_this());
    data_sp->GetBreakpointLocationCollection().Add(shared_from_this());
    m_owner.GetTarget().NotifyBreakpointChanged(m_owner, data_sp);
  }
}

std::optional<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() {
  auto preferred_opt = GetPreferredLineEntry();
  if (!preferred_opt)
    return {};
  LineEntry preferred = *preferred_opt;
  SymbolContext sc;
  if (!m_address.CalculateSymbolContext(&sc))
    return {};
  // Don't return anything special if frame 0 is the preferred line entry.
  // We not really telling the stack frame list to do anything special in that
  // case.
  if (!LineEntry::Compare(sc.line_entry, preferred))
    return {};

  if (!sc.block)
    return {};

  // Blocks have their line info in Declaration form, so make one here:
  Declaration preferred_decl(preferred.GetFile(), preferred.line,
                             preferred.column);

  uint32_t depth = 0;
  Block *inlined_block = sc.block->GetContainingInlinedBlock();
  while (inlined_block) {
    // If we've moved to a block that this isn't the start of, that's not
    // our inlining info or call site, so we can stop here.
    Address start_address;
    if (!inlined_block->GetStartAddress(start_address) ||
        start_address != m_address)
      return {};

    const InlineFunctionInfo *info = inlined_block->GetInlinedFunctionInfo();
    if (info) {
      if (preferred_decl == info->GetDeclaration())
        return depth;
      if (preferred_decl == info->GetCallSite())
        return depth + 1;
    }
    inlined_block = inlined_block->GetInlinedParent();
    depth++;
  }
  return {};
}

void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
  m_address = swap_from->m_address;
  m_should_resolve_indirect_functions =
      swap_from->m_should_resolve_indirect_functions;
  m_is_reexported = swap_from->m_is_reexported;
  m_is_indirect = swap_from->m_is_indirect;
  m_user_expression_sp.reset();
}

void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
  if (thread_id != LLDB_INVALID_THREAD_ID) {
    GetLocationOptions().SetThreadID(thread_id);
  } else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->SetThreadID(thread_id);
  }
}
