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
23namespace llvm {
24class DWARFContext;
25class DWARFDie;
26namespace object {
27class ObjectFile;
28}
29
30/// InstrProfCorrelator - A base class used to create raw instrumentation data
31/// to their functions.
32class InstrProfCorrelator {
33public:
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
72protected:
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
116private:
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.
125template <class IntPtrT>
126class InstrProfCorrelatorImpl : public InstrProfCorrelator {
127public:
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
144protected:
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
165private:
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.
174template <class IntPtrT>
175class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
176public:
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
182private:
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.
228template <class IntPtrT>
229class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
230public:
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
240private:
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

source code of llvm/include/llvm/ProfileData/InstrProfCorrelator.h