brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.1 KiB · 5a814b7 Raw
690 lines · c
1//===-- ProfiledBinary.h - Binary decoder -----------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_TOOLS_LLVM_PROFGEN_PROFILEDBINARY_H10#define LLVM_TOOLS_LLVM_PROFGEN_PROFILEDBINARY_H11 12#include "CallContext.h"13#include "ErrorHandling.h"14#include "llvm/ADT/DenseMap.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/StringSet.h"17#include "llvm/DebugInfo/DWARF/DWARFContext.h"18#include "llvm/DebugInfo/Symbolize/Symbolize.h"19#include "llvm/MC/MCAsmInfo.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCDisassembler/MCDisassembler.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstPrinter.h"24#include "llvm/MC/MCInstrAnalysis.h"25#include "llvm/MC/MCInstrInfo.h"26#include "llvm/MC/MCObjectFileInfo.h"27#include "llvm/MC/MCPseudoProbe.h"28#include "llvm/MC/MCRegisterInfo.h"29#include "llvm/MC/MCSubtargetInfo.h"30#include "llvm/MC/MCTargetOptions.h"31#include "llvm/Object/ELFObjectFile.h"32#include "llvm/ProfileData/SampleProf.h"33#include "llvm/Support/CommandLine.h"34#include "llvm/Support/Path.h"35#include "llvm/Transforms/IPO/SampleContextTracker.h"36#include <map>37#include <set>38#include <sstream>39#include <string>40#include <unordered_map>41#include <unordered_set>42#include <vector>43 44namespace llvm {45namespace sampleprof {46 47class ProfiledBinary;48class MissingFrameInferrer;49 50struct InstructionPointer {51  const ProfiledBinary *Binary;52  // Address of the executable segment of the binary.53  uint64_t Address;54  // Index to the sorted code address array of the binary.55  uint64_t Index = 0;56  InstructionPointer(const ProfiledBinary *Binary, uint64_t Address,57                     bool RoundToNext = false);58  bool advance();59  bool backward();60  void update(uint64_t Addr);61};62 63// The special frame addresses.64enum SpecialFrameAddr {65  // Dummy root of frame trie.66  DummyRoot = 0,67  // Represent all the addresses outside of current binary.68  // This's also used to indicate the call stack should be truncated since this69  // isn't a real call context the compiler will see.70  ExternalAddr = 1,71};72 73using RangesTy = std::vector<std::pair<uint64_t, uint64_t>>;74 75struct BinaryFunction {76  StringRef FuncName;77  // End of range is an exclusive bound.78  RangesTy Ranges;79 80  uint64_t getFuncSize() {81    uint64_t Sum = 0;82    for (auto &R : Ranges) {83      Sum += R.second - R.first;84    }85    return Sum;86  }87};88 89// Info about function range. A function can be split into multiple90// non-continuous ranges, each range corresponds to one FuncRange.91struct FuncRange {92  uint64_t StartAddress;93  // EndAddress is an exclusive bound.94  uint64_t EndAddress;95  // Function the range belongs to96  BinaryFunction *Func;97  // Whether the start address is the real entry of the function.98  bool IsFuncEntry = false;99 100  StringRef getFuncName() { return Func->FuncName; }101};102 103// PrologEpilog address tracker, used to filter out broken stack samples104// Currently we use a heuristic size (two) to infer prolog and epilog105// based on the start address and return address. In the future,106// we will switch to Dwarf CFI based tracker107struct PrologEpilogTracker {108  // A set of prolog and epilog addresses. Used by virtual unwinding.109  std::unordered_set<uint64_t> PrologEpilogSet;110  ProfiledBinary *Binary;111  PrologEpilogTracker(ProfiledBinary *Bin) : Binary(Bin){};112 113  // Take the two addresses from the start of function as prolog114  void115  inferPrologAddresses(std::map<uint64_t, FuncRange> &FuncStartAddressMap) {116    for (auto I : FuncStartAddressMap) {117      PrologEpilogSet.insert(I.first);118      InstructionPointer IP(Binary, I.first);119      if (!IP.advance())120        break;121      PrologEpilogSet.insert(IP.Address);122    }123  }124 125  // Take the last two addresses before the return address as epilog126  void inferEpilogAddresses(std::unordered_set<uint64_t> &RetAddrs) {127    for (auto Addr : RetAddrs) {128      PrologEpilogSet.insert(Addr);129      InstructionPointer IP(Binary, Addr);130      if (!IP.backward())131        break;132      PrologEpilogSet.insert(IP.Address);133    }134  }135};136 137// Track function byte size under different context (outlined version as well as138// various inlined versions). It also provides query support to get function139// size with the best matching context, which is used to help pre-inliner use140// accurate post-optimization size to make decisions.141// TODO: If an inlinee is completely optimized away, ideally we should have zero142// for its context size, currently we would misss such context since it doesn't143// have instructions. To fix this, we need to mark all inlinee with entry probe144// but without instructions as having zero size.145class BinarySizeContextTracker {146public:147  // Add instruction with given size to a context148  void addInstructionForContext(const SampleContextFrameVector &Context,149                                uint32_t InstrSize);150 151  // Get function size with a specific context. When there's no exact match152  // for the given context, try to retrieve the size of that function from153  // closest matching context.154  uint32_t getFuncSizeForContext(const ContextTrieNode *Context);155 156  // For inlinees that are full optimized away, we can establish zero size using157  // their remaining probes.158  void trackInlineesOptimizedAway(MCPseudoProbeDecoder &ProbeDecoder);159 160  using ProbeFrameStack = SmallVector<std::pair<StringRef, uint32_t>>;161  void162  trackInlineesOptimizedAway(MCPseudoProbeDecoder &ProbeDecoder,163                             const MCDecodedPseudoProbeInlineTree &ProbeNode,164                             ProbeFrameStack &Context);165 166  void dump() { RootContext.dumpTree(); }167 168private:169  // Root node for context trie tree, node that this is a reverse context trie170  // with callee as parent and caller as child. This way we can traverse from171  // root to find the best/longest matching context if an exact match does not172  // exist. It gives us the best possible estimate for function's post-inline,173  // post-optimization byte size.174  ContextTrieNode RootContext;175};176 177using AddressRange = std::pair<uint64_t, uint64_t>;178 179// The parsed MMap event180struct MMapEvent {181  int64_t PID = 0;182  uint64_t Address = 0;183  uint64_t Size = 0;184  uint64_t Offset = 0;185  StringRef MemProtectionFlag;186  StringRef BinaryPath;187};188 189class ProfiledBinary {190  // Absolute path of the executable binary.191  std::string Path;192  // Path of the debug info binary.193  std::string DebugBinaryPath;194  // The target triple.195  Triple TheTriple;196  // Path of symbolizer path which should be pointed to binary with debug info.197  StringRef SymbolizerPath;198  // Options used to configure the symbolizer199  symbolize::LLVMSymbolizer::Options SymbolizerOpts;200  // The runtime base address that the first executable segment is loaded at.201  uint64_t BaseAddress = 0;202  // The runtime base address that the first loadabe segment is loaded at.203  uint64_t FirstLoadableAddress = 0;204  // The preferred load address of each executable segment.205  std::vector<uint64_t> PreferredTextSegmentAddresses;206  // The file offset of each executable segment.207  std::vector<uint64_t> TextSegmentOffsets;208 209  // Mutiple MC component info210  std::unique_ptr<const MCRegisterInfo> MRI;211  std::unique_ptr<const MCAsmInfo> AsmInfo;212  std::unique_ptr<const MCSubtargetInfo> STI;213  std::unique_ptr<const MCInstrInfo> MII;214  std::unique_ptr<MCDisassembler> DisAsm;215  std::unique_ptr<const MCInstrAnalysis> MIA;216  std::unique_ptr<MCInstPrinter> IPrinter;217  // A list of text sections sorted by start RVA and size. Used to check218  // if a given RVA is a valid code address.219  std::set<std::pair<uint64_t, uint64_t>> TextSections;220 221  // A map of mapping function name to BinaryFunction info.222  std::unordered_map<std::string, BinaryFunction> BinaryFunctions;223 224  // Lookup BinaryFunctions using the function name's MD5 hash. Needed if the225  // profile is using MD5.226  std::unordered_map<uint64_t, BinaryFunction *> HashBinaryFunctions;227 228  // A list of binary functions that have samples.229  std::unordered_set<const BinaryFunction *> ProfiledFunctions;230 231  // GUID to symbol start address map232  DenseMap<uint64_t, uint64_t> SymbolStartAddrs;233 234  // These maps are for temporary use of warning diagnosis.235  DenseSet<int64_t> AddrsWithMultipleSymbols;236  DenseSet<std::pair<uint64_t, uint64_t>> AddrsWithInvalidInstruction;237 238  // Start address to symbol GUID map239  std::unordered_multimap<uint64_t, uint64_t> StartAddrToSymMap;240 241  // An ordered map of mapping function's start address to function range242  // relevant info. Currently to determine if the offset of ELF/COFF is the243  // start of a real function, we leverage the function range info from DWARF.244  std::map<uint64_t, FuncRange> StartAddrToFuncRangeMap;245 246  // Address to context location map. Used to expand the context.247  std::unordered_map<uint64_t, SampleContextFrameVector> AddressToLocStackMap;248 249  // Address to instruction size map. Also used for quick Address lookup.250  std::unordered_map<uint64_t, uint64_t> AddressToInstSizeMap;251 252  // An array of Addresses of all instructions sorted in increasing order. The253  // sorting is needed to fast advance to the next forward/backward instruction.254  std::vector<uint64_t> CodeAddressVec;255  // A set of call instruction addresses. Used by virtual unwinding.256  std::unordered_set<uint64_t> CallAddressSet;257  // A set of return instruction addresses. Used by virtual unwinding.258  std::unordered_set<uint64_t> RetAddressSet;259  // An ordered set of unconditional branch instruction addresses.260  std::set<uint64_t> UncondBranchAddrSet;261  // A set of branch instruction addresses.262  std::unordered_set<uint64_t> BranchAddressSet;263 264  // Estimate and track function prolog and epilog ranges.265  PrologEpilogTracker ProEpilogTracker;266 267  // Infer missing frames due to compiler optimizations such as tail call268  // elimination.269  std::unique_ptr<MissingFrameInferrer> MissingContextInferrer;270 271  // Track function sizes under different context272  BinarySizeContextTracker FuncSizeTracker;273 274  // The symbolizer used to get inline context for an instruction.275  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;276 277  // String table owning function name strings created from the symbolizer.278  std::unordered_set<std::string> NameStrings;279 280  // MMap events for PT_LOAD segments without 'x' memory protection flag.281  std::map<uint64_t, MMapEvent, std::greater<uint64_t>> NonTextMMapEvents;282 283  // Records the file offset, file size and virtual address of program headers.284  struct PhdrInfo {285    uint64_t FileOffset;286    uint64_t FileSz;287    uint64_t VirtualAddr;288  };289 290  // Program header information for non-text PT_LOAD segments.291  SmallVector<PhdrInfo> NonTextPhdrInfo;292 293  // A collection of functions to print disassembly for.294  StringSet<> DisassembleFunctionSet;295 296  // Pseudo probe decoder297  MCPseudoProbeDecoder ProbeDecoder;298 299  // Function name to probe frame map for top-level outlined functions.300  StringMap<MCDecodedPseudoProbeInlineTree *> TopLevelProbeFrameMap;301 302  bool UsePseudoProbes = false;303 304  bool UseFSDiscriminator = false;305 306  // Whether we need to symbolize all instructions to get function context size.307  bool TrackFuncContextSize = false;308 309  // Whether this is a kernel image;310  bool IsKernel = false;311 312  // Indicate if the base loading address is parsed from the mmap event or uses313  // the preferred address314  bool IsLoadedByMMap = false;315  // Use to avoid redundant warning.316  bool MissingMMapWarned = false;317 318  bool IsCOFF = false;319 320  void setPreferredTextSegmentAddresses(const object::ObjectFile *O);321 322  // LLVMSymbolizer's symbolize{Code, Data} interfaces requires a section index323  // for each address to be symbolized. This is a helper function to324  // construct a SectionedAddress object with the given address and section325  // index. The section index is set to UndefSection by default.326  static object::SectionedAddress getSectionedAddress(327      uint64_t Address,328      uint64_t SectionIndex = object::SectionedAddress::UndefSection) {329    return object::SectionedAddress{Address, SectionIndex};330  }331 332  template <class ELFT>333  void setPreferredTextSegmentAddresses(const object::ELFFile<ELFT> &Obj,334                                        StringRef FileName);335  void setPreferredTextSegmentAddresses(const object::COFFObjectFile *Obj,336                                        StringRef FileName);337 338  void checkPseudoProbe(const object::ObjectFile *Obj);339 340  void decodePseudoProbe(const object::ObjectFile *Obj);341 342  void checkUseFSDiscriminator(343      const object::ObjectFile *Obj,344      std::map<object::SectionRef, SectionSymbolsTy> &AllSymbols);345 346  // Set up disassembler and related components.347  void setUpDisassembler(const object::ObjectFile *Obj);348  symbolize::LLVMSymbolizer::Options getSymbolizerOpts() const;349 350  // Load debug info of subprograms from DWARF section.351  void loadSymbolsFromDWARF(object::ObjectFile &Obj);352 353  // Load debug info from DWARF unit.354  void loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit);355 356  // Create symbol to its start address mapping.357  void populateSymbolAddressList(const object::ObjectFile *O);358 359  // A function may be spilt into multiple non-continuous address ranges. We use360  // this to set whether start a function range is the real entry of the361  // function and also set false to the non-function label.362  void setIsFuncEntry(FuncRange *FRange, StringRef RangeSymName);363 364  // Warn if no entry range exists in the function.365  void warnNoFuncEntry();366 367  /// Dissassemble the text section and build various address maps.368  void disassemble(const object::ObjectFile *O);369 370  /// Helper function to dissassemble the symbol and extract info for unwinding371  bool dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes,372                          SectionSymbolsTy &Symbols,373                          const object::SectionRef &Section);374  /// Symbolize a given instruction pointer and return a full call context.375  SampleContextFrameVector symbolize(const InstructionPointer &IP,376                                     bool UseCanonicalFnName = false,377                                     bool UseProbeDiscriminator = false);378  /// Decode the interesting parts of the binary and build internal data379  /// structures. On high level, the parts of interest are:380  ///   1. Text sections, including the main code section and the PLT381  ///   entries that will be used to handle cross-module call transitions.382  ///   2. The .debug_line section, used by Dwarf-based profile generation.383  ///   3. Pseudo probe related sections, used by probe-based profile384  ///   generation.385  void load();386 387public:388  ProfiledBinary(const StringRef ExeBinPath, const StringRef DebugBinPath);389  ~ProfiledBinary();390 391  /// Symbolize an address and return the symbol name. The returned StringRef is392  /// owned by this ProfiledBinary object.393  StringRef symbolizeDataAddress(uint64_t Address);394 395  void decodePseudoProbe();396 397  StringRef getPath() const { return Path; }398  StringRef getName() const { return llvm::sys::path::filename(Path); }399  uint64_t getBaseAddress() const { return BaseAddress; }400  void setBaseAddress(uint64_t Address) { BaseAddress = Address; }401 402  bool isCOFF() const { return IsCOFF; }403 404  // Canonicalize to use preferred load address as base address.405  uint64_t canonicalizeVirtualAddress(uint64_t Address) {406    return Address - BaseAddress + getPreferredBaseAddress();407  }408  // Return the preferred load address for the first executable segment.409  uint64_t getPreferredBaseAddress() const {410    return PreferredTextSegmentAddresses[0];411  }412  // Return the preferred load address for the first loadable segment.413  uint64_t getFirstLoadableAddress() const { return FirstLoadableAddress; }414  // Return the file offset for the first executable segment.415  uint64_t getTextSegmentOffset() const { return TextSegmentOffsets[0]; }416  const std::vector<uint64_t> &getPreferredTextSegmentAddresses() const {417    return PreferredTextSegmentAddresses;418  }419  const std::vector<uint64_t> &getTextSegmentOffsets() const {420    return TextSegmentOffsets;421  }422 423  uint64_t getInstSize(uint64_t Address) const {424    auto I = AddressToInstSizeMap.find(Address);425    if (I == AddressToInstSizeMap.end())426      return 0;427    return I->second;428  }429 430  bool addressIsCode(uint64_t Address) const {431    return AddressToInstSizeMap.find(Address) != AddressToInstSizeMap.end();432  }433 434  bool addressIsCall(uint64_t Address) const {435    return CallAddressSet.count(Address);436  }437  bool addressIsReturn(uint64_t Address) const {438    return RetAddressSet.count(Address);439  }440  bool addressInPrologEpilog(uint64_t Address) const {441    return ProEpilogTracker.PrologEpilogSet.count(Address);442  }443 444  bool addressIsTransfer(uint64_t Address) {445    return BranchAddressSet.count(Address) || RetAddressSet.count(Address) ||446           CallAddressSet.count(Address);447  }448 449  bool rangeCrossUncondBranch(uint64_t Start, uint64_t End) {450    if (Start >= End)451      return false;452    auto R = UncondBranchAddrSet.lower_bound(Start);453    return R != UncondBranchAddrSet.end() && *R < End;454  }455 456  uint64_t getAddressforIndex(uint64_t Index) const {457    return CodeAddressVec[Index];458  }459 460  size_t getCodeAddrVecSize() const { return CodeAddressVec.size(); }461 462  bool usePseudoProbes() const { return UsePseudoProbes; }463  bool useFSDiscriminator() const { return UseFSDiscriminator; }464  bool isKernel() const { return IsKernel; }465 466  static bool isKernelImageName(StringRef BinaryName) {467    return BinaryName == "[kernel.kallsyms]" ||468           BinaryName == "[kernel.kallsyms]_stext" ||469           BinaryName == "[kernel.kallsyms]_text";470  }471 472  // Get the index in CodeAddressVec for the address473  // As we might get an address which is not the code474  // here it would round to the next valid code address by475  // using lower bound operation476  uint32_t getIndexForAddr(uint64_t Address) const {477    auto Low = llvm::lower_bound(CodeAddressVec, Address);478    return Low - CodeAddressVec.begin();479  }480 481  uint64_t getCallAddrFromFrameAddr(uint64_t FrameAddr) const {482    if (FrameAddr == ExternalAddr)483      return ExternalAddr;484    auto I = getIndexForAddr(FrameAddr);485    FrameAddr = I ? getAddressforIndex(I - 1) : 0;486    if (FrameAddr && addressIsCall(FrameAddr))487      return FrameAddr;488    return 0;489  }490 491  FuncRange *findFuncRangeForStartAddr(uint64_t Address) {492    auto I = StartAddrToFuncRangeMap.find(Address);493    if (I == StartAddrToFuncRangeMap.end())494      return nullptr;495    return &I->second;496  }497 498  // Binary search the function range which includes the input address.499  FuncRange *findFuncRange(uint64_t Address) {500    auto I = StartAddrToFuncRangeMap.upper_bound(Address);501    if (I == StartAddrToFuncRangeMap.begin())502      return nullptr;503    I--;504 505    if (Address >= I->second.EndAddress)506      return nullptr;507 508    return &I->second;509  }510 511  // Get all ranges of one function.512  RangesTy getRanges(uint64_t Address) {513    auto *FRange = findFuncRange(Address);514    // Ignore the range which falls into plt section or system lib.515    if (!FRange)516      return RangesTy();517 518    return FRange->Func->Ranges;519  }520 521  const std::unordered_map<std::string, BinaryFunction> &522  getAllBinaryFunctions() {523    return BinaryFunctions;524  }525 526  std::unordered_set<const BinaryFunction *> &getProfiledFunctions() {527    return ProfiledFunctions;528  }529 530  void setProfiledFunctions(std::unordered_set<const BinaryFunction *> &Funcs) {531    ProfiledFunctions = Funcs;532  }533 534  BinaryFunction *getBinaryFunction(FunctionId FName) {535    if (FName.isStringRef()) {536      auto I = BinaryFunctions.find(FName.str());537      if (I == BinaryFunctions.end())538        return nullptr;539      return &I->second;540    }541    auto I = HashBinaryFunctions.find(FName.getHashCode());542    if (I == HashBinaryFunctions.end())543      return nullptr;544    return I->second;545  }546 547  uint32_t getFuncSizeForContext(const ContextTrieNode *ContextNode) {548    return FuncSizeTracker.getFuncSizeForContext(ContextNode);549  }550 551  void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,552                          SmallVectorImpl<uint64_t> &NewContext);553 554  // Load the symbols from debug table and populate into symbol list.555  void populateSymbolListFromDWARF(ProfileSymbolList &SymbolList);556 557  SampleContextFrameVector558  getFrameLocationStack(uint64_t Address, bool UseProbeDiscriminator = false) {559    InstructionPointer IP(this, Address);560    return symbolize(IP, SymbolizerOpts.UseSymbolTable, UseProbeDiscriminator);561  }562 563  const SampleContextFrameVector &564  getCachedFrameLocationStack(uint64_t Address,565                              bool UseProbeDiscriminator = false) {566    auto I = AddressToLocStackMap.emplace(Address, SampleContextFrameVector());567    if (I.second) {568      I.first->second = getFrameLocationStack(Address, UseProbeDiscriminator);569    }570    return I.first->second;571  }572 573  std::optional<SampleContextFrame> getInlineLeafFrameLoc(uint64_t Address) {574    const auto &Stack = getCachedFrameLocationStack(Address);575    if (Stack.empty())576      return {};577    return Stack.back();578  }579 580  void flushSymbolizer() { Symbolizer.reset(); }581 582  MissingFrameInferrer *getMissingContextInferrer() {583    return MissingContextInferrer.get();584  }585 586  // Compare two addresses' inline context587  bool inlineContextEqual(uint64_t Add1, uint64_t Add2);588 589  // Get the full context of the current stack with inline context filled in.590  // It will search the disassembling info stored in AddressToLocStackMap. This591  // is used as the key of function sample map592  SampleContextFrameVector593  getExpandedContext(const SmallVectorImpl<uint64_t> &Stack,594                     bool &WasLeafInlined);595  // Go through instructions among the given range and record its size for the596  // inline context.597  void computeInlinedContextSizeForRange(uint64_t StartAddress,598                                         uint64_t EndAddress);599 600  void computeInlinedContextSizeForFunc(const BinaryFunction *Func);601 602  const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const {603    return ProbeDecoder.getCallProbeForAddr(Address);604  }605 606  void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe,607                                SampleContextFrameVector &InlineContextStack,608                                bool IncludeLeaf = false) const {609    SmallVector<MCPseudoProbeFrameLocation, 16> ProbeInlineContext;610    ProbeDecoder.getInlineContextForProbe(Probe, ProbeInlineContext,611                                          IncludeLeaf);612    for (uint32_t I = 0; I < ProbeInlineContext.size(); I++) {613      auto &Callsite = ProbeInlineContext[I];614      // Clear the current context for an unknown probe.615      if (Callsite.second == 0 && I != ProbeInlineContext.size() - 1) {616        InlineContextStack.clear();617        continue;618      }619      InlineContextStack.emplace_back(FunctionId(Callsite.first),620                                      LineLocation(Callsite.second, 0));621    }622  }623  const AddressProbesMap &getAddress2ProbesMap() const {624    return ProbeDecoder.getAddress2ProbesMap();625  }626  const MCPseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) {627    return ProbeDecoder.getFuncDescForGUID(GUID);628  }629 630  const MCPseudoProbeFuncDesc *631  getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) {632    return ProbeDecoder.getInlinerDescForProbe(Probe);633  }634 635  bool isNonOverlappingAddressInterval(std::pair<uint64_t, uint64_t> LHS,636                                       std::pair<uint64_t, uint64_t> RHS) {637    if (LHS.second <= RHS.first || RHS.second <= LHS.first)638      return true;639    return false;640  }641 642  Error addMMapNonTextEvent(MMapEvent Event) {643    // Given the mmap events of the profiled binary, the virtual address644    // intervals of mmaps most often doesn't overlap with each other. The645    // implementation validates so, and runtime data address is mapped to646    // a mmap event using look-up. With this implementation, data addresses647    // from dynamic shared libraries (not the profiled binary) are not mapped or648    // symbolized. To map runtime address to binary address in case of649    // overlapping mmap events, the implementation could store all the mmap650    // events in a vector and in the order they are added and reverse iterate651    // the vector to find the mmap events. We opt'ed for the non-overlapping652    // implementation for simplicity.653    for (const auto &ExistingMMap : NonTextMMapEvents) {654      if (isNonOverlappingAddressInterval(655              {ExistingMMap.second.Address,656               ExistingMMap.second.Address + ExistingMMap.second.Size},657              {Event.Address, Event.Address + Event.Size})) {658        continue;659      }660      return createStringError(661          inconvertibleErrorCode(),662          "Non-text mmap event overlaps with existing event at address: %lx",663          Event.Address);664    }665    NonTextMMapEvents[Event.Address] = Event;666    return Error::success();667  }668 669  // Given a non-text runtime address, canonicalize it to the virtual address in670  // the binary.671  // TODO: Consider unifying the canonicalization of text and non-text addresses672  // in the ProfiledBinary class.673  uint64_t CanonicalizeNonTextAddress(uint64_t Address);674 675  bool getTrackFuncContextSize() { return TrackFuncContextSize; }676 677  bool getIsLoadedByMMap() { return IsLoadedByMMap; }678 679  void setIsLoadedByMMap(bool Value) { IsLoadedByMMap = Value; }680 681  bool getMissingMMapWarned() { return MissingMMapWarned; }682 683  void setMissingMMapWarned(bool Value) { MissingMMapWarned = Value; }684};685 686} // end namespace sampleprof687} // end namespace llvm688 689#endif690