//===-- CPPLanguageRuntime.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 <cstring>
#include <iostream>

#include <memory>

#include "CPPLanguageRuntime.h"
#include "CommandObjectCPlusPlus.h"
#include "ItaniumABIRuntime.h"
#include "VerboseTrapFrameRecognizer.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"

#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"

#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Timer.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE_ADV(CPPLanguageRuntime, CPPRuntime)

static ConstString g_this = ConstString("this");
// Artificial coroutine-related variables emitted by clang.
static ConstString g_promise = ConstString("__promise");
static ConstString g_coro_frame = ConstString("__coro_frame");

char CPPLanguageRuntime::ID = 0;

/// A frame recognizer that is installed to hide libc++ implementation
/// details from the backtrace.
class LibCXXFrameRecognizer : public StackFrameRecognizer {
  std::array<RegularExpression, 2> m_hidden_regex;
  RecognizedStackFrameSP m_hidden_frame;

  struct LibCXXHiddenFrame : public RecognizedStackFrame {
    bool ShouldHide() override { return true; }
  };

public:
  LibCXXFrameRecognizer()
      : m_hidden_regex{
            // internal implementation details in the `std::` namespace
            //    std::__1::__function::__alloc_func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator()[abi:ne200000]
            //    std::__1::__function::__func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator()
            //    std::__1::__function::__value_func<void ()>::operator()[abi:ne200000]() const
            //    std::__2::__function::__policy_invoker<void (int, int)>::__call_impl[abi:ne200000]<std::__2::__function::__default_alloc_func<int (*)(int, int), int (int, int)>>
            //    std::__1::__invoke[abi:ne200000]<void (*&)()>
            //    std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne200000]<void (*&)()>
            RegularExpression{R"(^std::__[^:]*::__)"},
            // internal implementation details in the `std::ranges` namespace
            //    std::__1::ranges::__sort::__sort_fn_impl[abi:ne200000]<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, bool (*)(int, int), std::__1::identity>
            RegularExpression{R"(^std::__[^:]*::ranges::__)"},
        },
        m_hidden_frame(new LibCXXHiddenFrame()) {}

  std::string GetName() override { return "libc++ frame recognizer"; }

  lldb::RecognizedStackFrameSP
  RecognizeFrame(lldb::StackFrameSP frame_sp) override {
    if (!frame_sp)
      return {};
    const auto &sc = frame_sp->GetSymbolContext(lldb::eSymbolContextFunction);
    if (!sc.function)
      return {};

    // Check if we have a regex match
    for (RegularExpression &r : m_hidden_regex) {
      if (!r.Execute(sc.function->GetNameNoArguments()))
        continue;

      // Only hide this frame if the immediate caller is also within libc++.
      lldb::ThreadSP thread_sp = frame_sp->GetThread();
      if (!thread_sp)
        return {};
      lldb::StackFrameSP parent_frame_sp =
          thread_sp->GetStackFrameAtIndex(frame_sp->GetFrameIndex() + 1);
      if (!parent_frame_sp)
        return {};
      const auto &parent_sc =
          parent_frame_sp->GetSymbolContext(lldb::eSymbolContextFunction);
      if (!parent_sc.function)
        return {};
      if (parent_sc.function->GetNameNoArguments().GetStringRef().starts_with(
              "std::"))
        return m_hidden_frame;
    }

    return {};
  }
};

CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
    : LanguageRuntime(process) {
  if (process) {
    process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
        StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
        std::make_shared<RegularExpression>("^std::__[^:]*::"),
        /*mangling_preference=*/Mangled::ePreferDemangledWithoutArguments,
        /*first_instruction_only=*/false);

    RegisterVerboseTrapFrameRecognizer(*process);
  }

  m_abi_runtimes.emplace_back(new ItaniumABIRuntime(process));
}

bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
  return name == g_this || name == g_promise || name == g_coro_frame;
}

llvm::Error CPPLanguageRuntime::GetObjectDescription(Stream &str,
                                                     ValueObject &object) {
  // C++ has no generic way to do this.
  return llvm::createStringError("C++ does not support object descriptions");
}

llvm::Error
CPPLanguageRuntime::GetObjectDescription(Stream &str, Value &value,
                                         ExecutionContextScope *exe_scope) {
  // C++ has no generic way to do this.
  return llvm::createStringError("C++ does not support object descriptions");
}

bool contains_lambda_identifier(llvm::StringRef &str_ref) {
  return str_ref.contains("$_") || str_ref.contains("'lambda'");
}

CPPLanguageRuntime::LibCppStdFunctionCallableInfo
line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol,
                  llvm::StringRef first_template_param_sref, bool has_invoke) {

  CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info;

  Address address = sc.GetFunctionOrSymbolAddress();

  Address addr;
  if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
                                addr)) {
    LineEntry line_entry;
    addr.CalculateSymbolContextLineEntry(line_entry);

    if (contains_lambda_identifier(first_template_param_sref) || has_invoke) {
      // Case 1 and 2
      optional_info.callable_case = lldb_private::CPPLanguageRuntime::
          LibCppStdFunctionCallableCase::Lambda;
    } else {
      // Case 3
      optional_info.callable_case = lldb_private::CPPLanguageRuntime::
          LibCppStdFunctionCallableCase::CallableObject;
    }

    optional_info.callable_symbol = *symbol;
    optional_info.callable_line_entry = line_entry;
    optional_info.callable_address = addr;
  }

  return optional_info;
}

CPPLanguageRuntime::LibCppStdFunctionCallableInfo
CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
    lldb::ValueObjectSP &valobj_sp) {
  LLDB_SCOPED_TIMER();

  LibCppStdFunctionCallableInfo optional_info;

  if (!valobj_sp)
    return optional_info;

  // Member __f_ has type __base*, the contents of which will hold:
  // 1) a vtable entry which may hold type information needed to discover the
  //    lambda being called
  // 2) possibly hold a pointer to the callable object
  // e.g.
  //
  // (lldb) frame var -R  f_display
  // (std::__1::function<void (int)>) f_display = {
  //  __buf_ = {
  //  …
  // }
  //  __f_ = 0x00007ffeefbffa00
  // }
  // (lldb) memory read -fA 0x00007ffeefbffa00
  // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
  // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
  //
  // We will be handling five cases below, std::function is wrapping:
  //
  // 1) a lambda we know at compile time. We will obtain the name of the lambda
  //    from the first template pameter from __func's vtable. We will look up
  //    the lambda's operator()() and obtain the line table entry.
  // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
  //    will be stored after the vtable. We will obtain the lambdas name from
  //    this entry and lookup operator()() and obtain the line table entry.
  // 3) a callable object via operator()(). We will obtain the name of the
  //    object from the first template parameter from __func's vtable. We will
  //    look up the objects operator()() and obtain the line table entry.
  // 4) a member function. A pointer to the function will stored after the
  //    we will obtain the name from this pointer.
  // 5) a free function. A pointer to the function will stored after the vtable
  //    we will obtain the name from this pointer.
  ValueObjectSP member_f_(valobj_sp->GetChildMemberWithName("__f_"));

  if (member_f_) {
    ValueObjectSP sub_member_f_(member_f_->GetChildMemberWithName("__f_"));

    if (sub_member_f_)
      member_f_ = sub_member_f_;
  }

  if (!member_f_)
    return optional_info;

  lldb::addr_t member_f_pointer_value = member_f_->GetValueAsUnsigned(0);

  optional_info.member_f_pointer_value = member_f_pointer_value;

  if (!member_f_pointer_value)
    return optional_info;

  ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr)
    return optional_info;

  uint32_t address_size = process->GetAddressByteSize();

  // First item pointed to by __f_ should be the pointer to the vtable for
  // a __base object.
  llvm::Expected<lldb::addr_t> vtable_address_or_err =
      process->ReadPointerFromMemory(member_f_pointer_value);
  if (!vtable_address_or_err) {
    llvm::consumeError(vtable_address_or_err.takeError());
    return optional_info;
  }
  lldb::addr_t vtable_address = *vtable_address_or_err;

  ABISP abi_sp = process->GetABI();
  if (abi_sp)
    vtable_address = abi_sp->FixCodeAddress(vtable_address);

  llvm::Expected<lldb::addr_t> vtable_address_first_entry_or_err =
      process->ReadPointerFromMemory(vtable_address + address_size);
  if (!vtable_address_first_entry_or_err) {
    llvm::consumeError(vtable_address_first_entry_or_err.takeError());
    return optional_info;
  }
  lldb::addr_t vtable_address_first_entry = *vtable_address_first_entry_or_err;

  if (abi_sp)
    vtable_address_first_entry =
        abi_sp->FixCodeAddress(vtable_address_first_entry);

  lldb::addr_t address_after_vtable = member_f_pointer_value + address_size;
  // As commented above we may not have a function pointer but if we do we will
  // need it.
  llvm::Expected<lldb::addr_t> possible_function_address_or_err =
      process->ReadPointerFromMemory(address_after_vtable);
  if (!possible_function_address_or_err) {
    llvm::consumeError(possible_function_address_or_err.takeError());
    return optional_info;
  }
  lldb::addr_t possible_function_address = *possible_function_address_or_err;

  if (abi_sp)
    possible_function_address =
        abi_sp->FixCodeAddress(possible_function_address);

  Target &target = process->GetTarget();

  if (!target.HasLoadedSections())
    return optional_info;

  Address vtable_first_entry_resolved;

  if (!target.ResolveLoadAddress(vtable_address_first_entry,
                                 vtable_first_entry_resolved))
    return optional_info;

  Address vtable_addr_resolved;
  SymbolContext sc;
  Symbol *symbol = nullptr;

  if (!target.ResolveLoadAddress(vtable_address, vtable_addr_resolved))
    return optional_info;

  target.GetImages().ResolveSymbolContextForAddress(
      vtable_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return optional_info;

  llvm::StringRef vtable_name(symbol->GetName().GetStringRef());
  bool found_expected_start_string =
      vtable_name.starts_with("vtable for std::__1::__function::__func<");

  if (!found_expected_start_string)
    return optional_info;

  // Given case 1 or 3 we have a vtable name, we are want to extract the first
  // template parameter
  //
  //  ... __func<main::$_0, std::__1::allocator<main::$_0> ...
  //             ^^^^^^^^^
  //
  // We could see names such as:
  //    main::$_0
  //    Bar::add_num2(int)::'lambda'(int)
  //    Bar
  //
  // We do this by find the first < and , and extracting in between.
  //
  // This covers the case of the lambda known at compile time.
  size_t first_open_angle_bracket = vtable_name.find('<') + 1;
  size_t first_comma = vtable_name.find(',');

  llvm::StringRef first_template_parameter =
      vtable_name.slice(first_open_angle_bracket, first_comma);

  Address function_address_resolved;

  // Setup for cases 2, 4 and 5 we have a pointer to a function after the
  // vtable. We will use a process of elimination to drop through each case
  // and obtain the data we need.
  if (target.ResolveLoadAddress(possible_function_address,
                                function_address_resolved)) {
    target.GetImages().ResolveSymbolContextForAddress(
        function_address_resolved, eSymbolContextEverything, sc);
    symbol = sc.symbol;
  }

  // These conditions are used several times to simplify statements later on.
  bool has_invoke =
      (symbol ? symbol->GetName().GetStringRef().contains("__invoke") : false);
  auto calculate_symbol_context_helper = [](auto &t,
                                            SymbolContextList &sc_list) {
    SymbolContext sc;
    t->CalculateSymbolContext(&sc);
    sc_list.Append(sc);
  };

  // Case 2
  if (has_invoke) {
    SymbolContextList scl;
    calculate_symbol_context_helper(symbol, scl);

    return line_entry_helper(target, scl[0], symbol, first_template_parameter,
                             has_invoke);
  }

  // Case 4 or 5
  if (symbol && !symbol->GetName().GetStringRef().starts_with("vtable for") &&
      !contains_lambda_identifier(first_template_parameter) && !has_invoke) {
    optional_info.callable_case =
        LibCppStdFunctionCallableCase::FreeOrMemberFunction;
    optional_info.callable_address = function_address_resolved;
    optional_info.callable_symbol = *symbol;

    return optional_info;
  }

  std::string func_to_match = first_template_parameter.str();

  auto it = CallableLookupCache.find(func_to_match);
  if (it != CallableLookupCache.end())
    return it->second;

  SymbolContextList scl;

  CompileUnit *vtable_cu =
      vtable_first_entry_resolved.CalculateSymbolContextCompileUnit();
  llvm::StringRef name_to_use = func_to_match;

  // Case 3, we have a callable object instead of a lambda
  //
  // TODO
  // We currently don't support this case a callable object may have multiple
  // operator()() varying on const/non-const and number of arguments and we
  // don't have a way to currently distinguish them so we will bail out now.
  if (!contains_lambda_identifier(name_to_use))
    return optional_info;

  if (vtable_cu && !has_invoke) {
    lldb::FunctionSP func_sp =
        vtable_cu->FindFunction([name_to_use](const FunctionSP &f) {
          auto name = f->GetName().GetStringRef();
          if (name.starts_with(name_to_use) && name.contains("operator"))
            return true;

          return false;
        });

    if (func_sp) {
      calculate_symbol_context_helper(func_sp, scl);
    }
  }

  if (symbol == nullptr)
    return optional_info;

  // Case 1 or 3
  if (scl.GetSize() >= 1) {
    optional_info = line_entry_helper(target, scl[0], symbol,
                                      first_template_parameter, has_invoke);
  }

  CallableLookupCache[func_to_match] = optional_info;

  return optional_info;
}

lldb::ThreadPlanSP
CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
                                                 bool stop_others) {
  ThreadPlanSP ret_plan_sp;

  lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();

  TargetSP target_sp(thread.CalculateTarget());

  if (!target_sp->HasLoadedSections())
    return ret_plan_sp;

  Address pc_addr_resolved;
  SymbolContext sc;
  Symbol *symbol;

  if (!target_sp->ResolveLoadAddress(curr_pc, pc_addr_resolved))
    return ret_plan_sp;

  target_sp->GetImages().ResolveSymbolContextForAddress(
      pc_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return ret_plan_sp;

  llvm::StringRef function_name(symbol->GetName().GetCString());

  // Handling the case where we are attempting to step into std::function.
  // The behavior will be that we will attempt to obtain the wrapped
  // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
  // will return a ThreadPlanRunToAddress to the callable. Therefore we will
  // step into the wrapped callable.
  //
  bool found_expected_start_string =
      function_name.starts_with("std::__1::function<");

  if (!found_expected_start_string)
    return ret_plan_sp;

  AddressRange range_of_curr_func;
  sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);

  StackFrameSP frame = thread.GetStackFrameAtIndex(0);

  if (frame) {
    Address func_start_address =
        sc.function ? sc.function->GetAddress() : symbol->GetAddress();
    lldb::addr_t func_start =
        func_start_address.GetLoadAddress(target_sp.get());

    if (func_start == LLDB_INVALID_ADDRESS)
      return ret_plan_sp;

    // Advance past the prologue if we stopped there.
    uint32_t prologue_size = sc.function ? sc.function->GetPrologueByteSize()
                                         : symbol->GetPrologueByteSize();
    if (curr_pc < func_start + prologue_size) {
      func_start_address.Slide(prologue_size);
      return std::make_shared<ThreadPlanRunToAddress>(
          thread, func_start_address, stop_others);
    }

    ValueObjectSP value_sp = frame->FindVariable(g_this);

    CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
        FindLibCppStdFunctionCallableInfo(value_sp);

    if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
        value_sp->GetValueIsValid()) {
      // We found the std::function wrapped callable and we have its address.
      // We now create a ThreadPlan to run to the callable.
      ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
          thread, callable_info.callable_address, stop_others);
      return ret_plan_sp;
    } else {
      // We are in std::function but we could not obtain the callable.
      // We create a ThreadPlan to keep stepping through using the address range
      // of the current function.
      ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
          thread, range_of_curr_func, sc, std::string(), eOnlyThisThread,
          eLazyBoolYes, eLazyBoolYes);
      return ret_plan_sp;
    }
  }

  return ret_plan_sp;
}

bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) {
  llvm::StringRef mangled_name =
      symbol.GetMangled().GetMangledName().GetStringRef();
  // Virtual function overriding from a non-virtual base use a "Th" prefix.
  // Virtual function overriding from a virtual base must use a "Tv" prefix.
  // Virtual function overriding thunks with covariant returns use a "Tc"
  // prefix.
  return mangled_name.starts_with("_ZTh") || mangled_name.starts_with("_ZTv") ||
         mangled_name.starts_with("_ZTc");
}

bool CPPLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
  const bool check_cxx = true;
  const bool check_objc = false;
  return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx,
                                                          check_objc);
}

bool CPPLanguageRuntime::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &dynamic_address,
    Value::ValueType &value_type, llvm::ArrayRef<uint8_t> &local_buffer) {
  class_type_or_name.Clear();
  value_type = Value::ValueType::Scalar;

  if (!CouldHaveDynamicValue(in_value))
    return false;

  llvm::Expected<VTableInfoEntry> entry =
      GetVTableInfoEntry(in_value, /*check_type=*/false);
  if (!entry) {
    llvm::consumeError(entry.takeError());
    return false;
  }

  return entry->runtime->GetDynamicTypeAndAddress(
      in_value, use_dynamic, entry->info, class_type_or_name, dynamic_address);
}

TypeAndOrName
CPPLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
                                     ValueObject &static_value) {
  CompilerType static_type(static_value.GetCompilerType());
  Flags static_type_flags(static_type.GetTypeInfo());

  TypeAndOrName ret(type_and_or_name);
  if (type_and_or_name.HasType()) {
    // The type will always be the type of the dynamic object.  If our parent's
    // type was a pointer, then our type should be a pointer to the type of the
    // dynamic object.  If a reference, then the original type should be
    // okay...
    CompilerType orig_type = type_and_or_name.GetCompilerType();
    CompilerType corrected_type = orig_type;
    if (static_type_flags.AllSet(eTypeIsPointer))
      corrected_type = orig_type.GetPointerType();
    else if (static_type_flags.AllSet(eTypeIsReference))
      corrected_type = orig_type.GetLValueReferenceType();
    ret.SetCompilerType(corrected_type);
  } else {
    // If we are here we need to adjust our dynamic type name to include the
    // correct & or * symbol
    std::string corrected_name(type_and_or_name.GetName().GetCString());
    if (static_type_flags.AllSet(eTypeIsPointer))
      corrected_name.append(" *");
    else if (static_type_flags.AllSet(eTypeIsReference))
      corrected_name.append(" &");
    // the parent type should be a correctly pointer'ed or referenc'ed type
    ret.SetCompilerType(static_type);
    ret.SetName(corrected_name.c_str());
  }
  return ret;
}

LanguageRuntime *
CPPLanguageRuntime::CreateInstance(Process *process,
                                   lldb::LanguageType language) {
  if (language == eLanguageTypeC_plus_plus ||
      language == eLanguageTypeC_plus_plus_03 ||
      language == eLanguageTypeC_plus_plus_11 ||
      language == eLanguageTypeC_plus_plus_14)
    return new CPPLanguageRuntime(process);
  else
    return nullptr;
}

void CPPLanguageRuntime::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "C++ language runtime", CreateInstance,
      [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
        return CommandObjectSP(new CommandObjectCPlusPlus(interpreter));
      });
}

void CPPLanguageRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

llvm::Expected<LanguageRuntime::VTableInfo>
CPPLanguageRuntime::GetVTableInfo(ValueObject &in_value, bool check_type) {
  llvm::Expected<VTableInfoEntry> entry =
      GetVTableInfoEntry(in_value, check_type);
  if (!entry)
    return entry.takeError();
  return entry->info;
}

BreakpointResolverSP
CPPLanguageRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,
                                            bool catch_bp, bool throw_bp) {
  return CreateExceptionResolver(bkpt, catch_bp, throw_bp, false);
}

BreakpointResolverSP
CPPLanguageRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,
                                            bool catch_bp, bool throw_bp,
                                            bool for_expressions) {
  std::vector<const char *> exception_names;
  for (const auto &runtime : m_abi_runtimes)
    runtime->AppendExceptionBreakpointFunctions(exception_names, catch_bp,
                                                throw_bp, for_expressions);

  BreakpointResolverSP resolver_sp(new BreakpointResolverName(
      bkpt, exception_names.data(), exception_names.size(),
      eFunctionNameTypeBase, eLanguageTypeUnknown, 0, eLazyBoolNo));

  return resolver_sp;
}

lldb::SearchFilterSP CPPLanguageRuntime::CreateExceptionSearchFilter() {
  Target &target = m_process->GetTarget();

  FileSpecList filter_modules;
  for (const auto &runtime : m_abi_runtimes)
    runtime->AppendExceptionBreakpointFilterModules(filter_modules, target);

  return target.GetSearchFilterForModuleList(&filter_modules);
}

lldb::BreakpointSP CPPLanguageRuntime::CreateExceptionBreakpoint(
    bool catch_bp, bool throw_bp, bool for_expressions, bool is_internal) {
  Target &target = m_process->GetTarget();
  FileSpecList filter_modules;
  BreakpointResolverSP exception_resolver_sp =
      CreateExceptionResolver(nullptr, catch_bp, throw_bp, for_expressions);
  SearchFilterSP filter_sp(CreateExceptionSearchFilter());
  const bool hardware = false;
  const bool resolve_indirect_functions = false;
  return target.CreateBreakpoint(filter_sp, exception_resolver_sp, is_internal,
                                 hardware, resolve_indirect_functions);
}

void CPPLanguageRuntime::SetExceptionBreakpoints() {
  if (!m_process)
    return;

  const bool catch_bp = false;
  const bool throw_bp = true;
  const bool is_internal = true;
  const bool for_expressions = true;

  // For the exception breakpoints set by the Expression parser, we'll be a
  // little more aggressive and stop at exception allocation as well.

  if (m_cxx_exception_bp_sp) {
    m_cxx_exception_bp_sp->SetEnabled(true);
  } else {
    m_cxx_exception_bp_sp = CreateExceptionBreakpoint(
        catch_bp, throw_bp, for_expressions, is_internal);
    if (m_cxx_exception_bp_sp)
      m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
  }
}

void CPPLanguageRuntime::ClearExceptionBreakpoints() {
  if (!m_process)
    return;

  if (m_cxx_exception_bp_sp) {
    m_cxx_exception_bp_sp->SetEnabled(false);
  }
}

bool CPPLanguageRuntime::ExceptionBreakpointsAreSet() {
  return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
}

bool CPPLanguageRuntime::ExceptionBreakpointsExplainStop(
    lldb::StopInfoSP stop_reason) {
  if (!m_process)
    return false;

  if (!stop_reason || stop_reason->GetStopReason() != eStopReasonBreakpoint)
    return false;

  uint64_t break_site_id = stop_reason->GetValue();
  return m_process->GetBreakpointSiteList().StopPointSiteContainsBreakpoint(
      break_site_id, m_cxx_exception_bp_sp->GetID());
}

lldb::ValueObjectSP
CPPLanguageRuntime::GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
  for (const auto &runtime : m_abi_runtimes) {
    ValueObjectSP valobj = runtime->GetExceptionObjectForThread(thread_sp);
    if (valobj)
      return valobj;
  }
  return {};
}

static llvm::Error TypeHasVTable(CompilerType type) {
  // Check to make sure the class has a vtable.
  CompilerType original_type = type;
  if (type.IsPointerOrReferenceType()) {
    CompilerType pointee_type = type.GetPointeeType();
    if (pointee_type)
      type = pointee_type;
  }

  // Make sure this is a class or a struct first by checking the type class
  // bitfield that gets returned.
  if ((type.GetTypeClass() & (eTypeClassStruct | eTypeClassClass)) == 0) {
    return llvm::createStringError(
        std::errc::invalid_argument,
        "type \"%s\" is not a class or struct or a pointer to one",
        original_type.GetTypeName().AsCString("<invalid>"));
  }

  // Check if the type has virtual functions by asking it if it is polymorphic.
  if (!type.IsPolymorphicClass()) {
    return llvm::createStringError(std::errc::invalid_argument,
                                   "type \"%s\" doesn't have a vtable",
                                   type.GetTypeName().AsCString("<invalid>"));
  }
  return llvm::Error::success();
}

// This function can accept both pointers or references to classes as well as
// instances of classes. If you are using this function during dynamic type
// detection, only valid ValueObjects that return true to
// CouldHaveDynamicValue(...) should call this function and \a check_type
// should be set to false. This function is also used by ValueObjectVTable
// and is can pass in instances of classes which is not suitable for dynamic
// type detection, these cases should pass true for \a check_type.
llvm::Expected<CPPLanguageRuntime::VTableInfoEntry>
CPPLanguageRuntime::GetVTableInfoEntry(ValueObject &in_value, bool check_type) {

  CompilerType type = in_value.GetCompilerType();
  if (check_type) {
    if (llvm::Error err = TypeHasVTable(type))
      return std::move(err);
  }
  ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();
  if (process == nullptr)
    return llvm::createStringError(std::errc::invalid_argument,
                                   "invalid process");

  auto [original_ptr, address_type] =
      type.IsPointerOrReferenceType()
          ? in_value.GetPointerValue()
          : in_value.GetAddressOf(/*scalar_is_load_address=*/true);
  if (original_ptr == LLDB_INVALID_ADDRESS || address_type != eAddressTypeLoad)
    return llvm::createStringError(std::errc::invalid_argument,
                                   "failed to get the address of the value");

  llvm::Expected<lldb::addr_t> vtable_load_addr_or_err =
      process->ReadPointerFromMemory(original_ptr);
  if (!vtable_load_addr_or_err)
    return vtable_load_addr_or_err.takeError();
  lldb::addr_t vtable_load_addr = *vtable_load_addr_or_err;

  // The vtable load address can have authentication bits with
  // AArch64 targets on Darwin.
  vtable_load_addr = process->FixDataAddress(vtable_load_addr);

  // Find the symbol that contains the "vtable_load_addr" address
  Address vtable_addr;
  if (!process->GetTarget().ResolveLoadAddress(vtable_load_addr, vtable_addr))
    return llvm::createStringError(std::errc::invalid_argument,
                                   "failed to resolve vtable pointer 0x%" PRIx64
                                   "to a section",
                                   vtable_load_addr);

  // Check our cache first to see if we already have this info
  {
    auto vtable_info_map = m_vtable_info_map.Lock();
    auto pos = vtable_info_map->find(vtable_addr);
    if (pos != vtable_info_map->end())
      return pos->second;
  }

  Symbol *symbol = vtable_addr.CalculateSymbolContextSymbol();
  if (symbol == nullptr)
    return llvm::createStringError(std::errc::invalid_argument,
                                   "no symbol found for 0x%" PRIx64,
                                   vtable_load_addr);

  Mangled &mangled = symbol->GetMangled();
  Log *log = GetLog(LLDBLog::Object);
  for (const auto &runtime : m_abi_runtimes) {
    if (runtime->IsVTableSymbol(symbol->GetMangled())) {
      LLDB_LOG(log, "{0:x16} ({1}): symbol='{2}' matches {3}", original_ptr,
               in_value.GetTypeName(), mangled.GetDemangledName(),
               runtime->GetName());

      VTableInfoEntry entry{
          /*info=*/VTableInfo{vtable_addr, symbol},
          /*runtime=*/runtime.get(),
      };
      (*m_vtable_info_map.Lock())[vtable_addr] = entry;
      return entry;
    }
  }
  return llvm::createStringError(std::errc::invalid_argument,
                                 "symbol found that contains 0x%" PRIx64
                                 " is not a vtable symbol",
                                 vtable_load_addr);
}
