1 //===- InstrProfCorrelator.h ------------------------------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // This file defines InstrProfCorrelator used to generate PGO profiles from 9 // raw profile data and debug info. 10 //===----------------------------------------------------------------------===// 11 12 #ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H 13 #define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H 14 15 #include "llvm/ADT/DenseSet.h" 16 #include "llvm/ProfileData/InstrProf.h" 17 #include "llvm/Support/Error.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include <vector> 20 21 namespace llvm { 22 class DWARFContext; 23 class DWARFDie; 24 namespace object { 25 class ObjectFile; 26 } 27 28 /// InstrProfCorrelator - A base class used to create raw instrumentation data 29 /// to their functions. 30 class InstrProfCorrelator { 31 public: 32 static llvm::Expected<std::unique_ptr<InstrProfCorrelator>> 33 get(StringRef DebugInfoFilename); 34 35 /// Construct a ProfileData vector used to correlate raw instrumentation data 36 /// to their functions. 37 virtual Error correlateProfileData() = 0; 38 39 /// Return the number of ProfileData elements. 40 llvm::Optional<size_t> getDataSize() const; 41 42 /// Return a pointer to the names string that this class constructs. 43 const char *getNamesPointer() const { return Names.c_str(); } 44 45 /// Return the number of bytes in the names string. 46 size_t getNamesSize() const { return Names.size(); } 47 48 /// Return the size of the counters section in bytes. 49 uint64_t getCountersSectionSize() const { 50 return Ctx->CountersSectionEnd - Ctx->CountersSectionStart; 51 } 52 53 static const char *FunctionNameAttributeName; 54 static const char *CFGHashAttributeName; 55 static const char *NumCountersAttributeName; 56 57 enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit }; 58 InstrProfCorrelatorKind getKind() const { return Kind; } 59 virtual ~InstrProfCorrelator() = default; 60 61 protected: 62 struct Context { 63 static llvm::Expected<std::unique_ptr<Context>> 64 get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj); 65 std::unique_ptr<MemoryBuffer> Buffer; 66 /// The address range of the __llvm_prf_cnts section. 67 uint64_t CountersSectionStart; 68 uint64_t CountersSectionEnd; 69 /// True if target and host have different endian orders. 70 bool ShouldSwapBytes; 71 }; 72 const std::unique_ptr<InstrProfCorrelator::Context> Ctx; 73 74 InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx) 75 : Ctx(std::move(Ctx)), Kind(K) {} 76 77 std::string Names; 78 std::vector<std::string> NamesVec; 79 80 private: 81 static llvm::Expected<std::unique_ptr<InstrProfCorrelator>> 82 get(std::unique_ptr<MemoryBuffer> Buffer); 83 84 const InstrProfCorrelatorKind Kind; 85 }; 86 87 /// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template 88 /// pointer type so that the ProfileData vector can be materialized. 89 template <class IntPtrT> 90 class InstrProfCorrelatorImpl : public InstrProfCorrelator { 91 public: 92 InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx); 93 static bool classof(const InstrProfCorrelator *C); 94 95 /// Return a pointer to the underlying ProfileData vector that this class 96 /// constructs. 97 const RawInstrProf::ProfileData<IntPtrT> *getDataPointer() const { 98 return Data.empty() ? nullptr : Data.data(); 99 } 100 101 /// Return the number of ProfileData elements. 102 size_t getDataSize() const { return Data.size(); } 103 104 static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>> 105 get(std::unique_ptr<InstrProfCorrelator::Context> Ctx, 106 const object::ObjectFile &Obj); 107 108 protected: 109 std::vector<RawInstrProf::ProfileData<IntPtrT>> Data; 110 111 Error correlateProfileData() override; 112 virtual void correlateProfileDataImpl() = 0; 113 114 void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, 115 IntPtrT FunctionPtr, uint32_t NumCounters); 116 117 private: 118 InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind, 119 std::unique_ptr<InstrProfCorrelator::Context> Ctx) 120 : InstrProfCorrelator(Kind, std::move(Ctx)){}; 121 llvm::DenseSet<IntPtrT> CounterOffsets; 122 123 // Byte-swap the value if necessary. 124 template <class T> T maybeSwap(T Value) const { 125 return Ctx->ShouldSwapBytes ? sys::getSwappedBytes(Value) : Value; 126 } 127 }; 128 129 /// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes 130 /// DWARF debug info as input to correlate profiles. 131 template <class IntPtrT> 132 class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> { 133 public: 134 DwarfInstrProfCorrelator(std::unique_ptr<DWARFContext> DICtx, 135 std::unique_ptr<InstrProfCorrelator::Context> Ctx) 136 : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)), 137 DICtx(std::move(DICtx)) {} 138 139 private: 140 std::unique_ptr<DWARFContext> DICtx; 141 142 /// Return the address of the object that the provided DIE symbolizes. 143 llvm::Optional<uint64_t> getLocation(const DWARFDie &Die) const; 144 145 /// Returns true if the provided DIE symbolizes an instrumentation probe 146 /// symbol. 147 static bool isDIEOfProbe(const DWARFDie &Die); 148 149 /// Iterate over DWARF DIEs to find those that symbolize instrumentation 150 /// probes and construct the ProfileData vector and Names string. 151 /// 152 /// Here is some example DWARF for an instrumentation probe we are looking 153 /// for: 154 /// \code 155 /// DW_TAG_subprogram 156 /// DW_AT_low_pc (0x0000000000000000) 157 /// DW_AT_high_pc (0x0000000000000014) 158 /// DW_AT_name ("foo") 159 /// DW_TAG_variable 160 /// DW_AT_name ("__profc_foo") 161 /// DW_AT_location (DW_OP_addr 0x0) 162 /// DW_TAG_LLVM_annotation 163 /// DW_AT_name ("Function Name") 164 /// DW_AT_const_value ("foo") 165 /// DW_TAG_LLVM_annotation 166 /// DW_AT_name ("CFG Hash") 167 /// DW_AT_const_value (12345678) 168 /// DW_TAG_LLVM_annotation 169 /// DW_AT_name ("Num Counters") 170 /// DW_AT_const_value (2) 171 /// NULL 172 /// NULL 173 /// \endcode 174 void correlateProfileDataImpl() override; 175 }; 176 177 } // end namespace llvm 178 179 #endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H 180