1 //===- bolt/Rewrite/PseudoProbeRewriter.cpp -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implement support for pseudo probes.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Core/BinaryFunction.h"
14 #include "bolt/Rewrite/MetadataRewriter.h"
15 #include "bolt/Rewrite/MetadataRewriters.h"
16 #include "bolt/Utils/CommandLineOpts.h"
17 #include "bolt/Utils/Utils.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/MC/MCPseudoProbe.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/LEB128.h"
26 #define DEBUG_TYPE "pseudo-probe-rewriter"
33 enum PrintPseudoProbesOptions
{
35 PPP_Probes_Section_Decode
= 0x1,
36 PPP_Probes_Address_Conversion
= 0x2,
37 PPP_Encoded_Probes
= 0x3,
41 static cl::opt
<PrintPseudoProbesOptions
> PrintPseudoProbes(
42 "print-pseudo-probes", cl::desc("print pseudo probe info"),
44 cl::values(clEnumValN(PPP_Probes_Section_Decode
, "decode",
45 "decode probes section from binary"),
46 clEnumValN(PPP_Probes_Address_Conversion
, "address_conversion",
47 "update address2ProbesMap with output block address"),
48 clEnumValN(PPP_Encoded_Probes
, "encoded_probes",
49 "display the encoded probes in binary section"),
50 clEnumValN(PPP_All
, "all", "enable all debugging printout")),
51 cl::Hidden
, cl::cat(BoltCategory
));
53 extern cl::opt
<bool> ProfileWritePseudoProbes
;
54 extern cl::opt
<bool> StaleMatchingWithPseudoProbes
;
58 class PseudoProbeRewriter final
: public MetadataRewriter
{
59 /// .pseudo_probe_desc section.
60 /// Contains information about pseudo probe description, like its related
62 ErrorOr
<BinarySection
&> PseudoProbeDescSection
{std::errc::bad_address
};
64 /// .pseudo_probe section.
65 /// Contains information about pseudo probe details, like its address
66 ErrorOr
<BinarySection
&> PseudoProbeSection
{std::errc::bad_address
};
68 /// Update address of MCDecodedPseudoProbe.
69 void updatePseudoProbes();
71 /// Encode MCDecodedPseudoProbe.
72 void encodePseudoProbes();
74 /// Parse .pseudo_probe_desc section and .pseudo_probe section
75 /// Setup Pseudo probe decoder
76 /// If \p ProfiledOnly is set, only parse records for functions with profile.
77 void parsePseudoProbe(bool ProfiledOnly
= false);
79 /// PseudoProbe decoder
80 std::shared_ptr
<MCPseudoProbeDecoder
> ProbeDecoderPtr
;
83 PseudoProbeRewriter(BinaryContext
&BC
)
84 : MetadataRewriter("pseudo-probe-rewriter", BC
),
85 ProbeDecoderPtr(std::make_shared
<MCPseudoProbeDecoder
>()) {
86 BC
.setPseudoProbeDecoder(ProbeDecoderPtr
);
89 Error
preCFGInitializer() override
;
90 Error
postEmitFinalizer() override
;
92 ~PseudoProbeRewriter() override
{ ProbeDecoderPtr
.reset(); }
95 Error
PseudoProbeRewriter::preCFGInitializer() {
96 if (opts::ProfileWritePseudoProbes
|| opts::StaleMatchingWithPseudoProbes
)
97 parsePseudoProbe(opts::ProfileWritePseudoProbes
);
99 return Error::success();
102 Error
PseudoProbeRewriter::postEmitFinalizer() {
103 if (!opts::StaleMatchingWithPseudoProbes
)
105 updatePseudoProbes();
107 return Error::success();
110 void PseudoProbeRewriter::parsePseudoProbe(bool ProfiledOnly
) {
111 MCPseudoProbeDecoder
&ProbeDecoder(*ProbeDecoderPtr
);
112 PseudoProbeDescSection
= BC
.getUniqueSectionByName(".pseudo_probe_desc");
113 PseudoProbeSection
= BC
.getUniqueSectionByName(".pseudo_probe");
115 if (!PseudoProbeDescSection
&& !PseudoProbeSection
) {
116 // pesudo probe is not added to binary. It is normal and no warning needed.
120 // If only one section is found, it might mean the ELF is corrupted.
121 if (!PseudoProbeDescSection
) {
122 errs() << "BOLT-WARNING: fail in reading .pseudo_probe_desc binary\n";
124 } else if (!PseudoProbeSection
) {
125 errs() << "BOLT-WARNING: fail in reading .pseudo_probe binary\n";
129 StringRef Contents
= PseudoProbeDescSection
->getContents();
130 if (!ProbeDecoder
.buildGUID2FuncDescMap(
131 reinterpret_cast<const uint8_t *>(Contents
.data()), Contents
.size(),
132 /*IsMMapped*/ true)) {
133 errs() << "BOLT-WARNING: fail in building GUID2FuncDescMap\n";
137 MCPseudoProbeDecoder::Uint64Set GuidFilter
;
138 MCPseudoProbeDecoder::Uint64Map FuncStartAddrs
;
139 SmallVector
<StringRef
, 0> Suffixes(
140 {".destroy", ".resume", ".llvm.", ".cold", ".warm"});
141 for (const BinaryFunction
*F
: BC
.getAllBinaryFunctions()) {
142 bool HasProfile
= F
->hasProfileAvailable();
143 for (const MCSymbol
*Sym
: F
->getSymbols()) {
144 StringRef SymName
= Sym
->getName();
145 for (auto Name
: {std::optional(NameResolver::restore(SymName
)),
146 getCommonName(SymName
, false, Suffixes
)}) {
150 uint64_t GUID
= Function::getGUID(SymName
);
151 FuncStartAddrs
[GUID
] = F
->getAddress();
152 if (ProfiledOnly
&& HasProfile
)
153 GuidFilter
.insert(GUID
);
157 Contents
= PseudoProbeSection
->getContents();
158 if (!ProbeDecoder
.buildAddress2ProbeMap(
159 reinterpret_cast<const uint8_t *>(Contents
.data()), Contents
.size(),
160 GuidFilter
, FuncStartAddrs
)) {
161 errs() << "BOLT-WARNING: fail in building Address2ProbeMap\n";
165 if (opts::PrintPseudoProbes
== opts::PrintPseudoProbesOptions::PPP_All
||
166 opts::PrintPseudoProbes
==
167 opts::PrintPseudoProbesOptions::PPP_Probes_Section_Decode
) {
168 outs() << "Report of decoding input pseudo probe binaries \n";
169 ProbeDecoder
.printGUID2FuncDescMap(outs());
170 ProbeDecoder
.printProbesForAllAddresses(outs());
173 const GUIDProbeFunctionMap
&GUID2Func
= ProbeDecoder
.getGUID2FuncDescMap();
174 // Checks GUID in GUID2Func and returns it if it's present or null otherwise.
175 auto checkGUID
= [&](StringRef SymName
) -> uint64_t {
176 uint64_t GUID
= Function::getGUID(SymName
);
177 if (GUID2Func
.find(GUID
) == GUID2Func
.end())
181 for (BinaryFunction
*F
: BC
.getAllBinaryFunctions()) {
182 for (const MCSymbol
*Sym
: F
->getSymbols()) {
183 StringRef SymName
= NameResolver::restore(Sym
->getName());
184 uint64_t GUID
= checkGUID(SymName
);
185 std::optional
<StringRef
> CommonName
=
186 getCommonName(SymName
, false, Suffixes
);
187 if (!GUID
&& CommonName
)
188 GUID
= checkGUID(*CommonName
);
195 void PseudoProbeRewriter::updatePseudoProbes() {
196 MCPseudoProbeDecoder
&ProbeDecoder(*ProbeDecoderPtr
);
197 // check if there is pseudo probe section decoded
198 if (ProbeDecoder
.getAddress2ProbesMap().empty())
200 // input address converted to output
201 AddressProbesMap
&Address2ProbesMap
= ProbeDecoder
.getAddress2ProbesMap();
202 const GUIDProbeFunctionMap
&GUID2Func
= ProbeDecoder
.getGUID2FuncDescMap();
204 for (MCDecodedPseudoProbe
&Probe
: Address2ProbesMap
) {
205 uint64_t Address
= Probe
.getAddress();
206 BinaryFunction
*F
= BC
.getBinaryFunctionContainingAddress(Address
);
207 // If F is removed, eliminate all probes inside it from inline tree
208 // Setting probes' addresses as INT64_MAX means elimination
210 Probe
.setAddress(INT64_MAX
);
213 // If F is not emitted, the function will remain in the same address as its
218 uint64_t Offset
= Address
- F
->getAddress();
219 const BinaryBasicBlock
*BB
= F
->getBasicBlockContainingOffset(Offset
);
220 uint64_t BlkOutputAddress
= BB
->getOutputAddressRange().first
;
221 // Check if block output address is defined.
222 // If not, such block is removed from binary. Then remove the probes from
224 if (BlkOutputAddress
== 0) {
225 Probe
.setAddress(INT64_MAX
);
229 if (Probe
.isBlock()) {
230 Probe
.setAddress(BlkOutputAddress
);
231 } else if (Probe
.isCall()) {
232 // A call probe may be duplicated due to ICP
233 // Go through output of InputOffsetToAddressMap to collect all related
235 auto CallOutputAddresses
= BC
.getIOAddressMap().lookupAll(Address
);
236 auto CallOutputAddress
= CallOutputAddresses
.first
;
237 if (CallOutputAddress
== CallOutputAddresses
.second
) {
238 Probe
.setAddress(INT64_MAX
);
240 Probe
.setAddress(CallOutputAddress
->second
);
241 CallOutputAddress
= std::next(CallOutputAddress
);
244 while (CallOutputAddress
!= CallOutputAddresses
.second
) {
245 ProbeDecoder
.addInjectedProbe(Probe
, CallOutputAddress
->second
);
246 CallOutputAddress
= std::next(CallOutputAddress
);
251 if (opts::PrintPseudoProbes
== opts::PrintPseudoProbesOptions::PPP_All
||
252 opts::PrintPseudoProbes
==
253 opts::PrintPseudoProbesOptions::PPP_Probes_Address_Conversion
) {
254 outs() << "Pseudo Probe Address Conversion results:\n";
255 // table that correlates address to block
256 std::unordered_map
<uint64_t, StringRef
> Addr2BlockNames
;
257 for (auto &F
: BC
.getBinaryFunctions())
258 for (BinaryBasicBlock
&BinaryBlock
: F
.second
)
259 Addr2BlockNames
[BinaryBlock
.getOutputAddressRange().first
] =
260 BinaryBlock
.getName();
262 // scan all addresses -> correlate probe to block when print out
263 for (MCDecodedPseudoProbe
&Probe
: Address2ProbesMap
) {
264 if (Probe
.getAddress() == INT64_MAX
)
265 outs() << "Deleted Probe: ";
267 outs() << "Address: " << format_hex(Probe
.getAddress(), 8) << " ";
268 Probe
.print(outs(), GUID2Func
, true);
269 // print block name only if the probe is block type and undeleted.
270 if (Probe
.isBlock() && Probe
.getAddress() != INT64_MAX
)
271 outs() << format_hex(Probe
.getAddress(), 8) << " Probe is in "
272 << Addr2BlockNames
[Probe
.getAddress()] << "\n";
274 outs() << "=======================================\n";
277 // encode pseudo probes with updated addresses
278 encodePseudoProbes();
281 void PseudoProbeRewriter::encodePseudoProbes() {
282 MCPseudoProbeDecoder
&ProbeDecoder(*ProbeDecoderPtr
);
283 // Buffer for new pseudo probes section
284 SmallString
<8> Contents
;
285 MCDecodedPseudoProbe
*LastProbe
= nullptr;
287 auto EmitInt
= [&](uint64_t Value
, uint32_t Size
) {
288 const bool IsLittleEndian
= BC
.AsmInfo
->isLittleEndian();
289 uint64_t Swapped
= support::endian::byte_swap(
291 IsLittleEndian
? llvm::endianness::little
: llvm::endianness::big
);
292 unsigned Index
= IsLittleEndian
? 0 : 8 - Size
;
293 auto Entry
= StringRef(reinterpret_cast<char *>(&Swapped
) + Index
, Size
);
294 Contents
.append(Entry
.begin(), Entry
.end());
297 auto EmitULEB128IntValue
= [&](uint64_t Value
) {
298 SmallString
<128> Tmp
;
299 raw_svector_ostream
OSE(Tmp
);
300 encodeULEB128(Value
, OSE
, 0);
301 Contents
.append(OSE
.str().begin(), OSE
.str().end());
304 auto EmitSLEB128IntValue
= [&](int64_t Value
) {
305 SmallString
<128> Tmp
;
306 raw_svector_ostream
OSE(Tmp
);
307 encodeSLEB128(Value
, OSE
);
308 Contents
.append(OSE
.str().begin(), OSE
.str().end());
311 // Emit indiviual pseudo probes in a inline tree node
312 // Probe index, type, attribute, address type and address are encoded
313 // Address of the first probe is absolute.
314 // Other probes' address are represented by delta
315 auto EmitDecodedPseudoProbe
= [&](MCDecodedPseudoProbe
*&CurProbe
) {
316 assert(!isSentinelProbe(CurProbe
->getAttributes()) &&
317 "Sentinel probes should not be emitted");
318 EmitULEB128IntValue(CurProbe
->getIndex());
319 uint8_t PackedType
= CurProbe
->getType() | (CurProbe
->getAttributes() << 4);
321 LastProbe
? ((int8_t)MCPseudoProbeFlag::AddressDelta
<< 7) : 0;
322 EmitInt(Flag
| PackedType
, 1);
324 // Emit the delta between the address label and LastProbe.
325 int64_t Delta
= CurProbe
->getAddress() - LastProbe
->getAddress();
326 EmitSLEB128IntValue(Delta
);
328 // Emit absolute address for encoding the first pseudo probe.
329 uint32_t AddrSize
= BC
.AsmInfo
->getCodePointerSize();
330 EmitInt(CurProbe
->getAddress(), AddrSize
);
334 std::map
<InlineSite
, MCDecodedPseudoProbeInlineTree
*,
335 std::greater
<InlineSite
>>
338 // DFS of inline tree to emit pseudo probes in all tree node
339 // Inline site index of a probe is emitted first.
340 // Then tree node Guid, size of pseudo probes and children nodes, and detail
341 // of contained probes are emitted Deleted probes are skipped Root node is not
342 // encoded to binaries. It's a "wrapper" of inline trees of each function.
343 std::list
<std::pair
<uint64_t, MCDecodedPseudoProbeInlineTree
*>> NextNodes
;
344 const MCDecodedPseudoProbeInlineTree
&Root
=
345 ProbeDecoder
.getDummyInlineRoot();
346 for (auto Child
= Root
.getChildren().begin();
347 Child
!= Root
.getChildren().end(); ++Child
)
348 Inlinees
[Child
->getInlineSite()] = &*Child
;
350 for (auto Inlinee
: Inlinees
)
351 // INT64_MAX is "placeholder" of unused callsite index field in the pair
352 NextNodes
.push_back({INT64_MAX
, Inlinee
.second
});
356 while (!NextNodes
.empty()) {
357 uint64_t ProbeIndex
= NextNodes
.back().first
;
358 MCDecodedPseudoProbeInlineTree
*Cur
= NextNodes
.back().second
;
359 NextNodes
.pop_back();
361 if (Cur
->Parent
&& !Cur
->Parent
->isRoot())
362 // Emit probe inline site
363 EmitULEB128IntValue(ProbeIndex
);
365 // Emit probes grouped by GUID.
367 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
368 dbgs() << "GUID: " << Cur
->Guid
<< "\n";
371 EmitInt(Cur
->Guid
, 8);
372 // Emit number of probes in this node
373 uint64_t Deleted
= 0;
374 for (MCDecodedPseudoProbe
*&Probe
:
375 llvm::make_pointer_range(Cur
->getProbes()))
376 if (Probe
->getAddress() == INT64_MAX
)
378 LLVM_DEBUG(dbgs() << "Deleted Probes:" << Deleted
<< "\n");
379 size_t InjectedProbes
= ProbeDecoder
.getNumInjectedProbes(Cur
);
380 uint64_t ProbesSize
= Cur
->getProbes().size() - Deleted
+ InjectedProbes
;
381 EmitULEB128IntValue(ProbesSize
);
382 // Emit number of direct inlinees
383 EmitULEB128IntValue(Cur
->getChildren().size());
384 // Emit probes in this group
385 for (MCDecodedPseudoProbe
*&Probe
:
386 llvm::make_pointer_range(Cur
->getProbes())) {
387 if (Probe
->getAddress() == INT64_MAX
)
389 EmitDecodedPseudoProbe(Probe
);
392 if (InjectedProbes
) {
393 for (MCDecodedPseudoProbe
*&Probe
:
394 llvm::make_pointer_range(ProbeDecoder
.getInjectedProbes(Cur
))) {
395 if (Probe
->getAddress() == INT64_MAX
)
397 EmitDecodedPseudoProbe(Probe
);
402 for (auto Child
= Cur
->getChildren().begin();
403 Child
!= Cur
->getChildren().end(); ++Child
)
404 Inlinees
[Child
->getInlineSite()] = &*Child
;
405 for (const auto &Inlinee
: Inlinees
) {
406 assert(Cur
->Guid
!= 0 && "non root tree node must have nonzero Guid");
407 NextNodes
.push_back({std::get
<1>(Inlinee
.first
), Inlinee
.second
});
409 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
410 dbgs() << "InlineSite: " << std::get
<1>(Inlinee
.first
) << "\n";
416 // Create buffer for new contents for the section
417 // Freed when parent section is destroyed
418 uint8_t *Output
= new uint8_t[Contents
.str().size()];
419 memcpy(Output
, Contents
.str().data(), Contents
.str().size());
420 BC
.registerOrUpdateSection(".pseudo_probe", PseudoProbeSection
->getELFType(),
421 PseudoProbeSection
->getELFFlags(), Output
,
422 Contents
.str().size(), 1);
423 if (opts::PrintPseudoProbes
== opts::PrintPseudoProbesOptions::PPP_All
||
424 opts::PrintPseudoProbes
==
425 opts::PrintPseudoProbesOptions::PPP_Encoded_Probes
) {
426 // create a dummy decoder;
427 MCPseudoProbeDecoder DummyDecoder
;
428 StringRef DescContents
= PseudoProbeDescSection
->getContents();
429 DummyDecoder
.buildGUID2FuncDescMap(
430 reinterpret_cast<const uint8_t *>(DescContents
.data()),
431 DescContents
.size());
432 StringRef ProbeContents
= PseudoProbeSection
->getOutputContents();
433 MCPseudoProbeDecoder::Uint64Set GuidFilter
;
434 MCPseudoProbeDecoder::Uint64Map FuncStartAddrs
;
435 for (const BinaryFunction
*F
: BC
.getAllBinaryFunctions()) {
436 const uint64_t Addr
=
437 F
->isEmitted() ? F
->getOutputAddress() : F
->getAddress();
438 FuncStartAddrs
[Function::getGUID(
439 NameResolver::restore(F
->getOneName()))] = Addr
;
441 DummyDecoder
.buildAddress2ProbeMap(
442 reinterpret_cast<const uint8_t *>(ProbeContents
.data()),
443 ProbeContents
.size(), GuidFilter
, FuncStartAddrs
);
444 DummyDecoder
.printProbesForAllAddresses(outs());
449 std::unique_ptr
<MetadataRewriter
>
450 llvm::bolt::createPseudoProbeRewriter(BinaryContext
&BC
) {
451 return std::make_unique
<PseudoProbeRewriter
>(BC
);