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/coverage profiles 9 // from raw profile data and debug info/binary file. 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 "llvm/Support/YAMLTraits.h" 20 #include <optional> 21 #include <vector> 22 23 namespace llvm { 24 class DWARFContext; 25 class DWARFDie; 26 namespace object { 27 class ObjectFile; 28 } 29 30 /// InstrProfCorrelator - A base class used to create raw instrumentation data 31 /// to their functions. 32 class InstrProfCorrelator { 33 public: 34 /// Indicate if we should use the debug info or profile metadata sections to 35 /// correlate. 36 enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY }; 37 38 static llvm::Expected<std::unique_ptr<InstrProfCorrelator>> 39 get(StringRef Filename, ProfCorrelatorKind FileKind); 40 41 /// Construct a ProfileData vector used to correlate raw instrumentation data 42 /// to their functions. 43 /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) 44 virtual Error correlateProfileData(int MaxWarnings) = 0; 45 46 /// Process debug info and dump the correlation data. 47 /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) 48 virtual Error dumpYaml(int MaxWarnings, raw_ostream &OS) = 0; 49 50 /// Return the number of ProfileData elements. 51 std::optional<size_t> getDataSize() const; 52 53 /// Return a pointer to the names string that this class constructs. 54 const char *getNamesPointer() const { return Names.c_str(); } 55 56 /// Return the number of bytes in the names string. 57 size_t getNamesSize() const { return Names.size(); } 58 59 /// Return the size of the counters section in bytes. 60 uint64_t getCountersSectionSize() const { 61 return Ctx->CountersSectionEnd - Ctx->CountersSectionStart; 62 } 63 64 static const char *FunctionNameAttributeName; 65 static const char *CFGHashAttributeName; 66 static const char *NumCountersAttributeName; 67 68 enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit }; 69 InstrProfCorrelatorKind getKind() const { return Kind; } 70 virtual ~InstrProfCorrelator() = default; 71 72 protected: 73 struct Context { 74 static llvm::Expected<std::unique_ptr<Context>> 75 get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj, 76 ProfCorrelatorKind FileKind); 77 std::unique_ptr<MemoryBuffer> Buffer; 78 /// The address range of the __llvm_prf_cnts section. 79 uint64_t CountersSectionStart; 80 uint64_t CountersSectionEnd; 81 /// The pointer points to start/end of profile data/name sections if 82 /// FileKind is Binary. 83 const char *DataStart; 84 const char *DataEnd; 85 const char *NameStart; 86 size_t NameSize; 87 /// True if target and host have different endian orders. 88 bool ShouldSwapBytes; 89 }; 90 const std::unique_ptr<Context> Ctx; 91 92 InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx) 93 : Ctx(std::move(Ctx)), Kind(K) {} 94 95 std::string Names; 96 std::vector<std::string> NamesVec; 97 98 struct Probe { 99 std::string FunctionName; 100 std::optional<std::string> LinkageName; 101 yaml::Hex64 CFGHash; 102 yaml::Hex64 CounterOffset; 103 uint32_t NumCounters; 104 std::optional<std::string> FilePath; 105 std::optional<int> LineNumber; 106 }; 107 108 struct CorrelationData { 109 std::vector<Probe> Probes; 110 }; 111 112 friend struct yaml::MappingTraits<Probe>; 113 friend struct yaml::SequenceElementTraits<Probe>; 114 friend struct yaml::MappingTraits<CorrelationData>; 115 116 private: 117 static llvm::Expected<std::unique_ptr<InstrProfCorrelator>> 118 get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind); 119 120 const InstrProfCorrelatorKind Kind; 121 }; 122 123 /// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template 124 /// pointer type so that the ProfileData vector can be materialized. 125 template <class IntPtrT> 126 class InstrProfCorrelatorImpl : public InstrProfCorrelator { 127 public: 128 InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx); 129 static bool classof(const InstrProfCorrelator *C); 130 131 /// Return a pointer to the underlying ProfileData vector that this class 132 /// constructs. 133 const RawInstrProf::ProfileData<IntPtrT> *getDataPointer() const { 134 return Data.empty() ? nullptr : Data.data(); 135 } 136 137 /// Return the number of ProfileData elements. 138 size_t getDataSize() const { return Data.size(); } 139 140 static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>> 141 get(std::unique_ptr<InstrProfCorrelator::Context> Ctx, 142 const object::ObjectFile &Obj, ProfCorrelatorKind FileKind); 143 144 protected: 145 std::vector<RawInstrProf::ProfileData<IntPtrT>> Data; 146 147 Error correlateProfileData(int MaxWarnings) override; 148 virtual void correlateProfileDataImpl( 149 int MaxWarnings, 150 InstrProfCorrelator::CorrelationData *Data = nullptr) = 0; 151 152 virtual Error correlateProfileNameImpl() = 0; 153 154 Error dumpYaml(int MaxWarnings, raw_ostream &OS) override; 155 156 void addDataProbe(uint64_t FunctionName, uint64_t CFGHash, 157 IntPtrT CounterOffset, IntPtrT FunctionPtr, 158 uint32_t NumCounters); 159 160 // Byte-swap the value if necessary. 161 template <class T> T maybeSwap(T Value) const { 162 return Ctx->ShouldSwapBytes ? llvm::byteswap(Value) : Value; 163 } 164 165 private: 166 InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind, 167 std::unique_ptr<InstrProfCorrelator::Context> Ctx) 168 : InstrProfCorrelator(Kind, std::move(Ctx)){}; 169 llvm::DenseSet<IntPtrT> CounterOffsets; 170 }; 171 172 /// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes 173 /// DWARF debug info as input to correlate profiles. 174 template <class IntPtrT> 175 class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> { 176 public: 177 DwarfInstrProfCorrelator(std::unique_ptr<DWARFContext> DICtx, 178 std::unique_ptr<InstrProfCorrelator::Context> Ctx) 179 : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)), 180 DICtx(std::move(DICtx)) {} 181 182 private: 183 std::unique_ptr<DWARFContext> DICtx; 184 185 /// Return the address of the object that the provided DIE symbolizes. 186 std::optional<uint64_t> getLocation(const DWARFDie &Die) const; 187 188 /// Returns true if the provided DIE symbolizes an instrumentation probe 189 /// symbol. 190 static bool isDIEOfProbe(const DWARFDie &Die); 191 192 /// Iterate over DWARF DIEs to find those that symbolize instrumentation 193 /// probes and construct the ProfileData vector and Names string. 194 /// 195 /// Here is some example DWARF for an instrumentation probe we are looking 196 /// for: 197 /// \code 198 /// DW_TAG_subprogram 199 /// DW_AT_low_pc (0x0000000000000000) 200 /// DW_AT_high_pc (0x0000000000000014) 201 /// DW_AT_name ("foo") 202 /// DW_TAG_variable 203 /// DW_AT_name ("__profc_foo") 204 /// DW_AT_location (DW_OP_addr 0x0) 205 /// DW_TAG_LLVM_annotation 206 /// DW_AT_name ("Function Name") 207 /// DW_AT_const_value ("foo") 208 /// DW_TAG_LLVM_annotation 209 /// DW_AT_name ("CFG Hash") 210 /// DW_AT_const_value (12345678) 211 /// DW_TAG_LLVM_annotation 212 /// DW_AT_name ("Num Counters") 213 /// DW_AT_const_value (2) 214 /// NULL 215 /// NULL 216 /// \endcode 217 /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) 218 /// \param Data if provided, populate with the correlation data found 219 void correlateProfileDataImpl( 220 int MaxWarnings, 221 InstrProfCorrelator::CorrelationData *Data = nullptr) override; 222 223 Error correlateProfileNameImpl() override; 224 }; 225 226 /// BinaryInstrProfCorrelator - A child of InstrProfCorrelatorImpl that 227 /// takes an object file as input to correlate profiles. 228 template <class IntPtrT> 229 class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> { 230 public: 231 BinaryInstrProfCorrelator(std::unique_ptr<InstrProfCorrelator::Context> Ctx) 232 : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)) {} 233 234 /// Return a pointer to the names string that this class constructs. 235 const char *getNamesPointer() const { return this->Ctx.NameStart; } 236 237 /// Return the number of bytes in the names string. 238 size_t getNamesSize() const { return this->Ctx.NameSize; } 239 240 private: 241 void correlateProfileDataImpl( 242 int MaxWarnings, 243 InstrProfCorrelator::CorrelationData *Data = nullptr) override; 244 245 Error correlateProfileNameImpl() override; 246 }; 247 248 } // end namespace llvm 249 250 #endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H 251