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

#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/lldb-private-interfaces.h"

#include "llvm/ADT/StringRef.h"

#include <memory>

#include <cassert>

using namespace lldb;
using namespace lldb_private;

DynamicLoader *DynamicLoader::FindPlugin(Process *process,
                                         llvm::StringRef plugin_name) {
  DynamicLoaderCreateInstance create_callback = nullptr;
  if (!plugin_name.empty()) {
    create_callback =
        PluginManager::GetDynamicLoaderCreateCallbackForPluginName(plugin_name);
    if (create_callback) {
      std::unique_ptr<DynamicLoader> instance_up(
          create_callback(process, true));
      if (instance_up)
        return instance_up.release();
    }
  } else {
    for (auto create_callback :
         PluginManager::GetDynamicLoaderCreateCallbacks()) {
      std::unique_ptr<DynamicLoader> instance_up(
          create_callback(process, false));
      if (instance_up)
        return instance_up.release();
    }
  }
  return nullptr;
}

DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}

// Accessors to the global setting as to whether to stop at image (shared
// library) loading/unloading.

bool DynamicLoader::GetStopWhenImagesChange() const {
  return m_process->GetStopOnSharedLibraryEvents();
}

void DynamicLoader::SetStopWhenImagesChange(bool stop) {
  m_process->SetStopOnSharedLibraryEvents(stop);
}

ModuleSP DynamicLoader::GetTargetExecutable() {
  Target &target = m_process->GetTarget();
  ModuleSP executable = target.GetExecutableModule();

  if (executable) {
    if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
      ModuleSpec module_spec(executable->GetFileSpec(),
                             executable->GetArchitecture());
      auto module_sp = std::make_shared<Module>(module_spec);
      // If we're a coredump and we already have a main executable, we don't
      // need to reload the module list that target already has
      if (!m_process->IsLiveDebugSession()) {
        return executable;
      }
      // Check if the executable has changed and set it to the target
      // executable if they differ.
      if (module_sp && module_sp->GetUUID().IsValid() &&
          executable->GetUUID().IsValid()) {
        if (module_sp->GetUUID() != executable->GetUUID())
          executable.reset();
      } else if (executable->FileHasChanged()) {
        executable.reset();
      }

      if (!executable) {
        executable = target.GetOrCreateModule(module_spec, true /* notify */);
        if (executable.get() != target.GetExecutableModulePointer()) {
          // Don't load dependent images since we are in dyld where we will
          // know and find out about all images that are loaded
          target.SetExecutableModule(executable, eLoadDependentsNo);
        }
      }
    }
  }
  return executable;
}

void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
                                         addr_t base_addr,
                                         bool base_addr_is_offset) {
  UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}

void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
                                               addr_t base_addr,
                                               bool base_addr_is_offset) {
  bool changed;
  module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
                         changed);
}

void DynamicLoader::UnloadSections(const ModuleSP module) {
  UnloadSectionsCommon(module);
}

void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
  Target &target = m_process->GetTarget();
  const SectionList *sections = GetSectionListFromModule(module);

  assert(sections && "SectionList missing from unloaded module.");

  const size_t num_sections = sections->GetSize();
  for (size_t i = 0; i < num_sections; ++i) {
    SectionSP section_sp(sections->GetSectionAtIndex(i));
    target.SetSectionUnloaded(section_sp);
  }
}

const SectionList *
DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
  SectionList *sections = nullptr;
  if (module) {
    ObjectFile *obj_file = module->GetObjectFile();
    if (obj_file != nullptr) {
      sections = obj_file->GetSectionList();
    }
  }
  return sections;
}

ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
  Target &target = m_process->GetTarget();
  ModuleSpec module_spec(file, target.GetArchitecture());
  if (UUID uuid = m_process->FindModuleUUID(file.GetPath())) {
    // Process may be able to augment the module_spec with UUID, e.g. ELF core.
    module_spec.GetUUID() = uuid;
  }

  if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
    return module_sp;

  if (ModuleSP module_sp =
          target.GetOrCreateModule(module_spec, /*notify=*/false))
    return module_sp;

  return nullptr;
}

ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
                                            addr_t link_map_addr,
                                            addr_t base_addr,
                                            bool base_addr_is_offset) {
  ModuleSP module_sp = FindModuleViaTarget(file);
  // We have a core file, try to load the image from memory if we didn't find
  // the module.
  if (!module_sp && !m_process->IsLiveDebugSession()) {
    llvm::Expected<ModuleSP> memory_module_sp_or_err =
        m_process->ReadModuleFromMemory(file, base_addr);
    if (auto err = memory_module_sp_or_err.takeError())
      LLDB_LOG_ERROR(GetLog(LLDBLog::DynamicLoader), std::move(err),
                     "Failed to read module from memory: {0}");
    else {
      module_sp = *memory_module_sp_or_err;
      m_process->GetTarget().GetImages().AppendIfNeeded(module_sp, false);
    }
  }
  if (module_sp)
    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
                         base_addr_is_offset);
  return module_sp;
}

static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr,
                                        llvm::StringRef name) {
  char namebuf[80];
  if (name.empty()) {
    snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
    name = namebuf;
  }
  llvm::Expected<ModuleSP> module_sp_or_err =
      process->ReadModuleFromMemory(FileSpec(name), addr);
  if (auto err = module_sp_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::DynamicLoader), std::move(err),
                   "Failed to read module from memory: {0}");
    return {};
  }
  return *module_sp_or_err;
}

ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
    Process *process, llvm::StringRef name, UUID uuid, addr_t value,
    bool value_is_offset, bool force_symbol_search, bool notify,
    bool set_address_in_target, bool allow_memory_image_last_resort) {
  ModuleSP memory_module_sp;
  ModuleSP module_sp;
  PlatformSP platform_sp = process->GetTarget().GetPlatform();
  Target &target = process->GetTarget();
  Status error;

  StreamString prog_str;
  if (!name.empty()) {
    prog_str << name.str() << " ";
  }
  if (uuid.IsValid())
    prog_str << uuid.GetAsString();
  if (value_is_offset == 0 && value != LLDB_INVALID_ADDRESS) {
    prog_str << " at 0x";
    prog_str.PutHex64(value);
  }

  if (!uuid.IsValid() && !value_is_offset) {
    memory_module_sp = ReadUnnamedMemoryModule(process, value, name);

    if (memory_module_sp) {
      uuid = memory_module_sp->GetUUID();
      if (uuid.IsValid()) {
        prog_str << " ";
        prog_str << uuid.GetAsString();
      }
    }
  }
  ModuleSpec module_spec;
  module_spec.SetTarget(target.shared_from_this());
  module_spec.GetUUID() = uuid;
  FileSpec name_filespec(name);
  if (FileSystem::Instance().Exists(name_filespec))
    module_spec.GetFileSpec() = name_filespec;

  if (uuid.IsValid()) {
    Progress progress("Locating binary", prog_str.GetString().str());

    // Has lldb already seen a module with this UUID?
    // Or have external lookup enabled in DebugSymbols on macOS.
    if (!module_sp)
      error =
          ModuleList::GetSharedModule(module_spec, module_sp, nullptr, nullptr);

    // Can lldb's symbol/executable location schemes
    // find an executable and symbol file.
    if (!module_sp) {
      FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
      StatisticsMap symbol_locator_map;
      module_spec.GetSymbolFileSpec() =
          PluginManager::LocateExecutableSymbolFile(module_spec, search_paths,
                                                    symbol_locator_map);
      ModuleSpec objfile_module_spec =
          PluginManager::LocateExecutableObjectFile(module_spec,
                                                    symbol_locator_map);
      module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
      if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
          FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
        module_sp = std::make_shared<Module>(module_spec);
      }

      if (module_sp) {
        module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
      }
    }

    // If we haven't found a binary, or we don't have a SymbolFile, see
    // if there is an external search tool that can find it.
    if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
      PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
                                                 force_symbol_search);
      if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
        module_sp = std::make_shared<Module>(module_spec);
      } else if (force_symbol_search && error.AsCString("") &&
                 error.AsCString("")[0] != '\0') {
        *target.GetDebugger().GetAsyncErrorStream() << error.AsCString();
      }
    }

    // If we only found the executable, create a Module based on that.
    if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec()))
      module_sp = std::make_shared<Module>(module_spec);
  }

  // If we couldn't find the binary anywhere else, as a last resort,
  // read it out of memory.
  if (allow_memory_image_last_resort && !module_sp.get() &&
      value != LLDB_INVALID_ADDRESS && !value_is_offset) {
    if (!memory_module_sp)
      memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
    if (memory_module_sp)
      module_sp = memory_module_sp;
  }

  Log *log = GetLog(LLDBLog::DynamicLoader);
  if (module_sp.get()) {
    // Ensure the Target has an architecture set in case
    // we need it while processing this binary/eh_frame/debug info.
    if (!target.GetArchitecture().IsValid())
      target.SetArchitecture(module_sp->GetArchitecture());
    target.GetImages().AppendIfNeeded(module_sp, false);

    bool changed = false;
    if (set_address_in_target) {
      if (module_sp->GetObjectFile()) {
        if (value != LLDB_INVALID_ADDRESS) {
          LLDB_LOGF(log,
                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
                    "binary %s UUID %s at %s 0x%" PRIx64,
                    name.str().c_str(), uuid.GetAsString().c_str(),
                    value_is_offset ? "offset" : "address", value);
          module_sp->SetLoadAddress(target, value, value_is_offset, changed);
        } else {
          // No address/offset/slide, load the binary at file address,
          // offset 0.
          LLDB_LOGF(log,
                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
                    "binary %s UUID %s at file address",
                    name.str().c_str(), uuid.GetAsString().c_str());
          module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
                                    changed);
        }
      } else {
        // In-memory image, load at its true address, offset 0.
        LLDB_LOGF(log,
                  "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
                  "%s UUID %s from memory at address 0x%" PRIx64,
                  name.str().c_str(), uuid.GetAsString().c_str(), value);
        module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
                                  changed);
      }
    }

    if (notify) {
      ModuleList added_module;
      added_module.Append(module_sp, false);
      target.ModulesDidLoad(added_module);
    }
  } else {
    if (force_symbol_search) {
      lldb::StreamUP s = target.GetDebugger().GetAsyncErrorStream();
      s->Printf("Unable to find file");
      if (!name.empty())
        s->Printf(" %s", name.str().c_str());
      if (uuid.IsValid())
        s->Printf(" with UUID %s", uuid.GetAsString().c_str());
      if (value != LLDB_INVALID_ADDRESS) {
        if (value_is_offset)
          s->Printf(" with slide 0x%" PRIx64, value);
        else
          s->Printf(" at address 0x%" PRIx64, value);
      }
      s->Printf("\n");
    }
    LLDB_LOGF(log,
              "Unable to find binary %s with UUID %s and load it at "
              "%s 0x%" PRIx64,
              name.str().c_str(), uuid.GetAsString().c_str(),
              value_is_offset ? "offset" : "address", value);
  }

  return module_sp;
}

int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
                                                      int size_in_bytes) {
  Status error;
  uint64_t value =
      m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
  if (error.Fail())
    return -1;
  else
    return (int64_t)value;
}

addr_t DynamicLoader::ReadPointer(addr_t addr) {
  Status error;
  addr_t value = m_process->ReadPointerFromMemory(addr, error);
  if (error.Fail())
    return LLDB_INVALID_ADDRESS;
  else
    return value;
}

void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
{
    if (m_process)
        m_process->LoadOperatingSystemPlugin(flush);
}
