//===-- ProfiledBinary.h - Binary decoder -----------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_PROFGEN_PROFILEDBINARY_H
#define LLVM_TOOLS_LLVM_PROFGEN_PROFILEDBINARY_H

#include "CallContext.h"
#include "ErrorHandling.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCPseudoProbe.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Transforms/IPO/SampleContextTracker.h"
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace llvm {
namespace sampleprof {

class ProfiledBinary;
class MissingFrameInferrer;

struct InstructionPointer {
  const ProfiledBinary *Binary;
  // Address of the executable segment of the binary.
  uint64_t Address;
  // Index to the sorted code address array of the binary.
  uint64_t Index = 0;
  InstructionPointer(const ProfiledBinary *Binary, uint64_t Address,
                     bool RoundToNext = false);
  bool advance();
  bool backward();
  void update(uint64_t Addr);
};

// The special frame addresses.
enum SpecialFrameAddr {
  // Dummy root of frame trie.
  DummyRoot = 0,
  // Represent all the addresses outside of current binary.
  // This's also used to indicate the call stack should be truncated since this
  // isn't a real call context the compiler will see.
  ExternalAddr = 1,
};

using RangesTy = std::vector<std::pair<uint64_t, uint64_t>>;

enum DwarfNameStatus {
  // Dwarf name matches with the symbol table (or symbol table just doesn't have
  // this entry)
  Matched = 0,
  // Dwarf name is missing, but we fixed it with the name from symbol table
  Missing = 1,
  // Symbol table has different names on this. Log these GUIDs in
  // AlternativeFunctionGUIDs
  Mismatch = 2,
};

struct BinaryFunction {
  StringRef FuncName;
  // End of range is an exclusive bound.
  RangesTy Ranges;
  DwarfNameStatus NameStatus = DwarfNameStatus::Matched;

  uint64_t getFuncSize() {
    uint64_t Sum = 0;
    for (auto &R : Ranges) {
      Sum += R.second - R.first;
    }
    return Sum;
  }
};

// Info about function range. A function can be split into multiple
// non-continuous ranges, each range corresponds to one FuncRange.
struct FuncRange {
  uint64_t StartAddress;
  // EndAddress is an exclusive bound.
  uint64_t EndAddress;
  // Function the range belongs to
  BinaryFunction *Func;
  // Whether the start address is the real entry of the function.
  bool IsFuncEntry = false;

  StringRef getFuncName() { return Func->FuncName; }
};

// PrologEpilog address tracker, used to filter out broken stack samples
// Currently we use a heuristic size (two) to infer prolog and epilog
// based on the start address and return address. In the future,
// we will switch to Dwarf CFI based tracker
struct PrologEpilogTracker {
  // A set of prolog and epilog addresses. Used by virtual unwinding.
  std::unordered_set<uint64_t> PrologEpilogSet;
  ProfiledBinary *Binary;
  PrologEpilogTracker(ProfiledBinary *Bin) : Binary(Bin){};

  // Take the two addresses from the start of function as prolog
  void
  inferPrologAddresses(std::map<uint64_t, FuncRange> &FuncStartAddressMap) {
    for (auto I : FuncStartAddressMap) {
      PrologEpilogSet.insert(I.first);
      InstructionPointer IP(Binary, I.first);
      if (!IP.advance())
        break;
      PrologEpilogSet.insert(IP.Address);
    }
  }

  // Take the last two addresses before the return address as epilog
  void inferEpilogAddresses(std::unordered_set<uint64_t> &RetAddrs) {
    for (auto Addr : RetAddrs) {
      PrologEpilogSet.insert(Addr);
      InstructionPointer IP(Binary, Addr);
      if (!IP.backward())
        break;
      PrologEpilogSet.insert(IP.Address);
    }
  }
};

// Track function byte size under different context (outlined version as well as
// various inlined versions). It also provides query support to get function
// size with the best matching context, which is used to help pre-inliner use
// accurate post-optimization size to make decisions.
// TODO: If an inlinee is completely optimized away, ideally we should have zero
// for its context size, currently we would misss such context since it doesn't
// have instructions. To fix this, we need to mark all inlinee with entry probe
// but without instructions as having zero size.
class BinarySizeContextTracker {
public:
  // Add instruction with given size to a context
  void addInstructionForContext(const SampleContextFrameVector &Context,
                                uint32_t InstrSize);

  // Get function size with a specific context. When there's no exact match
  // for the given context, try to retrieve the size of that function from
  // closest matching context.
  uint32_t getFuncSizeForContext(const ContextTrieNode *Context);

  // For inlinees that are full optimized away, we can establish zero size using
  // their remaining probes.
  void trackInlineesOptimizedAway(MCPseudoProbeDecoder &ProbeDecoder);

  using ProbeFrameStack = SmallVector<std::pair<StringRef, uint32_t>>;
  void
  trackInlineesOptimizedAway(MCPseudoProbeDecoder &ProbeDecoder,
                             const MCDecodedPseudoProbeInlineTree &ProbeNode,
                             ProbeFrameStack &Context);

  void dump() { RootContext.dumpTree(); }

private:
  // Root node for context trie tree, node that this is a reverse context trie
  // with callee as parent and caller as child. This way we can traverse from
  // root to find the best/longest matching context if an exact match does not
  // exist. It gives us the best possible estimate for function's post-inline,
  // post-optimization byte size.
  ContextTrieNode RootContext;
};

using AddressRange = std::pair<uint64_t, uint64_t>;

// The parsed MMap event
struct MMapEvent {
  int64_t PID = 0;
  uint64_t Address = 0;
  uint64_t Size = 0;
  uint64_t Offset = 0;
  StringRef MemProtectionFlag;
  StringRef BinaryPath;
};

class ProfiledBinary {
  // Absolute path of the executable binary.
  std::string Path;
  // Path of the debug info binary.
  std::string DebugBinaryPath;
  // The target triple.
  Triple TheTriple;
  // Path of symbolizer path which should be pointed to binary with debug info.
  StringRef SymbolizerPath;
  // Options used to configure the symbolizer
  symbolize::LLVMSymbolizer::Options SymbolizerOpts;
  // The runtime base address that the first executable segment is loaded at.
  uint64_t BaseAddress = 0;
  // The runtime base address that the first loadabe segment is loaded at.
  uint64_t FirstLoadableAddress = 0;
  // The preferred load address of each executable segment.
  std::vector<uint64_t> PreferredTextSegmentAddresses;
  // The file offset of each executable segment.
  std::vector<uint64_t> TextSegmentOffsets;

  // Mutiple MC component info
  std::unique_ptr<const MCRegisterInfo> MRI;
  std::unique_ptr<const MCAsmInfo> AsmInfo;
  std::unique_ptr<const MCSubtargetInfo> STI;
  std::unique_ptr<const MCInstrInfo> MII;
  std::unique_ptr<MCDisassembler> DisAsm;
  std::unique_ptr<const MCInstrAnalysis> MIA;
  std::unique_ptr<MCInstPrinter> IPrinter;
  // A list of text sections sorted by start RVA and size. Used to check
  // if a given RVA is a valid code address.
  std::set<std::pair<uint64_t, uint64_t>> TextSections;

  // A map of mapping function name to BinaryFunction info.
  std::unordered_map<std::string, BinaryFunction> BinaryFunctions;

  // Lookup BinaryFunctions using the function name's MD5 hash. Needed if the
  // profile is using MD5.
  std::unordered_map<uint64_t, BinaryFunction *> HashBinaryFunctions;

  // A list of binary functions that have samples.
  std::unordered_set<const BinaryFunction *> ProfiledFunctions;

  // GUID to symbol start address map
  DenseMap<uint64_t, uint64_t> SymbolStartAddrs;

  // Binary function to GUID mapping that stores the alternative names in symbol
  // table, despite the original name from DWARF info
  std::unordered_multimap<const BinaryFunction *, uint64_t>
      AlternativeFunctionGUIDs;

  // Mapping of profiled binary function to its pseudo probe name
  std::unordered_map<const BinaryFunction *, StringRef> PseudoProbeNames;

  // These maps are for temporary use of warning diagnosis.
  DenseSet<int64_t> AddrsWithMultipleSymbols;
  DenseSet<std::pair<uint64_t, uint64_t>> AddrsWithInvalidInstruction;

  // Start address to symbol GUID map
  std::unordered_multimap<uint64_t, uint64_t> StartAddrToSymMap;

  // An ordered map of mapping function's start address to function range
  // relevant info. Currently to determine if the offset of ELF/COFF is the
  // start of a real function, we leverage the function range info from DWARF.
  std::map<uint64_t, FuncRange> StartAddrToFuncRangeMap;

  // Address to context location map. Used to expand the context.
  std::unordered_map<uint64_t, SampleContextFrameVector> AddressToLocStackMap;

  // Address to instruction size map. Also used for quick Address lookup.
  std::unordered_map<uint64_t, uint64_t> AddressToInstSizeMap;

  // An array of Addresses of all instructions sorted in increasing order. The
  // sorting is needed to fast advance to the next forward/backward instruction.
  std::vector<uint64_t> CodeAddressVec;
  // A set of call instruction addresses. Used by virtual unwinding.
  std::unordered_set<uint64_t> CallAddressSet;
  // A set of return instruction addresses. Used by virtual unwinding.
  std::unordered_set<uint64_t> RetAddressSet;
  // An ordered set of unconditional branch instruction addresses.
  std::set<uint64_t> UncondBranchAddrSet;
  // A set of branch instruction addresses.
  std::unordered_set<uint64_t> BranchAddressSet;

  // Estimate and track function prolog and epilog ranges.
  PrologEpilogTracker ProEpilogTracker;

  // Infer missing frames due to compiler optimizations such as tail call
  // elimination.
  std::unique_ptr<MissingFrameInferrer> MissingContextInferrer;

  // Track function sizes under different context
  BinarySizeContextTracker FuncSizeTracker;

  // The symbolizer used to get inline context for an instruction.
  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;

  // String table owning function name strings created from the symbolizer.
  std::unordered_set<std::string> NameStrings;

  // MMap events for PT_LOAD segments without 'x' memory protection flag.
  std::map<uint64_t, MMapEvent, std::greater<uint64_t>> NonTextMMapEvents;

  // Records the file offset, file size and virtual address of program headers.
  struct PhdrInfo {
    uint64_t FileOffset;
    uint64_t FileSz;
    uint64_t VirtualAddr;
  };

  // Program header information for non-text PT_LOAD segments.
  SmallVector<PhdrInfo> NonTextPhdrInfo;

  // A collection of functions to print disassembly for.
  StringSet<> DisassembleFunctionSet;

  // Pseudo probe decoder
  MCPseudoProbeDecoder ProbeDecoder;

  // Function name to probe frame map for top-level outlined functions.
  StringMap<MCDecodedPseudoProbeInlineTree *> TopLevelProbeFrameMap;

  bool UsePseudoProbes = false;

  bool UseFSDiscriminator = false;

  // Whether we need to symbolize all instructions to get function context size.
  bool TrackFuncContextSize = false;

  // Whether this is a kernel image;
  bool IsKernel = false;

  // Indicate if the base loading address is parsed from the mmap event or uses
  // the preferred address
  bool IsLoadedByMMap = false;
  // Use to avoid redundant warning.
  bool MissingMMapWarned = false;

  bool IsCOFF = false;

  void setPreferredTextSegmentAddresses(const object::ObjectFile *O);

  // LLVMSymbolizer's symbolize{Code, Data} interfaces requires a section index
  // for each address to be symbolized. This is a helper function to
  // construct a SectionedAddress object with the given address and section
  // index. The section index is set to UndefSection by default.
  static object::SectionedAddress getSectionedAddress(
      uint64_t Address,
      uint64_t SectionIndex = object::SectionedAddress::UndefSection) {
    return object::SectionedAddress{Address, SectionIndex};
  }

  template <class ELFT>
  void setPreferredTextSegmentAddresses(const object::ELFFile<ELFT> &Obj,
                                        StringRef FileName);
  void setPreferredTextSegmentAddresses(const object::COFFObjectFile *Obj,
                                        StringRef FileName);

  void checkPseudoProbe(const object::ObjectFile *Obj);

  void decodePseudoProbe(const object::ObjectFile *Obj);

  void checkUseFSDiscriminator(
      const object::ObjectFile *Obj,
      std::map<object::SectionRef, SectionSymbolsTy> &AllSymbols);

  // Set up disassembler and related components.
  void setUpDisassembler(const object::ObjectFile *Obj);
  symbolize::LLVMSymbolizer::Options getSymbolizerOpts() const;

  // Load debug info of subprograms from DWARF section.
  void loadSymbolsFromDWARF(object::ObjectFile &Obj);

  // Load debug info from DWARF unit.
  void loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit);

  // Create symbol to its start address mapping.
  void populateSymbolAddressList(const object::ObjectFile *O);

  // Load functions from its symbol table (when DWARF info is missing).
  void loadSymbolsFromSymtab(const object::ObjectFile *O);

  // A function may be spilt into multiple non-continuous address ranges. We use
  // this to set whether start a function range is the real entry of the
  // function and also set false to the non-function label.
  void setIsFuncEntry(FuncRange *FRange, StringRef RangeSymName);

  // Warn if no entry range exists in the function.
  void warnNoFuncEntry();

  /// Dissassemble the text section and build various address maps.
  void disassemble(const object::ObjectFile *O);

  /// Helper function to dissassemble the symbol and extract info for unwinding
  bool dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes,
                          SectionSymbolsTy &Symbols,
                          const object::SectionRef &Section);
  /// Symbolize a given instruction pointer and return a full call context.
  SampleContextFrameVector symbolize(const InstructionPointer &IP,
                                     bool UseCanonicalFnName = false,
                                     bool UseProbeDiscriminator = false);
  /// Decode the interesting parts of the binary and build internal data
  /// structures. On high level, the parts of interest are:
  ///   1. Text sections, including the main code section and the PLT
  ///   entries that will be used to handle cross-module call transitions.
  ///   2. The .debug_line section, used by Dwarf-based profile generation.
  ///   3. Pseudo probe related sections, used by probe-based profile
  ///   generation.
  void load();

public:
  ProfiledBinary(const StringRef ExeBinPath, const StringRef DebugBinPath);
  ~ProfiledBinary();

  /// Symbolize an address and return the symbol name. The returned StringRef is
  /// owned by this ProfiledBinary object.
  StringRef symbolizeDataAddress(uint64_t Address);

  void decodePseudoProbe();

  StringRef getPath() const { return Path; }
  StringRef getName() const { return llvm::sys::path::filename(Path); }
  uint64_t getBaseAddress() const { return BaseAddress; }
  void setBaseAddress(uint64_t Address) { BaseAddress = Address; }

  bool isCOFF() const { return IsCOFF; }

  // Canonicalize to use preferred load address as base address.
  uint64_t canonicalizeVirtualAddress(uint64_t Address) {
    return Address - BaseAddress + getPreferredBaseAddress();
  }
  // Return the preferred load address for the first executable segment.
  uint64_t getPreferredBaseAddress() const {
    return PreferredTextSegmentAddresses[0];
  }
  // Return the preferred load address for the first loadable segment.
  uint64_t getFirstLoadableAddress() const { return FirstLoadableAddress; }
  // Return the file offset for the first executable segment.
  uint64_t getTextSegmentOffset() const { return TextSegmentOffsets[0]; }
  const std::vector<uint64_t> &getPreferredTextSegmentAddresses() const {
    return PreferredTextSegmentAddresses;
  }
  const std::vector<uint64_t> &getTextSegmentOffsets() const {
    return TextSegmentOffsets;
  }

  uint64_t getInstSize(uint64_t Address) const {
    auto I = AddressToInstSizeMap.find(Address);
    if (I == AddressToInstSizeMap.end())
      return 0;
    return I->second;
  }

  bool addressIsCode(uint64_t Address) const {
    return AddressToInstSizeMap.find(Address) != AddressToInstSizeMap.end();
  }

  bool addressIsCall(uint64_t Address) const {
    return CallAddressSet.count(Address);
  }
  bool addressIsReturn(uint64_t Address) const {
    return RetAddressSet.count(Address);
  }
  bool addressInPrologEpilog(uint64_t Address) const {
    return ProEpilogTracker.PrologEpilogSet.count(Address);
  }

  bool addressIsTransfer(uint64_t Address) {
    return BranchAddressSet.count(Address) || RetAddressSet.count(Address) ||
           CallAddressSet.count(Address);
  }

  bool rangeCrossUncondBranch(uint64_t Start, uint64_t End) {
    if (Start >= End)
      return false;
    auto R = UncondBranchAddrSet.lower_bound(Start);
    return R != UncondBranchAddrSet.end() && *R < End;
  }

  uint64_t getAddressforIndex(uint64_t Index) const {
    return CodeAddressVec[Index];
  }

  size_t getCodeAddrVecSize() const { return CodeAddressVec.size(); }

  bool usePseudoProbes() const { return UsePseudoProbes; }
  bool useFSDiscriminator() const { return UseFSDiscriminator; }
  bool isKernel() const { return IsKernel; }

  static bool isKernelImageName(StringRef BinaryName) {
    return BinaryName == "[kernel.kallsyms]" ||
           BinaryName == "[kernel.kallsyms]_stext" ||
           BinaryName == "[kernel.kallsyms]_text";
  }

  // Get the index in CodeAddressVec for the address
  // As we might get an address which is not the code
  // here it would round to the next valid code address by
  // using lower bound operation
  uint32_t getIndexForAddr(uint64_t Address) const {
    auto Low = llvm::lower_bound(CodeAddressVec, Address);
    return Low - CodeAddressVec.begin();
  }

  uint64_t getCallAddrFromFrameAddr(uint64_t FrameAddr) const {
    if (FrameAddr == ExternalAddr)
      return ExternalAddr;
    auto I = getIndexForAddr(FrameAddr);
    FrameAddr = I ? getAddressforIndex(I - 1) : 0;
    if (FrameAddr && addressIsCall(FrameAddr))
      return FrameAddr;
    return 0;
  }

  FuncRange *findFuncRangeForStartAddr(uint64_t Address) {
    auto I = StartAddrToFuncRangeMap.find(Address);
    if (I == StartAddrToFuncRangeMap.end())
      return nullptr;
    return &I->second;
  }

  // Binary search the function range which includes the input address.
  FuncRange *findFuncRange(uint64_t Address) {
    auto I = StartAddrToFuncRangeMap.upper_bound(Address);
    if (I == StartAddrToFuncRangeMap.begin())
      return nullptr;
    I--;

    if (Address >= I->second.EndAddress)
      return nullptr;

    return &I->second;
  }

  // Get all ranges of one function.
  RangesTy getRanges(uint64_t Address) {
    auto *FRange = findFuncRange(Address);
    // Ignore the range which falls into plt section or system lib.
    if (!FRange)
      return RangesTy();

    return FRange->Func->Ranges;
  }

  const std::unordered_map<std::string, BinaryFunction> &
  getAllBinaryFunctions() {
    return BinaryFunctions;
  }

  std::unordered_set<const BinaryFunction *> &getProfiledFunctions() {
    return ProfiledFunctions;
  }

  void setProfiledFunctions(std::unordered_set<const BinaryFunction *> &Funcs) {
    ProfiledFunctions = Funcs;
  }

  BinaryFunction *getBinaryFunction(FunctionId FName) {
    if (FName.isStringRef()) {
      auto I = BinaryFunctions.find(FName.str());
      if (I == BinaryFunctions.end())
        return nullptr;
      return &I->second;
    }
    auto I = HashBinaryFunctions.find(FName.getHashCode());
    if (I == HashBinaryFunctions.end())
      return nullptr;
    return I->second;
  }

  uint32_t getFuncSizeForContext(const ContextTrieNode *ContextNode) {
    return FuncSizeTracker.getFuncSizeForContext(ContextNode);
  }

  void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
                          SmallVectorImpl<uint64_t> &NewContext);

  // Load the symbols from debug table and populate into symbol list.
  void populateSymbolListFromDWARF(ProfileSymbolList &SymbolList);

  SampleContextFrameVector
  getFrameLocationStack(uint64_t Address, bool UseProbeDiscriminator = false) {
    InstructionPointer IP(this, Address);
    return symbolize(IP, SymbolizerOpts.UseSymbolTable, UseProbeDiscriminator);
  }

  const SampleContextFrameVector &
  getCachedFrameLocationStack(uint64_t Address,
                              bool UseProbeDiscriminator = false) {
    auto I = AddressToLocStackMap.emplace(Address, SampleContextFrameVector());
    if (I.second) {
      I.first->second = getFrameLocationStack(Address, UseProbeDiscriminator);
    }
    return I.first->second;
  }

  std::optional<SampleContextFrame> getInlineLeafFrameLoc(uint64_t Address) {
    const auto &Stack = getCachedFrameLocationStack(Address);
    if (Stack.empty())
      return {};
    return Stack.back();
  }

  void flushSymbolizer() { Symbolizer.reset(); }

  MissingFrameInferrer *getMissingContextInferrer() {
    return MissingContextInferrer.get();
  }

  // Compare two addresses' inline context
  bool inlineContextEqual(uint64_t Add1, uint64_t Add2);

  // Get the full context of the current stack with inline context filled in.
  // It will search the disassembling info stored in AddressToLocStackMap. This
  // is used as the key of function sample map
  SampleContextFrameVector
  getExpandedContext(const SmallVectorImpl<uint64_t> &Stack,
                     bool &WasLeafInlined);
  // Go through instructions among the given range and record its size for the
  // inline context.
  void computeInlinedContextSizeForRange(uint64_t StartAddress,
                                         uint64_t EndAddress);

  void computeInlinedContextSizeForFunc(const BinaryFunction *Func);

  void loadSymbolsFromPseudoProbe();

  StringRef findPseudoProbeName(const BinaryFunction *Func);

  const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const {
    return ProbeDecoder.getCallProbeForAddr(Address);
  }

  void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe,
                                SampleContextFrameVector &InlineContextStack,
                                bool IncludeLeaf = false) const {
    SmallVector<MCPseudoProbeFrameLocation, 16> ProbeInlineContext;
    ProbeDecoder.getInlineContextForProbe(Probe, ProbeInlineContext,
                                          IncludeLeaf);
    for (uint32_t I = 0; I < ProbeInlineContext.size(); I++) {
      auto &Callsite = ProbeInlineContext[I];
      // Clear the current context for an unknown probe.
      if (Callsite.second == 0 && I != ProbeInlineContext.size() - 1) {
        InlineContextStack.clear();
        continue;
      }
      InlineContextStack.emplace_back(FunctionId(Callsite.first),
                                      LineLocation(Callsite.second, 0));
    }
  }
  const AddressProbesMap &getAddress2ProbesMap() const {
    return ProbeDecoder.getAddress2ProbesMap();
  }
  const MCPseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) {
    return ProbeDecoder.getFuncDescForGUID(GUID);
  }

  const MCPseudoProbeFuncDesc *
  getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) {
    return ProbeDecoder.getInlinerDescForProbe(Probe);
  }

  bool isNonOverlappingAddressInterval(std::pair<uint64_t, uint64_t> LHS,
                                       std::pair<uint64_t, uint64_t> RHS) {
    if (LHS.second <= RHS.first || RHS.second <= LHS.first)
      return true;
    return false;
  }

  Error addMMapNonTextEvent(MMapEvent Event) {
    // Given the mmap events of the profiled binary, the virtual address
    // intervals of mmaps most often doesn't overlap with each other. The
    // implementation validates so, and runtime data address is mapped to
    // a mmap event using look-up. With this implementation, data addresses
    // from dynamic shared libraries (not the profiled binary) are not mapped or
    // symbolized. To map runtime address to binary address in case of
    // overlapping mmap events, the implementation could store all the mmap
    // events in a vector and in the order they are added and reverse iterate
    // the vector to find the mmap events. We opt'ed for the non-overlapping
    // implementation for simplicity.
    for (const auto &ExistingMMap : NonTextMMapEvents) {
      if (isNonOverlappingAddressInterval(
              {ExistingMMap.second.Address,
               ExistingMMap.second.Address + ExistingMMap.second.Size},
              {Event.Address, Event.Address + Event.Size})) {
        continue;
      }
      return createStringError(
          inconvertibleErrorCode(),
          "Non-text mmap event overlaps with existing event at address: %lx",
          Event.Address);
    }
    NonTextMMapEvents[Event.Address] = Event;
    return Error::success();
  }

  // Given a non-text runtime address, canonicalize it to the virtual address in
  // the binary.
  // TODO: Consider unifying the canonicalization of text and non-text addresses
  // in the ProfiledBinary class.
  uint64_t CanonicalizeNonTextAddress(uint64_t Address);

  bool getTrackFuncContextSize() { return TrackFuncContextSize; }

  bool getIsLoadedByMMap() { return IsLoadedByMMap; }

  void setIsLoadedByMMap(bool Value) { IsLoadedByMMap = Value; }

  bool getMissingMMapWarned() { return MissingMMapWarned; }

  void setMissingMMapWarned(bool Value) { MissingMMapWarned = Value; }
};

} // end namespace sampleprof
} // end namespace llvm

#endif
