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