//===-- 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/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObject.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/Log.h"
#include "lldb/Utility/StreamString.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 hardware, bool check_for_resolver)
    : StoppointLocation(loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()),
                        hardware),
      m_being_created(true), m_should_resolve_indirect_functions(false),
      m_is_reexported(false), m_is_indirect(false), m_address(addr),
      m_owner(owner), m_options_up(), m_bp_site_sp(), m_condition_mutex() {
  if (check_for_resolver) {
    Symbol *symbol = m_address.CalculateSymbolContextSymbol();
    if (symbol && symbol->IsIndirect()) {
      SetShouldResolveIndirectFunctions(true);
    }
  }

  SetThreadID(tid);
  m_being_created = false;
}

BreakpointLocation::~BreakpointLocation() { 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.get();
  else
    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;
  else if (m_options_up != nullptr)
    return m_options_up->IsEnabled();
  else
    return true;
}

void BreakpointLocation::SetEnabled(bool enabled) {
  GetLocationOptions()->SetEnabled(enabled);
  if (enabled) {
    ResolveBreakpointSite();
  } else {
    ClearBreakpointSite();
  }
  SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
                                             : eBreakpointEventTypeDisabled);
}

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

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

void BreakpointLocation::SetThreadID(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);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

lldb::tid_t BreakpointLocation::GetThreadID() {
  const ThreadSpec *thread_spec = 
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          ->GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetTID();
  else
    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();
  else
    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();
  else
    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();
  else
    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());
  else
    return m_owner.InvokeCallback(context, GetID());
}

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 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(const char *condition) {
  GetLocationOptions()->SetCondition(condition);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
}

const char *BreakpointLocation::GetConditionText(size_t *hash) const {
  return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
      ->GetConditionText(hash);
}

bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
                                           Status &error) {
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);

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

  size_t condition_hash;
  const char *condition_text = GetConditionText(&condition_hash);

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

  error.Clear();

  DiagnosticManager diagnostics;

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

    m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
        condition_text, llvm::StringRef(), 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.SetErrorStringWithFormat(
          "Couldn't parse conditional expression:\n%s",
          diagnostics.GetString().c_str());
      m_user_expression_sp.reset();
      return true;
    }

    m_condition_hash = condition_hash;
  }

  // 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.SetResultIsInternal(
      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.SetErrorString("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.SetErrorString(
              "Failed to get an integer result from the expression");
          ret = false;
        }
      }
    } else {
      ret = false;
      error.SetErrorString("Failed to get any result from the expression");
    }
  } else {
    ret = false;
    error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
                                   diagnostics.GetString().c_str());
  }

  return ret;
}

uint32_t BreakpointLocation::GetIgnoreCount() {
  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() {
  if (m_options_up != nullptr) {
    uint32_t loc_ignore = m_options_up->GetIgnoreCount();
    if (loc_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.get();
}

bool BreakpointLocation::ValidForThisThread(Thread *thread) {
  return thread
      ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
      ->GetThreadSpecNoCreate());
}

// 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) {
  bool should_stop = true;
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);

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

  if (!IgnoreCountShouldStop())
    return false;

  if (!m_owner.IgnoreCountShouldStop())
    return false;

  // 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");
  }

  return should_stop;
}

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

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

bool BreakpointLocation::IsResolved() const {
  return m_bp_site_sp.get() != nullptr;
}

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

bool BreakpointLocation::ResolveBreakpointSite() {
  if (m_bp_site_sp)
    return true;

  Process *process = m_owner.GetTarget().GetProcessSP().get();
  if (process == nullptr)
    return false;

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

  if (new_id == LLDB_INVALID_BREAK_ID) {
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
    if (log)
      log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
                   m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
  }

  return IsResolved();
}

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

bool BreakpointLocation::ClearBreakpointSite() {
  if (m_bp_site_sp.get()) {
    ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
    // 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 (process_sp)
      process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
                                                GetID(), m_bp_site_sp);
    else
      m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());

    m_bp_site_sp.reset();
    return true;
  }
  return false;
}

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

  // 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 (m_address.IsSectionOffset()) {
    m_address.CalculateSymbolContext(&sc);

    if (level == lldb::eDescriptionLevelFull ||
        level == eDescriptionLevelInitial) {
      if (IsReExported())
        s->PutCString("re-exported target = ");
      else
        s->PutCString("where = ");
      sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
                         false, true, false, true, true);
    } 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 (sc.line_entry.line > 0) {
          s->EOL();
          s->Indent("location = ");
          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 (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);
    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());
    }
  }

  if (level == lldb::eDescriptionLevelVerbose) {
    s->EOL();
    s->Indent();
    s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
    s->Indent();
    s->Printf("hardware = %s\n", IsHardware() ? "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 ", (IsResolved() ? "" : "un"),
              (IsHardware() ? "hardware, " : ""), GetHitCount());
    if (m_options_up) {
      m_options_up->GetDescription(s, level);
    }
  }
}

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

  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  "
            "hw_index = %i  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",
            IsHardware() ? "hardware" : "software", GetHardwareIndex(),
            GetHitCount(),
            GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
                ->GetIgnoreCount());
}

void BreakpointLocation::SendBreakpointLocationChangedEvent(
    lldb::BreakpointEventType eventKind) {
  if (!m_being_created && !m_owner.IsInternal() &&
      m_owner.GetTarget().EventTypeHasListeners(
          Target::eBroadcastBitBreakpointChanged)) {
    Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
        eventKind, m_owner.shared_from_this());
    data->GetBreakpointLocationCollection().Add(shared_from_this());
    m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
                                       data);
  }
}

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();
}
