//===--------- ELFDebugObjectPlugin.cpp - JITLink debug objects -----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// FIXME: Update Plugin to poke the debug object into a new JITLink section,
//        rather than creating a new allocation.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"

#include <set>

#define DEBUG_TYPE "orc"

using namespace llvm::jitlink;
using namespace llvm::object;

namespace llvm {
namespace orc {

// Helper class to emit and fixup an individual debug object
class DebugObject {
public:
  using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;

  DebugObject(StringRef Name, SimpleSegmentAlloc Alloc, JITLinkContext &Ctx,
              ExecutionSession &ES)
      : Name(Name), WorkingMem(std::move(Alloc)),
        MemMgr(Ctx.getMemoryManager()), ES(ES) {}

  ~DebugObject() {
    assert(!FinalizeFuture.valid());
    if (Alloc) {
      std::vector<FinalizedAlloc> Allocs;
      Allocs.push_back(std::move(Alloc));
      if (Error Err = MemMgr.deallocate(std::move(Allocs)))
        ES.reportError(std::move(Err));
    }
  }

  MutableArrayRef<char> getBuffer() {
    auto SegInfo = WorkingMem.getSegInfo(MemProt::Read);
    return SegInfo.WorkingMem;
  }

  SimpleSegmentAlloc collectTargetAlloc() {
    FinalizeFuture = FinalizePromise.get_future();
    return std::move(WorkingMem);
  }

  void trackFinalizedAlloc(FinalizedAlloc FA) { Alloc = std::move(FA); }

  bool hasPendingTargetMem() const { return FinalizeFuture.valid(); }

  Expected<ExecutorAddrRange> awaitTargetMem() {
    assert(FinalizeFuture.valid() &&
           "FinalizeFuture is not valid. Perhaps there is no pending target "
           "memory transaction?");
    return FinalizeFuture.get();
  }

  void reportTargetMem(ExecutorAddrRange TargetMem) {
    FinalizePromise.set_value(TargetMem);
  }

  void failMaterialization(Error Err) {
    FinalizePromise.set_value(std::move(Err));
  }

  void releasePendingResources() {
    if (FinalizeFuture.valid()) {
      // Error before step 4: Finalization error was not reported
      Expected<ExecutorAddrRange> TargetMem = FinalizeFuture.get();
      if (!TargetMem)
        ES.reportError(TargetMem.takeError());
    } else {
      // Error before step 3: WorkingMem was not collected
      WorkingMem.abandon(
          [ES = &this->ES](Error Err) { ES->reportError(std::move(Err)); });
    }
  }

  using GetLoadAddressFn = llvm::unique_function<ExecutorAddr(StringRef)>;
  Error visitSections(GetLoadAddressFn Callback);

  template <typename ELFT>
  Error visitSectionLoadAddresses(GetLoadAddressFn Callback);

private:
  std::string Name;
  SimpleSegmentAlloc WorkingMem;
  JITLinkMemoryManager &MemMgr;
  ExecutionSession &ES;

  std::promise<MSVCPExpected<ExecutorAddrRange>> FinalizePromise;
  std::future<MSVCPExpected<ExecutorAddrRange>> FinalizeFuture;

  FinalizedAlloc Alloc;
};

template <typename ELFT>
Error DebugObject::visitSectionLoadAddresses(GetLoadAddressFn Callback) {
  using SectionHeader = typename ELFT::Shdr;

  MutableArrayRef<char> Buffer = getBuffer();
  StringRef BufferRef(Buffer.data(), Buffer.size());
  Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(BufferRef);
  if (!ObjRef)
    return ObjRef.takeError();

  Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
  if (!Sections)
    return Sections.takeError();

  for (const SectionHeader &Header : *Sections) {
    Expected<StringRef> Name = ObjRef->getSectionName(Header);
    if (!Name)
      return Name.takeError();
    if (Name->empty())
      continue;
    ExecutorAddr LoadAddress = Callback(*Name);
    if (LoadAddress)
      const_cast<SectionHeader &>(Header).sh_addr =
          static_cast<typename ELFT::uint>(LoadAddress.getValue());
  }

  LLVM_DEBUG({
    dbgs() << "Section load-addresses in debug object for \"" << Name
           << "\":\n";
    for (const SectionHeader &Header : *Sections) {
      StringRef Name = cantFail(ObjRef->getSectionName(Header));
      if (uint64_t Addr = Header.sh_addr) {
        dbgs() << formatv("  {0:x16} {1}\n", Addr, Name);
      } else {
        dbgs() << formatv("                     {0}\n", Name);
      }
    }
  });

  return Error::success();
}

Error DebugObject::visitSections(GetLoadAddressFn Callback) {
  unsigned char Class, Endian;
  MutableArrayRef<char> Buf = getBuffer();
  std::tie(Class, Endian) = getElfArchType(StringRef(Buf.data(), Buf.size()));

  switch (Class) {
  case ELF::ELFCLASS32:
    if (Endian == ELF::ELFDATA2LSB)
      return visitSectionLoadAddresses<ELF32LE>(std::move(Callback));
    if (Endian == ELF::ELFDATA2MSB)
      return visitSectionLoadAddresses<ELF32BE>(std::move(Callback));
    break;

  case ELF::ELFCLASS64:
    if (Endian == ELF::ELFDATA2LSB)
      return visitSectionLoadAddresses<ELF64LE>(std::move(Callback));
    if (Endian == ELF::ELFDATA2MSB)
      return visitSectionLoadAddresses<ELF64BE>(std::move(Callback));
    break;

  default:
    break;
  }
  llvm_unreachable("Checked class and endian in notifyMaterializing()");
}

ELFDebugObjectPlugin::ELFDebugObjectPlugin(ExecutionSession &ES,
                                           bool RequireDebugSections,
                                           Error &Err)
    : ES(ES), RequireDebugSections(RequireDebugSections) {
  // Pass bootstrap symbol for registration function to enable debugging
  ErrorAsOutParameter _(&Err);
  Err = lookupAndApply(ES.getBootstrapJITDylib(),
                       {recordAddr(rt::RegisterJITLoaderGDBAllocActionName,
                                   &RegistrationAction)});
}

ELFDebugObjectPlugin::~ELFDebugObjectPlugin() = default;

static const std::set<StringRef> DwarfSectionNames = {
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
  ELF_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
};

static bool isDwarfSection(StringRef SectionName) {
  return DwarfSectionNames.count(SectionName) == 1;
}

void ELFDebugObjectPlugin::notifyMaterializing(
    MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
    MemoryBufferRef InputObj) {
  if (InputObj.getBufferSize() == 0)
    return;
  if (G.getTargetTriple().getObjectFormat() != Triple::ELF)
    return;

  unsigned char Class, Endian;
  std::tie(Class, Endian) = getElfArchType(InputObj.getBuffer());
  if (Class != ELF::ELFCLASS64 && Class != ELF::ELFCLASS32)
    return ES.reportError(
        createStringError(object_error::invalid_file_type,
                          "Skipping debug object registration: Invalid arch "
                          "0x%02x in ELF LinkGraph %s",
                          Class, G.getName().c_str()));
  if (Endian != ELF::ELFDATA2LSB && Endian != ELF::ELFDATA2MSB)
    return ES.reportError(
        createStringError(object_error::invalid_file_type,
                          "Skipping debug object registration: Invalid endian "
                          "0x%02x in ELF LinkGraph %s",
                          Endian, G.getName().c_str()));

  // Step 1: We copy the raw input object into the working memory of a
  // single-segment read-only allocation
  size_t Size = InputObj.getBufferSize();
  auto Alignment = sys::Process::getPageSizeEstimate();
  SimpleSegmentAlloc::Segment Segment{Size, Align(Alignment)};

  auto Alloc = SimpleSegmentAlloc::Create(
      Ctx.getMemoryManager(), ES.getSymbolStringPool(), ES.getTargetTriple(),
      Ctx.getJITLinkDylib(), {{MemProt::Read, Segment}});
  if (!Alloc) {
    ES.reportError(Alloc.takeError());
    return;
  }

  std::lock_guard<std::mutex> Lock(PendingObjsLock);
  assert(PendingObjs.count(&MR) == 0 && "One debug object per materialization");
  PendingObjs[&MR] = std::make_unique<DebugObject>(
      InputObj.getBufferIdentifier(), std::move(*Alloc), Ctx, ES);

  MutableArrayRef<char> Buffer = PendingObjs[&MR]->getBuffer();
  memcpy(Buffer.data(), InputObj.getBufferStart(), Size);
}

DebugObject *
ELFDebugObjectPlugin::getPendingDebugObj(MaterializationResponsibility &MR) {
  std::lock_guard<std::mutex> Lock(PendingObjsLock);
  auto It = PendingObjs.find(&MR);
  return It == PendingObjs.end() ? nullptr : It->second.get();
}

void ELFDebugObjectPlugin::modifyPassConfig(MaterializationResponsibility &MR,
                                            LinkGraph &G,
                                            PassConfiguration &PassConfig) {
  if (!getPendingDebugObj(MR))
    return;

  PassConfig.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) -> Error {
    size_t SectionsPatched = 0;
    bool HasDebugSections = false;
    DebugObject *DebugObj = getPendingDebugObj(MR);
    assert(DebugObj && "Don't inject passes if we have no debug object");

    // Step 2: Once the target memory layout is ready, we write the
    // addresses of the LinkGraph sections into the load-address fields of the
    // section headers in our debug object allocation
    Error Err = DebugObj->visitSections(
        [&G, &SectionsPatched, &HasDebugSections](StringRef Name) {
          Section *S = G.findSectionByName(Name);
          if (!S) {
            // The section may have been merged into a different one during
            // linking, ignore it.
            return ExecutorAddr();
          }

          SectionsPatched += 1;
          if (isDwarfSection(Name))
            HasDebugSections = true;
          return SectionRange(*S).getStart();
        });

    if (Err)
      return Err;
    if (!SectionsPatched) {
      LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
                        << G.getName() << "': no debug info\n");
      return Error::success();
    }

    if (RequireDebugSections && !HasDebugSections) {
      LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
                        << G.getName() << "': no debug info\n");
      return Error::success();
    }

    // Step 3: We start copying the debug object into target memory
    SimpleSegmentAlloc Alloc = DebugObj->collectTargetAlloc();

    // FIXME: FA->getAddress() below is supposed to be the address of the memory
    // range on the target, but InProcessMemoryManager returns the address of a
    // FinalizedAllocInfo helper instead
    auto ROSeg = Alloc.getSegInfo(MemProt::Read);
    ExecutorAddrRange R(ROSeg.Addr, ROSeg.WorkingMem.size());
    Alloc.finalize([this, R, &MR](Expected<DebugObject::FinalizedAlloc> FA) {
      // Bail out if materialization failed in the meantime
      std::lock_guard<std::mutex> Lock(PendingObjsLock);
      auto It = PendingObjs.find(&MR);
      if (It == PendingObjs.end()) {
        if (!FA)
          ES.reportError(FA.takeError());
        return;
      }

      DebugObject *DebugObj = It->second.get();
      if (!FA)
        DebugObj->failMaterialization(FA.takeError());

      // Keep allocation alive until the corresponding code is removed
      DebugObj->trackFinalizedAlloc(std::move(*FA));

      // Unblock post-fixup pass
      DebugObj->reportTargetMem(R);
    });

    return Error::success();
  });

  PassConfig.PostFixupPasses.push_back([this, &MR](LinkGraph &G) -> Error {
    // Step 4: We wait for the debug object copy to finish, so we can
    // register the memory range with the GDB JIT Interface in an allocation
    // action of the LinkGraph's own allocation
    DebugObject *DebugObj = getPendingDebugObj(MR);
    assert(DebugObj && "Don't inject passes if we have no debug object");
    // Post-allocation phases would bail out if there is no debug section,
    // in which case we wouldn't collect target memory and therefore shouldn't
    // wait for the transaction to finish.
    if (!DebugObj->hasPendingTargetMem())
      return Error::success();
    Expected<ExecutorAddrRange> R = DebugObj->awaitTargetMem();
    if (!R)
      return R.takeError();

    // Step 5: We have to keep the allocation alive until the corresponding
    // code is removed
    Error Err = MR.withResourceKeyDo([&](ResourceKey K) {
      std::lock_guard<std::mutex> LockPending(PendingObjsLock);
      std::lock_guard<std::mutex> LockRegistered(RegisteredObjsLock);
      auto It = PendingObjs.find(&MR);
      RegisteredObjs[K].push_back(std::move(It->second));
      PendingObjs.erase(It);
    });

    if (Err)
      return Err;

    if (R->empty())
      return Error::success();

    using namespace shared;
    G.allocActions().push_back(
        {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
             RegistrationAction, *R)),
         {/* no deregistration */}});
    return Error::success();
  });
}

Error ELFDebugObjectPlugin::notifyFailed(MaterializationResponsibility &MR) {
  std::lock_guard<std::mutex> Lock(PendingObjsLock);
  auto It = PendingObjs.find(&MR);
  It->second->releasePendingResources();
  PendingObjs.erase(It);
  return Error::success();
}

void ELFDebugObjectPlugin::notifyTransferringResources(JITDylib &JD,
                                                       ResourceKey DstKey,
                                                       ResourceKey SrcKey) {
  // Debug objects are stored by ResourceKey only after registration.
  // Thus, pending objects don't need to be updated here.
  std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  auto SrcIt = RegisteredObjs.find(SrcKey);
  if (SrcIt != RegisteredObjs.end()) {
    // Resources from distinct MaterializationResponsibilitys can get merged
    // after emission, so we can have multiple debug objects per resource key.
    for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
      RegisteredObjs[DstKey].push_back(std::move(DebugObj));
    RegisteredObjs.erase(SrcIt);
  }
}

Error ELFDebugObjectPlugin::notifyRemovingResources(JITDylib &JD,
                                                    ResourceKey Key) {
  // Removing the resource for a pending object fails materialization, so they
  // get cleaned up in the notifyFailed() handler.
  std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  RegisteredObjs.erase(Key);

  // TODO: Implement unregister notifications.
  return Error::success();
}

} // namespace orc
} // namespace llvm
