//===- elfnix_platform.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
//
//===----------------------------------------------------------------------===//
//
// This file contains code required to load the rest of the ELF-on-*IX runtime.
//
//===----------------------------------------------------------------------===//

#include "elfnix_platform.h"
#include "common.h"
#include "compiler.h"
#include "error.h"
#include "jit_dispatch.h"
#include "record_section_tracker.h"
#include "wrapper_function_utils.h"

#include <algorithm>
#include <map>
#include <mutex>
#include <sstream>
#include <string_view>
#include <unordered_map>
#include <vector>

using namespace orc_rt;
using namespace orc_rt::elfnix;

// Declare function tags for functions in the JIT process.
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_reoptimize_tag)
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_push_initializers_tag)
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag)

// eh-frame registration functions, made available via aliases
// installed by the Platform
extern "C" void __register_frame(const void *);
extern "C" void __deregister_frame(const void *);

extern "C" void
__unw_add_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT;
extern "C" void
__unw_remove_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT;

namespace {

struct TLSInfoEntry {
  unsigned long Key = 0;
  unsigned long DataAddress = 0;
};

struct TLSDescriptor {
  void (*Resolver)(void *);
  TLSInfoEntry *InfoEntry;
};

class ELFNixPlatformRuntimeState {
private:
  struct AtExitEntry {
    void (*Func)(void *);
    void *Arg;
  };

  using AtExitsVector = std::vector<AtExitEntry>;

  struct PerJITDylibState {
    std::string Name;
    void *Header = nullptr;
    size_t RefCount = 0;
    size_t LinkedAgainstRefCount = 0;
    bool AllowReinitialization = false;
    AtExitsVector AtExits;
    std::vector<PerJITDylibState *> Deps;
    RecordSectionsTracker<void (*)()> RecordedInits;

    bool referenced() const {
      return LinkedAgainstRefCount != 0 || RefCount != 0;
    }
  };

public:
  static void initialize(void *DSOHandle);
  static ELFNixPlatformRuntimeState &get();
  static void destroy();

  ELFNixPlatformRuntimeState(void *DSOHandle);

  // Delete copy and move constructors.
  ELFNixPlatformRuntimeState(const ELFNixPlatformRuntimeState &) = delete;
  ELFNixPlatformRuntimeState &
  operator=(const ELFNixPlatformRuntimeState &) = delete;
  ELFNixPlatformRuntimeState(ELFNixPlatformRuntimeState &&) = delete;
  ELFNixPlatformRuntimeState &operator=(ELFNixPlatformRuntimeState &&) = delete;

  Error registerObjectSections(ELFNixPerObjectSectionsToRegister POSR);
  Error registerJITDylib(std::string &Name, void *Handle);
  Error deregisterJITDylib(void *Handle);
  Error registerInits(ExecutorAddr HeaderAddr,
                      std::vector<ExecutorAddrRange> Inits);
  Error deregisterInits(ExecutorAddr HeaderAddr,
                        std::vector<ExecutorAddrRange> Inits);
  Error deregisterObjectSections(ELFNixPerObjectSectionsToRegister POSR);

  const char *dlerror();
  void *dlopen(std::string_view Name, int Mode);
  int dlupdate(void *DSOHandle);
  int dlclose(void *DSOHandle);
  void *dlsym(void *DSOHandle, std::string_view Symbol);

  int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);
  void runAtExits(void *DSOHandle);
  void runAtExits(std::unique_lock<std::recursive_mutex> &JDStateLock,
                  PerJITDylibState &JDS);

  /// Returns the base address of the section containing ThreadData.
  Expected<std::pair<const char *, size_t>>
  getThreadDataSectionFor(const char *ThreadData);

  void *getPlatformJDDSOHandle() { return PlatformJDDSOHandle; }

private:
  PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);
  PerJITDylibState *getJITDylibStateByName(std::string_view Path);

  Error registerThreadDataSection(span<const char> ThreadDataSection);

  Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
                                                std::string_view Symbol);

  Error runInits(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                 PerJITDylibState &JDS);
  Expected<void *> dlopenImpl(std::string_view Path, int Mode);
  Error dlopenFull(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                   PerJITDylibState &JDS);
  Error dlopenInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                         PerJITDylibState &JDS,
                         ELFNixJITDylibDepInfoMap &DepInfo);
  Error dlupdateImpl(void *DSOHandle);
  Error dlupdateFull(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                     PerJITDylibState &JDS);

  Error dlcloseImpl(void *DSOHandle);
  Error dlcloseInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                          PerJITDylibState &JDS);

  static ELFNixPlatformRuntimeState *MOPS;

  void *PlatformJDDSOHandle;

  // Frame registration functions:
  void (*registerEHFrameSection)(const void *) = nullptr;
  void (*deregisterEHFrameSection)(const void *) = nullptr;

  // FIXME: Move to thread-state.
  std::string DLFcnError;

  std::recursive_mutex JDStatesMutex;
  std::unordered_map<void *, PerJITDylibState> JDStates;
  std::unordered_map<std::string, void *> JDNameToHeader;

  std::mutex ThreadDataSectionsMutex;
  std::map<const char *, size_t> ThreadDataSections;
};

ELFNixPlatformRuntimeState *ELFNixPlatformRuntimeState::MOPS = nullptr;

void ELFNixPlatformRuntimeState::initialize(void *DSOHandle) {
  assert(!MOPS && "ELFNixPlatformRuntimeState should be null");
  MOPS = new ELFNixPlatformRuntimeState(DSOHandle);
}

ELFNixPlatformRuntimeState &ELFNixPlatformRuntimeState::get() {
  assert(MOPS && "ELFNixPlatformRuntimeState not initialized");
  return *MOPS;
}

void ELFNixPlatformRuntimeState::destroy() {
  assert(MOPS && "ELFNixPlatformRuntimeState not initialized");
  delete MOPS;
}

ELFNixPlatformRuntimeState::ELFNixPlatformRuntimeState(void *DSOHandle)
    : PlatformJDDSOHandle(DSOHandle) {
  if (__unw_add_dynamic_eh_frame_section &&
      __unw_remove_dynamic_eh_frame_section) {
    registerEHFrameSection = __unw_add_dynamic_eh_frame_section;
    deregisterEHFrameSection = __unw_remove_dynamic_eh_frame_section;
  } else {
    registerEHFrameSection = __register_frame;
    deregisterEHFrameSection = __deregister_frame;
  }
}

Error ELFNixPlatformRuntimeState::registerObjectSections(
    ELFNixPerObjectSectionsToRegister POSR) {
  if (POSR.EHFrameSection.Start)
    registerEHFrameSection(POSR.EHFrameSection.Start.toPtr<const char *>());

  if (POSR.ThreadDataSection.Start) {
    if (auto Err = registerThreadDataSection(
            POSR.ThreadDataSection.toSpan<const char>()))
      return Err;
  }

  return Error::success();
}

Error ELFNixPlatformRuntimeState::deregisterObjectSections(
    ELFNixPerObjectSectionsToRegister POSR) {
  if (POSR.EHFrameSection.Start)
    deregisterEHFrameSection(POSR.EHFrameSection.Start.toPtr<const char *>());

  return Error::success();
}

Error ELFNixPlatformRuntimeState::registerJITDylib(std::string &Name,
                                                   void *Handle) {
  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);

  if (JDStates.count(Handle)) {
    std::ostringstream ErrStream;
    ErrStream << "Duplicate JITDylib registration for header " << Handle
              << " (name = " << Name << ")";
    return make_error<StringError>(ErrStream.str());
  }

  if (JDNameToHeader.count(Name)) {
    std::ostringstream ErrStream;
    ErrStream << "Duplicate JITDylib registration for header " << Handle
              << " (header = " << Handle << ")";
    return make_error<StringError>(ErrStream.str());
  }

  auto &JD = JDStates[Handle];
  JD.Header = Handle;
  JD.Name = std::move(Name);
  JDNameToHeader[JD.Name] = Handle;
  return Error::success();
}

Error ELFNixPlatformRuntimeState::deregisterJITDylib(void *Handle) {
  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);

  auto I = JDStates.find(Handle);
  if (I == JDStates.end()) {
    std::ostringstream ErrStream;
    ErrStream << "Attempted to deregister unrecognized header " << Handle;
    return make_error<StringError>(ErrStream.str());
  }

  auto J = JDNameToHeader.find(
      std::string(I->second.Name.data(), I->second.Name.size()));
  assert(J != JDNameToHeader.end() &&
         "Missing JDNameToHeader entry for JITDylib");
  JDNameToHeader.erase(J);
  JDStates.erase(I);
  return Error::success();
}

Error ELFNixPlatformRuntimeState::registerInits(
    ExecutorAddr HeaderAddr, std::vector<ExecutorAddrRange> Inits) {
  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
  PerJITDylibState *JDS =
      getJITDylibStateByHeaderAddr(HeaderAddr.toPtr<void *>());

  if (!JDS) {
    std::ostringstream ErrStream;
    ErrStream << "Could not register object platform sections for "
                 "unrecognized header "
              << HeaderAddr.toPtr<void *>();
    return make_error<StringError>(ErrStream.str());
  }

  for (auto &I : Inits) {
    JDS->RecordedInits.add(I.toSpan<void (*)()>());
  }

  return Error::success();
}

Error ELFNixPlatformRuntimeState::deregisterInits(
    ExecutorAddr HeaderAddr, std::vector<ExecutorAddrRange> Inits) {

  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
  PerJITDylibState *JDS =
      getJITDylibStateByHeaderAddr(HeaderAddr.toPtr<void *>());

  if (!JDS) {
    std::ostringstream ErrStream;
    ErrStream << "Could not register object platform sections for unrecognized "
                 "header "
              << HeaderAddr.toPtr<void *>();
    return make_error<StringError>(ErrStream.str());
  }

  for (auto &I : Inits) {
    JDS->RecordedInits.removeIfPresent(I);
  }

  return Error::success();
}

const char *ELFNixPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }

void *ELFNixPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
  if (auto H = dlopenImpl(Path, Mode))
    return *H;
  else {
    // FIXME: Make dlerror thread safe.
    DLFcnError = toString(H.takeError());
    return nullptr;
  }
}

int ELFNixPlatformRuntimeState::dlupdate(void *DSOHandle) {
  if (auto Err = dlupdateImpl(DSOHandle)) {
    // FIXME: Make dlerror thread safe.
    DLFcnError = toString(std::move(Err));
    return -1;
  }
  return 0;
}

int ELFNixPlatformRuntimeState::dlclose(void *DSOHandle) {
  if (auto Err = dlcloseImpl(DSOHandle)) {
    DLFcnError = toString(std::move(Err));
    return -1;
  }
  return 0;
}

void *ELFNixPlatformRuntimeState::dlsym(void *DSOHandle,
                                        std::string_view Symbol) {
  auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);
  if (!Addr) {
    DLFcnError = toString(Addr.takeError());
    return 0;
  }

  return Addr->toPtr<void *>();
}

int ELFNixPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,
                                               void *DSOHandle) {
  // FIXME: Handle out-of-memory errors, returning -1 if OOM.
  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
  auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
  assert(JDS && "JITDylib state not initialized");
  JDS->AtExits.push_back({F, Arg});
  return 0;
}

void ELFNixPlatformRuntimeState::runAtExits(void *DSOHandle) {
  std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);
  PerJITDylibState *JDS = getJITDylibStateByHeaderAddr(DSOHandle);

  if (JDS)
    runAtExits(Lock, *JDS);
}

void ELFNixPlatformRuntimeState::runAtExits(
    std::unique_lock<std::recursive_mutex> &JDStateLock,
    PerJITDylibState &JDS) {
  AtExitsVector V = std::move(JDS.AtExits);

  while (!V.empty()) {
    auto &AE = V.back();
    AE.Func(AE.Arg);
    V.pop_back();
  }
}

Expected<std::pair<const char *, size_t>>
ELFNixPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
  std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
  auto I = ThreadDataSections.upper_bound(ThreadData);
  // Check that we have a valid entry conovering this address.
  if (I == ThreadDataSections.begin())
    return make_error<StringError>("No thread local data section for key");
  I = std::prev(I);
  if (ThreadData >= I->first + I->second)
    return make_error<StringError>("No thread local data section for key");
  return *I;
}

ELFNixPlatformRuntimeState::PerJITDylibState *
ELFNixPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) {
  auto I = JDStates.find(DSOHandle);
  if (I == JDStates.end())
    return nullptr;

  return &I->second;
}

ELFNixPlatformRuntimeState::PerJITDylibState *
ELFNixPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) {
  // FIXME: Avoid creating string copy here.
  auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));
  if (I == JDNameToHeader.end())
    return nullptr;
  void *H = I->second;
  auto J = JDStates.find(H);
  assert(J != JDStates.end() &&
         "JITDylib has name map entry but no header map entry");
  return &J->second;
}

Error ELFNixPlatformRuntimeState::registerThreadDataSection(
    span<const char> ThreadDataSection) {
  std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
  auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
  if (I != ThreadDataSections.begin()) {
    auto J = std::prev(I);
    if (J->first + J->second > ThreadDataSection.data())
      return make_error<StringError>("Overlapping .tdata sections");
  }
  ThreadDataSections.insert(
      I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
  return Error::success();
}

Expected<ExecutorAddr>
ELFNixPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
                                                   std::string_view Sym) {
  Expected<ExecutorAddr> Result((ExecutorAddr()));
  if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(
          SPSExecutorAddr,
          SPSString)>::call(JITDispatch(&__orc_rt_elfnix_symbol_lookup_tag),
                            Result, ExecutorAddr::fromPtr(DSOHandle), Sym))
    return std::move(Err);
  return Result;
}

Error ELFNixPlatformRuntimeState::runInits(
    std::unique_lock<std::recursive_mutex> &JDStatesLock,
    PerJITDylibState &JDS) {
  std::vector<span<void (*)()>> InitSections;
  InitSections.reserve(JDS.RecordedInits.numNewSections());

  JDS.RecordedInits.processNewSections(
      [&](span<void (*)()> Inits) { InitSections.push_back(Inits); });

  JDStatesLock.unlock();
  for (auto Sec : InitSections)
    for (auto *Init : Sec)
      Init();

  JDStatesLock.lock();

  return Error::success();
}

Expected<void *> ELFNixPlatformRuntimeState::dlopenImpl(std::string_view Path,
                                                        int Mode) {
  std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);
  PerJITDylibState *JDS = getJITDylibStateByName(Path);

  if (!JDS)
    return make_error<StringError>("No registered JTIDylib for path " +
                                   std::string(Path.data(), Path.size()));

  if (auto Err = dlopenFull(Lock, *JDS))
    return std::move(Err);

  ++JDS->RefCount;

  return JDS->Header;
}

Error ELFNixPlatformRuntimeState::dlopenFull(
    std::unique_lock<std::recursive_mutex> &JDStateLock,
    PerJITDylibState &JDS) {
  Expected<ELFNixJITDylibDepInfoMap> DepInfo((ELFNixJITDylibDepInfoMap()));
  JDStateLock.unlock();
  if (auto Err = WrapperFunction<SPSExpected<SPSELFNixJITDylibDepInfoMap>(
          SPSExecutorAddr)>::
          call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag), DepInfo,
               ExecutorAddr::fromPtr(JDS.Header)))
    return Err;
  JDStateLock.lock();

  if (!DepInfo)
    return DepInfo.takeError();

  if (auto Err = dlopenInitialize(JDStateLock, JDS, *DepInfo))
    return Err;

  if (!DepInfo->empty()) {
    std::ostringstream ErrStream;
    ErrStream << "Encountered unrecognized dep-info key headers "
                 "while processing dlopen of "
              << JDS.Name;
    return make_error<StringError>(ErrStream.str());
  }

  return Error::success();
}

Error ELFNixPlatformRuntimeState::dlopenInitialize(
    std::unique_lock<std::recursive_mutex> &JDStatesLock, PerJITDylibState &JDS,
    ELFNixJITDylibDepInfoMap &DepInfo) {

  auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));
  if (I == DepInfo.end())
    return Error::success();

  auto Deps = std::move(I->second);
  DepInfo.erase(I);

  std::vector<PerJITDylibState *> OldDeps;
  std::swap(JDS.Deps, OldDeps);
  JDS.Deps.reserve(Deps.size());
  for (auto H : Deps) {
    PerJITDylibState *DepJDS = getJITDylibStateByHeaderAddr(H.toPtr<void *>());
    if (!DepJDS) {
      std::ostringstream ErrStream;
      ErrStream << "Encountered unrecognized dep header " << H.toPtr<void *>()
                << " while initializing " << JDS.Name;
      return make_error<StringError>(ErrStream.str());
    }
    ++DepJDS->LinkedAgainstRefCount;
    if (auto Err = dlopenInitialize(JDStatesLock, *DepJDS, DepInfo))
      return Err;
  }

  if (auto Err = runInits(JDStatesLock, JDS))
    return Err;

  for (auto *DepJDS : OldDeps) {
    --DepJDS->LinkedAgainstRefCount;
    if (!DepJDS->referenced())
      if (auto Err = dlcloseInitialize(JDStatesLock, *DepJDS))
        return Err;
  }
  return Error::success();
}

Error ELFNixPlatformRuntimeState::dlupdateImpl(void *DSOHandle) {
  std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);

  // Try to find JITDylib state by name.
  auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);

  if (!JDS) {
    std::ostringstream ErrStream;
    ErrStream << "No registered JITDylib for " << DSOHandle;
    return make_error<StringError>(ErrStream.str());
  }

  if (!JDS->referenced())
    return make_error<StringError>("dlupdate failed, JITDylib must be open.");

  if (auto Err = dlupdateFull(Lock, *JDS))
    return Err;

  return Error::success();
}

Error ELFNixPlatformRuntimeState::dlupdateFull(
    std::unique_lock<std::recursive_mutex> &JDStatesLock,
    PerJITDylibState &JDS) {
  // Call back to the JIT to push the initializers.
  Expected<ELFNixJITDylibDepInfoMap> DepInfo((ELFNixJITDylibDepInfoMap()));
  // Unlock so that we can accept the initializer update.
  JDStatesLock.unlock();
  if (auto Err = WrapperFunction<SPSExpected<SPSELFNixJITDylibDepInfoMap>(
          SPSExecutorAddr)>::
          call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag), DepInfo,
               ExecutorAddr::fromPtr(JDS.Header)))
    return Err;
  JDStatesLock.lock();

  if (!DepInfo)
    return DepInfo.takeError();

  if (auto Err = runInits(JDStatesLock, JDS))
    return Err;

  return Error::success();
}

Error ELFNixPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {

  std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);
  PerJITDylibState *JDS = getJITDylibStateByHeaderAddr(DSOHandle);

  if (!JDS) {
    std::ostringstream ErrStream;
    ErrStream << "No registered JITDylib for " << DSOHandle;
    return make_error<StringError>(ErrStream.str());
  }

  --JDS->RefCount;

  if (!JDS->referenced())
    return dlcloseInitialize(Lock, *JDS);

  return Error::success();
}

Error ELFNixPlatformRuntimeState::dlcloseInitialize(
    std::unique_lock<std::recursive_mutex> &JDStatesLock,
    PerJITDylibState &JDS) {
  runAtExits(JDStatesLock, JDS);
  JDS.RecordedInits.reset();
  for (auto *DepJDS : JDS.Deps)
    if (!JDS.referenced())
      if (auto Err = dlcloseInitialize(JDStatesLock, *DepJDS))
        return Err;

  return Error::success();
}

class ELFNixPlatformRuntimeTLVManager {
public:
  void *getInstance(const char *ThreadData);

private:
  std::unordered_map<const char *, char *> Instances;
  std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
};

void *ELFNixPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
  auto I = Instances.find(ThreadData);
  if (I != Instances.end())
    return I->second;
  auto TDS =
      ELFNixPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
  if (!TDS) {
    __orc_rt_log_error(toString(TDS.takeError()).c_str());
    return nullptr;
  }

  auto &Allocated = AllocatedSections[TDS->first];
  if (!Allocated) {
    Allocated = std::make_unique<char[]>(TDS->second);
    memcpy(Allocated.get(), TDS->first, TDS->second);
  }
  size_t ThreadDataDelta = ThreadData - TDS->first;
  assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");

  char *Instance = Allocated.get() + ThreadDataDelta;
  Instances[ThreadData] = Instance;
  return Instance;
}

void destroyELFNixTLVMgr(void *ELFNixTLVMgr) {
  delete static_cast<ELFNixPlatformRuntimeTLVManager *>(ELFNixTLVMgr);
}

} // end anonymous namespace

//------------------------------------------------------------------------------
//                             JIT entry points
//------------------------------------------------------------------------------

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_platform_bootstrap(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
             ArgData, ArgSize,
             [](ExecutorAddr DSOHandle) {
               ELFNixPlatformRuntimeState::initialize(
                   DSOHandle.toPtr<void *>());
               return Error::success();
             })
      .release();
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_platform_shutdown(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError()>::handle(
             ArgData, ArgSize,
             []() {
               ELFNixPlatformRuntimeState::destroy();
               return Error::success();
             })
      .release();
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_register_jitdylib(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle(
             ArgData, ArgSize,
             [](std::string &JDName, ExecutorAddr HeaderAddr) {
               return ELFNixPlatformRuntimeState::get().registerJITDylib(
                   JDName, HeaderAddr.toPtr<void *>());
             })
      .release();
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_deregister_jitdylib(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
             ArgData, ArgSize,
             [](ExecutorAddr HeaderAddr) {
               return ELFNixPlatformRuntimeState::get().deregisterJITDylib(
                   HeaderAddr.toPtr<void *>());
             })
      .release();
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_register_init_sections(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSExecutorAddr,
                                  SPSSequence<SPSExecutorAddrRange>)>::
      handle(ArgData, ArgSize,
             [](ExecutorAddr HeaderAddr,
                std::vector<ExecutorAddrRange> &Inits) {
               return ELFNixPlatformRuntimeState::get().registerInits(
                   HeaderAddr, std::move(Inits));
             })
          .release();
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_deregister_init_sections(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSExecutorAddr,
                                  SPSSequence<SPSExecutorAddrRange>)>::
      handle(ArgData, ArgSize,
             [](ExecutorAddr HeaderAddr,
                std::vector<ExecutorAddrRange> &Inits) {
               return ELFNixPlatformRuntimeState::get().deregisterInits(
                   HeaderAddr, std::move(Inits));
             })
          .release();
}

/// Wrapper function for registering metadata on a per-object basis.
ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_register_object_sections(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::
      handle(ArgData, ArgSize,
             [](ELFNixPerObjectSectionsToRegister &POSR) {
               return ELFNixPlatformRuntimeState::get().registerObjectSections(
                   std::move(POSR));
             })
          .release();
}

/// Wrapper for releasing per-object metadat.
ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_deregister_object_sections(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::
      handle(ArgData, ArgSize,
             [](ELFNixPerObjectSectionsToRegister &POSR) {
               return ELFNixPlatformRuntimeState::get()
                   .deregisterObjectSections(std::move(POSR));
             })
          .release();
}

//------------------------------------------------------------------------------
//                           TLV support
//------------------------------------------------------------------------------

ORC_RT_INTERFACE void *__orc_rt_elfnix_tls_get_addr_impl(TLSInfoEntry *D) {
  auto *TLVMgr = static_cast<ELFNixPlatformRuntimeTLVManager *>(
      pthread_getspecific(D->Key));
  if (!TLVMgr)
    TLVMgr = new ELFNixPlatformRuntimeTLVManager();
  if (pthread_setspecific(D->Key, TLVMgr)) {
    __orc_rt_log_error("Call to pthread_setspecific failed");
    return nullptr;
  }

  return TLVMgr->getInstance(
      reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
}

ORC_RT_INTERFACE ptrdiff_t ___orc_rt_elfnix_tlsdesc_resolver_impl(
    TLSDescriptor *D, const char *ThreadPointer) {
  const char *TLVPtr = reinterpret_cast<const char *>(
      __orc_rt_elfnix_tls_get_addr_impl(D->InfoEntry));
  return TLVPtr - ThreadPointer;
}

ORC_RT_INTERFACE orc_rt_WrapperFunctionResult
__orc_rt_elfnix_create_pthread_key(char *ArgData, size_t ArgSize) {
  return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
             ArgData, ArgSize,
             []() -> Expected<uint64_t> {
               pthread_key_t Key;
               if (int Err = pthread_key_create(&Key, destroyELFNixTLVMgr)) {
                 __orc_rt_log_error("Call to pthread_key_create failed");
                 return make_error<StringError>(strerror(Err));
               }
               return static_cast<uint64_t>(Key);
             })
      .release();
}

//------------------------------------------------------------------------------
//                           cxa_atexit support
//------------------------------------------------------------------------------

int __orc_rt_elfnix_cxa_atexit(void (*func)(void *), void *arg,
                               void *dso_handle) {
  return ELFNixPlatformRuntimeState::get().registerAtExit(func, arg,
                                                          dso_handle);
}

int __orc_rt_elfnix_atexit(void (*func)(void *)) {
  auto &PlatformRTState = ELFNixPlatformRuntimeState::get();
  return ELFNixPlatformRuntimeState::get().registerAtExit(
      func, NULL, PlatformRTState.getPlatformJDDSOHandle());
}

void __orc_rt_elfnix_cxa_finalize(void *dso_handle) {
  ELFNixPlatformRuntimeState::get().runAtExits(dso_handle);
}

//------------------------------------------------------------------------------
//                        JIT'd dlfcn alternatives.
//------------------------------------------------------------------------------

const char *__orc_rt_elfnix_jit_dlerror() {
  return ELFNixPlatformRuntimeState::get().dlerror();
}

void *__orc_rt_elfnix_jit_dlopen(const char *path, int mode) {
  return ELFNixPlatformRuntimeState::get().dlopen(path, mode);
}

int __orc_rt_elfnix_jit_dlupdate(void *dso_handle) {
  return ELFNixPlatformRuntimeState::get().dlupdate(dso_handle);
}

int __orc_rt_elfnix_jit_dlclose(void *dso_handle) {
  return ELFNixPlatformRuntimeState::get().dlclose(dso_handle);
}

void *__orc_rt_elfnix_jit_dlsym(void *dso_handle, const char *symbol) {
  return ELFNixPlatformRuntimeState::get().dlsym(dso_handle, symbol);
}

//------------------------------------------------------------------------------
//                             ELFNix Run Program
//------------------------------------------------------------------------------

ORC_RT_INTERFACE int64_t __orc_rt_elfnix_run_program(
    const char *JITDylibName, const char *EntrySymbolName, int argc,
    char *argv[]) {
  using MainTy = int (*)(int, char *[]);

  void *H = __orc_rt_elfnix_jit_dlopen(JITDylibName,
                                       orc_rt::elfnix::ORC_RT_RTLD_LAZY);
  if (!H) {
    __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
    return -1;
  }

  auto *Main =
      reinterpret_cast<MainTy>(__orc_rt_elfnix_jit_dlsym(H, EntrySymbolName));

  if (!Main) {
    __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
    return -1;
  }

  int Result = Main(argc, argv);

  if (__orc_rt_elfnix_jit_dlclose(H) == -1)
    __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());

  return Result;
}
