//===--------- 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/StringMap.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/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/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/MemoryBuffer.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); }

  Expected<ExecutorAddrRange> awaitTargetMem() { 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,
                                           bool AutoRegisterCode, Error &Err)
    : ES(ES), RequireDebugSections(RequireDebugSections),
      AutoRegisterCode(AutoRegisterCode) {
  // Pass bootstrap symbol for registration function to enable debugging
  ErrorAsOutParameter _(&Err);
  Err = ES.getExecutorProcessControl().getBootstrapSymbols(
      {{RegistrationAction, rt::RegisterJITLoaderGDBAllocActionName}});
}

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);
    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, bool>>(
             RegistrationAction, *R, AutoRegisterCode)),
         {/* 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
