//===-- 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 (uint32_t idx = 0;
         (create_callback =
              PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
         nullptr;
         ++idx) {
      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, 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) {
  if (ModuleSP module_sp = FindModuleViaTarget(file)) {
    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
                         base_addr_is_offset);
    return module_sp;
  }

  return nullptr;
}

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;
  }
  return process->ReadModuleFromMemory(FileSpec(name), addr);
}

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.GetUUID() = uuid;
  FileSpec name_filespec(name);

  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, nullptr);

    // Can lldb's symbol/executable location schemes
    // find an executable and symbol file.
    if (!module_sp) {
      FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
      module_spec.GetSymbolFileSpec() =
          PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
      ModuleSpec objfile_module_spec =
          PluginManager::LocateExecutableObjectFile(module_spec);
      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 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().GetErrorStream() << 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) {
      Stream &s = target.GetDebugger().GetErrorStream();
      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);
}
