//===------- DebuggerSupportPlugin.cpp - Utils for debugger support -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/MachOBuilder.h"

#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"

#include <chrono>

#define DEBUG_TYPE "orc"

using namespace llvm;
using namespace llvm::jitlink;
using namespace llvm::orc;

static const char *SynthDebugSectionName = "__jitlink_synth_debug_object";

namespace {

class MachODebugObjectSynthesizerBase
    : public GDBJITDebugInfoRegistrationPlugin::DebugSectionSynthesizer {
public:
  static bool isDebugSection(Section &Sec) {
    return Sec.getName().starts_with("__DWARF,");
  }

  MachODebugObjectSynthesizerBase(LinkGraph &G, ExecutorAddr RegisterActionAddr)
      : G(G), RegisterActionAddr(RegisterActionAddr) {}
  virtual ~MachODebugObjectSynthesizerBase() = default;

  Error preserveDebugSections() {
    if (G.findSectionByName(SynthDebugSectionName)) {
      LLVM_DEBUG({
        dbgs() << "MachODebugObjectSynthesizer skipping graph " << G.getName()
               << " which contains an unexpected existing "
               << SynthDebugSectionName << " section.\n";
      });
      return Error::success();
    }

    LLVM_DEBUG({
      dbgs() << "MachODebugObjectSynthesizer visiting graph " << G.getName()
             << "\n";
    });
    for (auto &Sec : G.sections()) {
      if (!isDebugSection(Sec))
        continue;
      // Preserve blocks in this debug section by marking one existing symbol
      // live for each block, and introducing a new live, anonymous symbol for
      // each currently unreferenced block.
      LLVM_DEBUG({
        dbgs() << "  Preserving debug section " << Sec.getName() << "\n";
      });
      SmallSet<Block *, 8> PreservedBlocks;
      for (auto *Sym : Sec.symbols()) {
        bool NewPreservedBlock =
            PreservedBlocks.insert(&Sym->getBlock()).second;
        if (NewPreservedBlock)
          Sym->setLive(true);
      }
      for (auto *B : Sec.blocks())
        if (!PreservedBlocks.count(B))
          G.addAnonymousSymbol(*B, 0, 0, false, true);
    }

    return Error::success();
  }

protected:
  LinkGraph &G;
  ExecutorAddr RegisterActionAddr;
};

template <typename MachOTraits>
class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
public:
  MachODebugObjectSynthesizer(ExecutionSession &ES, LinkGraph &G,
                              ExecutorAddr RegisterActionAddr)
      : MachODebugObjectSynthesizerBase(G, RegisterActionAddr),
        Builder(ES.getPageSize()) {}

  using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;

  Error startSynthesis() override {
    LLVM_DEBUG({
      dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName()
             << "\n";
    });

    for (auto &Sec : G.sections()) {
      if (Sec.blocks().empty())
        continue;

      // Skip sections whose name's don't fit the MachO standard.
      if (Sec.getName().empty() || Sec.getName().size() > 33 ||
          Sec.getName().find(',') > 16)
        continue;

      if (isDebugSection(Sec))
        DebugSections.push_back({&Sec, nullptr});
      else if (Sec.getMemLifetime() != MemLifetime::NoAlloc)
        NonDebugSections.push_back({&Sec, nullptr});
    }

    // Bail out early if no debug sections.
    if (DebugSections.empty())
      return Error::success();

    // Write MachO header and debug section load commands.
    Builder.Header.filetype = MachO::MH_OBJECT;
    if (auto CPUType = MachO::getCPUType(G.getTargetTriple()))
      Builder.Header.cputype = *CPUType;
    else
      return CPUType.takeError();
    if (auto CPUSubType = MachO::getCPUSubType(G.getTargetTriple()))
      Builder.Header.cpusubtype = *CPUSubType;
    else
      return CPUSubType.takeError();

    Seg = &Builder.addSegment("");

    StringMap<std::unique_ptr<MemoryBuffer>> DebugSectionMap;
    StringRef DebugLineSectionData;
    for (auto &DSec : DebugSections) {
      auto [SegName, SecName] = DSec.GraphSec->getName().split(',');
      DSec.BuilderSec = &Seg->addSection(SecName, SegName);

      SectionRange SR(*DSec.GraphSec);
      DSec.BuilderSec->Content.Size = SR.getSize();
      if (!SR.empty()) {
        DSec.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
        StringRef SectionData(SR.getFirstBlock()->getContent().data(),
                              SR.getFirstBlock()->getSize());
        DebugSectionMap[SecName.drop_front(2)] = // drop "__" prefix.
            MemoryBuffer::getMemBuffer(SectionData, G.getName(), false);
        if (SecName == "__debug_line")
          DebugLineSectionData = SectionData;
      }
    }

    std::optional<StringRef> FileName;
    if (!DebugLineSectionData.empty()) {
      assert((G.getEndianness() == llvm::endianness::big ||
              G.getEndianness() == llvm::endianness::little) &&
             "G.getEndianness() must be either big or little");
      auto DWARFCtx =
          DWARFContext::create(DebugSectionMap, G.getPointerSize(),
                               G.getEndianness() == llvm::endianness::little);
      DWARFDataExtractor DebugLineData(
          DebugLineSectionData, G.getEndianness() == llvm::endianness::little,
          G.getPointerSize());
      uint64_t Offset = 0;
      DWARFDebugLine::Prologue P;

      // Try to parse line data. Consume error on failure.
      if (auto Err = P.parse(DebugLineData, &Offset, consumeError, *DWARFCtx)) {
        handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
          LLVM_DEBUG({
            dbgs() << "Cannot parse line table for \"" << G.getName() << "\": ";
            EIB.log(dbgs());
            dbgs() << "\n";
          });
        });
      } else {
        for (auto &FN : P.FileNames)
          if ((FileName = dwarf::toString(FN.Name))) {
            LLVM_DEBUG({
              dbgs() << "Using FileName = \"" << *FileName
                     << "\" from DWARF line table\n";
            });
            break;
          }
      }
    }

    // If no line table (or unable to use) then use graph name.
    // FIXME: There are probably other debug sections we should look in first.
    if (!FileName) {
      LLVM_DEBUG({
        dbgs() << "Could not find source name from DWARF line table. "
                  "Using FileName = \"\"\n";
      });
      FileName = "";
    }

    Builder.addSymbol("", MachO::N_SO, 0, 0, 0);
    Builder.addSymbol(*FileName, MachO::N_SO, 0, 0, 0);
    auto TimeStamp = std::chrono::duration_cast<std::chrono::seconds>(
                         std::chrono::system_clock::now().time_since_epoch())
                         .count();
    Builder.addSymbol("", MachO::N_OSO, 3, 1, TimeStamp);

    for (auto &NDSP : NonDebugSections) {
      auto [SegName, SecName] = NDSP.GraphSec->getName().split(',');
      NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
      SectionRange SR(*NDSP.GraphSec);
      if (!SR.empty())
        NDSP.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());

      // Add stabs.
      for (auto *Sym : NDSP.GraphSec->symbols()) {
        // Skip anonymous symbols.
        if (!Sym->hasName())
          continue;

        uint8_t SymType = Sym->isCallable() ? MachO::N_FUN : MachO::N_GSYM;

        Builder.addSymbol("", MachO::N_BNSYM, 1, 0, 0);
        StabSymbols.push_back(
            {*Sym, Builder.addSymbol(*Sym->getName(), SymType, 1, 0, 0),
             Builder.addSymbol(*Sym->getName(), SymType, 0, 0, 0)});
        Builder.addSymbol("", MachO::N_ENSYM, 1, 0, 0);
      }
    }

    Builder.addSymbol("", MachO::N_SO, 1, 0, 0);

    // Lay out the debug object, create a section and block for it.
    size_t DebugObjectSize = Builder.layout();

    auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
    MachOContainerBlock = &G.createMutableContentBlock(
        SDOSec, G.allocateBuffer(DebugObjectSize), orc::ExecutorAddr(), 8, 0);

    return Error::success();
  }

  Error completeSynthesisAndRegister() override {
    if (!MachOContainerBlock) {
      LLVM_DEBUG({
        dbgs() << "Not writing MachO debug object header for " << G.getName()
               << " since createDebugSection failed\n";
      });

      return Error::success();
    }
    ExecutorAddr MaxAddr;
    for (auto &NDSec : NonDebugSections) {
      SectionRange SR(*NDSec.GraphSec);
      NDSec.BuilderSec->addr = SR.getStart().getValue();
      NDSec.BuilderSec->size = SR.getSize();
      NDSec.BuilderSec->offset = SR.getStart().getValue();
      if (SR.getEnd() > MaxAddr)
        MaxAddr = SR.getEnd();
    }

    for (auto &DSec : DebugSections) {
      if (DSec.GraphSec->blocks_size() != 1)
        return make_error<StringError>(
            "Unexpected number of blocks in debug info section",
            inconvertibleErrorCode());

      if (ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size > MaxAddr)
        MaxAddr = ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size;

      auto &B = **DSec.GraphSec->blocks().begin();
      DSec.BuilderSec->Content.Data = B.getContent().data();
      DSec.BuilderSec->Content.Size = B.getContent().size();
      DSec.BuilderSec->flags |= MachO::S_ATTR_DEBUG;
    }

    LLVM_DEBUG({
      dbgs() << "Writing MachO debug object header for " << G.getName() << "\n";
    });

    // Update stab symbol addresses.
    for (auto &SS : StabSymbols) {
      SS.StartStab.nlist().n_value = SS.Sym.getAddress().getValue();
      SS.EndStab.nlist().n_value = SS.Sym.getSize();
    }

    Builder.write(MachOContainerBlock->getAlreadyMutableContent());

    static constexpr bool AutoRegisterCode = true;
    SectionRange R(MachOContainerBlock->getSection());
    G.allocActions().push_back(
        {cantFail(shared::WrapperFunctionCall::Create<
                  shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
             RegisterActionAddr, R.getRange(), AutoRegisterCode)),
         {}});

    return Error::success();
  }

private:
  struct SectionPair {
    Section *GraphSec = nullptr;
    typename MachOBuilder<MachOTraits>::Section *BuilderSec = nullptr;
  };

  struct StabSymbolsEntry {
    using RelocTarget = typename MachOBuilder<MachOTraits>::RelocTarget;

    StabSymbolsEntry(Symbol &Sym, RelocTarget StartStab, RelocTarget EndStab)
        : Sym(Sym), StartStab(StartStab), EndStab(EndStab) {}

    Symbol &Sym;
    RelocTarget StartStab, EndStab;
  };

  using BuilderType = MachOBuilder<MachOTraits>;

  Block *MachOContainerBlock = nullptr;
  MachOBuilder<MachOTraits> Builder;
  typename MachOBuilder<MachOTraits>::Segment *Seg = nullptr;
  std::vector<StabSymbolsEntry> StabSymbols;
  SmallVector<SectionPair, 16> DebugSections;
  SmallVector<SectionPair, 16> NonDebugSections;
};

} // end anonymous namespace

namespace llvm {
namespace orc {

Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>>
GDBJITDebugInfoRegistrationPlugin::Create(ExecutionSession &ES,
                                          JITDylib &ProcessJD,
                                          const Triple &TT) {
  auto RegisterActionAddr =
      TT.isOSBinFormatMachO()
          ? ES.intern("_llvm_orc_registerJITLoaderGDBAllocAction")
          : ES.intern("llvm_orc_registerJITLoaderGDBAllocAction");

  if (auto RegisterSym = ES.lookup({&ProcessJD}, RegisterActionAddr))
    return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
        RegisterSym->getAddress());
  else
    return RegisterSym.takeError();
}

Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
    MaterializationResponsibility &MR) {
  return Error::success();
}

Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
    JITDylib &JD, ResourceKey K) {
  return Error::success();
}

void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
    JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {}

void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig(
    MaterializationResponsibility &MR, LinkGraph &LG,
    PassConfiguration &PassConfig) {

  if (LG.getTargetTriple().getObjectFormat() == Triple::MachO)
    modifyPassConfigForMachO(MR, LG, PassConfig);
  else {
    LLVM_DEBUG({
      dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unspported graph "
             << LG.getName() << "(triple = " << LG.getTargetTriple().str()
             << "\n";
    });
  }
}

void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
    MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
    jitlink::PassConfiguration &PassConfig) {

  switch (LG.getTargetTriple().getArch()) {
  case Triple::x86_64:
  case Triple::aarch64:
    // Supported, continue.
    assert(LG.getPointerSize() == 8 && "Graph has incorrect pointer size");
    assert(LG.getEndianness() == llvm::endianness::little &&
           "Graph has incorrect endianness");
    break;
  default:
    // Unsupported.
    LLVM_DEBUG({
      dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unsupported "
             << "MachO graph " << LG.getName()
             << "(triple = " << LG.getTargetTriple().str()
             << ", pointer size = " << LG.getPointerSize() << ", endianness = "
             << (LG.getEndianness() == llvm::endianness::big ? "big" : "little")
             << ")\n";
    });
    return;
  }

  // Scan for debug sections. If we find one then install passes.
  bool HasDebugSections = false;
  for (auto &Sec : LG.sections())
    if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) {
      HasDebugSections = true;
      break;
    }

  if (HasDebugSections) {
    LLVM_DEBUG({
      dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
             << " contains debug info. Installing debugger support passes.\n";
    });

    auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
        MR.getTargetJITDylib().getExecutionSession(), LG, RegisterActionAddr);
    PassConfig.PrePrunePasses.push_back(
        [=](LinkGraph &G) { return MDOS->preserveDebugSections(); });
    PassConfig.PostPrunePasses.push_back(
        [=](LinkGraph &G) { return MDOS->startSynthesis(); });
    PassConfig.PostFixupPasses.push_back(
        [=](LinkGraph &G) { return MDOS->completeSynthesisAndRegister(); });
  } else {
    LLVM_DEBUG({
      dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
             << " contains no debug info. Skipping.\n";
    });
  }
}

} // namespace orc
} // namespace llvm
