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

#include "lldb/Core/AddressRange.h"
#include "lldb/Core/AddressResolverFileLine.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Symtab.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"

#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#endif

#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"

#include <assert.h>
#include <cstdint>
#include <inttypes.h>
#include <map>
#include <stdarg.h>
#include <string.h>
#include <type_traits>
#include <utility>

namespace lldb_private {
class CompilerDeclContext;
}
namespace lldb_private {
class VariableList;
}

using namespace lldb;
using namespace lldb_private;

// Shared pointers to modules track module lifetimes in targets and in the
// global module, but this collection will track all module objects that are
// still alive
typedef std::vector<Module *> ModuleCollection;

static ModuleCollection &GetModuleCollection() {
  // This module collection needs to live past any module, so we could either
  // make it a shared pointer in each module or just leak is.  Since it is only
  // an empty vector by the time all the modules have gone away, we just leak
  // it for now.  If we decide this is a big problem we can introduce a
  // Finalize method that will tear everything down in a predictable order.

  static ModuleCollection *g_module_collection = nullptr;
  if (g_module_collection == nullptr)
    g_module_collection = new ModuleCollection();

  return *g_module_collection;
}

std::recursive_mutex &Module::GetAllocationModuleCollectionMutex() {
  // NOTE: The mutex below must be leaked since the global module list in
  // the ModuleList class will get torn at some point, and we can't know if it
  // will tear itself down before the "g_module_collection_mutex" below will.
  // So we leak a Mutex object below to safeguard against that

  static std::recursive_mutex *g_module_collection_mutex = nullptr;
  if (g_module_collection_mutex == nullptr)
    g_module_collection_mutex = new std::recursive_mutex; // NOTE: known leak
  return *g_module_collection_mutex;
}

size_t Module::GetNumberAllocatedModules() {
  std::lock_guard<std::recursive_mutex> guard(
      GetAllocationModuleCollectionMutex());
  return GetModuleCollection().size();
}

Module *Module::GetAllocatedModuleAtIndex(size_t idx) {
  std::lock_guard<std::recursive_mutex> guard(
      GetAllocationModuleCollectionMutex());
  ModuleCollection &modules = GetModuleCollection();
  if (idx < modules.size())
    return modules[idx];
  return nullptr;
}

Module::Module(const ModuleSpec &module_spec)
    : m_object_offset(0), m_file_has_changed(false),
      m_first_file_changed_log(false) {
  // Scope for locker below...
  {
    std::lock_guard<std::recursive_mutex> guard(
        GetAllocationModuleCollectionMutex());
    GetModuleCollection().push_back(this);
  }

  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT |
                                                  LIBLLDB_LOG_MODULES));
  if (log != nullptr)
    LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')",
              static_cast<void *>(this),
              module_spec.GetArchitecture().GetArchitectureName(),
              module_spec.GetFileSpec().GetPath().c_str(),
              module_spec.GetObjectName().IsEmpty() ? "" : "(",
              module_spec.GetObjectName().IsEmpty()
                  ? ""
                  : module_spec.GetObjectName().AsCString(""),
              module_spec.GetObjectName().IsEmpty() ? "" : ")");

  // First extract all module specifications from the file using the local file
  // path. If there are no specifications, then don't fill anything in
  ModuleSpecList modules_specs;
  if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0,
                                          modules_specs) == 0)
    return;

  // Now make sure that one of the module specifications matches what we just
  // extract. We might have a module specification that specifies a file
  // "/usr/lib/dyld" with UUID XXX, but we might have a local version of
  // "/usr/lib/dyld" that has
  // UUID YYY and we don't want those to match. If they don't match, just don't
  // fill any ivars in so we don't accidentally grab the wrong file later since
  // they don't match...
  ModuleSpec matching_module_spec;
  if (!modules_specs.FindMatchingModuleSpec(module_spec,
                                            matching_module_spec)) {
    if (log) {
      LLDB_LOGF(log, "Found local object file but the specs didn't match");
    }
    return;
  }

  if (module_spec.GetFileSpec())
    m_mod_time = FileSystem::Instance().GetModificationTime(module_spec.GetFileSpec());
  else if (matching_module_spec.GetFileSpec())
    m_mod_time =
        FileSystem::Instance().GetModificationTime(matching_module_spec.GetFileSpec());

  // Copy the architecture from the actual spec if we got one back, else use
  // the one that was specified
  if (matching_module_spec.GetArchitecture().IsValid())
    m_arch = matching_module_spec.GetArchitecture();
  else if (module_spec.GetArchitecture().IsValid())
    m_arch = module_spec.GetArchitecture();

  // Copy the file spec over and use the specified one (if there was one) so we
  // don't use a path that might have gotten resolved a path in
  // 'matching_module_spec'
  if (module_spec.GetFileSpec())
    m_file = module_spec.GetFileSpec();
  else if (matching_module_spec.GetFileSpec())
    m_file = matching_module_spec.GetFileSpec();

  // Copy the platform file spec over
  if (module_spec.GetPlatformFileSpec())
    m_platform_file = module_spec.GetPlatformFileSpec();
  else if (matching_module_spec.GetPlatformFileSpec())
    m_platform_file = matching_module_spec.GetPlatformFileSpec();

  // Copy the symbol file spec over
  if (module_spec.GetSymbolFileSpec())
    m_symfile_spec = module_spec.GetSymbolFileSpec();
  else if (matching_module_spec.GetSymbolFileSpec())
    m_symfile_spec = matching_module_spec.GetSymbolFileSpec();

  // Copy the object name over
  if (matching_module_spec.GetObjectName())
    m_object_name = matching_module_spec.GetObjectName();
  else
    m_object_name = module_spec.GetObjectName();

  // Always trust the object offset (file offset) and object modification time
  // (for mod time in a BSD static archive) of from the matching module
  // specification
  m_object_offset = matching_module_spec.GetObjectOffset();
  m_object_mod_time = matching_module_spec.GetObjectModificationTime();
}

Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
               const ConstString *object_name, lldb::offset_t object_offset,
               const llvm::sys::TimePoint<> &object_mod_time)
    : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), m_arch(arch),
      m_file(file_spec), m_object_offset(object_offset),
      m_object_mod_time(object_mod_time), m_file_has_changed(false),
      m_first_file_changed_log(false) {
  // Scope for locker below...
  {
    std::lock_guard<std::recursive_mutex> guard(
        GetAllocationModuleCollectionMutex());
    GetModuleCollection().push_back(this);
  }

  if (object_name)
    m_object_name = *object_name;

  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT |
                                                  LIBLLDB_LOG_MODULES));
  if (log != nullptr)
    LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')",
              static_cast<void *>(this), m_arch.GetArchitectureName(),
              m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(",
              m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
              m_object_name.IsEmpty() ? "" : ")");
}

Module::Module()
    : m_object_offset(0), m_file_has_changed(false),
      m_first_file_changed_log(false) {
  std::lock_guard<std::recursive_mutex> guard(
      GetAllocationModuleCollectionMutex());
  GetModuleCollection().push_back(this);
}

Module::~Module() {
  // Lock our module down while we tear everything down to make sure we don't
  // get any access to the module while it is being destroyed
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  // Scope for locker below...
  {
    std::lock_guard<std::recursive_mutex> guard(
        GetAllocationModuleCollectionMutex());
    ModuleCollection &modules = GetModuleCollection();
    ModuleCollection::iterator end = modules.end();
    ModuleCollection::iterator pos = std::find(modules.begin(), end, this);
    assert(pos != end);
    modules.erase(pos);
  }
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT |
                                                  LIBLLDB_LOG_MODULES));
  if (log != nullptr)
    LLDB_LOGF(log, "%p Module::~Module((%s) '%s%s%s%s')",
              static_cast<void *>(this), m_arch.GetArchitectureName(),
              m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(",
              m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
              m_object_name.IsEmpty() ? "" : ")");
  // Release any auto pointers before we start tearing down our member
  // variables since the object file and symbol files might need to make
  // function calls back into this module object. The ordering is important
  // here because symbol files can require the module object file. So we tear
  // down the symbol file first, then the object file.
  m_sections_up.reset();
  m_symfile_up.reset();
  m_objfile_sp.reset();
}

ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp,
                                        lldb::addr_t header_addr, Status &error,
                                        size_t size_to_read) {
  if (m_objfile_sp) {
    error.SetErrorString("object file already exists");
  } else {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    if (process_sp) {
      m_did_load_objfile = true;
      auto data_up = std::make_unique<DataBufferHeap>(size_to_read, 0);
      Status readmem_error;
      const size_t bytes_read =
          process_sp->ReadMemory(header_addr, data_up->GetBytes(),
                                 data_up->GetByteSize(), readmem_error);
      if (bytes_read == size_to_read) {
        DataBufferSP data_sp(data_up.release());
        m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp,
                                              header_addr, data_sp);
        if (m_objfile_sp) {
          StreamString s;
          s.Printf("0x%16.16" PRIx64, header_addr);
          m_object_name.SetString(s.GetString());

          // Once we get the object file, update our module with the object
          // file's architecture since it might differ in vendor/os if some
          // parts were unknown.
          m_arch = m_objfile_sp->GetArchitecture();

          // Augment the arch with the target's information in case
          // we are unable to extract the os/environment from memory.
          m_arch.MergeFrom(process_sp->GetTarget().GetArchitecture());
        } else {
          error.SetErrorString("unable to find suitable object file plug-in");
        }
      } else {
        error.SetErrorStringWithFormat("unable to read header from memory: %s",
                                       readmem_error.AsCString());
      }
    } else {
      error.SetErrorString("invalid process");
    }
  }
  return m_objfile_sp.get();
}

const lldb_private::UUID &Module::GetUUID() {
  if (!m_did_set_uuid.load()) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    if (!m_did_set_uuid.load()) {
      ObjectFile *obj_file = GetObjectFile();

      if (obj_file != nullptr) {
        m_uuid = obj_file->GetUUID();
        m_did_set_uuid = true;
      }
    }
  }
  return m_uuid;
}

void Module::SetUUID(const lldb_private::UUID &uuid) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  if (!m_did_set_uuid) {
    m_uuid = uuid;
    m_did_set_uuid = true;
  } else {
    lldbassert(0 && "Attempting to overwrite the existing module UUID");
  }
}

llvm::Expected<TypeSystem &>
Module::GetTypeSystemForLanguage(LanguageType language) {
  return m_type_system_map.GetTypeSystemForLanguage(language, this, true);
}

void Module::ParseAllDebugSymbols() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  size_t num_comp_units = GetNumCompileUnits();
  if (num_comp_units == 0)
    return;

  SymbolContext sc;
  sc.module_sp = shared_from_this();
  SymbolFile *symbols = GetSymbolFile();

  for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) {
    sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get();
    if (!sc.comp_unit)
      continue;

    symbols->ParseVariablesForContext(sc);

    symbols->ParseFunctions(*sc.comp_unit);

    sc.comp_unit->ForeachFunction([&sc, &symbols](const FunctionSP &f) {
      symbols->ParseBlocksRecursive(*f);

      // Parse the variables for this function and all its blocks
      sc.function = f.get();
      symbols->ParseVariablesForContext(sc);
      return false;
    });

    // Parse all types for this compile unit
    symbols->ParseTypes(*sc.comp_unit);
  }
}

void Module::CalculateSymbolContext(SymbolContext *sc) {
  sc->module_sp = shared_from_this();
}

ModuleSP Module::CalculateSymbolContextModule() { return shared_from_this(); }

void Module::DumpSymbolContext(Stream *s) {
  s->Printf(", Module{%p}", static_cast<void *>(this));
}

size_t Module::GetNumCompileUnits() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, "Module::GetNumCompileUnits (module = %p)",
                     static_cast<void *>(this));
  if (SymbolFile *symbols = GetSymbolFile())
    return symbols->GetNumCompileUnits();
  return 0;
}

CompUnitSP Module::GetCompileUnitAtIndex(size_t index) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  size_t num_comp_units = GetNumCompileUnits();
  CompUnitSP cu_sp;

  if (index < num_comp_units) {
    if (SymbolFile *symbols = GetSymbolFile())
      cu_sp = symbols->GetCompileUnitAtIndex(index);
  }
  return cu_sp;
}

bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat,
                     "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")",
                     vm_addr);
  SectionList *section_list = GetSectionList();
  if (section_list)
    return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list);
  return false;
}

uint32_t Module::ResolveSymbolContextForAddress(
    const Address &so_addr, lldb::SymbolContextItem resolve_scope,
    SymbolContext &sc, bool resolve_tail_call_address) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  uint32_t resolved_flags = 0;

  // Clear the result symbol context in case we don't find anything, but don't
  // clear the target
  sc.Clear(false);

  // Get the section from the section/offset address.
  SectionSP section_sp(so_addr.GetSection());

  // Make sure the section matches this module before we try and match anything
  if (section_sp && section_sp->GetModule().get() == this) {
    // If the section offset based address resolved itself, then this is the
    // right module.
    sc.module_sp = shared_from_this();
    resolved_flags |= eSymbolContextModule;

    SymbolFile *symfile = GetSymbolFile();
    if (!symfile)
      return resolved_flags;

    // Resolve the compile unit, function, block, line table or line entry if
    // requested.
    if (resolve_scope & eSymbolContextCompUnit ||
        resolve_scope & eSymbolContextFunction ||
        resolve_scope & eSymbolContextBlock ||
        resolve_scope & eSymbolContextLineEntry ||
        resolve_scope & eSymbolContextVariable) {
      resolved_flags |=
          symfile->ResolveSymbolContext(so_addr, resolve_scope, sc);
    }

    // Resolve the symbol if requested, but don't re-look it up if we've
    // already found it.
    if (resolve_scope & eSymbolContextSymbol &&
        !(resolved_flags & eSymbolContextSymbol)) {
      Symtab *symtab = symfile->GetSymtab();
      if (symtab && so_addr.IsSectionOffset()) {
        Symbol *matching_symbol = nullptr;

        symtab->ForEachSymbolContainingFileAddress(
            so_addr.GetFileAddress(),
            [&matching_symbol](Symbol *symbol) -> bool {
              if (symbol->GetType() != eSymbolTypeInvalid) {
                matching_symbol = symbol;
                return false; // Stop iterating
              }
              return true; // Keep iterating
            });
        sc.symbol = matching_symbol;
        if (!sc.symbol && resolve_scope & eSymbolContextFunction &&
            !(resolved_flags & eSymbolContextFunction)) {
          bool verify_unique = false; // No need to check again since
                                      // ResolveSymbolContext failed to find a
                                      // symbol at this address.
          if (ObjectFile *obj_file = sc.module_sp->GetObjectFile())
            sc.symbol =
                obj_file->ResolveSymbolForAddress(so_addr, verify_unique);
        }

        if (sc.symbol) {
          if (sc.symbol->IsSynthetic()) {
            // We have a synthetic symbol so lets check if the object file from
            // the symbol file in the symbol vendor is different than the
            // object file for the module, and if so search its symbol table to
            // see if we can come up with a better symbol. For example dSYM
            // files on MacOSX have an unstripped symbol table inside of them.
            ObjectFile *symtab_objfile = symtab->GetObjectFile();
            if (symtab_objfile && symtab_objfile->IsStripped()) {
              ObjectFile *symfile_objfile = symfile->GetObjectFile();
              if (symfile_objfile != symtab_objfile) {
                Symtab *symfile_symtab = symfile_objfile->GetSymtab();
                if (symfile_symtab) {
                  Symbol *symbol =
                      symfile_symtab->FindSymbolContainingFileAddress(
                          so_addr.GetFileAddress());
                  if (symbol && !symbol->IsSynthetic()) {
                    sc.symbol = symbol;
                  }
                }
              }
            }
          }
          resolved_flags |= eSymbolContextSymbol;
        }
      }
    }

    // For function symbols, so_addr may be off by one.  This is a convention
    // consistent with FDE row indices in eh_frame sections, but requires extra
    // logic here to permit symbol lookup for disassembly and unwind.
    if (resolve_scope & eSymbolContextSymbol &&
        !(resolved_flags & eSymbolContextSymbol) && resolve_tail_call_address &&
        so_addr.IsSectionOffset()) {
      Address previous_addr = so_addr;
      previous_addr.Slide(-1);

      bool do_resolve_tail_call_address = false; // prevent recursion
      const uint32_t flags = ResolveSymbolContextForAddress(
          previous_addr, resolve_scope, sc, do_resolve_tail_call_address);
      if (flags & eSymbolContextSymbol) {
        AddressRange addr_range;
        if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
                               false, addr_range)) {
          if (addr_range.GetBaseAddress().GetSection() ==
              so_addr.GetSection()) {
            // If the requested address is one past the address range of a
            // function (i.e. a tail call), or the decremented address is the
            // start of a function (i.e. some forms of trampoline), indicate
            // that the symbol has been resolved.
            if (so_addr.GetOffset() ==
                    addr_range.GetBaseAddress().GetOffset() ||
                so_addr.GetOffset() ==
                    addr_range.GetBaseAddress().GetOffset() +
                        addr_range.GetByteSize()) {
              resolved_flags |= flags;
            }
          } else {
            sc.symbol =
                nullptr; // Don't trust the symbol if the sections didn't match.
          }
        }
      }
    }
  }
  return resolved_flags;
}

uint32_t Module::ResolveSymbolContextForFilePath(
    const char *file_path, uint32_t line, bool check_inlines,
    lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
  FileSpec file_spec(file_path);
  return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
                                          resolve_scope, sc_list);
}

uint32_t Module::ResolveSymbolContextsForFileSpec(
    const FileSpec &file_spec, uint32_t line, bool check_inlines,
    lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat,
                     "Module::ResolveSymbolContextForFilePath (%s:%u, "
                     "check_inlines = %s, resolve_scope = 0x%8.8x)",
                     file_spec.GetPath().c_str(), line,
                     check_inlines ? "yes" : "no", resolve_scope);

  const uint32_t initial_count = sc_list.GetSize();

  if (SymbolFile *symbols = GetSymbolFile())
    symbols->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope,
                                  sc_list);

  return sc_list.GetSize() - initial_count;
}

void Module::FindGlobalVariables(ConstString name,
                                 const CompilerDeclContext *parent_decl_ctx,
                                 size_t max_matches, VariableList &variables) {
  if (SymbolFile *symbols = GetSymbolFile())
    symbols->FindGlobalVariables(name, parent_decl_ctx, max_matches, variables);
}

void Module::FindGlobalVariables(const RegularExpression &regex,
                                 size_t max_matches, VariableList &variables) {
  SymbolFile *symbols = GetSymbolFile();
  if (symbols)
    symbols->FindGlobalVariables(regex, max_matches, variables);
}

void Module::FindCompileUnits(const FileSpec &path,
                              SymbolContextList &sc_list) {
  const size_t num_compile_units = GetNumCompileUnits();
  SymbolContext sc;
  sc.module_sp = shared_from_this();
  const bool compare_directory = (bool)path.GetDirectory();
  for (size_t i = 0; i < num_compile_units; ++i) {
    sc.comp_unit = GetCompileUnitAtIndex(i).get();
    if (sc.comp_unit) {
      if (FileSpec::Equal(*sc.comp_unit, path, compare_directory))
        sc_list.Append(sc);
    }
  }
}

Module::LookupInfo::LookupInfo(ConstString name,
                               FunctionNameType name_type_mask,
                               LanguageType language)
    : m_name(name), m_lookup_name(), m_language(language),
      m_name_type_mask(eFunctionNameTypeNone),
      m_match_name_after_lookup(false) {
  const char *name_cstr = name.GetCString();
  llvm::StringRef basename;
  llvm::StringRef context;

  if (name_type_mask & eFunctionNameTypeAuto) {
    if (CPlusPlusLanguage::IsCPPMangledName(name_cstr))
      m_name_type_mask = eFunctionNameTypeFull;
    else if ((language == eLanguageTypeUnknown ||
              Language::LanguageIsObjC(language)) &&
             ObjCLanguage::IsPossibleObjCMethodName(name_cstr))
      m_name_type_mask = eFunctionNameTypeFull;
    else if (Language::LanguageIsC(language)) {
      m_name_type_mask = eFunctionNameTypeFull;
    } else {
      if ((language == eLanguageTypeUnknown ||
           Language::LanguageIsObjC(language)) &&
          ObjCLanguage::IsPossibleObjCSelector(name_cstr))
        m_name_type_mask |= eFunctionNameTypeSelector;

      CPlusPlusLanguage::MethodName cpp_method(name);
      basename = cpp_method.GetBasename();
      if (basename.empty()) {
        if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
                                                           basename))
          m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
        else
          m_name_type_mask |= eFunctionNameTypeFull;
      } else {
        m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
      }
    }
  } else {
    m_name_type_mask = name_type_mask;
    if (name_type_mask & eFunctionNameTypeMethod ||
        name_type_mask & eFunctionNameTypeBase) {
      // If they've asked for a CPP method or function name and it can't be
      // that, we don't even need to search for CPP methods or names.
      CPlusPlusLanguage::MethodName cpp_method(name);
      if (cpp_method.IsValid()) {
        basename = cpp_method.GetBasename();

        if (!cpp_method.GetQualifiers().empty()) {
          // There is a "const" or other qualifier following the end of the
          // function parens, this can't be a eFunctionNameTypeBase
          m_name_type_mask &= ~(eFunctionNameTypeBase);
          if (m_name_type_mask == eFunctionNameTypeNone)
            return;
        }
      } else {
        // If the CPP method parser didn't manage to chop this up, try to fill
        // in the base name if we can. If a::b::c is passed in, we need to just
        // look up "c", and then we'll filter the result later.
        CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
                                                       basename);
      }
    }

    if (name_type_mask & eFunctionNameTypeSelector) {
      if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) {
        m_name_type_mask &= ~(eFunctionNameTypeSelector);
        if (m_name_type_mask == eFunctionNameTypeNone)
          return;
      }
    }

    // Still try and get a basename in case someone specifies a name type mask
    // of eFunctionNameTypeFull and a name like "A::func"
    if (basename.empty()) {
      if (name_type_mask & eFunctionNameTypeFull &&
          !CPlusPlusLanguage::IsCPPMangledName(name_cstr)) {
        CPlusPlusLanguage::MethodName cpp_method(name);
        basename = cpp_method.GetBasename();
        if (basename.empty())
          CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
                                                         basename);
      }
    }
  }

  if (!basename.empty()) {
    // The name supplied was a partial C++ path like "a::count". In this case
    // we want to do a lookup on the basename "count" and then make sure any
    // matching results contain "a::count" so that it would match "b::a::count"
    // and "a::count". This is why we set "match_name_after_lookup" to true
    m_lookup_name.SetString(basename);
    m_match_name_after_lookup = true;
  } else {
    // The name is already correct, just use the exact name as supplied, and we
    // won't need to check if any matches contain "name"
    m_lookup_name = name;
    m_match_name_after_lookup = false;
  }
}

void Module::LookupInfo::Prune(SymbolContextList &sc_list,
                               size_t start_idx) const {
  if (m_match_name_after_lookup && m_name) {
    SymbolContext sc;
    size_t i = start_idx;
    while (i < sc_list.GetSize()) {
      if (!sc_list.GetContextAtIndex(i, sc))
        break;
      ConstString full_name(sc.GetFunctionName());
      if (full_name &&
          ::strstr(full_name.GetCString(), m_name.GetCString()) == nullptr) {
        sc_list.RemoveContextAtIndex(i);
      } else {
        ++i;
      }
    }
  }

  // If we have only full name matches we might have tried to set breakpoint on
  // "func" and specified eFunctionNameTypeFull, but we might have found
  // "a::func()", "a::b::func()", "c::func()", "func()" and "func". Only
  // "func()" and "func" should end up matching.
  if (m_name_type_mask == eFunctionNameTypeFull) {
    SymbolContext sc;
    size_t i = start_idx;
    while (i < sc_list.GetSize()) {
      if (!sc_list.GetContextAtIndex(i, sc))
        break;
      // Make sure the mangled and demangled names don't match before we try to
      // pull anything out
      ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled));
      ConstString full_name(sc.GetFunctionName());
      if (mangled_name != m_name && full_name != m_name)
      {
        CPlusPlusLanguage::MethodName cpp_method(full_name);
        if (cpp_method.IsValid()) {
          if (cpp_method.GetContext().empty()) {
            if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) {
              sc_list.RemoveContextAtIndex(i);
              continue;
            }
          } else {
            std::string qualified_name;
            llvm::StringRef anon_prefix("(anonymous namespace)");
            if (cpp_method.GetContext() == anon_prefix)
              qualified_name = cpp_method.GetBasename().str();
            else
              qualified_name = cpp_method.GetScopeQualifiedName();
            if (qualified_name != m_name.GetCString()) {
              sc_list.RemoveContextAtIndex(i);
              continue;
            }
          }
        }
      }
      ++i;
    }
  }
}

void Module::FindFunctions(ConstString name,
                           const CompilerDeclContext *parent_decl_ctx,
                           FunctionNameType name_type_mask,
                           bool include_symbols, bool include_inlines,
                           SymbolContextList &sc_list) {
  const size_t old_size = sc_list.GetSize();

  // Find all the functions (not symbols, but debug information functions...
  SymbolFile *symbols = GetSymbolFile();

  if (name_type_mask & eFunctionNameTypeAuto) {
    LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);

    if (symbols) {
      symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx,
                             lookup_info.GetNameTypeMask(), include_inlines,
                             sc_list);

      // Now check our symbol table for symbols that are code symbols if
      // requested
      if (include_symbols) {
        Symtab *symtab = symbols->GetSymtab();
        if (symtab)
          symtab->FindFunctionSymbols(lookup_info.GetLookupName(),
                                      lookup_info.GetNameTypeMask(), sc_list);
      }
    }

    const size_t new_size = sc_list.GetSize();

    if (old_size < new_size)
      lookup_info.Prune(sc_list, old_size);
  } else {
    if (symbols) {
      symbols->FindFunctions(name, parent_decl_ctx, name_type_mask,
                             include_inlines, sc_list);

      // Now check our symbol table for symbols that are code symbols if
      // requested
      if (include_symbols) {
        Symtab *symtab = symbols->GetSymtab();
        if (symtab)
          symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
      }
    }
  }
}

void Module::FindFunctions(const RegularExpression &regex, bool include_symbols,
                           bool include_inlines,
                           SymbolContextList &sc_list) {
  const size_t start_size = sc_list.GetSize();

  if (SymbolFile *symbols = GetSymbolFile()) {
    symbols->FindFunctions(regex, include_inlines, sc_list);

    // Now check our symbol table for symbols that are code symbols if
    // requested
    if (include_symbols) {
      Symtab *symtab = symbols->GetSymtab();
      if (symtab) {
        std::vector<uint32_t> symbol_indexes;
        symtab->AppendSymbolIndexesMatchingRegExAndType(
            regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny,
            symbol_indexes);
        const size_t num_matches = symbol_indexes.size();
        if (num_matches) {
          SymbolContext sc(this);
          const size_t end_functions_added_index = sc_list.GetSize();
          size_t num_functions_added_to_sc_list =
              end_functions_added_index - start_size;
          if (num_functions_added_to_sc_list == 0) {
            // No functions were added, just symbols, so we can just append
            // them
            for (size_t i = 0; i < num_matches; ++i) {
              sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
              SymbolType sym_type = sc.symbol->GetType();
              if (sc.symbol && (sym_type == eSymbolTypeCode ||
                                sym_type == eSymbolTypeResolver))
                sc_list.Append(sc);
            }
          } else {
            typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap;
            FileAddrToIndexMap file_addr_to_index;
            for (size_t i = start_size; i < end_functions_added_index; ++i) {
              const SymbolContext &sc = sc_list[i];
              if (sc.block)
                continue;
              file_addr_to_index[sc.function->GetAddressRange()
                                     .GetBaseAddress()
                                     .GetFileAddress()] = i;
            }

            FileAddrToIndexMap::const_iterator end = file_addr_to_index.end();
            // Functions were added so we need to merge symbols into any
            // existing function symbol contexts
            for (size_t i = start_size; i < num_matches; ++i) {
              sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
              SymbolType sym_type = sc.symbol->GetType();
              if (sc.symbol && sc.symbol->ValueIsAddress() &&
                  (sym_type == eSymbolTypeCode ||
                   sym_type == eSymbolTypeResolver)) {
                FileAddrToIndexMap::const_iterator pos =
                    file_addr_to_index.find(
                        sc.symbol->GetAddressRef().GetFileAddress());
                if (pos == end)
                  sc_list.Append(sc);
                else
                  sc_list[pos->second].symbol = sc.symbol;
              }
            }
          }
        }
      }
    }
  }
}

void Module::FindAddressesForLine(const lldb::TargetSP target_sp,
                                  const FileSpec &file, uint32_t line,
                                  Function *function,
                                  std::vector<Address> &output_local,
                                  std::vector<Address> &output_extern) {
  SearchFilterByModule filter(target_sp, m_file);
  AddressResolverFileLine resolver(file, line, true);
  resolver.ResolveAddress(filter);

  for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) {
    Address addr = resolver.GetAddressRangeAtIndex(n).GetBaseAddress();
    Function *f = addr.CalculateSymbolContextFunction();
    if (f && f == function)
      output_local.push_back(addr);
    else
      output_extern.push_back(addr);
  }
}

void Module::FindTypes_Impl(
    ConstString name, const CompilerDeclContext *parent_decl_ctx,
    size_t max_matches,
    llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
    TypeMap &types) {
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
  if (SymbolFile *symbols = GetSymbolFile())
    symbols->FindTypes(name, parent_decl_ctx, max_matches,
                       searched_symbol_files, types);
}

void Module::FindTypesInNamespace(ConstString type_name,
                                  const CompilerDeclContext *parent_decl_ctx,
                                  size_t max_matches, TypeList &type_list) {
  TypeMap types_map;
  llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
  FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files,
                 types_map);
  if (types_map.GetSize()) {
    SymbolContext sc;
    sc.module_sp = shared_from_this();
    sc.SortTypeList(types_map, type_list);
  }
}

lldb::TypeSP Module::FindFirstType(const SymbolContext &sc,
                                   ConstString name, bool exact_match) {
  TypeList type_list;
  llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
  FindTypes(name, exact_match, 1, searched_symbol_files, type_list);
  if (type_list.GetSize())
    return type_list.GetTypeAtIndex(0);
  return TypeSP();
}

void Module::FindTypes(
    ConstString name, bool exact_match, size_t max_matches,
    llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
    TypeList &types) {
  const char *type_name_cstr = name.GetCString();
  llvm::StringRef type_scope;
  llvm::StringRef type_basename;
  TypeClass type_class = eTypeClassAny;
  TypeMap typesmap;

  if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename,
                                    type_class)) {
    // Check if "name" starts with "::" which means the qualified type starts
    // from the root namespace and implies and exact match. The typenames we
    // get back from clang do not start with "::" so we need to strip this off
    // in order to get the qualified names to match
    exact_match = type_scope.consume_front("::");

    ConstString type_basename_const_str(type_basename);
    FindTypes_Impl(type_basename_const_str, nullptr, max_matches,
                   searched_symbol_files, typesmap);
    if (typesmap.GetSize())
      typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
                                     exact_match);
  } else {
    // The type is not in a namespace/class scope, just search for it by
    // basename
    if (type_class != eTypeClassAny && !type_basename.empty()) {
      // The "type_name_cstr" will have been modified if we have a valid type
      // class prefix (like "struct", "class", "union", "typedef" etc).
      FindTypes_Impl(ConstString(type_basename), nullptr, UINT_MAX,
                     searched_symbol_files, typesmap);
      typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
                                     exact_match);
    } else {
      FindTypes_Impl(name, nullptr, UINT_MAX, searched_symbol_files, typesmap);
      if (exact_match) {
        std::string name_str(name.AsCString(""));
        typesmap.RemoveMismatchedTypes(type_scope, name_str, type_class,
                                       exact_match);
      }
    }
  }
  if (typesmap.GetSize()) {
    SymbolContext sc;
    sc.module_sp = shared_from_this();
    sc.SortTypeList(typesmap, types);
  }
}

void Module::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
                       LanguageSet languages, TypeMap &types) {
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
  if (SymbolFile *symbols = GetSymbolFile())
    symbols->FindTypes(pattern, languages, types);
}

SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {
  if (!m_did_load_symfile.load()) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    if (!m_did_load_symfile.load() && can_create) {
      ObjectFile *obj_file = GetObjectFile();
      if (obj_file != nullptr) {
        static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
        Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
        m_symfile_up.reset(
            SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
        m_did_load_symfile = true;
      }
    }
  }
  return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr;
}

Symtab *Module::GetSymtab() {
  if (SymbolFile *symbols = GetSymbolFile())
    return symbols->GetSymtab();
  return nullptr;
}

void Module::SetFileSpecAndObjectName(const FileSpec &file,
                                      ConstString object_name) {
  // Container objects whose paths do not specify a file directly can call this
  // function to correct the file and object names.
  m_file = file;
  m_mod_time = FileSystem::Instance().GetModificationTime(file);
  m_object_name = object_name;
}

const ArchSpec &Module::GetArchitecture() const { return m_arch; }

std::string Module::GetSpecificationDescription() const {
  std::string spec(GetFileSpec().GetPath());
  if (m_object_name) {
    spec += '(';
    spec += m_object_name.GetCString();
    spec += ')';
  }
  return spec;
}

void Module::GetDescription(Stream *s, lldb::DescriptionLevel level) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  if (level >= eDescriptionLevelFull) {
    if (m_arch.IsValid())
      s->Printf("(%s) ", m_arch.GetArchitectureName());
  }

  if (level == eDescriptionLevelBrief) {
    const char *filename = m_file.GetFilename().GetCString();
    if (filename)
      s->PutCString(filename);
  } else {
    char path[PATH_MAX];
    if (m_file.GetPath(path, sizeof(path)))
      s->PutCString(path);
  }

  const char *object_name = m_object_name.GetCString();
  if (object_name)
    s->Printf("(%s)", object_name);
}

void Module::ReportError(const char *format, ...) {
  if (format && format[0]) {
    StreamString strm;
    strm.PutCString("error: ");
    GetDescription(&strm, lldb::eDescriptionLevelBrief);
    strm.PutChar(' ');
    va_list args;
    va_start(args, format);
    strm.PrintfVarArg(format, args);
    va_end(args);

    const int format_len = strlen(format);
    if (format_len > 0) {
      const char last_char = format[format_len - 1];
      if (last_char != '\n' && last_char != '\r')
        strm.EOL();
    }
    Host::SystemLog(Host::eSystemLogError, "%s", strm.GetData());
  }
}

bool Module::FileHasChanged() const {
  if (!m_file_has_changed)
    m_file_has_changed =
        (FileSystem::Instance().GetModificationTime(m_file) != m_mod_time);
  return m_file_has_changed;
}

void Module::ReportErrorIfModifyDetected(const char *format, ...) {
  if (!m_first_file_changed_log) {
    if (FileHasChanged()) {
      m_first_file_changed_log = true;
      if (format) {
        StreamString strm;
        strm.PutCString("error: the object file ");
        GetDescription(&strm, lldb::eDescriptionLevelFull);
        strm.PutCString(" has been modified\n");

        va_list args;
        va_start(args, format);
        strm.PrintfVarArg(format, args);
        va_end(args);

        const int format_len = strlen(format);
        if (format_len > 0) {
          const char last_char = format[format_len - 1];
          if (last_char != '\n' && last_char != '\r')
            strm.EOL();
        }
        strm.PutCString("The debug session should be aborted as the original "
                        "debug information has been overwritten.\n");
        Host::SystemLog(Host::eSystemLogError, "%s", strm.GetData());
      }
    }
  }
}

void Module::ReportWarning(const char *format, ...) {
  if (format && format[0]) {
    StreamString strm;
    strm.PutCString("warning: ");
    GetDescription(&strm, lldb::eDescriptionLevelFull);
    strm.PutChar(' ');

    va_list args;
    va_start(args, format);
    strm.PrintfVarArg(format, args);
    va_end(args);

    const int format_len = strlen(format);
    if (format_len > 0) {
      const char last_char = format[format_len - 1];
      if (last_char != '\n' && last_char != '\r')
        strm.EOL();
    }
    Host::SystemLog(Host::eSystemLogWarning, "%s", strm.GetData());
  }
}

void Module::LogMessage(Log *log, const char *format, ...) {
  if (log != nullptr) {
    StreamString log_message;
    GetDescription(&log_message, lldb::eDescriptionLevelFull);
    log_message.PutCString(": ");
    va_list args;
    va_start(args, format);
    log_message.PrintfVarArg(format, args);
    va_end(args);
    log->PutCString(log_message.GetData());
  }
}

void Module::LogMessageVerboseBacktrace(Log *log, const char *format, ...) {
  if (log != nullptr) {
    StreamString log_message;
    GetDescription(&log_message, lldb::eDescriptionLevelFull);
    log_message.PutCString(": ");
    va_list args;
    va_start(args, format);
    log_message.PrintfVarArg(format, args);
    va_end(args);
    if (log->GetVerbose()) {
      std::string back_trace;
      llvm::raw_string_ostream stream(back_trace);
      llvm::sys::PrintStackTrace(stream);
      log_message.PutCString(back_trace);
    }
    log->PutCString(log_message.GetData());
  }
}

void Module::Dump(Stream *s) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
  s->Indent();
  s->Printf("Module %s%s%s%s\n", m_file.GetPath().c_str(),
            m_object_name ? "(" : "",
            m_object_name ? m_object_name.GetCString() : "",
            m_object_name ? ")" : "");

  s->IndentMore();

  ObjectFile *objfile = GetObjectFile();
  if (objfile)
    objfile->Dump(s);

  if (SymbolFile *symbols = GetSymbolFile())
    symbols->Dump(*s);

  s->IndentLess();
}

ConstString Module::GetObjectName() const { return m_object_name; }

ObjectFile *Module::GetObjectFile() {
  if (!m_did_load_objfile.load()) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    if (!m_did_load_objfile.load()) {
      static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
      Timer scoped_timer(func_cat, "Module::GetObjectFile () module = %s",
                         GetFileSpec().GetFilename().AsCString(""));
      DataBufferSP data_sp;
      lldb::offset_t data_offset = 0;
      const lldb::offset_t file_size =
          FileSystem::Instance().GetByteSize(m_file);
      if (file_size > m_object_offset) {
        m_did_load_objfile = true;
        m_objfile_sp = ObjectFile::FindPlugin(
            shared_from_this(), &m_file, m_object_offset,
            file_size - m_object_offset, data_sp, data_offset);
        if (m_objfile_sp) {
          // Once we get the object file, update our module with the object
          // file's architecture since it might differ in vendor/os if some
          // parts were unknown.  But since the matching arch might already be
          // more specific than the generic COFF architecture, only merge in
          // those values that overwrite unspecified unknown values.
          m_arch.MergeFrom(m_objfile_sp->GetArchitecture());
        } else {
          ReportError("failed to load objfile for %s",
                      GetFileSpec().GetPath().c_str());
        }
      }
    }
  }
  return m_objfile_sp.get();
}

SectionList *Module::GetSectionList() {
  // Populate m_sections_up with sections from objfile.
  if (!m_sections_up) {
    ObjectFile *obj_file = GetObjectFile();
    if (obj_file != nullptr)
      obj_file->CreateSections(*GetUnifiedSectionList());
  }
  return m_sections_up.get();
}

void Module::SectionFileAddressesChanged() {
  ObjectFile *obj_file = GetObjectFile();
  if (obj_file)
    obj_file->SectionFileAddressesChanged();
  if (SymbolFile *symbols = GetSymbolFile())
    symbols->SectionFileAddressesChanged();
}

UnwindTable &Module::GetUnwindTable() {
  if (!m_unwind_table)
    m_unwind_table.emplace(*this);
  return *m_unwind_table;
}

SectionList *Module::GetUnifiedSectionList() {
  if (!m_sections_up)
    m_sections_up = std::make_unique<SectionList>();
  return m_sections_up.get();
}

const Symbol *Module::FindFirstSymbolWithNameAndType(ConstString name,
                                                     SymbolType symbol_type) {
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(
      func_cat, "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
      name.AsCString(), symbol_type);
  if (Symtab *symtab = GetSymtab())
    return symtab->FindFirstSymbolWithNameAndType(
        name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny);
  return nullptr;
}
void Module::SymbolIndicesToSymbolContextList(
    Symtab *symtab, std::vector<uint32_t> &symbol_indexes,
    SymbolContextList &sc_list) {
  // No need to protect this call using m_mutex all other method calls are
  // already thread safe.

  size_t num_indices = symbol_indexes.size();
  if (num_indices > 0) {
    SymbolContext sc;
    CalculateSymbolContext(&sc);
    for (size_t i = 0; i < num_indices; i++) {
      sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
      if (sc.symbol)
        sc_list.Append(sc);
    }
  }
}

void Module::FindFunctionSymbols(ConstString name,
                                   uint32_t name_type_mask,
                                   SymbolContextList &sc_list) {
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat,
                     "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)",
                     name.AsCString(), name_type_mask);
  if (Symtab *symtab = GetSymtab())
    symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
}

void Module::FindSymbolsWithNameAndType(ConstString name,
                                          SymbolType symbol_type,
                                          SymbolContextList &sc_list) {
  // No need to protect this call using m_mutex all other method calls are
  // already thread safe.

  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(
      func_cat, "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
      name.AsCString(), symbol_type);
  if (Symtab *symtab = GetSymtab()) {
    std::vector<uint32_t> symbol_indexes;
    symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes);
    SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
  }
}

void Module::FindSymbolsMatchingRegExAndType(const RegularExpression &regex,
                                             SymbolType symbol_type,
                                             SymbolContextList &sc_list) {
  // No need to protect this call using m_mutex all other method calls are
  // already thread safe.

  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(
      func_cat,
      "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
      regex.GetText().str().c_str(), symbol_type);
  if (Symtab *symtab = GetSymtab()) {
    std::vector<uint32_t> symbol_indexes;
    symtab->FindAllSymbolsMatchingRexExAndType(
        regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny,
        symbol_indexes);
    SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
  }
}

void Module::PreloadSymbols() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  SymbolFile *sym_file = GetSymbolFile();
  if (!sym_file)
    return;

  // Prime the symbol file first, since it adds symbols to the symbol table.
  sym_file->PreloadSymbols();

  // Now we can prime the symbol table.
  if (Symtab *symtab = sym_file->GetSymtab())
    symtab->PreloadSymbols();
}

void Module::SetSymbolFileFileSpec(const FileSpec &file) {
  if (!FileSystem::Instance().Exists(file))
    return;
  if (m_symfile_up) {
    // Remove any sections in the unified section list that come from the
    // current symbol vendor.
    SectionList *section_list = GetSectionList();
    SymbolFile *symbol_file = GetSymbolFile();
    if (section_list && symbol_file) {
      ObjectFile *obj_file = symbol_file->GetObjectFile();
      // Make sure we have an object file and that the symbol vendor's objfile
      // isn't the same as the module's objfile before we remove any sections
      // for it...
      if (obj_file) {
        // Check to make sure we aren't trying to specify the file we already
        // have
        if (obj_file->GetFileSpec() == file) {
          // We are being told to add the exact same file that we already have
          // we don't have to do anything.
          return;
        }

        // Cleare the current symtab as we are going to replace it with a new
        // one
        obj_file->ClearSymtab();

        // Clear the unwind table too, as that may also be affected by the
        // symbol file information.
        m_unwind_table.reset();

        // The symbol file might be a directory bundle ("/tmp/a.out.dSYM")
        // instead of a full path to the symbol file within the bundle
        // ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to
        // check this

        if (FileSystem::Instance().IsDirectory(file)) {
          std::string new_path(file.GetPath());
          std::string old_path(obj_file->GetFileSpec().GetPath());
          if (old_path.find(new_path) == 0) {
            // We specified the same bundle as the symbol file that we already
            // have
            return;
          }
        }

        if (obj_file != m_objfile_sp.get()) {
          size_t num_sections = section_list->GetNumSections(0);
          for (size_t idx = num_sections; idx > 0; --idx) {
            lldb::SectionSP section_sp(
                section_list->GetSectionAtIndex(idx - 1));
            if (section_sp->GetObjectFile() == obj_file) {
              section_list->DeleteSection(idx - 1);
            }
          }
        }
      }
    }
    // Keep all old symbol files around in case there are any lingering type
    // references in any SBValue objects that might have been handed out.
    m_old_symfiles.push_back(std::move(m_symfile_up));
  }
  m_symfile_spec = file;
  m_symfile_up.reset();
  m_did_load_symfile = false;
}

bool Module::IsExecutable() {
  if (GetObjectFile() == nullptr)
    return false;
  else
    return GetObjectFile()->IsExecutable();
}

bool Module::IsLoadedInTarget(Target *target) {
  ObjectFile *obj_file = GetObjectFile();
  if (obj_file) {
    SectionList *sections = GetSectionList();
    if (sections != nullptr) {
      size_t num_sections = sections->GetSize();
      for (size_t sect_idx = 0; sect_idx < num_sections; sect_idx++) {
        SectionSP section_sp = sections->GetSectionAtIndex(sect_idx);
        if (section_sp->GetLoadBaseAddress(target) != LLDB_INVALID_ADDRESS) {
          return true;
        }
      }
    }
  }
  return false;
}

bool Module::LoadScriptingResourceInTarget(Target *target, Status &error,
                                           Stream *feedback_stream) {
  if (!target) {
    error.SetErrorString("invalid destination Target");
    return false;
  }

  LoadScriptFromSymFile should_load =
      target->TargetProperties::GetLoadScriptFromSymbolFile();

  if (should_load == eLoadScriptFromSymFileFalse)
    return false;

  Debugger &debugger = target->GetDebugger();
  const ScriptLanguage script_language = debugger.GetScriptLanguage();
  if (script_language != eScriptLanguageNone) {

    PlatformSP platform_sp(target->GetPlatform());

    if (!platform_sp) {
      error.SetErrorString("invalid Platform");
      return false;
    }

    FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources(
        target, *this, feedback_stream);

    const uint32_t num_specs = file_specs.GetSize();
    if (num_specs) {
      ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
      if (script_interpreter) {
        for (uint32_t i = 0; i < num_specs; ++i) {
          FileSpec scripting_fspec(file_specs.GetFileSpecAtIndex(i));
          if (scripting_fspec &&
              FileSystem::Instance().Exists(scripting_fspec)) {
            if (should_load == eLoadScriptFromSymFileWarn) {
              if (feedback_stream)
                feedback_stream->Printf(
                    "warning: '%s' contains a debug script. To run this script "
                    "in "
                    "this debug session:\n\n    command script import "
                    "\"%s\"\n\n"
                    "To run all discovered debug scripts in this session:\n\n"
                    "    settings set target.load-script-from-symbol-file "
                    "true\n",
                    GetFileSpec().GetFileNameStrippingExtension().GetCString(),
                    scripting_fspec.GetPath().c_str());
              return false;
            }
            StreamString scripting_stream;
            scripting_fspec.Dump(&scripting_stream);
            const bool can_reload = true;
            const bool init_lldb_globals = false;
            bool did_load = script_interpreter->LoadScriptingModule(
                scripting_stream.GetData(), can_reload, init_lldb_globals,
                error);
            if (!did_load)
              return false;
          }
        }
      } else {
        error.SetErrorString("invalid ScriptInterpreter");
        return false;
      }
    }
  }
  return true;
}

bool Module::SetArchitecture(const ArchSpec &new_arch) {
  if (!m_arch.IsValid()) {
    m_arch = new_arch;
    return true;
  }
  return m_arch.IsCompatibleMatch(new_arch);
}

bool Module::SetLoadAddress(Target &target, lldb::addr_t value,
                            bool value_is_offset, bool &changed) {
  ObjectFile *object_file = GetObjectFile();
  if (object_file != nullptr) {
    changed = object_file->SetLoadAddress(target, value, value_is_offset);
    return true;
  } else {
    changed = false;
  }
  return false;
}

bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) {
  const UUID &uuid = module_ref.GetUUID();

  if (uuid.IsValid()) {
    // If the UUID matches, then nothing more needs to match...
    return (uuid == GetUUID());
  }

  const FileSpec &file_spec = module_ref.GetFileSpec();
  if (file_spec) {
    if (!FileSpec::Equal(file_spec, m_file, (bool)file_spec.GetDirectory()) &&
        !FileSpec::Equal(file_spec, m_platform_file,
                         (bool)file_spec.GetDirectory()))
      return false;
  }

  const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec();
  if (platform_file_spec) {
    if (!FileSpec::Equal(platform_file_spec, GetPlatformFileSpec(),
                         (bool)platform_file_spec.GetDirectory()))
      return false;
  }

  const ArchSpec &arch = module_ref.GetArchitecture();
  if (arch.IsValid()) {
    if (!m_arch.IsCompatibleMatch(arch))
      return false;
  }

  ConstString object_name = module_ref.GetObjectName();
  if (object_name) {
    if (object_name != GetObjectName())
      return false;
  }
  return true;
}

bool Module::FindSourceFile(const FileSpec &orig_spec,
                            FileSpec &new_spec) const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  return m_source_mappings.FindFile(orig_spec, new_spec);
}

bool Module::RemapSourceFile(llvm::StringRef path,
                             std::string &new_path) const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  return m_source_mappings.RemapPath(path, new_path);
}

bool Module::MergeArchitecture(const ArchSpec &arch_spec) {
  if (!arch_spec.IsValid())
    return false;
  LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES),
           "module has arch %s, merging/replacing with arch %s",
           m_arch.GetTriple().getTriple().c_str(),
           arch_spec.GetTriple().getTriple().c_str());
  if (!m_arch.IsCompatibleMatch(arch_spec)) {
    // The new architecture is different, we just need to replace it.
    return SetArchitecture(arch_spec);
  }

  // Merge bits from arch_spec into "merged_arch" and set our architecture.
  ArchSpec merged_arch(m_arch);
  merged_arch.MergeFrom(arch_spec);
  // SetArchitecture() is a no-op if m_arch is already valid.
  m_arch = ArchSpec();
  return SetArchitecture(merged_arch);
}

llvm::VersionTuple Module::GetVersion() {
  if (ObjectFile *obj_file = GetObjectFile())
    return obj_file->GetVersion();
  return llvm::VersionTuple();
}

bool Module::GetIsDynamicLinkEditor() {
  ObjectFile *obj_file = GetObjectFile();

  if (obj_file)
    return obj_file->GetIsDynamicLinkEditor();

  return false;
}
