//===-- BreakpointLocation.cpp ----------------------------------*- C++ -*-===//
//
// 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()) {
      if (log)
        log->Printf("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()) {
          log->Printf("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.reset(new 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);
    log->Printf("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);
      }

      if (sc.comp_unit != nullptr) {
        s->EOL();
        s->Indent("compile unit = ");
        static_cast<FileSpec *>(sc.comp_unit)->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("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, hit count = %u ", (IsResolved() ? "" : "un"),
              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();
}
