//===-- DynamicLoaderPOSIXDYLD.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
//
//===----------------------------------------------------------------------===//

// Main header include
#include "DynamicLoaderPOSIXDYLD.h"

#include "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h"
#include "lldb/Breakpoint/BreakpointLocation.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/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/ProcessInfo.h"
#include "llvm/Support/ThreadPool.h"

#include <memory>
#include <optional>

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD, DynamicLoaderPosixDYLD)

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

void DynamicLoaderPOSIXDYLD::Terminate() {}

llvm::StringRef DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() {
  return "Dynamic loader plug-in that watches for shared library "
         "loads/unloads in POSIX processes.";
}

DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process,
                                                      bool force) {
  bool create = force;
  if (!create) {
    const llvm::Triple &triple_ref =
        process->GetTarget().GetArchitecture().GetTriple();
    if (triple_ref.getOS() == llvm::Triple::FreeBSD ||
        triple_ref.getOS() == llvm::Triple::Linux ||
        triple_ref.getOS() == llvm::Triple::NetBSD ||
        triple_ref.getOS() == llvm::Triple::OpenBSD)
      create = true;
  }

  if (create)
    return new DynamicLoaderPOSIXDYLD(process);
  return nullptr;
}

DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
    : DynamicLoader(process), m_rendezvous(process),
      m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),
      m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID),
      m_vdso_base(LLDB_INVALID_ADDRESS),
      m_interpreter_base(LLDB_INVALID_ADDRESS), m_initial_modules_added(false) {
}

DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() {
  if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
    m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid);
    m_dyld_bid = LLDB_INVALID_BREAK_ID;
  }
}

void DynamicLoaderPOSIXDYLD::DidAttach() {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__,
            m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
  m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());

  LLDB_LOGF(
      log, "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data",
      __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);

  ModuleSP executable_sp = GetTargetExecutable();
  ResolveExecutableModule(executable_sp);
  m_rendezvous.UpdateExecutablePath();

  // find the main process load offset
  addr_t load_offset = ComputeLoadOffset();
  LLDB_LOGF(log,
            "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
            " executable '%s', load_offset 0x%" PRIx64,
            __FUNCTION__,
            m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
            executable_sp ? executable_sp->GetFileSpec().GetPath().c_str()
                          : "<null executable>",
            load_offset);

  EvalSpecialModulesStatus();

  // if we dont have a load address we cant re-base
  bool rebase_exec = load_offset != LLDB_INVALID_ADDRESS;

  // if the target executable should be re-based
  if (rebase_exec) {
    ModuleList module_list;

    module_list.Append(executable_sp);
    LLDB_LOGF(log,
              "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
              " added executable '%s' to module load list",
              __FUNCTION__,
              m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
              executable_sp->GetFileSpec().GetPath().c_str());

    UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset,
                         true);

    LoadAllCurrentModules();

    m_process->GetTarget().ModulesDidLoad(module_list);
    if (log) {
      LLDB_LOGF(log,
                "DynamicLoaderPOSIXDYLD::%s told the target about the "
                "modules that loaded:",
                __FUNCTION__);
      for (auto module_sp : module_list.Modules()) {
        LLDB_LOGF(log, "-- [module] %s (pid %" PRIu64 ")",
                  module_sp ? module_sp->GetFileSpec().GetPath().c_str()
                            : "<null>",
                  m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
      }
    }
  }

  if (executable_sp.get()) {
    if (!SetRendezvousBreakpoint()) {
      // If we cannot establish rendezvous breakpoint right now we'll try again
      // at entry point.
      ProbeEntry();
    }
  }
}

void DynamicLoaderPOSIXDYLD::DidLaunch() {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__);

  ModuleSP executable;
  addr_t load_offset;

  m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());

  executable = GetTargetExecutable();
  load_offset = ComputeLoadOffset();
  EvalSpecialModulesStatus();

  if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) {
    ModuleList module_list;
    module_list.Append(executable);
    UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);

    LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()",
              __FUNCTION__);

    if (!SetRendezvousBreakpoint()) {
      // If we cannot establish rendezvous breakpoint right now we'll try again
      // at entry point.
      ProbeEntry();
    }

    LoadVDSO();
    m_process->GetTarget().ModulesDidLoad(module_list);
  }
}

Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); }

void DynamicLoaderPOSIXDYLD::SetLoadedModule(const ModuleSP &module_sp,
                                             addr_t link_map_addr) {
  llvm::sys::ScopedWriter lock(m_loaded_modules_rw_mutex);
  m_loaded_modules[module_sp] = link_map_addr;
}

void DynamicLoaderPOSIXDYLD::UnloadModule(const ModuleSP &module_sp) {
  llvm::sys::ScopedWriter lock(m_loaded_modules_rw_mutex);
  m_loaded_modules.erase(module_sp);
}

std::optional<lldb::addr_t>
DynamicLoaderPOSIXDYLD::GetLoadedModuleLinkAddr(const ModuleSP &module_sp) {
  llvm::sys::ScopedReader lock(m_loaded_modules_rw_mutex);
  auto it = m_loaded_modules.find(module_sp);
  if (it != m_loaded_modules.end())
    return it->second;
  return std::nullopt;
}

void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,
                                                  addr_t link_map_addr,
                                                  addr_t base_addr,
                                                  bool base_addr_is_offset) {
  SetLoadedModule(module, link_map_addr);

  UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}

void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) {
  UnloadModule(module);

  UnloadSectionsCommon(module);
}

void DynamicLoaderPOSIXDYLD::ProbeEntry() {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  // If we have a core file, we don't need any breakpoints.
  if (IsCoreFile())
    return;

  const addr_t entry = GetEntryPoint();
  if (entry == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(
        log,
        "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
        " GetEntryPoint() returned no address, not setting entry breakpoint",
        __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
    return;
  }

  LLDB_LOGF(log,
            "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
            " GetEntryPoint() returned address 0x%" PRIx64
            ", setting entry breakpoint",
            __FUNCTION__,
            m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry);

  if (m_process) {
    Breakpoint *const entry_break =
        m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
    entry_break->SetCallback(EntryBreakpointHit, this, true);
    entry_break->SetBreakpointKind("shared-library-event");

    // Shoudn't hit this more than once.
    entry_break->SetOneShot(true);
  }
}

// The runtime linker has run and initialized the rendezvous structure once the
// process has hit its entry point.  When we hit the corresponding breakpoint
// we interrogate the rendezvous structure to get the load addresses of all
// dependent modules for the process.  Similarly, we can discover the runtime
// linker function and setup a breakpoint to notify us of any dynamically
// loaded modules (via dlopen).
bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  assert(baton && "null baton");
  if (!baton)
    return false;

  Log *log = GetLog(LLDBLog::DynamicLoader);
  DynamicLoaderPOSIXDYLD *const dyld_instance =
      static_cast<DynamicLoaderPOSIXDYLD *>(baton);
  LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,
            __FUNCTION__,
            dyld_instance->m_process ? dyld_instance->m_process->GetID()
                                     : LLDB_INVALID_PROCESS_ID);

  // Disable the breakpoint --- if a stop happens right after this, which we've
  // seen on occasion, we don't want the breakpoint stepping thread-plan logic
  // to show a breakpoint instruction at the disassembled entry point to the
  // program.  Disabling it prevents it.  (One-shot is not enough - one-shot
  // removal logic only happens after the breakpoint goes public, which wasn't
  // happening in our scenario).
  if (dyld_instance->m_process) {
    BreakpointSP breakpoint_sp =
        dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id);
    if (breakpoint_sp) {
      LLDB_LOGF(log,
                "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
                " disabling breakpoint id %" PRIu64,
                __FUNCTION__, dyld_instance->m_process->GetID(), break_id);
      breakpoint_sp->SetEnabled(false);
    } else {
      LLDB_LOGF(log,
                "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
                " failed to find breakpoint for breakpoint id %" PRIu64,
                __FUNCTION__, dyld_instance->m_process->GetID(), break_id);
    }
  } else {
    LLDB_LOGF(log,
              "DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64
              " no Process instance!  Cannot disable breakpoint",
              __FUNCTION__, break_id);
  }

  dyld_instance->LoadAllCurrentModules();
  dyld_instance->SetRendezvousBreakpoint();
  return false; // Continue running.
}

bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  // If we have a core file, we don't need any breakpoints.
  if (IsCoreFile())
    return false;

  if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
    LLDB_LOG(log,
             "Rendezvous breakpoint breakpoint id {0} for pid {1}"
             "is already set.",
             m_dyld_bid,
             m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
    return true;
  }

  addr_t break_addr;
  Target &target = m_process->GetTarget();
  BreakpointSP dyld_break;
  if (m_rendezvous.IsValid() && m_rendezvous.GetBreakAddress() != 0) {
    break_addr = m_rendezvous.GetBreakAddress();
    LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}",
             m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
             break_addr);
    dyld_break = target.CreateBreakpoint(break_addr, true, false);
  } else {
    LLDB_LOG(log, "Rendezvous structure is not set up yet. "
                  "Trying to locate rendezvous breakpoint in the interpreter "
                  "by symbol name.");
    // Function names from different dynamic loaders that are known to be
    // used as rendezvous between the loader and debuggers.
    static std::vector<std::string> DebugStateCandidates{
        "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
        "r_debug_state",   "_r_debug_state",     "_rtld_debug_state",
    };

    ModuleSP interpreter = LoadInterpreterModule();
    FileSpecList containingModules;
    if (interpreter)
      containingModules.Append(interpreter->GetFileSpec());
    else
      containingModules.Append(
          m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec());

    dyld_break = target.CreateBreakpoint(
        &containingModules, /*containingSourceFiles=*/nullptr,
        DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
        /*m_offset=*/0,
        /*skip_prologue=*/eLazyBoolNo,
        /*internal=*/true,
        /*request_hardware=*/false);
  }

  if (dyld_break->GetNumResolvedLocations() != 1) {
    LLDB_LOG(
        log,
        "Rendezvous breakpoint has abnormal number of"
        " resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.",
        dyld_break->GetNumResolvedLocations(),
        m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);

    target.RemoveBreakpointByID(dyld_break->GetID());
    return false;
  }

  BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0);
  LLDB_LOG(log,
           "Successfully set rendezvous breakpoint at address {0:x} "
           "for pid {1}",
           location->GetLoadAddress(),
           m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);

  dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
  dyld_break->SetBreakpointKind("shared-library-event");
  m_dyld_bid = dyld_break->GetID();
  return true;
}

bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  assert(baton && "null baton");
  if (!baton)
    return false;

  Log *log = GetLog(LLDBLog::DynamicLoader);
  DynamicLoaderPOSIXDYLD *const dyld_instance =
      static_cast<DynamicLoaderPOSIXDYLD *>(baton);
  LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,
            __FUNCTION__,
            dyld_instance->m_process ? dyld_instance->m_process->GetID()
                                     : LLDB_INVALID_PROCESS_ID);

  dyld_instance->RefreshModules();

  // Return true to stop the target, false to just let the target run.
  const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange();
  LLDB_LOGF(log,
            "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
            " stop_when_images_change=%s",
            __FUNCTION__,
            dyld_instance->m_process ? dyld_instance->m_process->GetID()
                                     : LLDB_INVALID_PROCESS_ID,
            stop_when_images_change ? "true" : "false");
  return stop_when_images_change;
}

void DynamicLoaderPOSIXDYLD::RefreshModules() {
  if (!m_rendezvous.Resolve())
    return;

  // The rendezvous class doesn't enumerate the main module, so track that
  // ourselves here.
  ModuleSP executable = GetTargetExecutable();
  SetLoadedModule(executable, m_rendezvous.GetLinkMapAddress());

  DYLDRendezvous::iterator I;
  DYLDRendezvous::iterator E;

  ModuleList &loaded_modules = m_process->GetTarget().GetImages();

  if (m_rendezvous.ModulesDidLoad() || !m_initial_modules_added) {
    ModuleList new_modules;

    // If this is the first time rendezvous breakpoint fires, we need
    // to take care of adding all the initial modules reported by
    // the loader.  This is necessary to list ld-linux.so on Linux,
    // and all DT_NEEDED entries on *BSD.
    if (m_initial_modules_added) {
      I = m_rendezvous.loaded_begin();
      E = m_rendezvous.loaded_end();
    } else {
      I = m_rendezvous.begin();
      E = m_rendezvous.end();
      m_initial_modules_added = true;
    }

    // Synchronize reading and writing of `m_interpreter_module`.
    std::mutex interpreter_module_mutex;
    // We should be able to take SOEntry as reference since the data
    // exists for the duration of this call in `m_rendezvous`.
    auto load_module_fn =
        [this, &loaded_modules, &new_modules,
         &interpreter_module_mutex](const DYLDRendezvous::SOEntry &so_entry) {
          // Don't load a duplicate copy of ld.so if we have already loaded it
          // earlier in LoadInterpreterModule. If we instead loaded then
          // unloaded it later, the section information for ld.so would be
          // removed. That information is required for placing breakpoints on
          // Arm/Thumb systems.
          {
            // `m_interpreter_module` may be modified by another thread at the
            // same time, so we guard the access here.
            std::lock_guard<std::mutex> lock(interpreter_module_mutex);
            if ((m_interpreter_module.lock() != nullptr) &&
                (so_entry.base_addr == m_interpreter_base))
              return;
          }

          ModuleSP module_sp = LoadModuleAtAddress(
              so_entry.file_spec, so_entry.link_addr, so_entry.base_addr,
              /*base_addr_is_offset=*/true);
          if (!module_sp.get())
            return;

          {
            // `m_interpreter_module` may be modified by another thread at the
            // same time, so we guard the access here.
            std::lock_guard<std::mutex> lock(interpreter_module_mutex);
            // Set the interpreter module, if this is the interpreter.
            if (module_sp->GetObjectFile()->GetBaseAddress().GetLoadAddress(
                    &m_process->GetTarget()) == m_interpreter_base) {
              ModuleSP interpreter_sp = m_interpreter_module.lock();
              if (m_interpreter_module.lock() == nullptr) {
                m_interpreter_module = module_sp;
              } else if (module_sp == interpreter_sp) {
                // Module already loaded.
                return;
              }
            }
          }

          // Note: in a multi-threaded environment, these module lists may be
          // appended to out-of-order. This is fine, since there's no
          // expectation for `loaded_modules` or `new_modules` to be in any
          // particular order, and appending to each module list is thread-safe.
          // Also, `new_modules` is only used for the `ModulesDidLoad` call at
          // the end of this function.
          loaded_modules.AppendIfNeeded(module_sp);
          new_modules.Append(module_sp);
        };

    if (m_process->GetTarget().GetParallelModuleLoad()) {
      llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
      for (; I != E; ++I)
        task_group.async(load_module_fn, *I);
      task_group.wait();
    } else {
      for (; I != E; ++I)
        load_module_fn(*I);
    }

    m_process->GetTarget().ModulesDidLoad(new_modules);
  }

  if (m_rendezvous.ModulesDidUnload()) {
    ModuleList old_modules;

    E = m_rendezvous.unloaded_end();
    for (I = m_rendezvous.unloaded_begin(); I != E; ++I) {
      ModuleSpec module_spec{I->file_spec};
      ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec);

      if (module_sp.get()) {
        old_modules.Append(module_sp);
        UnloadSections(module_sp);
      }
    }
    loaded_modules.Remove(old_modules);
    m_process->GetTarget().ModulesDidUnload(old_modules, false);
  }
}

ThreadPlanSP
DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
                                                     bool stop) {
  ThreadPlanSP thread_plan_sp;

  StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
  const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
  const Symbol *sym = context.symbol;

  if (sym == nullptr || !sym->IsTrampoline())
    return thread_plan_sp;

  ConstString sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
  if (!sym_name)
    return thread_plan_sp;

  SymbolContextList target_symbols;
  Target &target = thread.GetProcess()->GetTarget();
  const ModuleList &images = target.GetImages();

  llvm::StringRef target_name = sym_name.GetStringRef();
  // On AArch64, the trampoline name has a prefix (__AArch64ADRPThunk_ or
  // __AArch64AbsLongThunk_) added to the function name. If we detect a
  // trampoline with the prefix, we need to remove the prefix to find the
  // function symbol.
  if (target_name.consume_front("__AArch64ADRPThunk_") ||
      target_name.consume_front("__AArch64AbsLongThunk_")) {
    // An empty target name can happen for trampolines generated for
    // section-referencing relocations.
    if (!target_name.empty()) {
      sym_name = ConstString(target_name);
    }
  }
  images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
  if (!target_symbols.GetSize())
    return thread_plan_sp;

  typedef std::vector<lldb::addr_t> AddressVector;
  AddressVector addrs;
  for (const SymbolContext &context : target_symbols) {
    addr_t addr = context.GetFunctionOrSymbolAddress().GetLoadAddress(&target);
    if (addr != LLDB_INVALID_ADDRESS)
      addrs.push_back(addr);
  }

  if (addrs.size() > 0) {
    AddressVector::iterator start = addrs.begin();
    AddressVector::iterator end = addrs.end();

    llvm::sort(start, end);
    addrs.erase(std::unique(start, end), end);
    thread_plan_sp =
        std::make_shared<ThreadPlanRunToAddress>(thread, addrs, stop);
  }

  return thread_plan_sp;
}

void DynamicLoaderPOSIXDYLD::LoadVDSO() {
  if (m_vdso_base == LLDB_INVALID_ADDRESS)
    return;

  FileSpec file("[vdso]");

  Log *log = GetLog(LLDBLog::DynamicLoader);
  MemoryRegionInfo info;
  Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info);
  if (status.Fail()) {
    LLDB_LOG(log, "Failed to get vdso region info: {0}", status);
    return;
  }

  llvm::Expected<ModuleSP> module_sp_or_err = m_process->ReadModuleFromMemory(
      file, m_vdso_base, info.GetRange().GetByteSize());
  if (auto err = module_sp_or_err.takeError()) {
    LLDB_LOG_ERROR(log, std::move(err),
                   "Failed to read module from memory: {0}");
  } else if (ModuleSP module_sp = *module_sp_or_err) {
    UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_vdso_base, false);
    m_process->GetTarget().GetImages().AppendIfNeeded(module_sp);
  }
}

ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
  if (m_interpreter_base == LLDB_INVALID_ADDRESS)
    return nullptr;

  MemoryRegionInfo info;
  Target &target = m_process->GetTarget();
  Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info);
  if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes ||
      info.GetName().IsEmpty()) {
    Log *log = GetLog(LLDBLog::DynamicLoader);
    LLDB_LOG(log, "Failed to get interpreter region info: {0}", status);
    return nullptr;
  }

  FileSpec file(info.GetName().GetCString());
  ModuleSpec module_spec(file, target.GetArchitecture());

  // Don't notify that module is added here because its loading section
  // addresses are not updated yet. We manually notify it below.
  if (ModuleSP module_sp =
          target.GetOrCreateModule(module_spec, /*notify=*/false)) {
    UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
                         false);
    // Manually notify that dynamic linker is loaded after updating load section
    // addersses so that breakpoints can be resolved.
    ModuleList module_list;
    module_list.Append(module_sp);
    target.ModulesDidLoad(module_list);
    m_interpreter_module = module_sp;
    return module_sp;
  }
  return nullptr;
}

ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,
                                                     addr_t link_map_addr,
                                                     addr_t base_addr,
                                                     bool base_addr_is_offset) {
  if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
          file, link_map_addr, base_addr, base_addr_is_offset))
    return module_sp;

  // This works around an dynamic linker "bug" on android <= 23, where the
  // dynamic linker would report the application name
  // (e.g. com.example.myapplication) instead of the main process binary
  // (/system/bin/app_process(32)). The logic is not sound in general (it
  // assumes base_addr is the real address, even though it actually is a load
  // bias), but it happens to work on android because app_process has a file
  // address of zero.
  // This should be removed after we drop support for android-23.
  if (m_process->GetTarget().GetArchitecture().GetTriple().isAndroid()) {
    MemoryRegionInfo memory_info;
    Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
    if (error.Success() && memory_info.GetMapped() &&
        memory_info.GetRange().GetRangeBase() == base_addr &&
        !(memory_info.GetName().IsEmpty())) {
      if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
              FileSpec(memory_info.GetName().GetStringRef()), link_map_addr,
              base_addr, base_addr_is_offset))
        return module_sp;
    }
  }

  return nullptr;
}

void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
  DYLDRendezvous::iterator I;
  DYLDRendezvous::iterator E;
  ModuleList module_list;
  Log *log = GetLog(LLDBLog::DynamicLoader);

  LoadVDSO();

  if (!m_rendezvous.Resolve()) {
    LLDB_LOGF(log,
              "DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD "
              "rendezvous address",
              __FUNCTION__);
    return;
  }

  // The rendezvous class doesn't enumerate the main module, so track that
  // ourselves here.
  ModuleSP executable = GetTargetExecutable();
  SetLoadedModule(executable, m_rendezvous.GetLinkMapAddress());

  Target &target = m_process->GetTarget();
  std::vector<FileSpec> module_names;
  for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
    module_names.push_back(I->file_spec);
  m_process->PrefetchModuleSpecs(module_names,
                                 target.GetArchitecture().GetTriple());

  auto load_module_fn = [this, &module_list, &target,
                         &log](const DYLDRendezvous::SOEntry &so_entry) {
    ModuleSP module_sp = LoadModuleAtAddress(
        so_entry.file_spec, so_entry.link_addr, so_entry.base_addr, true);
    if (!module_sp && !m_process->IsLiveDebugSession()) {
      // Create placeholder modules for any modules we couldn't load from disk
      // or from memory.
      ModuleSpec module_spec(so_entry.file_spec, target.GetArchitecture());
      if (UUID uuid = m_process->FindModuleUUID(so_entry.file_spec.GetPath()))
        module_spec.GetUUID() = uuid;
      module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>(
          module_spec, so_entry.base_addr, 512);
      bool load_addr_changed = false;
      target.GetImages().Append(module_sp, false);
      module_sp->SetLoadAddress(target, so_entry.base_addr, false,
                                load_addr_changed);
    }
    if (module_sp.get()) {
      LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",
               so_entry.file_spec.GetFilename());
      module_list.Append(module_sp);
    } else {
      LLDB_LOGF(
          log,
          "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,
          __FUNCTION__, so_entry.file_spec.GetPath().c_str(),
          so_entry.base_addr);
    }
  };
  if (m_process->GetTarget().GetParallelModuleLoad()) {
    llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
    for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
      task_group.async(load_module_fn, *I);
    task_group.wait();
  } else {
    for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
      load_module_fn(*I);
  }

  m_process->GetTarget().ModulesDidLoad(module_list);
  m_initial_modules_added = true;
}

addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {
  addr_t virt_entry;

  if (m_load_offset != LLDB_INVALID_ADDRESS)
    return m_load_offset;

  if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
    return LLDB_INVALID_ADDRESS;

  ModuleSP module = m_process->GetTarget().GetExecutableModule();
  if (!module)
    return LLDB_INVALID_ADDRESS;

  ObjectFile *exe = module->GetObjectFile();
  if (!exe)
    return LLDB_INVALID_ADDRESS;

  Address file_entry = exe->GetEntryPointAddress();

  if (!file_entry.IsValid())
    return LLDB_INVALID_ADDRESS;

  m_load_offset = virt_entry - file_entry.GetFileAddress();
  return m_load_offset;
}

void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() {
  if (std::optional<uint64_t> vdso_base =
          m_auxv->GetAuxValue(AuxVector::AUXV_AT_SYSINFO_EHDR))
    m_vdso_base = *vdso_base;

  if (std::optional<uint64_t> interpreter_base =
          m_auxv->GetAuxValue(AuxVector::AUXV_AT_BASE))
    m_interpreter_base = *interpreter_base;
}

addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() {
  if (m_entry_point != LLDB_INVALID_ADDRESS)
    return m_entry_point;

  if (m_auxv == nullptr)
    return LLDB_INVALID_ADDRESS;

  std::optional<uint64_t> entry_point =
      m_auxv->GetAuxValue(AuxVector::AUXV_AT_ENTRY);
  if (!entry_point)
    return LLDB_INVALID_ADDRESS;

  m_entry_point = static_cast<addr_t>(*entry_point);

  const ArchSpec &arch = m_process->GetTarget().GetArchitecture();

  // On ppc64, the entry point is actually a descriptor.  Dereference it.
  if (arch.GetMachine() == llvm::Triple::ppc64)
    m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8);

  return m_entry_point;
}

lldb::addr_t
DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp,
                                           const lldb::ThreadSP thread,
                                           lldb::addr_t tls_file_addr) {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  std::optional<addr_t> link_map_addr_opt = GetLoadedModuleLinkAddr(module_sp);
  if (!link_map_addr_opt.has_value()) {
    LLDB_LOGF(
        log, "GetThreadLocalData error: module(%s) not found in loaded modules",
        module_sp->GetObjectName().AsCString());
    return LLDB_INVALID_ADDRESS;
  }

  addr_t link_map = link_map_addr_opt.value();
  if (link_map == LLDB_INVALID_ADDRESS || link_map == 0) {
    LLDB_LOGF(log,
              "GetThreadLocalData error: invalid link map address=0x%" PRIx64,
              link_map);
    return LLDB_INVALID_ADDRESS;
  }

  const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();
  if (!metadata.valid) {
    LLDB_LOGF(log,
              "GetThreadLocalData error: fail to read thread info metadata");
    return LLDB_INVALID_ADDRESS;
  }

  LLDB_LOGF(log,
            "GetThreadLocalData info: link_map=0x%" PRIx64
            ", thread info metadata: "
            "modid_offset=0x%" PRIx32 ", dtv_offset=0x%" PRIx32
            ", tls_offset=0x%" PRIx32 ", dtv_slot_size=%" PRIx32 "\n",
            link_map, metadata.modid_offset, metadata.dtv_offset,
            metadata.tls_offset, metadata.dtv_slot_size);

  // Get the thread pointer.
  addr_t tp = thread->GetThreadPointer();
  if (tp == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(log, "GetThreadLocalData error: fail to read thread pointer");
    return LLDB_INVALID_ADDRESS;
  }

  // Find the module's modid.
  int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit
  int64_t modid = ReadUnsignedIntWithSizeInBytes(
      link_map + metadata.modid_offset, modid_size);
  if (modid == -1) {
    LLDB_LOGF(log, "GetThreadLocalData error: fail to read modid");
    return LLDB_INVALID_ADDRESS;
  }

  // Lookup the DTV structure for this thread.
  addr_t dtv_ptr = tp + metadata.dtv_offset;
  addr_t dtv = ReadPointer(dtv_ptr);
  if (dtv == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(log, "GetThreadLocalData error: fail to read dtv");
    return LLDB_INVALID_ADDRESS;
  }

  // Find the TLS block for this module.
  addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid;
  addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset);

  LLDB_LOGF(log,
            "DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
            "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64
            ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n",
            module_sp->GetObjectName().AsCString(""), link_map, tp,
            (int64_t)modid, tls_block);

  if (tls_block == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(log, "GetThreadLocalData error: fail to read tls_block");
    return LLDB_INVALID_ADDRESS;
  } else
    return tls_block + tls_file_addr;
}

void DynamicLoaderPOSIXDYLD::ResolveExecutableModule(
    lldb::ModuleSP &module_sp) {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  if (m_process == nullptr)
    return;

  auto &target = m_process->GetTarget();
  const auto platform_sp = target.GetPlatform();

  ProcessInstanceInfo process_info;
  if (!m_process->GetProcessInfo(process_info)) {
    LLDB_LOGF(log,
              "DynamicLoaderPOSIXDYLD::%s - failed to get process info for "
              "pid %" PRIu64,
              __FUNCTION__, m_process->GetID());
    return;
  }

  LLDB_LOGF(
      log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s",
      __FUNCTION__, m_process->GetID(),
      process_info.GetExecutableFile().GetPath().c_str());

  ModuleSpec module_spec(process_info.GetExecutableFile(),
                         process_info.GetArchitecture());
  if (module_sp && module_sp->MatchesModuleSpec(module_spec))
    return;

  module_spec.SetTarget(target.shared_from_this());
  const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths());
  auto error = platform_sp->ResolveExecutable(module_spec, module_sp);
  if (error.Fail()) {
    StreamString stream;
    module_spec.Dump(stream);

    LLDB_LOGF(log,
              "DynamicLoaderPOSIXDYLD::%s - failed to resolve executable "
              "with module spec \"%s\": %s",
              __FUNCTION__, stream.GetData(), error.AsCString());
    return;
  }

  target.SetExecutableModule(module_sp, eLoadDependentsNo);
}

bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(
    lldb_private::SymbolContext &sym_ctx) {
  ModuleSP module_sp;
  if (sym_ctx.symbol)
    module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
  if (!module_sp && sym_ctx.function)
    module_sp = sym_ctx.function->GetAddress().GetModule();
  if (!module_sp)
    return false;

  return module_sp->GetFileSpec().GetPath() == "[vdso]";
}

bool DynamicLoaderPOSIXDYLD::IsCoreFile() const {
  return !m_process->IsLiveDebugSession();
}

// For our ELF/POSIX builds save off the fs_base/gs_base regions
static void AddThreadLocalMemoryRegions(Process &process, ThreadSP &thread_sp,
                                        std::vector<MemoryRegionInfo> &ranges) {
  lldb::RegisterContextSP reg_ctx = thread_sp->GetRegisterContext();
  if (!reg_ctx)
    return;

  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
      lldb::RegisterKind::eRegisterKindGeneric, LLDB_REGNUM_GENERIC_TP);
  if (!reg_info)
    return;

  lldb_private::RegisterValue thread_local_register_value;
  bool success = reg_ctx->ReadRegister(reg_info, thread_local_register_value);
  if (!success)
    return;

  const uint64_t fail_value = UINT64_MAX;
  bool readSuccess = false;
  const lldb::addr_t reg_value_addr =
      thread_local_register_value.GetAsUInt64(fail_value, &readSuccess);
  if (!readSuccess || reg_value_addr == fail_value)
    return;

  MemoryRegionInfo thread_local_region;
  Status err = process.GetMemoryRegionInfo(reg_value_addr, thread_local_region);
  if (err.Fail())
    return;

  ranges.push_back(thread_local_region);
}

// Save off the link map for core files.
static void AddLinkMapSections(Process &process,
                               std::vector<MemoryRegionInfo> &ranges) {
  ModuleList &module_list = process.GetTarget().GetImages();
  Target *target = &process.GetTarget();
  for (size_t idx = 0; idx < module_list.GetSize(); idx++) {
    ModuleSP module_sp = module_list.GetModuleAtIndex(idx);
    if (!module_sp)
      continue;

    ObjectFile *obj = module_sp->GetObjectFile();
    if (!obj)
      continue;
    Address addr = obj->GetImageInfoAddress(target);
    addr_t load_addr = addr.GetLoadAddress(target);
    if (load_addr == LLDB_INVALID_ADDRESS)
      continue;

    MemoryRegionInfo link_map_section;
    Status err = process.GetMemoryRegionInfo(load_addr, link_map_section);
    if (err.Fail())
      continue;

    ranges.push_back(link_map_section);
  }
}

void DynamicLoaderPOSIXDYLD::CalculateDynamicSaveCoreRanges(
    lldb_private::Process &process,
    std::vector<lldb_private::MemoryRegionInfo> &ranges,
    llvm::function_ref<bool(const lldb_private::Thread &)>
        save_thread_predicate) {
  ThreadList &thread_list = process.GetThreadList();
  for (size_t idx = 0; idx < thread_list.GetSize(); idx++) {
    ThreadSP thread_sp = thread_list.GetThreadAtIndex(idx);
    if (!thread_sp)
      continue;

    if (!save_thread_predicate(*thread_sp))
      continue;

    AddThreadLocalMemoryRegions(process, thread_sp, ranges);
  }

  AddLinkMapSections(process, ranges);
}
