//===-- 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)) {
    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();

  ModuleSP memory_module_sp =
      process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);

  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_linker_file_list_struct_addr(LLDB_INVALID_ADDRESS),
      m_linker_file_head_addr(LLDB_INVALID_ADDRESS),
      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))
        size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) +
                       elf_eheader.e_phnum * elf_eheader.e_phentsize;
    }
  }

  memory_module_sp =
      process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);

  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()) {
    Stream &s = target.GetDebugger().GetOutputStream();
    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)) {
          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) {
        Stream &s = target.GetDebugger().GetOutputStream();
        s.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()) {
    Stream &s = target.GetDebugger().GetOutputStream();
    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());
      }
    }
    s.Flush();
  }

  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");
}
