//===------- 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/DebuggerSupportPlugin.h"

#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/MachO.h"

#define DEBUG_TYPE "orc"

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

static const char *SynthDebugSectionName = "__jitlink_synth_debug_object";

namespace {

struct MachO64LE {
  using UIntPtr = uint64_t;

  using Header = MachO::mach_header_64;
  using SegmentLC = MachO::segment_command_64;
  using Section = MachO::section_64;
  using NList = MachO::nlist_64;

  static constexpr support::endianness Endianness = support::little;
  static constexpr const uint32_t Magic = MachO::MH_MAGIC_64;
  static constexpr const uint32_t SegmentCmd = MachO::LC_SEGMENT_64;
};

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

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

  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 {
private:
  class MachOStructWriter {
  public:
    MachOStructWriter(MutableArrayRef<char> Buffer) : Buffer(Buffer) {}

    size_t getOffset() const { return Offset; }

    template <typename MachOStruct> void write(MachOStruct S) {
      assert(Offset + sizeof(S) <= Buffer.size() &&
             "Container block overflow while constructing debug MachO");
      if (MachOTraits::Endianness != support::endian::system_endianness())
        MachO::swapStruct(S);
      memcpy(Buffer.data() + Offset, &S, sizeof(S));
      Offset += sizeof(S);
    }

  private:
    MutableArrayRef<char> Buffer;
    size_t Offset = 0;
  };

public:
  using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;

  Error startSynthesis() override {
    LLVM_DEBUG({
      dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName()
             << "\n";
    });
    auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);

    struct DebugSectionInfo {
      Section *Sec = nullptr;
      StringRef SegName;
      StringRef SecName;
      JITTargetAddress Alignment = 0;
      JITTargetAddress StartAddr = 0;
      uint64_t Size = 0;
    };

    SmallVector<DebugSectionInfo, 12> DebugSecInfos;
    size_t NumSections = 0;
    for (auto &Sec : G.sections()) {
      if (llvm::empty(Sec.blocks()))
        continue;

      ++NumSections;
      if (isDebugSection(Sec)) {
        size_t SepPos = Sec.getName().find(',');
        if (SepPos > 16 || (Sec.getName().size() - (SepPos + 1) > 16)) {
          LLVM_DEBUG({
            dbgs() << "Skipping debug object synthesis for graph "
                   << G.getName()
                   << ": encountered non-standard DWARF section name \""
                   << Sec.getName() << "\"\n";
          });
          return Error::success();
        }
        DebugSecInfos.push_back({&Sec, Sec.getName().substr(0, SepPos),
                                 Sec.getName().substr(SepPos + 1), 0, 0});
      } else
        NonDebugSections.push_back(&Sec);
    }

    // Create container block.
    size_t SectionsCmdSize =
        sizeof(typename MachOTraits::Section) * NumSections;
    size_t SegmentLCSize =
        sizeof(typename MachOTraits::SegmentLC) + SectionsCmdSize;
    size_t ContainerBlockSize =
        sizeof(typename MachOTraits::Header) + SegmentLCSize;
    auto ContainerBlockContent = G.allocateBuffer(ContainerBlockSize);
    MachOContainerBlock =
        &G.createMutableContentBlock(SDOSec, ContainerBlockContent, 0, 8, 0);

    // Copy debug section blocks and symbols.
    JITTargetAddress NextBlockAddr = MachOContainerBlock->getSize();
    for (auto &SI : DebugSecInfos) {
      assert(!llvm::empty(SI.Sec->blocks()) && "Empty debug info section?");

      // Update addresses in debug section.
      LLVM_DEBUG({
        dbgs() << "  Appending " << SI.Sec->getName() << " ("
               << SI.Sec->blocks_size() << " block(s)) at "
               << formatv("{0:x8}", NextBlockAddr) << "\n";
      });
      for (auto *B : SI.Sec->blocks()) {
        NextBlockAddr = alignToBlock(NextBlockAddr, *B);
        B->setAddress(NextBlockAddr);
        NextBlockAddr += B->getSize();
      }

      auto &FirstBlock = **SI.Sec->blocks().begin();
      if (FirstBlock.getAlignmentOffset() != 0)
        return make_error<StringError>(
            "First block in " + SI.Sec->getName() +
                " section has non-zero alignment offset",
            inconvertibleErrorCode());
      if (FirstBlock.getAlignment() > std::numeric_limits<uint32_t>::max())
        return make_error<StringError>("First block in " + SI.Sec->getName() +
                                           " has alignment >4Gb",
                                       inconvertibleErrorCode());

      SI.Alignment = FirstBlock.getAlignment();
      SI.StartAddr = FirstBlock.getAddress();
      SI.Size = NextBlockAddr - SI.StartAddr;
      G.mergeSections(SDOSec, *SI.Sec);
      SI.Sec = nullptr;
    }
    size_t DebugSectionsSize = NextBlockAddr - MachOContainerBlock->getSize();

    // Write MachO header and debug section load commands.
    MachOStructWriter Writer(MachOContainerBlock->getAlreadyMutableContent());
    typename MachOTraits::Header Hdr;
    memset(&Hdr, 0, sizeof(Hdr));
    Hdr.magic = MachOTraits::Magic;
    switch (G.getTargetTriple().getArch()) {
    case Triple::x86_64:
      Hdr.cputype = MachO::CPU_TYPE_X86_64;
      Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
      break;
    case Triple::aarch64:
      Hdr.cputype = MachO::CPU_TYPE_ARM64;
      Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
      break;
    default:
      llvm_unreachable("Unsupported architecture");
    }
    Hdr.filetype = MachO::MH_OBJECT;
    Hdr.ncmds = 1;
    Hdr.sizeofcmds = SegmentLCSize;
    Hdr.flags = 0;
    Writer.write(Hdr);

    typename MachOTraits::SegmentLC SegLC;
    memset(&SegLC, 0, sizeof(SegLC));
    SegLC.cmd = MachOTraits::SegmentCmd;
    SegLC.cmdsize = SegmentLCSize;
    SegLC.vmaddr = ContainerBlockSize;
    SegLC.vmsize = DebugSectionsSize;
    SegLC.fileoff = ContainerBlockSize;
    SegLC.filesize = DebugSectionsSize;
    SegLC.maxprot =
        MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
    SegLC.initprot =
        MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
    SegLC.nsects = NumSections;
    SegLC.flags = 0;
    Writer.write(SegLC);

    StringSet<> ExistingLongNames;
    for (auto &SI : DebugSecInfos) {
      typename MachOTraits::Section Sec;
      memset(&Sec, 0, sizeof(Sec));
      memcpy(Sec.sectname, SI.SecName.data(), SI.SecName.size());
      memcpy(Sec.segname, SI.SegName.data(), SI.SegName.size());
      Sec.addr = SI.StartAddr;
      Sec.size = SI.Size;
      Sec.offset = SI.StartAddr;
      Sec.align = SI.Alignment;
      Sec.reloff = 0;
      Sec.nreloc = 0;
      Sec.flags = MachO::S_ATTR_DEBUG;
      Writer.write(Sec);
    }

    // Set MachOContainerBlock to indicate success to
    // completeSynthesisAndRegister.
    NonDebugSectionsStart = Writer.getOffset();
    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();
    }

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

    MachOStructWriter Writer(
        MachOContainerBlock->getAlreadyMutableContent().drop_front(
            NonDebugSectionsStart));

    unsigned LongSectionNameIdx = 0;
    for (auto *Sec : NonDebugSections) {
      size_t SepPos = Sec->getName().find(',');
      StringRef SegName, SecName;
      std::string CustomSecName;

      if ((SepPos == StringRef::npos && Sec->getName().size() <= 16)) {
        // No embedded segment name, short section name.
        SegName = "__JITLINK_CUSTOM";
        SecName = Sec->getName();
      } else if (SepPos < 16 && (Sec->getName().size() - (SepPos + 1) <= 16)) {
        // Canonical embedded segment and section name.
        SegName = Sec->getName().substr(0, SepPos);
        SecName = Sec->getName().substr(SepPos + 1);
      } else {
        // Long section name that needs to be truncated.
        assert(Sec->getName().size() > 16 &&
               "Short section name should have been handled above");
        SegName = "__JITLINK_CUSTOM";
        auto IdxStr = std::to_string(++LongSectionNameIdx);
        CustomSecName = Sec->getName().substr(0, 15 - IdxStr.size()).str();
        CustomSecName += ".";
        CustomSecName += IdxStr;
        SecName = StringRef(CustomSecName.data(), 16);
      }

      SectionRange R(*Sec);
      if (R.getFirstBlock()->getAlignmentOffset() != 0)
        return make_error<StringError>(
            "While building MachO debug object for " + G.getName() +
                " first block has non-zero alignment offset",
            inconvertibleErrorCode());

      typename MachOTraits::Section SecCmd;
      memset(&SecCmd, 0, sizeof(SecCmd));
      memcpy(SecCmd.sectname, SecName.data(), SecName.size());
      memcpy(SecCmd.segname, SegName.data(), SegName.size());
      SecCmd.addr = R.getStart();
      SecCmd.size = R.getSize();
      SecCmd.offset = 0;
      SecCmd.align = R.getFirstBlock()->getAlignment();
      SecCmd.reloff = 0;
      SecCmd.nreloc = 0;
      SecCmd.flags = 0;
      Writer.write(SecCmd);
    }

    SectionRange R(MachOContainerBlock->getSection());
    G.allocActions().push_back(
        {{RegisterActionAddr.getValue(), R.getStart(), R.getSize()}, {}});
    return Error::success();
  }

private:
  Block *MachOContainerBlock = nullptr;
  SmallVector<Section *, 16> NonDebugSections;
  size_t NonDebugSectionsStart = 0;
};

} // 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 Addr = ES.lookup({&ProcessJD}, RegisterActionAddr))
    return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
        ExecutorAddr(Addr->getAddress()));
  else
    return Addr.takeError();
}

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

Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
    ResourceKey K) {
  return Error::success();
}

void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
    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() == support::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() == support::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>>(
        LG, RegisterActionAddr);
    PassConfig.PrePrunePasses.push_back(
        [=](LinkGraph &G) { return MDOS->preserveDebugSections(); });
    PassConfig.PostPrunePasses.push_back(
        [=](LinkGraph &G) { return MDOS->startSynthesis(); });
    PassConfig.PreFixupPasses.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
