1 //===- lib/MC/MCPseudoProbe.cpp - Pseudo probe encoding support ----------===//
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 #include "llvm/MC/MCPseudoProbe.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/IR/PseudoProbe.h"
12 #include "llvm/MC/MCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCFragment.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCObjectStreamer.h"
18 #include "llvm/MC/MCSymbol.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/LEB128.h"
21 #include "llvm/Support/MD5.h"
22 #include "llvm/Support/raw_ostream.h"
30 #define DEBUG_TYPE "mcpseudoprobe"
33 using namespace support
;
36 int MCPseudoProbeTable::DdgPrintIndent
= 0;
39 static const MCExpr
*buildSymbolDiff(MCObjectStreamer
*MCOS
, const MCSymbol
*A
,
41 MCContext
&Context
= MCOS
->getContext();
42 MCSymbolRefExpr::VariantKind Variant
= MCSymbolRefExpr::VK_None
;
43 const MCExpr
*ARef
= MCSymbolRefExpr::create(A
, Variant
, Context
);
44 const MCExpr
*BRef
= MCSymbolRefExpr::create(B
, Variant
, Context
);
45 const MCExpr
*AddrDelta
=
46 MCBinaryExpr::create(MCBinaryExpr::Sub
, ARef
, BRef
, Context
);
50 void MCPseudoProbe::emit(MCObjectStreamer
*MCOS
,
51 const MCPseudoProbe
*LastProbe
) const {
52 bool IsSentinel
= isSentinelProbe(getAttributes());
53 assert((LastProbe
|| IsSentinel
) &&
54 "Last probe should not be null for non-sentinel probes");
57 MCOS
->emitULEB128IntValue(Index
);
58 // Emit Type and the flag:
59 // Type (bit 0 to 3), with bit 4 to 6 for attributes.
60 // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
61 // the following field is a symbolic code address or an address delta.
62 // Emit FS discriminator
63 assert(Type
<= 0xF && "Probe type too big to encode, exceeding 15");
64 auto NewAttributes
= Attributes
;
66 NewAttributes
|= (uint32_t)PseudoProbeAttributes::HasDiscriminator
;
67 assert(NewAttributes
<= 0x7 &&
68 "Probe attributes too big to encode, exceeding 7");
69 uint8_t PackedType
= Type
| (NewAttributes
<< 4);
71 !IsSentinel
? ((int8_t)MCPseudoProbeFlag::AddressDelta
<< 7) : 0;
72 MCOS
->emitInt8(Flag
| PackedType
);
75 // Emit the delta between the address label and LastProbe.
76 const MCExpr
*AddrDelta
=
77 buildSymbolDiff(MCOS
, Label
, LastProbe
->getLabel());
79 if (AddrDelta
->evaluateAsAbsolute(Delta
, MCOS
->getAssemblerPtr())) {
80 MCOS
->emitSLEB128IntValue(Delta
);
82 MCOS
->insert(new MCPseudoProbeAddrFragment(AddrDelta
));
85 // Emit the GUID of the split function that the sentinel probe represents.
86 MCOS
->emitInt64(Guid
);
90 MCOS
->emitULEB128IntValue(Discriminator
);
93 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
94 dbgs() << "Probe: " << Index
<< "\n";
98 void MCPseudoProbeInlineTree::addPseudoProbe(
99 const MCPseudoProbe
&Probe
, const MCPseudoProbeInlineStack
&InlineStack
) {
100 // The function should not be called on the root.
101 assert(isRoot() && "Should only be called on root");
103 // When it comes here, the input look like:
104 // Probe: GUID of C, ...
105 // InlineStack: [88, A], [66, B]
106 // which means, Function A inlines function B at call site with a probe id of
107 // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
108 // A], [88, B], [66, C]} to locate the tree node where the probe should be
109 // added. Note that the edge [0, A] means A is the top-level function we are
110 // emitting probes for.
112 // Make a [0, A] edge.
113 // An empty inline stack means the function that the probe originates from
114 // is a top-level function.
116 if (InlineStack
.empty()) {
117 Top
= InlineSite(Probe
.getGuid(), 0);
119 Top
= InlineSite(std::get
<0>(InlineStack
.front()), 0);
122 auto *Cur
= getOrAddNode(Top
);
124 // Make interior edges by walking the inline stack. Once it's done, Cur should
125 // point to the node that the probe originates from.
126 if (!InlineStack
.empty()) {
127 auto Iter
= InlineStack
.begin();
128 auto Index
= std::get
<1>(*Iter
);
130 for (; Iter
!= InlineStack
.end(); Iter
++) {
131 // Make an edge by using the previous probe id and current GUID.
132 Cur
= Cur
->getOrAddNode(InlineSite(std::get
<0>(*Iter
), Index
));
133 Index
= std::get
<1>(*Iter
);
135 Cur
= Cur
->getOrAddNode(InlineSite(Probe
.getGuid(), Index
));
138 Cur
->Probes
.push_back(Probe
);
141 void MCPseudoProbeInlineTree::emit(MCObjectStreamer
*MCOS
,
142 const MCPseudoProbe
*&LastProbe
) {
144 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
145 dbgs() << "Group [\n";
146 MCPseudoProbeTable::DdgPrintIndent
+= 2;
148 assert(!isRoot() && "Root should be handled seperately");
150 // Emit probes grouped by GUID.
152 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
153 dbgs() << "GUID: " << Guid
<< "\n";
156 MCOS
->emitInt64(Guid
);
157 // Emit number of probes in this node, including a sentinel probe for
158 // top-level functions if needed.
159 bool NeedSentinel
= false;
160 if (Parent
->isRoot()) {
161 assert(isSentinelProbe(LastProbe
->getAttributes()) &&
162 "Starting probe of a top-level function should be a sentinel probe");
163 // The main body of a split function doesn't need a sentinel probe.
164 if (LastProbe
->getGuid() != Guid
)
168 MCOS
->emitULEB128IntValue(Probes
.size() + NeedSentinel
);
169 // Emit number of direct inlinees
170 MCOS
->emitULEB128IntValue(Children
.size());
171 // Emit sentinel probe for top-level functions
173 LastProbe
->emit(MCOS
, nullptr);
175 // Emit probes in this group
176 for (const auto &Probe
: Probes
) {
177 Probe
.emit(MCOS
, LastProbe
);
181 // Emit sorted descendant. InlineSite is unique for each pair, so there will
182 // be no ordering of Inlinee based on MCPseudoProbeInlineTree*
183 using InlineeType
= std::pair
<InlineSite
, MCPseudoProbeInlineTree
*>;
184 auto Comparer
= [](const InlineeType
&A
, const InlineeType
&B
) {
185 return A
.first
< B
.first
;
187 std::vector
<InlineeType
> Inlinees
;
188 for (const auto &Child
: Children
)
189 Inlinees
.emplace_back(Child
.first
, Child
.second
.get());
190 std::sort(Inlinees
.begin(), Inlinees
.end(), Comparer
);
192 for (const auto &Inlinee
: Inlinees
) {
194 MCOS
->emitULEB128IntValue(std::get
<1>(Inlinee
.first
));
196 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
197 dbgs() << "InlineSite: " << std::get
<1>(Inlinee
.first
) << "\n";
200 Inlinee
.second
->emit(MCOS
, LastProbe
);
204 MCPseudoProbeTable::DdgPrintIndent
-= 2;
205 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent
);
210 void MCPseudoProbeSections::emit(MCObjectStreamer
*MCOS
) {
211 MCContext
&Ctx
= MCOS
->getContext();
212 for (auto &ProbeSec
: MCProbeDivisions
) {
213 const auto *FuncSym
= ProbeSec
.first
;
214 const auto &Root
= ProbeSec
.second
;
215 if (auto *S
= Ctx
.getObjectFileInfo()->getPseudoProbeSection(
216 FuncSym
->getSection())) {
217 // Switch to the .pseudoprobe section or a comdat group.
218 MCOS
->switchSection(S
);
219 // Emit probes grouped by GUID.
220 // Emit sorted descendant. InlineSite is unique for each pair, so there
221 // will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
222 using InlineeType
= std::pair
<InlineSite
, MCPseudoProbeInlineTree
*>;
223 auto Comparer
= [](const InlineeType
&A
, const InlineeType
&B
) {
224 return A
.first
< B
.first
;
226 std::vector
<InlineeType
> Inlinees
;
227 for (const auto &Child
: Root
.getChildren())
228 Inlinees
.emplace_back(Child
.first
, Child
.second
.get());
229 std::sort(Inlinees
.begin(), Inlinees
.end(), Comparer
);
231 for (const auto &Inlinee
: Inlinees
) {
232 // Emit the group guarded by a sentinel probe.
233 MCPseudoProbe
SentinelProbe(
234 const_cast<MCSymbol
*>(FuncSym
), MD5Hash(FuncSym
->getName()),
235 (uint32_t)PseudoProbeReservedId::Invalid
,
236 (uint32_t)PseudoProbeType::Block
,
237 (uint32_t)PseudoProbeAttributes::Sentinel
, 0);
238 const MCPseudoProbe
*Probe
= &SentinelProbe
;
239 Inlinee
.second
->emit(MCOS
, Probe
);
246 // This emits the pseudo probe tables.
248 void MCPseudoProbeTable::emit(MCObjectStreamer
*MCOS
) {
249 MCContext
&Ctx
= MCOS
->getContext();
250 auto &ProbeTable
= Ctx
.getMCPseudoProbeTable();
252 // Bail out early so we don't switch to the pseudo_probe section needlessly
253 // and in doing so create an unnecessary (if empty) section.
254 auto &ProbeSections
= ProbeTable
.getProbeSections();
255 if (ProbeSections
.empty())
258 LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent
= 0);
260 // Put out the probe.
261 ProbeSections
.emit(MCOS
);
264 static StringRef
getProbeFNameForGUID(const GUIDProbeFunctionMap
&GUID2FuncMAP
,
266 auto It
= GUID2FuncMAP
.find(GUID
);
267 assert(It
!= GUID2FuncMAP
.end() &&
268 "Probe function must exist for a valid GUID");
269 return It
->second
.FuncName
;
272 void MCPseudoProbeFuncDesc::print(raw_ostream
&OS
) {
273 OS
<< "GUID: " << FuncGUID
<< " Name: " << FuncName
<< "\n";
274 OS
<< "Hash: " << FuncHash
<< "\n";
277 void MCDecodedPseudoProbe::getInlineContext(
278 SmallVectorImpl
<MCPseduoProbeFrameLocation
> &ContextStack
,
279 const GUIDProbeFunctionMap
&GUID2FuncMAP
) const {
280 uint32_t Begin
= ContextStack
.size();
281 MCDecodedPseudoProbeInlineTree
*Cur
= InlineTree
;
282 // It will add the string of each node's inline site during iteration.
283 // Note that it won't include the probe's belonging function(leaf location)
284 while (Cur
->hasInlineSite()) {
285 StringRef FuncName
= getProbeFNameForGUID(GUID2FuncMAP
, Cur
->Parent
->Guid
);
286 ContextStack
.emplace_back(
287 MCPseduoProbeFrameLocation(FuncName
, std::get
<1>(Cur
->ISite
)));
288 Cur
= static_cast<MCDecodedPseudoProbeInlineTree
*>(Cur
->Parent
);
290 // Make the ContextStack in caller-callee order
291 std::reverse(ContextStack
.begin() + Begin
, ContextStack
.end());
294 std::string
MCDecodedPseudoProbe::getInlineContextStr(
295 const GUIDProbeFunctionMap
&GUID2FuncMAP
) const {
296 std::ostringstream OContextStr
;
297 SmallVector
<MCPseduoProbeFrameLocation
, 16> ContextStack
;
298 getInlineContext(ContextStack
, GUID2FuncMAP
);
299 for (auto &Cxt
: ContextStack
) {
300 if (OContextStr
.str().size())
301 OContextStr
<< " @ ";
302 OContextStr
<< Cxt
.first
.str() << ":" << Cxt
.second
;
304 return OContextStr
.str();
307 static const char *PseudoProbeTypeStr
[3] = {"Block", "IndirectCall",
310 void MCDecodedPseudoProbe::print(raw_ostream
&OS
,
311 const GUIDProbeFunctionMap
&GUID2FuncMAP
,
312 bool ShowName
) const {
315 StringRef FuncName
= getProbeFNameForGUID(GUID2FuncMAP
, Guid
);
316 OS
<< FuncName
.str() << " ";
320 OS
<< "Index: " << Index
<< " ";
322 OS
<< "Discriminator: " << Discriminator
<< " ";
323 OS
<< "Type: " << PseudoProbeTypeStr
[static_cast<uint8_t>(Type
)] << " ";
324 std::string InlineContextStr
= getInlineContextStr(GUID2FuncMAP
);
325 if (InlineContextStr
.size()) {
327 OS
<< InlineContextStr
;
332 template <typename T
> ErrorOr
<T
> MCPseudoProbeDecoder::readUnencodedNumber() {
333 if (Data
+ sizeof(T
) > End
) {
334 return std::error_code();
336 T Val
= endian::readNext
<T
, little
, unaligned
>(Data
);
337 return ErrorOr
<T
>(Val
);
340 template <typename T
> ErrorOr
<T
> MCPseudoProbeDecoder::readUnsignedNumber() {
341 unsigned NumBytesRead
= 0;
342 uint64_t Val
= decodeULEB128(Data
, &NumBytesRead
);
343 if (Val
> std::numeric_limits
<T
>::max() || (Data
+ NumBytesRead
> End
)) {
344 return std::error_code();
346 Data
+= NumBytesRead
;
347 return ErrorOr
<T
>(static_cast<T
>(Val
));
350 template <typename T
> ErrorOr
<T
> MCPseudoProbeDecoder::readSignedNumber() {
351 unsigned NumBytesRead
= 0;
352 int64_t Val
= decodeSLEB128(Data
, &NumBytesRead
);
353 if (Val
> std::numeric_limits
<T
>::max() || (Data
+ NumBytesRead
> End
)) {
354 return std::error_code();
356 Data
+= NumBytesRead
;
357 return ErrorOr
<T
>(static_cast<T
>(Val
));
360 ErrorOr
<StringRef
> MCPseudoProbeDecoder::readString(uint32_t Size
) {
361 StringRef
Str(reinterpret_cast<const char *>(Data
), Size
);
362 if (Data
+ Size
> End
) {
363 return std::error_code();
366 return ErrorOr
<StringRef
>(Str
);
369 bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start
,
371 // The pseudo_probe_desc section has a format like:
372 // .section .pseudo_probe_desc,"",@progbits
373 // .quad -5182264717993193164 // GUID
374 // .quad 4294967295 // Hash
375 // .uleb 3 // Name size
376 // .ascii "foo" // Name
377 // .quad -2624081020897602054
378 // .quad 174696971957
386 auto ErrorOrGUID
= readUnencodedNumber
<uint64_t>();
390 auto ErrorOrHash
= readUnencodedNumber
<uint64_t>();
394 auto ErrorOrNameSize
= readUnsignedNumber
<uint32_t>();
395 if (!ErrorOrNameSize
)
397 uint32_t NameSize
= std::move(*ErrorOrNameSize
);
399 auto ErrorOrName
= readString(NameSize
);
403 uint64_t GUID
= std::move(*ErrorOrGUID
);
404 uint64_t Hash
= std::move(*ErrorOrHash
);
405 StringRef Name
= std::move(*ErrorOrName
);
407 // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
408 GUID2FuncDescMap
.emplace(GUID
, MCPseudoProbeFuncDesc(GUID
, Hash
, Name
));
410 assert(Data
== End
&& "Have unprocessed data in pseudo_probe_desc section");
414 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
415 MCDecodedPseudoProbeInlineTree
*Cur
, uint64_t &LastAddr
,
416 const Uint64Set
&GuidFilter
, const Uint64Map
&FuncStartAddrs
) {
417 // The pseudo_probe section encodes an inline forest and each tree has a
418 // format defined in MCPseudoProbe.h
421 bool IsTopLevelFunc
= Cur
== &DummyInlineRoot
;
422 if (IsTopLevelFunc
) {
423 // Use a sequential id for top level inliner.
424 Index
= Cur
->getChildren().size();
426 // Read inline site for inlinees
427 auto ErrorOrIndex
= readUnsignedNumber
<uint32_t>();
430 Index
= std::move(*ErrorOrIndex
);
434 auto ErrorOrCurGuid
= readUnencodedNumber
<uint64_t>();
437 uint64_t Guid
= std::move(*ErrorOrCurGuid
);
439 // Decide if top-level node should be disgarded.
440 if (IsTopLevelFunc
&& !GuidFilter
.empty() && !GuidFilter
.count(Guid
))
443 // If the incoming node is null, all its children nodes should be disgarded.
445 // Switch/add to a new tree node(inlinee)
446 Cur
= Cur
->getOrAddNode(std::make_tuple(Guid
, Index
));
448 if (IsTopLevelFunc
&& !EncodingIsAddrBased
) {
449 if (auto V
= FuncStartAddrs
.lookup(Guid
))
454 // Read number of probes in the current node.
455 auto ErrorOrNodeCount
= readUnsignedNumber
<uint32_t>();
456 if (!ErrorOrNodeCount
)
458 uint32_t NodeCount
= std::move(*ErrorOrNodeCount
);
459 // Read number of direct inlinees
460 auto ErrorOrCurChildrenToProcess
= readUnsignedNumber
<uint32_t>();
461 if (!ErrorOrCurChildrenToProcess
)
463 // Read all probes in this node
464 for (std::size_t I
= 0; I
< NodeCount
; I
++) {
466 auto ErrorOrIndex
= readUnsignedNumber
<uint32_t>();
469 uint32_t Index
= std::move(*ErrorOrIndex
);
471 auto ErrorOrValue
= readUnencodedNumber
<uint8_t>();
474 uint8_t Value
= std::move(*ErrorOrValue
);
475 uint8_t Kind
= Value
& 0xf;
476 uint8_t Attr
= (Value
& 0x70) >> 4;
480 auto ErrorOrOffset
= readSignedNumber
<int64_t>();
483 int64_t Offset
= std::move(*ErrorOrOffset
);
484 Addr
= LastAddr
+ Offset
;
486 auto ErrorOrAddr
= readUnencodedNumber
<int64_t>();
489 Addr
= std::move(*ErrorOrAddr
);
490 if (isSentinelProbe(Attr
)) {
491 // For sentinel probe, the addr field actually stores the GUID of the
492 // split function. Convert it to the real address.
493 if (auto V
= FuncStartAddrs
.lookup(Addr
))
496 // For now we assume all probe encoding should be either based on
497 // leading probe address or function start address.
498 // The scheme is for downwards compatibility.
499 // TODO: retire this scheme once compatibility is no longer an issue.
500 EncodingIsAddrBased
= true;
504 uint32_t Discriminator
= 0;
505 if (hasDiscriminator(Attr
)) {
506 auto ErrorOrDiscriminator
= readUnsignedNumber
<uint32_t>();
507 if (!ErrorOrDiscriminator
)
509 Discriminator
= std::move(*ErrorOrDiscriminator
);
512 if (Cur
&& !isSentinelProbe(Attr
)) {
513 // Populate Address2ProbesMap
514 auto &Probes
= Address2ProbesMap
[Addr
];
515 Probes
.emplace_back(Addr
, Cur
->Guid
, Index
, PseudoProbeType(Kind
), Attr
,
517 Cur
->addProbes(&Probes
.back());
522 uint32_t ChildrenToProcess
= std::move(*ErrorOrCurChildrenToProcess
);
523 for (uint32_t I
= 0; I
< ChildrenToProcess
; I
++) {
524 buildAddress2ProbeMap(Cur
, LastAddr
, GuidFilter
, FuncStartAddrs
);
530 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
531 const uint8_t *Start
, std::size_t Size
, const Uint64Set
&GuidFilter
,
532 const Uint64Map
&FuncStartAddrs
) {
535 uint64_t LastAddr
= 0;
537 buildAddress2ProbeMap(&DummyInlineRoot
, LastAddr
, GuidFilter
,
539 assert(Data
== End
&& "Have unprocessed data in pseudo_probe section");
543 void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream
&OS
) {
544 OS
<< "Pseudo Probe Desc:\n";
545 // Make the output deterministic
546 std::map
<uint64_t, MCPseudoProbeFuncDesc
> OrderedMap(GUID2FuncDescMap
.begin(),
547 GUID2FuncDescMap
.end());
548 for (auto &I
: OrderedMap
) {
553 void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream
&OS
,
555 auto It
= Address2ProbesMap
.find(Address
);
556 if (It
!= Address2ProbesMap
.end()) {
557 for (auto &Probe
: It
->second
) {
559 Probe
.print(OS
, GUID2FuncDescMap
, true);
564 void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream
&OS
) {
565 std::vector
<uint64_t> Addresses
;
566 for (auto Entry
: Address2ProbesMap
)
567 Addresses
.push_back(Entry
.first
);
568 llvm::sort(Addresses
);
569 for (auto K
: Addresses
) {
573 printProbeForAddress(OS
, K
);
577 const MCDecodedPseudoProbe
*
578 MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address
) const {
579 auto It
= Address2ProbesMap
.find(Address
);
580 if (It
== Address2ProbesMap
.end())
582 const auto &Probes
= It
->second
;
584 const MCDecodedPseudoProbe
*CallProbe
= nullptr;
585 for (const auto &Probe
: Probes
) {
586 if (Probe
.isCall()) {
588 "There should be only one call probe corresponding to address "
589 "which is a callsite.");
596 const MCPseudoProbeFuncDesc
*
597 MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID
) const {
598 auto It
= GUID2FuncDescMap
.find(GUID
);
599 assert(It
!= GUID2FuncDescMap
.end() && "Function descriptor doesn't exist");
603 void MCPseudoProbeDecoder::getInlineContextForProbe(
604 const MCDecodedPseudoProbe
*Probe
,
605 SmallVectorImpl
<MCPseduoProbeFrameLocation
> &InlineContextStack
,
606 bool IncludeLeaf
) const {
607 Probe
->getInlineContext(InlineContextStack
, GUID2FuncDescMap
);
610 // Note that the context from probe doesn't include leaf frame,
611 // hence we need to retrieve and prepend leaf if requested.
612 const auto *FuncDesc
= getFuncDescForGUID(Probe
->getGuid());
613 InlineContextStack
.emplace_back(
614 MCPseduoProbeFrameLocation(FuncDesc
->FuncName
, Probe
->getIndex()));
617 const MCPseudoProbeFuncDesc
*MCPseudoProbeDecoder::getInlinerDescForProbe(
618 const MCDecodedPseudoProbe
*Probe
) const {
619 MCDecodedPseudoProbeInlineTree
*InlinerNode
= Probe
->getInlineTreeNode();
620 if (!InlinerNode
->hasInlineSite())
622 return getFuncDescForGUID(InlinerNode
->Parent
->Guid
);