//===-- DynamicLoaderFreeBSDKernel.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/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"

#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"

#include "DynamicLoaderFreeBSDKernel.h"
#include <memory>
#include <mutex>

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel)

void DynamicLoaderFreeBSDKernel::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInit);
}

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

llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() {
  return "The Dynamic Loader Plugin For FreeBSD Kernel";
}

static bool is_kernel(Module *module) {
  if (!module)
    return false;

  ObjectFile *objfile = module->GetObjectFile();
  if (!objfile)
    return false;
  if (objfile->GetType() != ObjectFile::eTypeExecutable)
    return false;
  if (objfile->GetStrata() != ObjectFile::eStrataUnknown &&
      objfile->GetStrata() != ObjectFile::eStrataKernel)
    return false;

  return true;
}

static bool is_kmod(Module *module) {
  if (!module)
    return false;
  if (!module->GetObjectFile())
    return false;
  ObjectFile *objfile = module->GetObjectFile();
  if (objfile->GetType() != ObjectFile::eTypeObjectFile &&
      objfile->GetType() != ObjectFile::eTypeSharedLibrary)
    return false;

  return true;
}

static bool is_reloc(Module *module) {
  if (!module)
    return false;
  if (!module->GetObjectFile())
    return false;
  ObjectFile *objfile = module->GetObjectFile();
  if (objfile->GetType() != ObjectFile::eTypeObjectFile)
    return false;

  return true;
}

// Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when
// Register the Plugin
DynamicLoader *
DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process,
                                           bool force) {
  // Check the environment when the plugin is not force loaded
  Module *exec = process->GetTarget().GetExecutableModulePointer();
  if (exec && !is_kernel(exec)) {
    return nullptr;
  }
  if (!force) {
    // Check if the target is kernel
    const llvm::Triple &triple_ref =
        process->GetTarget().GetArchitecture().GetTriple();
    if (!triple_ref.isOSFreeBSD()) {
      return nullptr;
    }
  }

  // At this point we have checked the target is a FreeBSD kernel and all we
  // have to do is to find the kernel address
  const addr_t kernel_address = FindFreeBSDKernel(process);

  if (CheckForKernelImageAtAddress(process, kernel_address).IsValid())
    return new DynamicLoaderFreeBSDKernel(process, kernel_address);

  return nullptr;
}

addr_t
DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) {
  addr_t kernel_addr = process->GetImageInfoAddress();
  if (kernel_addr == LLDB_INVALID_ADDRESS)
    kernel_addr = FindKernelAtLoadAddress(process);
  return kernel_addr;
}

// Get the kernel address if the kernel is not loaded with a slide
addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress(
    lldb_private::Process *process) {
  Module *exe_module = process->GetTarget().GetExecutableModulePointer();

  if (!is_kernel(exe_module))
    return LLDB_INVALID_ADDRESS;

  ObjectFile *exe_objfile = exe_module->GetObjectFile();

  if (!exe_objfile->GetBaseAddress().IsValid())
    return LLDB_INVALID_ADDRESS;

  if (CheckForKernelImageAtAddress(
          process, exe_objfile->GetBaseAddress().GetFileAddress())
          .IsValid())
    return exe_objfile->GetBaseAddress().GetFileAddress();

  return LLDB_INVALID_ADDRESS;
}

// Read ELF header from memry and return
bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process,
                                               lldb::addr_t addr,
                                               llvm::ELF::Elf32_Ehdr &header,
                                               bool *read_error) {
  Status error;
  if (read_error)
    *read_error = false;

  if (process->ReadMemory(addr, &header, sizeof(header), error) !=
          sizeof(header) ||
      error.Fail()) {
    if (read_error)
      *read_error = true;
    return false;
  }

  if (!header.checkMagic())
    return false;

  return true;
}

// Check the correctness of Kernel and return UUID
lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
    Process *process, lldb::addr_t addr, bool *read_error) {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  if (addr == LLDB_INVALID_ADDRESS) {
    if (read_error)
      *read_error = true;
    return UUID();
  }

  LLDB_LOGF(log,
            "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
            "looking for kernel binary at 0x%" PRIx64,
            addr);

  llvm::ELF::Elf32_Ehdr header;
  if (!ReadELFHeader(process, addr, header)) {
    *read_error = true;
    return UUID();
  }

  // Check header type
  if (header.e_type != llvm::ELF::ET_EXEC)
    return UUID();

  llvm::Expected<ModuleSP> memory_module_sp_or_err =
      process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);
  if (auto err = memory_module_sp_or_err.takeError()) {
    LLDB_LOG_ERROR(log, std::move(err),
                   "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
                   "Failed to read module in memory -- {0}");
    *read_error = true;
    return UUID();
  }

  ModuleSP memory_module_sp = *memory_module_sp_or_err;
  if (!memory_module_sp.get()) {
    *read_error = true;
    return UUID();
  }

  ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
  if (exe_objfile == nullptr) {
    LLDB_LOGF(log,
              "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress "
              "found a binary at 0x%" PRIx64
              " but could not create an object file from memory",
              addr);
    return UUID();
  }

  // In here, I should check is_kernel for memory_module_sp
  // However, the ReadModuleFromMemory reads wrong section so that this check
  // will failed
  ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine));

  if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
    process->GetTarget().SetArchitecture(kernel_arch);

  std::string uuid_str;
  if (memory_module_sp->GetUUID().IsValid()) {
    uuid_str = "with UUID ";
    uuid_str += memory_module_sp->GetUUID().GetAsString();
  } else {
    uuid_str = "and no LC_UUID found in load commands ";
  }
  LLDB_LOGF(log,
            "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
            "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
            addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());

  return memory_module_sp->GetUUID();
}

void DynamicLoaderFreeBSDKernel::DebuggerInit(
    lldb_private::Debugger &debugger) {}

DynamicLoaderFreeBSDKernel::DynamicLoaderFreeBSDKernel(Process *process,
                                                       addr_t kernel_address)
    : DynamicLoader(process), m_process(process),
      m_kernel_load_address(kernel_address), m_mutex() {
  process->SetCanRunCode(false);
}

DynamicLoaderFreeBSDKernel::~DynamicLoaderFreeBSDKernel() { Clear(true); }

void DynamicLoaderFreeBSDKernel::Update() {
  LoadKernelModules();
  SetNotificationBreakPoint();
}

// Create in memory Module at the load address
bool DynamicLoaderFreeBSDKernel::KModImageInfo::ReadMemoryModule(
    lldb_private::Process *process) {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  if (m_memory_module_sp)
    return true;
  if (m_load_address == LLDB_INVALID_ADDRESS)
    return false;

  FileSpec file_spec(m_name);

  ModuleSP memory_module_sp;

  llvm::ELF::Elf32_Ehdr elf_eheader;
  size_t size_to_read = 512;

  if (ReadELFHeader(process, m_load_address, elf_eheader)) {
    if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
      size_to_read = sizeof(llvm::ELF::Elf32_Ehdr) +
                     elf_eheader.e_phnum * elf_eheader.e_phentsize;
    } else if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] ==
               llvm::ELF::ELFCLASS64) {
      llvm::ELF::Elf64_Ehdr elf_eheader;
      Status error;
      if (process->ReadMemory(m_load_address, &elf_eheader, sizeof(elf_eheader),
                              error) == sizeof(elf_eheader) &&
          error.Success())
        size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) +
                       elf_eheader.e_phnum * elf_eheader.e_phentsize;
    }
  }

  llvm::Expected<ModuleSP> memory_module_sp_or_err =
      process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);
  if (auto err = memory_module_sp_or_err.takeError()) {
    LLDB_LOG_ERROR(log, std::move(err),
                   "KextImageInfo::ReadMemoryModule: Failed to read module "
                   "from memory -- {0}");
    return false;
  }
  memory_module_sp = *memory_module_sp_or_err;

  if (!memory_module_sp)
    return false;

  bool this_is_kernel = is_kernel(memory_module_sp.get());

  if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
    m_uuid = memory_module_sp->GetUUID();

  m_memory_module_sp = memory_module_sp;
  m_is_kernel = this_is_kernel;

  // The kernel binary is from memory
  if (this_is_kernel) {
    LLDB_LOGF(log, "KextImageInfo::ReadMemoryModule read the kernel binary out "
                   "of memory");

    if (memory_module_sp->GetArchitecture().IsValid())
      process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
  }

  return true;
}

bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
    lldb_private::Process *process) {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  if (IsLoaded())
    return true;

  Target &target = process->GetTarget();

  if (IsKernel() && m_uuid.IsValid()) {
    lldb::StreamUP s = target.GetDebugger().GetAsyncOutputStream();
    s->Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
    s->Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
  }

  // Test if the module is loaded into the taget,
  // maybe the module is loaded manually by user by doing target module add
  // So that we have to create the module manually
  if (!m_module_sp) {
    const ModuleList &target_images = target.GetImages();
    m_module_sp = target_images.FindModule(m_uuid);

    // Search in the file system
    if (!m_module_sp) {
      ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture());
      if (IsKernel()) {
        Status error;
        if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
                                                       true) &&
            error.Success()) {
          if (FileSystem::Instance().Exists(module_spec.GetFileSpec()))
            m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
                                                   target.GetArchitecture());
        }
      }

      if (!m_module_sp)
        m_module_sp = target.GetOrCreateModule(module_spec, true);
      if (IsKernel() && !m_module_sp) {
        target.GetDebugger().GetAsyncOutputStream()->Printf(
            "WARNING: Unable to locate kernel binary on the debugger "
            "system.\n");
      }
    }

    if (m_module_sp) {
      // If the file is not kernel or kmod, the target should be loaded once and
      // don't reload again
      if (!IsKernel() && !is_kmod(m_module_sp.get())) {
        ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid);
        if (existing_module_sp &&
            existing_module_sp->IsLoadedInTarget(&target)) {
          LLDB_LOGF(log,
                    "'%s' with UUID %s is not a kmod or kernel, and is "
                    "already registered in target, not loading.",
                    m_name.c_str(), m_uuid.GetAsString().c_str());
          return true;
        }
      }
      m_uuid = m_module_sp->GetUUID();

      // or append to the images
      target.GetImages().AppendIfNeeded(m_module_sp, false);
    }
  }

  // If this file is relocatable kernel module(x86_64), adjust it's
  // section(PT_LOAD segment) and return Because the kernel module's load
  // address is the text section. lldb cannot create full memory module upon
  // relocatable file So what we do is to set the load address only.
  if (is_kmod(m_module_sp.get()) && is_reloc(m_module_sp.get())) {
    m_stop_id = process->GetStopID();
    bool changed = false;
    m_module_sp->SetLoadAddress(target, m_load_address, true, changed);
    return true;
  }

  if (m_module_sp)
    ReadMemoryModule(process);

  // Calculate the slides of in memory module
  if (!m_memory_module_sp || !m_module_sp) {
    m_module_sp.reset();
    return false;
  }

  ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
  ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();

  if (!ondisk_object_file || !memory_object_file)
    m_module_sp.reset();

  // Find the slide address
  addr_t fixed_slide = LLDB_INVALID_ADDRESS;
  if (llvm::dyn_cast<ObjectFileELF>(memory_object_file)) {
    addr_t load_address = memory_object_file->GetBaseAddress().GetFileAddress();

    if (load_address != LLDB_INVALID_ADDRESS &&
        m_load_address != load_address) {
      fixed_slide = m_load_address - load_address;
      LLDB_LOGF(log,
                "kmod %s in-memory LOAD vmaddr is not correct, using a "
                "fixed slide of 0x%" PRIx64,
                m_name.c_str(), fixed_slide);
    }
  }

  SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
  SectionList *memory_section_list = memory_object_file->GetSectionList();

  if (memory_section_list && ondisk_object_file) {
    const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
    uint32_t num_load_sections = 0;

    for (uint32_t section_idx = 0; section_idx < num_ondisk_sections;
         ++section_idx) {
      SectionSP on_disk_section_sp =
          ondisk_section_list->GetSectionAtIndex(section_idx);

      if (!on_disk_section_sp)
        continue;
      if (fixed_slide != LLDB_INVALID_ADDRESS) {
        target.SetSectionLoadAddress(on_disk_section_sp,
                                     on_disk_section_sp->GetFileAddress() +
                                         fixed_slide);

      } else {
        const Section *memory_section =
            memory_section_list
                ->FindSectionByName(on_disk_section_sp->GetName())
                .get();
        if (memory_section) {
          target.SetSectionLoadAddress(on_disk_section_sp,
                                       memory_section->GetFileAddress());
          ++num_load_sections;
        }
      }
    }

    if (num_load_sections)
      m_stop_id = process->GetStopID();
    else
      m_module_sp.reset();
  } else {
    m_module_sp.reset();
  }

  if (IsLoaded() && m_module_sp && IsKernel()) {
    lldb::StreamUP s = target.GetDebugger().GetAsyncOutputStream();
    ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
    if (kernel_object_file) {
      addr_t file_address =
          kernel_object_file->GetBaseAddress().GetFileAddress();
      if (m_load_address != LLDB_INVALID_ADDRESS &&
          file_address != LLDB_INVALID_ADDRESS) {
        s->Printf("Kernel slide 0x%" PRIx64 " in memory.\n",
                  m_load_address - file_address);
        s->Printf("Loaded kernel file %s\n",
                  m_module_sp->GetFileSpec().GetPath().c_str());
      }
    }
  }

  return IsLoaded();
}

// This function is work for kernel file, others it wil reset load address and
// return false
bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingFileAddress(
    lldb_private::Process *process) {
  if (IsLoaded())
    return true;

  if (m_module_sp) {
    bool changed = false;
    if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed))
      m_stop_id = process->GetStopID();
  }

  return false;
}

// Get the head of found_list
bool DynamicLoaderFreeBSDKernel::ReadKmodsListHeader() {
  std::lock_guard<decltype(m_mutex)> guard(m_mutex);

  if (m_linker_file_list_struct_addr.IsValid()) {
    // Get tqh_first struct element from linker_files
    Status error;
    addr_t address = m_process->ReadPointerFromMemory(
        m_linker_file_list_struct_addr.GetLoadAddress(&m_process->GetTarget()),
        error);
    if (address != LLDB_INVALID_ADDRESS && error.Success()) {
      m_linker_file_head_addr = Address(address);
    } else {
      m_linker_file_list_struct_addr.Clear();
      return false;
    }

    if (!m_linker_file_head_addr.IsValid() ||
        m_linker_file_head_addr.GetFileAddress() == 0) {
      m_linker_file_list_struct_addr.Clear();
      return false;
    }
  }
  return true;
}

// Parse Kmod info in found_list
bool DynamicLoaderFreeBSDKernel::ParseKmods(Address linker_files_head_addr) {
  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
  KModImageInfo::collection_type linker_files_list;
  Log *log = GetLog(LLDBLog::DynamicLoader);

  if (!ReadAllKmods(linker_files_head_addr, linker_files_list))
    return false;
  LLDB_LOGF(
      log,
      "Kmod-changed breakpoint hit, there are %zu kernel modules currently.\n",
      linker_files_list.size());

  ModuleList &modules = m_process->GetTarget().GetImages();
  ModuleList remove_modules;
  ModuleList add_modules;

  for (ModuleSP module : modules.Modules()) {
    if (is_kernel(module.get()))
      continue;
    if (is_kmod(module.get()))
      remove_modules.AppendIfNeeded(module);
  }

  m_process->GetTarget().ModulesDidUnload(remove_modules, false);

  for (KModImageInfo &image_info : linker_files_list) {
    auto it = m_kld_name_to_uuid.find(image_info.GetName());
    if (it != m_kld_name_to_uuid.end())
      image_info.SetUUID(it->second);
    bool failed_to_load = false;
    if (!image_info.LoadImageUsingMemoryModule(m_process)) {
      image_info.LoadImageUsingFileAddress(m_process);
      failed_to_load = true;
    } else {
      m_linker_files_list.push_back(image_info);
      m_kld_name_to_uuid[image_info.GetName()] = image_info.GetUUID();
    }

    if (!failed_to_load)
      add_modules.AppendIfNeeded(image_info.GetModule());
  }
  m_process->GetTarget().ModulesDidLoad(add_modules);
  return true;
}

// Read all kmod from a given arrays of list
bool DynamicLoaderFreeBSDKernel::ReadAllKmods(
    Address linker_files_head_addr,
    KModImageInfo::collection_type &kmods_list) {

  // Get offset of next member and load address symbol
  static ConstString kld_off_address_symbol_name("kld_off_address");
  static ConstString kld_off_next_symbol_name("kld_off_next");
  static ConstString kld_off_filename_symbol_name("kld_off_filename");
  static ConstString kld_off_pathname_symbol_name("kld_off_pathname");
  const Symbol *kld_off_address_symbol =
      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
          kld_off_address_symbol_name, eSymbolTypeData);
  const Symbol *kld_off_next_symbol =
      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
          kld_off_next_symbol_name, eSymbolTypeData);
  const Symbol *kld_off_filename_symbol =
      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
          kld_off_filename_symbol_name, eSymbolTypeData);
  const Symbol *kld_off_pathname_symbol =
      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
          kld_off_pathname_symbol_name, eSymbolTypeData);

  if (!kld_off_address_symbol || !kld_off_next_symbol ||
      !kld_off_filename_symbol || !kld_off_pathname_symbol)
    return false;

  Status error;
  const int32_t kld_off_address = m_process->ReadSignedIntegerFromMemory(
      kld_off_address_symbol->GetAddress().GetLoadAddress(
          &m_process->GetTarget()),
      4, 0, error);
  if (error.Fail())
    return false;
  const int32_t kld_off_next = m_process->ReadSignedIntegerFromMemory(
      kld_off_next_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()),
      4, 0, error);
  if (error.Fail())
    return false;
  const int32_t kld_off_filename = m_process->ReadSignedIntegerFromMemory(
      kld_off_filename_symbol->GetAddress().GetLoadAddress(
          &m_process->GetTarget()),
      4, 0, error);
  if (error.Fail())
    return false;

  const int32_t kld_off_pathname = m_process->ReadSignedIntegerFromMemory(
      kld_off_pathname_symbol->GetAddress().GetLoadAddress(
          &m_process->GetTarget()),
      4, 0, error);
  if (error.Fail())
    return false;

  // Parse KMods
  addr_t kld_load_addr(LLDB_INVALID_ADDRESS);
  char kld_filename[255];
  char kld_pathname[255];
  addr_t current_kld =
      linker_files_head_addr.GetLoadAddress(&m_process->GetTarget());

  while (current_kld != 0) {
    addr_t kld_filename_addr =
        m_process->ReadPointerFromMemory(current_kld + kld_off_filename, error);
    if (error.Fail())
      return false;
    addr_t kld_pathname_addr =
        m_process->ReadPointerFromMemory(current_kld + kld_off_pathname, error);
    if (error.Fail())
      return false;

    m_process->ReadCStringFromMemory(kld_filename_addr, kld_filename,
                                     sizeof(kld_filename), error);
    if (error.Fail())
      return false;
    m_process->ReadCStringFromMemory(kld_pathname_addr, kld_pathname,
                                     sizeof(kld_pathname), error);
    if (error.Fail())
      return false;
    kld_load_addr =
        m_process->ReadPointerFromMemory(current_kld + kld_off_address, error);
    if (error.Fail())
      return false;

    kmods_list.emplace_back();
    KModImageInfo &kmod_info = kmods_list.back();
    kmod_info.SetName(kld_filename);
    kmod_info.SetLoadAddress(kld_load_addr);
    kmod_info.SetPath(kld_pathname);

    current_kld =
        m_process->ReadPointerFromMemory(current_kld + kld_off_next, error);
    if (kmod_info.GetName() == "kernel")
      kmods_list.pop_back();
    if (error.Fail())
      return false;
  }

  return true;
}

// Read all kmods
void DynamicLoaderFreeBSDKernel::ReadAllKmods() {
  std::lock_guard<decltype(m_mutex)> guard(m_mutex);

  if (ReadKmodsListHeader()) {
    if (m_linker_file_head_addr.IsValid()) {
      if (!ParseKmods(m_linker_file_head_addr))
        m_linker_files_list.clear();
    }
  }
}

// Load all Kernel Modules
void DynamicLoaderFreeBSDKernel::LoadKernelModules() {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
                 "Start loading Kernel Module");

  // Initialize Kernel Image Information at the first time
  if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
    ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
    if (is_kernel(module_sp.get())) {
      m_kernel_image_info.SetModule(module_sp);
      m_kernel_image_info.SetIsKernel(true);
    }

    // Set name for kernel
    llvm::StringRef kernel_name("freebsd_kernel");
    module_sp = m_kernel_image_info.GetModule();
    if (module_sp.get() && module_sp->GetObjectFile() &&
        !module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
      kernel_name = module_sp->GetObjectFile()
                        ->GetFileSpec()
                        .GetFilename()
                        .GetStringRef();
    m_kernel_image_info.SetName(kernel_name.data());

    if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
      m_kernel_image_info.SetLoadAddress(m_kernel_load_address);
    }

    // Build In memory Module
    if (m_kernel_image_info.GetLoadAddress() != LLDB_INVALID_ADDRESS) {
      // If the kernel is not loaded in the memory, use file to load
      if (!m_kernel_image_info.LoadImageUsingMemoryModule(m_process))
        m_kernel_image_info.LoadImageUsingFileAddress(m_process);
    }
  }

  LoadOperatingSystemPlugin(false);

  if (!m_kernel_image_info.IsLoaded() || !m_kernel_image_info.GetModule()) {
    m_kernel_image_info.Clear();
    return;
  }

  static ConstString modlist_symbol_name("linker_files");

  const Symbol *symbol =
      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
          modlist_symbol_name, lldb::eSymbolTypeData);

  if (symbol) {
    m_linker_file_list_struct_addr = symbol->GetAddress();
    ReadAllKmods();
  } else {
    LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
                   "cannot file modlist symbol");
  }
}

// Update symbol when use kldload by setting callback function on kldload
void DynamicLoaderFreeBSDKernel::SetNotificationBreakPoint() {}

// Hook called when attach to a process
void DynamicLoaderFreeBSDKernel::DidAttach() {
  PrivateInitialize(m_process);
  Update();
}

// Hook called after attach to a process
void DynamicLoaderFreeBSDKernel::DidLaunch() {
  PrivateInitialize(m_process);
  Update();
}

// Clear all member except kernel address
void DynamicLoaderFreeBSDKernel::Clear(bool clear_process) {
  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
  if (clear_process)
    m_process = nullptr;
  m_linker_file_head_addr.Clear();
  m_linker_file_list_struct_addr.Clear();
  m_kernel_image_info.Clear();
  m_linker_files_list.clear();
}

// Reinitialize class
void DynamicLoaderFreeBSDKernel::PrivateInitialize(Process *process) {
  Clear(true);
  m_process = process;
}

ThreadPlanSP DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan(
    lldb_private::Thread &thread, bool stop_others) {
  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan is "
                 "not yet implemented.");
  return {};
}

Status DynamicLoaderFreeBSDKernel::CanLoadImage() {
  return Status::FromErrorString("shared object cannot be loaded into kernel");
}
