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

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Architecture.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb;
using namespace lldb_private;

BreakpointResolverName::BreakpointResolverName(
    const BreakpointSP &bkpt, const char *name_cstr,
    FunctionNameType name_type_mask, LanguageType language,
    Breakpoint::MatchType type, lldb::addr_t offset, bool offset_is_insn_count,
    bool skip_prologue)
    : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset,
                         offset_is_insn_count),
      m_match_type(type), m_language(language), m_skip_prologue(skip_prologue) {
  if (m_match_type == Breakpoint::Regexp) {
    m_regex = RegularExpression(name_cstr);
    if (!m_regex.IsValid()) {
      Log *log = GetLog(LLDBLog::Breakpoints);

      if (log)
        log->Warning("function name regexp: \"%s\" did not compile.",
                     name_cstr);
    }
  } else {
    AddNameLookup(ConstString(name_cstr), name_type_mask);
  }
}

BreakpointResolverName::BreakpointResolverName(
    const BreakpointSP &bkpt, const char *names[], size_t num_names,
    FunctionNameType name_type_mask, LanguageType language, lldb::addr_t offset,
    bool skip_prologue)
    : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
      m_match_type(Breakpoint::Exact), m_language(language),
      m_skip_prologue(skip_prologue) {
  for (size_t i = 0; i < num_names; i++) {
    AddNameLookup(ConstString(names[i]), name_type_mask);
  }
}

BreakpointResolverName::BreakpointResolverName(
    const BreakpointSP &bkpt, const std::vector<std::string> &names,
    FunctionNameType name_type_mask, LanguageType language, lldb::addr_t offset,
    bool skip_prologue)
    : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
      m_match_type(Breakpoint::Exact), m_language(language),
      m_skip_prologue(skip_prologue) {
  for (const std::string &name : names) {
    AddNameLookup(ConstString(name.c_str(), name.size()), name_type_mask);
  }
}

BreakpointResolverName::BreakpointResolverName(const BreakpointSP &bkpt,
                                               RegularExpression func_regex,
                                               lldb::LanguageType language,
                                               lldb::addr_t offset,
                                               bool skip_prologue)
    : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
      m_regex(std::move(func_regex)), m_match_type(Breakpoint::Regexp),
      m_language(language), m_skip_prologue(skip_prologue) {}

BreakpointResolverName::BreakpointResolverName(
    const BreakpointResolverName &rhs)
    : BreakpointResolver(rhs.GetBreakpoint(), BreakpointResolver::NameResolver,
                         rhs.GetOffset(), rhs.GetOffsetIsInsnCount()),
      m_lookups(rhs.m_lookups), m_regex(rhs.m_regex),
      m_match_type(rhs.m_match_type), m_language(rhs.m_language),
      m_skip_prologue(rhs.m_skip_prologue) {}

BreakpointResolverSP BreakpointResolverName::CreateFromStructuredData(
    const StructuredData::Dictionary &options_dict, Status &error) {
  LanguageType language = eLanguageTypeUnknown;
  llvm::StringRef language_name;
  bool success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::LanguageName), language_name);
  if (success) {
    language = Language::GetLanguageTypeFromString(language_name);
    if (language == eLanguageTypeUnknown) {
      error = Status::FromErrorStringWithFormatv(
          "BRN::CFSD: Unknown language: {0}.", language_name);
      return nullptr;
    }
  }

  lldb::offset_t offset = 0;
  success =
      options_dict.GetValueForKeyAsInteger(GetKey(OptionNames::Offset), offset);
  if (!success) {
    error = Status::FromErrorString("BRN::CFSD: Missing offset entry.");
    return nullptr;
  }

  bool skip_prologue;
  success = options_dict.GetValueForKeyAsBoolean(
      GetKey(OptionNames::SkipPrologue), skip_prologue);
  if (!success) {
    error = Status::FromErrorString("BRN::CFSD: Missing Skip prologue entry.");
    return nullptr;
  }

  llvm::StringRef regex_text;
  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::RegexString), regex_text);
  if (success) {
    return std::make_shared<BreakpointResolverName>(
        nullptr, RegularExpression(regex_text), language, offset,
        skip_prologue);
  }
  StructuredData::Array *names_array;
  success = options_dict.GetValueForKeyAsArray(
      GetKey(OptionNames::SymbolNameArray), names_array);
  if (!success) {
    error = Status::FromErrorString("BRN::CFSD: Missing symbol names entry.");
    return nullptr;
  }
    StructuredData::Array *names_mask_array;
    success = options_dict.GetValueForKeyAsArray(
        GetKey(OptionNames::NameMaskArray), names_mask_array);
    if (!success) {
      error = Status::FromErrorString(
          "BRN::CFSD: Missing symbol names mask entry.");
      return nullptr;
    }

    size_t num_elem = names_array->GetSize();
    if (num_elem != names_mask_array->GetSize()) {
      error = Status::FromErrorString(
          "BRN::CFSD: names and names mask arrays have different sizes.");
      return nullptr;
    }

    if (num_elem == 0) {
      error = Status::FromErrorString(
          "BRN::CFSD: no name entry in a breakpoint by name breakpoint.");
      return nullptr;
    }
    std::vector<std::string> names;
    std::vector<FunctionNameType> name_masks;
    for (size_t i = 0; i < num_elem; i++) {
      std::optional<llvm::StringRef> maybe_name =
          names_array->GetItemAtIndexAsString(i);
      if (!maybe_name) {
        error =
            Status::FromErrorString("BRN::CFSD: name entry is not a string.");
        return nullptr;
      }
      auto maybe_fnt = names_mask_array->GetItemAtIndexAsInteger<
          std::underlying_type<FunctionNameType>::type>(i);
      if (!maybe_fnt) {
        error = Status::FromErrorString(
            "BRN::CFSD: name mask entry is not an integer.");
        return nullptr;
      }
      names.push_back(std::string(*maybe_name));
      name_masks.push_back(static_cast<FunctionNameType>(*maybe_fnt));
    }

    std::shared_ptr<BreakpointResolverName> resolver_sp =
        std::make_shared<BreakpointResolverName>(
            nullptr, names[0].c_str(), name_masks[0], language,
            Breakpoint::MatchType::Exact, offset,
            /*offset_is_insn_count = */ false, skip_prologue);
    for (size_t i = 1; i < num_elem; i++) {
      resolver_sp->AddNameLookup(ConstString(names[i]), name_masks[i]);
    }
    return resolver_sp;
}

StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {
  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());

  if (m_regex.IsValid()) {
    options_dict_sp->AddStringItem(GetKey(OptionNames::RegexString),
                                   m_regex.GetText());
  } else {
    StructuredData::ArraySP names_sp(new StructuredData::Array());
    StructuredData::ArraySP name_masks_sp(new StructuredData::Array());
    for (auto lookup : m_lookups) {
      names_sp->AddItem(std::make_shared<StructuredData::String>(
          lookup.GetName().GetStringRef()));
      name_masks_sp->AddItem(std::make_shared<StructuredData::UnsignedInteger>(
          lookup.GetNameTypeMask()));
    }
    options_dict_sp->AddItem(GetKey(OptionNames::SymbolNameArray), names_sp);
    options_dict_sp->AddItem(GetKey(OptionNames::NameMaskArray), name_masks_sp);
  }
  if (m_language != eLanguageTypeUnknown)
    options_dict_sp->AddStringItem(
        GetKey(OptionNames::LanguageName),
        Language::GetNameForLanguageType(m_language));
  options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
                                  m_skip_prologue);

  return WrapOptionsDict(options_dict_sp);
}

void BreakpointResolverName::AddNameLookup(ConstString name,
                                           FunctionNameType name_type_mask) {
  std::vector<Module::LookupInfo> infos =
      Module::LookupInfo::MakeLookupInfos(name, name_type_mask, m_language);
  llvm::append_range(m_lookups, infos);

  auto add_variant_funcs = [&](Language *lang) {
    for (Language::MethodNameVariant variant :
         lang->GetMethodNameVariants(name)) {
      // FIXME: Should we be adding variants that aren't of type Full?
      if (variant.GetType() & lldb::eFunctionNameTypeFull) {
        std::vector<Module::LookupInfo> variant_lookups =
            Module::LookupInfo::MakeLookupInfos(name, variant.GetType(),
                                                lang->GetLanguageType(),
                                                variant.GetName());
        llvm::append_range(m_lookups, variant_lookups);
      }
    }
    return IterationAction::Continue;
  };

  if (Language *lang = Language::FindPlugin(m_language)) {
    add_variant_funcs(lang);
  } else {
    // Most likely m_language is eLanguageTypeUnknown. We check each language for
    // possible variants or more qualified names and create lookups for those as
    // well.
    Language::ForEach(add_variant_funcs);
  }
}

// FIXME: Right now we look at the module level, and call the module's
// "FindFunctions".
// Greg says he will add function tables, maybe at the CompileUnit level to
// accelerate function lookup.  At that point, we should switch the depth to
// CompileUnit, and look in these tables.

Searcher::CallbackReturn
BreakpointResolverName::SearchCallback(SearchFilter &filter,
                                       SymbolContext &context, Address *addr) {
  Log *log = GetLog(LLDBLog::Breakpoints);

  SymbolContextList func_list;
  bool filter_by_cu =
      (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
  bool filter_by_language = (m_language != eLanguageTypeUnknown);

  ModuleFunctionSearchOptions function_options;
  function_options.include_symbols = !filter_by_cu;
  function_options.include_inlines = true;

  switch (m_match_type) {
  case Breakpoint::Exact:
    if (context.module_sp) {
      for (const auto &lookup : m_lookups) {
        const size_t start_func_idx = func_list.GetSize();
        context.module_sp->FindFunctions(lookup, CompilerDeclContext(),
                                         function_options, func_list);

        const size_t end_func_idx = func_list.GetSize();

        if (start_func_idx < end_func_idx)
          lookup.Prune(func_list, start_func_idx);
      }
    }
    break;
  case Breakpoint::Regexp:
    if (context.module_sp) {
      context.module_sp->FindFunctions(m_regex, function_options, func_list);
    }
    break;
  case Breakpoint::Glob:
    if (log)
      log->Warning("glob is not supported yet.");
    break;
  }

  // If the filter specifies a Compilation Unit, remove the ones that don't
  // pass at this point.
  if (filter_by_cu || filter_by_language) {
    uint32_t num_functions = func_list.GetSize();

    for (size_t idx = 0; idx < num_functions; idx++) {
      bool remove_it = false;
      SymbolContext sc;
      func_list.GetContextAtIndex(idx, sc);
      if (filter_by_cu) {
        if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
          remove_it = true;
      }

      if (filter_by_language) {
        LanguageType sym_language = sc.GetLanguage();
        if ((Language::GetPrimaryLanguage(sym_language) !=
             Language::GetPrimaryLanguage(m_language)) &&
            (sym_language != eLanguageTypeUnknown)) {
          remove_it = true;
        }
      }

      if (remove_it) {
        func_list.RemoveContextAtIndex(idx);
        num_functions--;
        idx--;
      }
    }
  }

  BreakpointSP breakpoint_sp = GetBreakpoint();
  Breakpoint &breakpoint = *breakpoint_sp;
  Address break_addr;

  // Remove any duplicates between the function list and the symbol list
  for (const SymbolContext &sc : func_list) {
    bool is_reexported = false;

    if (sc.block && sc.block->GetInlinedFunctionInfo()) {
      if (!sc.block->GetStartAddress(break_addr))
        break_addr.Clear();
    } else if (sc.function) {
      break_addr = sc.function->GetAddress();
      if (m_skip_prologue && break_addr.IsValid()) {
        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
        if (prologue_byte_size)
          break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
      }
    } else if (sc.symbol) {
      if (sc.symbol->GetType() == eSymbolTypeReExported) {
        const Symbol *actual_symbol =
            sc.symbol->ResolveReExportedSymbol(breakpoint.GetTarget());
        if (actual_symbol) {
          is_reexported = true;
          break_addr = actual_symbol->GetAddress();
        }
      } else {
        break_addr = sc.symbol->GetAddress();
      }

      if (m_skip_prologue && break_addr.IsValid()) {
        const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
        if (prologue_byte_size)
          break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
        else {
          const Architecture *arch =
              breakpoint.GetTarget().GetArchitecturePlugin();
          if (arch)
            arch->AdjustBreakpointAddress(*sc.symbol, break_addr);
        }
      }
    }

    if (!break_addr.IsValid())
      continue;

    if (!filter.AddressPasses(break_addr))
      continue;

    bool new_location;
    BreakpointLocationSP bp_loc_sp(AddLocation(break_addr, &new_location));
    bp_loc_sp->SetIsReExported(is_reexported);
    if (bp_loc_sp && new_location && !breakpoint.IsInternal()) {
      if (log) {
        StreamString s;
        bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
        LLDB_LOGF(log, "Added location: %s\n", s.GetData());
      }
    }
  }

  return Searcher::eCallbackReturnContinue;
}

lldb::SearchDepth BreakpointResolverName::GetDepth() {
  return lldb::eSearchDepthModule;
}

void BreakpointResolverName::GetDescription(Stream *s) {
  if (m_match_type == Breakpoint::Regexp)
    s->Printf("regex = '%s'", m_regex.GetText().str().c_str());
  else {
    // Since there may be many lookups objects for the same name breakpoint (one
    // per language available), unique them by name, and operate on those unique
    // names.
    std::vector<ConstString> unique_lookups;
    for (auto &lookup : m_lookups) {
      if (!llvm::is_contained(unique_lookups, lookup.GetName()))
        unique_lookups.push_back(lookup.GetName());
    }
    if (unique_lookups.size() == 1)
      s->Printf("name = '%s'", unique_lookups[0].GetCString());
    else {
      size_t num_names = unique_lookups.size();
      s->Printf("names = {");
      for (size_t i = 0; i < num_names; i++) {
        s->Printf("%s'%s'", (i == 0 ? "" : ", "),
                  unique_lookups[i].GetCString());
      }
      s->Printf("}");
    }
  }
  if (m_language != eLanguageTypeUnknown) {
    s->Printf(", language = %s", Language::GetNameForLanguageType(m_language));
  }
}

void BreakpointResolverName::Dump(Stream *s) const {}

lldb::BreakpointResolverSP
BreakpointResolverName::CopyForBreakpoint(BreakpointSP &breakpoint) {
  lldb::BreakpointResolverSP ret_sp(new BreakpointResolverName(*this));
  ret_sp->SetBreakpoint(breakpoint);
  return ret_sp;
}
