//===-- Watchpoint.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/Watchpoint.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointResource.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectMemory.h"

using namespace lldb;
using namespace lldb_private;

Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size,
                       const CompilerType *type, bool hardware)
    : StoppointSite(0, addr, size, hardware), m_target(target),
      m_enabled(false), m_is_hardware(hardware), m_is_watch_variable(false),
      m_is_ephemeral(false), m_disabled_count(0), m_watch_read(0),
      m_watch_write(0), m_watch_modify(0), m_ignore_count(0) {

  if (type && type->IsValid())
    m_type = *type;
  else {
    // If we don't have a known type, then we force it to unsigned int of the
    // right size.
    auto type_system_or_err =
        target.GetScratchTypeSystemForLanguage(eLanguageTypeC);
    if (auto err = type_system_or_err.takeError()) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err),
                     "Failed to set type: {0}");
    } else {
      if (auto ts = *type_system_or_err) {
        if (size <= target.GetArchitecture().GetAddressByteSize()) {
          m_type =
              ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
        } else {
          CompilerType clang_uint8_type =
              ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
          m_type = clang_uint8_type.GetArrayType(size);
        }
      } else
        LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err),
                       "Failed to set type: Typesystem is no longer live: {0}");
    }
  }

  // Set the initial value of the watched variable:
  if (m_target.GetProcessSP()) {
    ExecutionContext exe_ctx;
    m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx);
    CaptureWatchedValue(exe_ctx);
  }
}

Watchpoint::~Watchpoint() = default;

// This function is used when "baton" doesn't need to be freed
void Watchpoint::SetCallback(WatchpointHitCallback 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.
  m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),
                        is_synchronous);

  SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged);
}

// This function is used when a baton needs to be freed and therefore is
// contained in a "Baton" subclass.
void Watchpoint::SetCallback(WatchpointHitCallback callback,
                             const BatonSP &callback_baton_sp,
                             bool is_synchronous) {
  m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
  SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged);
}

bool Watchpoint::SetupVariableWatchpointDisabler(StackFrameSP frame_sp) const {
  if (!frame_sp)
    return false;

  ThreadSP thread_sp = frame_sp->GetThread();
  if (!thread_sp)
    return false;

  uint32_t return_frame_index =
      thread_sp->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame) + 1;
  if (return_frame_index >= LLDB_INVALID_FRAME_ID)
    return false;

  StackFrameSP return_frame_sp(
      thread_sp->GetStackFrameAtIndex(return_frame_index));
  if (!return_frame_sp)
    return false;

  ExecutionContext exe_ctx(return_frame_sp);
  TargetSP target_sp = exe_ctx.GetTargetSP();
  if (!target_sp)
    return false;

  Address return_address(return_frame_sp->GetFrameCodeAddress());
  lldb::addr_t return_addr = return_address.GetLoadAddress(target_sp.get());
  if (return_addr == LLDB_INVALID_ADDRESS)
    return false;

  BreakpointSP bp_sp = target_sp->CreateBreakpoint(
      return_addr, /*internal=*/true, /*request_hardware=*/false);
  if (!bp_sp || !bp_sp->HasResolvedLocations())
    return false;

  auto wvc_up = std::make_unique<WatchpointVariableContext>(GetID(), exe_ctx);
  auto baton_sp = std::make_shared<WatchpointVariableBaton>(std::move(wvc_up));
  bp_sp->SetCallback(VariableWatchpointDisabler, baton_sp);
  bp_sp->SetOneShot(true);
  bp_sp->SetBreakpointKind("variable watchpoint disabler");
  return true;
}

bool Watchpoint::VariableWatchpointDisabler(void *baton,
                                            StoppointCallbackContext *context,
                                            user_id_t break_id,
                                            user_id_t break_loc_id) {
  assert(baton && "null baton");
  if (!baton || !context)
    return false;

  Log *log = GetLog(LLDBLog::Watchpoints);

  WatchpointVariableContext *wvc =
      static_cast<WatchpointVariableContext *>(baton);

  LLDB_LOGF(log, "called by breakpoint %" PRIu64 ".%" PRIu64, break_id,
            break_loc_id);

  if (wvc->watch_id == LLDB_INVALID_WATCH_ID)
    return false;

  TargetSP target_sp = context->exe_ctx_ref.GetTargetSP();
  if (!target_sp)
    return false;

  ProcessSP process_sp = target_sp->GetProcessSP();
  if (!process_sp)
    return false;

  WatchpointSP watch_sp =
      target_sp->GetWatchpointList().FindByID(wvc->watch_id);
  if (!watch_sp)
    return false;

  if (wvc->exe_ctx == context->exe_ctx_ref) {
    LLDB_LOGF(log,
              "callback for watchpoint %" PRId32
              " matched internal breakpoint execution context",
              watch_sp->GetID());
    process_sp->DisableWatchpoint(watch_sp);
    return false;
  }
  LLDB_LOGF(log,
            "callback for watchpoint %" PRId32
            " didn't match internal breakpoint execution context",
            watch_sp->GetID());
  return false;
}

void Watchpoint::ClearCallback() {
  m_options.ClearCallback();
  SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged);
}

void Watchpoint::SetDeclInfo(const std::string &str) { m_decl_str = str; }

std::string Watchpoint::GetWatchSpec() { return m_watch_spec_str; }

void Watchpoint::SetWatchSpec(const std::string &str) {
  m_watch_spec_str = str;
}

bool Watchpoint::IsHardware() const {
  lldbassert(m_is_hardware || !HardwareRequired());
  return m_is_hardware;
}

bool Watchpoint::IsWatchVariable() const { return m_is_watch_variable; }

void Watchpoint::SetWatchVariable(bool val) { m_is_watch_variable = val; }

bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) {
  ConstString g_watch_name("$__lldb__watch_value");
  m_old_value_sp = m_new_value_sp;
  Address watch_address(GetLoadAddress());
  if (!m_type.IsValid()) {
    // Don't know how to report new & old values, since we couldn't make a
    // scalar type for this watchpoint. This works around an assert in
    // ValueObjectMemory::Create.
    // FIXME: This should not happen, but if it does in some case we care about,
    // we can go grab the value raw and print it as unsigned.
    return false;
  }
  m_new_value_sp = ValueObjectMemory::Create(
      exe_ctx.GetBestExecutionContextScope(), g_watch_name.GetStringRef(),
      watch_address, m_type);
  m_new_value_sp = m_new_value_sp->CreateConstantValue(g_watch_name);
  return (m_new_value_sp && m_new_value_sp->GetError().Success());
}

bool Watchpoint::WatchedValueReportable(const ExecutionContext &exe_ctx) {
  if (!m_watch_modify || m_watch_read)
    return true;
  if (!m_type.IsValid())
    return true;

  ConstString g_watch_name("$__lldb__watch_value");
  Address watch_address(GetLoadAddress());
  ValueObjectSP newest_valueobj_sp = ValueObjectMemory::Create(
      exe_ctx.GetBestExecutionContextScope(), g_watch_name.GetStringRef(),
      watch_address, m_type);
  newest_valueobj_sp = newest_valueobj_sp->CreateConstantValue(g_watch_name);
  Status error;

  DataExtractor new_data;
  DataExtractor old_data;

  newest_valueobj_sp->GetData(new_data, error);
  if (error.Fail())
    return true;
  m_new_value_sp->GetData(old_data, error);
  if (error.Fail())
    return true;

  if (new_data.GetByteSize() != old_data.GetByteSize() ||
      new_data.GetByteSize() == 0)
    return true;

  if (memcmp(new_data.GetDataStart(), old_data.GetDataStart(),
             old_data.GetByteSize()) == 0)
    return false; // Value has not changed, user requested modify watchpoint

  return true;
}

// RETURNS - true if we should stop at this breakpoint, false if we
// should continue.

bool Watchpoint::ShouldStop(StoppointCallbackContext *context) {
  m_hit_counter.Increment();

  return IsEnabled();
}

void Watchpoint::GetDescription(Stream *s, lldb::DescriptionLevel level) {
  DumpWithLevel(s, level);
}

void Watchpoint::Dump(Stream *s) const {
  DumpWithLevel(s, lldb::eDescriptionLevelBrief);
}

// If prefix is nullptr, we display the watch id and ignore the prefix
// altogether.
bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const {
  bool printed_anything = false;

  // For read watchpoints, don't display any before/after value changes.
  if (m_watch_read && !m_watch_modify && !m_watch_write)
    return printed_anything;

  s->PutCString("\n");
  s->Printf("Watchpoint %u hit:\n", GetID());

  StreamString values_ss;
  if (prefix)
    values_ss.Indent(prefix);

  if (m_old_value_sp) {
    if (auto *old_value_cstr = m_old_value_sp->GetValueAsCString()) {
      values_ss.Printf("old value: %s", old_value_cstr);
    } else {
      if (auto *old_summary_cstr = m_old_value_sp->GetSummaryAsCString())
        values_ss.Printf("old value: %s", old_summary_cstr);
      else {
        StreamString strm;
        DumpValueObjectOptions options;
        options.SetUseDynamicType(eNoDynamicValues)
            .SetHideRootType(true)
            .SetHideRootName(true)
            .SetHideName(true);
        if (llvm::Error error = m_old_value_sp->Dump(strm, options))
          strm << "error: " << toString(std::move(error));

        if (strm.GetData())
          values_ss.Printf("old value: %s", strm.GetData());
      }
    }
  }

  if (m_new_value_sp) {
    if (values_ss.GetSize()) {
      values_ss.PutChar('\n');
      values_ss.Indent(prefix);
    }

    if (auto *new_value_cstr = m_new_value_sp->GetValueAsCString())
      values_ss.Printf("new value: %s", new_value_cstr);
    else {
      if (auto *new_summary_cstr = m_new_value_sp->GetSummaryAsCString())
        values_ss.Printf("new value: %s", new_summary_cstr);
      else {
        StreamString strm;
        DumpValueObjectOptions options;
        options.SetUseDynamicType(eNoDynamicValues)
            .SetHideRootType(true)
            .SetHideRootName(true)
            .SetHideName(true);
        if (llvm::Error error = m_new_value_sp->Dump(strm, options))
          strm << "error: " << toString(std::move(error));

        if (strm.GetData())
          values_ss.Printf("new value: %s", strm.GetData());
      }
    }
  }

  if (values_ss.GetSize()) {
    s->PutCString(values_ss.GetData());
    printed_anything = true;
  }

  return printed_anything;
}

void Watchpoint::DumpWithLevel(Stream *s,
                               lldb::DescriptionLevel description_level) const {
  if (s == nullptr)
    return;

  assert(description_level >= lldb::eDescriptionLevelBrief &&
         description_level <= lldb::eDescriptionLevelVerbose);

  s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64
            ", size = %u, state = %s, type = %s%s%s",
            GetID(), GetLoadAddress(), m_byte_size,
            IsEnabled() ? "enabled" : "disabled", m_watch_read ? "r" : "",
            m_watch_write ? "w" : "", m_watch_modify ? "m" : "");

  if (description_level >= lldb::eDescriptionLevelFull) {
    if (!m_decl_str.empty())
      s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
    if (!m_watch_spec_str.empty())
      s->Printf("\n    watchpoint spec = '%s'", m_watch_spec_str.c_str());
    if (IsEnabled()) {
      if (ProcessSP process_sp = m_target.GetProcessSP()) {
        auto &resourcelist = process_sp->GetWatchpointResourceList();
        size_t idx = 0;
        s->PutCString("\n    watchpoint resources:");
        for (WatchpointResourceSP &wpres : resourcelist.Sites()) {
          if (wpres->ConstituentsContains(this)) {
            s->Printf("\n       #%zu: ", idx);
            wpres->Dump(s);
          }
          idx++;
        }
      }
    }

    // Dump the snapshots we have taken.
    DumpSnapshots(s, "    ");

    if (GetConditionText())
      s->Printf("\n    condition = '%s'", GetConditionText());
    m_options.GetCallbackDescription(s, description_level);
  }

  if (description_level >= lldb::eDescriptionLevelVerbose) {
    s->Printf("\n    hit_count = %-4u  ignore_count = %-4u", GetHitCount(),
              GetIgnoreCount());
  }
}

bool Watchpoint::IsEnabled() const { return m_enabled; }

// Within StopInfo.cpp, we purposely turn on the ephemeral mode right before
// temporarily disable the watchpoint in order to perform possible watchpoint
// actions without triggering further watchpoint events. After the temporary
// disabled watchpoint is enabled, we then turn off the ephemeral mode.

void Watchpoint::TurnOnEphemeralMode() { m_is_ephemeral = true; }

void Watchpoint::TurnOffEphemeralMode() {
  m_is_ephemeral = false;
  // Leaving ephemeral mode, reset the m_disabled_count!
  m_disabled_count = 0;
}

bool Watchpoint::IsDisabledDuringEphemeralMode() {
  return m_disabled_count > 1 && m_is_ephemeral;
}

void Watchpoint::SetEnabled(bool enabled, bool notify) {
  if (!enabled) {
    if (m_is_ephemeral)
      ++m_disabled_count;

    // Don't clear the snapshots for now.
    // Within StopInfo.cpp, we purposely do disable/enable watchpoint while
    // performing watchpoint actions.
  }
  bool changed = enabled != m_enabled;
  m_enabled = enabled;
  if (notify && !m_is_ephemeral && changed)
    SendWatchpointChangedEvent(enabled ? eWatchpointEventTypeEnabled
                                       : eWatchpointEventTypeDisabled);
}

void Watchpoint::SetWatchpointType(uint32_t type, bool notify) {
  int old_watch_read = m_watch_read;
  int old_watch_write = m_watch_write;
  int old_watch_modify = m_watch_modify;
  m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
  m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
  m_watch_modify = (type & LLDB_WATCH_TYPE_MODIFY) != 0;
  if (notify &&
      (old_watch_read != m_watch_read || old_watch_write != m_watch_write ||
       old_watch_modify != m_watch_modify))
    SendWatchpointChangedEvent(eWatchpointEventTypeTypeChanged);
}

bool Watchpoint::WatchpointRead() const { return m_watch_read != 0; }

bool Watchpoint::WatchpointWrite() const { return m_watch_write != 0; }

bool Watchpoint::WatchpointModify() const { return m_watch_modify != 0; }

uint32_t Watchpoint::GetIgnoreCount() const { return m_ignore_count; }

void Watchpoint::SetIgnoreCount(uint32_t n) {
  bool changed = m_ignore_count != n;
  m_ignore_count = n;
  if (changed)
    SendWatchpointChangedEvent(eWatchpointEventTypeIgnoreChanged);
}

bool Watchpoint::InvokeCallback(StoppointCallbackContext *context) {
  return m_options.InvokeCallback(context, GetID());
}

void Watchpoint::SetCondition(const char *condition) {
  if (condition == nullptr || condition[0] == '\0') {
    if (m_condition_up)
      m_condition_up.reset();
  } else {
    // Pass nullptr for expr_prefix (no translation-unit level definitions).
    Status error;
    m_condition_up.reset(m_target.GetUserExpressionForLanguage(
        condition, {}, {}, UserExpression::eResultTypeAny,
        EvaluateExpressionOptions(), nullptr, error));
    if (error.Fail()) {
      // FIXME: Log something...
      m_condition_up.reset();
    }
  }
  SendWatchpointChangedEvent(eWatchpointEventTypeConditionChanged);
}

const char *Watchpoint::GetConditionText() const {
  if (m_condition_up)
    return m_condition_up->GetUserText();
  return nullptr;
}

void Watchpoint::SendWatchpointChangedEvent(
    lldb::WatchpointEventType eventKind) {
  if (GetTarget().EventTypeHasListeners(
          Target::eBroadcastBitWatchpointChanged)) {
    auto data_sp =
        std::make_shared<WatchpointEventData>(eventKind, shared_from_this());
    GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged, data_sp);
  }
}

Watchpoint::WatchpointEventData::WatchpointEventData(
    WatchpointEventType sub_type, const WatchpointSP &new_watchpoint_sp)
    : m_watchpoint_event(sub_type), m_new_watchpoint_sp(new_watchpoint_sp) {}

Watchpoint::WatchpointEventData::~WatchpointEventData() = default;

llvm::StringRef Watchpoint::WatchpointEventData::GetFlavorString() {
  return "Watchpoint::WatchpointEventData";
}

llvm::StringRef Watchpoint::WatchpointEventData::GetFlavor() const {
  return WatchpointEventData::GetFlavorString();
}

WatchpointSP &Watchpoint::WatchpointEventData::GetWatchpoint() {
  return m_new_watchpoint_sp;
}

WatchpointEventType
Watchpoint::WatchpointEventData::GetWatchpointEventType() const {
  return m_watchpoint_event;
}

void Watchpoint::WatchpointEventData::Dump(Stream *s) const {}

const Watchpoint::WatchpointEventData *
Watchpoint::WatchpointEventData::GetEventDataFromEvent(const Event *event) {
  if (event) {
    const EventData *event_data = event->GetData();
    if (event_data &&
        event_data->GetFlavor() == WatchpointEventData::GetFlavorString())
      return static_cast<const WatchpointEventData *>(event->GetData());
  }
  return nullptr;
}

WatchpointEventType
Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent(
    const EventSP &event_sp) {
  const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get());

  if (data == nullptr)
    return eWatchpointEventTypeInvalidType;
  return data->GetWatchpointEventType();
}

WatchpointSP Watchpoint::WatchpointEventData::GetWatchpointFromEvent(
    const EventSP &event_sp) {
  WatchpointSP wp_sp;

  const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get());
  if (data)
    wp_sp = data->m_new_watchpoint_sp;

  return wp_sp;
}
