xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- lib/MC/MCPseudoProbe.cpp - Pseudo probe encoding support ----------===//
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 
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/MCAssembler.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCFragment.h"
17 #include "llvm/MC/MCObjectFileInfo.h"
18 #include "llvm/MC/MCObjectStreamer.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/LEB128.h"
22 #include "llvm/Support/MD5.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include <algorithm>
25 #include <cassert>
26 #include <limits>
27 #include <memory>
28 #include <sstream>
29 #include <vector>
30 
31 #define DEBUG_TYPE "mcpseudoprobe"
32 
33 using namespace llvm;
34 using namespace support;
35 
36 #ifndef NDEBUG
37 int MCPseudoProbeTable::DdgPrintIndent = 0;
38 #endif
39 
buildSymbolDiff(MCObjectStreamer * MCOS,const MCSymbol * A,const MCSymbol * B)40 static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,
41                                      const MCSymbol *B) {
42   MCContext &Context = MCOS->getContext();
43   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
44   const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
45   const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
46   const MCExpr *AddrDelta =
47       MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
48   return AddrDelta;
49 }
50 
emit(MCObjectStreamer * MCOS,const MCPseudoProbe * LastProbe) const51 void MCPseudoProbe::emit(MCObjectStreamer *MCOS,
52                          const MCPseudoProbe *LastProbe) const {
53   bool IsSentinel = isSentinelProbe(getAttributes());
54   assert((LastProbe || IsSentinel) &&
55          "Last probe should not be null for non-sentinel probes");
56 
57   // Emit Index
58   MCOS->emitULEB128IntValue(Index);
59   // Emit Type and the flag:
60   // Type (bit 0 to 3), with bit 4 to 6 for attributes.
61   // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
62   // the following field is a symbolic code address or an address delta.
63   // Emit FS discriminator
64   assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");
65   auto NewAttributes = Attributes;
66   if (Discriminator)
67     NewAttributes |= (uint32_t)PseudoProbeAttributes::HasDiscriminator;
68   assert(NewAttributes <= 0x7 &&
69          "Probe attributes too big to encode, exceeding 7");
70   uint8_t PackedType = Type | (NewAttributes << 4);
71   uint8_t Flag =
72       !IsSentinel ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;
73   MCOS->emitInt8(Flag | PackedType);
74 
75   if (!IsSentinel) {
76     // Emit the delta between the address label and LastProbe.
77     const MCExpr *AddrDelta =
78         buildSymbolDiff(MCOS, Label, LastProbe->getLabel());
79     int64_t Delta;
80     if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {
81       MCOS->emitSLEB128IntValue(Delta);
82     } else {
83       MCOS->insert(MCOS->getContext().allocFragment<MCPseudoProbeAddrFragment>(
84           AddrDelta));
85     }
86   } else {
87     // Emit the GUID of the split function that the sentinel probe represents.
88     MCOS->emitInt64(Guid);
89   }
90 
91   if (Discriminator)
92     MCOS->emitULEB128IntValue(Discriminator);
93 
94   LLVM_DEBUG({
95     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
96     dbgs() << "Probe: " << Index << "\n";
97   });
98 }
99 
addPseudoProbe(const MCPseudoProbe & Probe,const MCPseudoProbeInlineStack & InlineStack)100 void MCPseudoProbeInlineTree::addPseudoProbe(
101     const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
102   // The function should not be called on the root.
103   assert(isRoot() && "Should only be called on root");
104 
105   // When it comes here, the input look like:
106   //    Probe: GUID of C, ...
107   //    InlineStack: [88, A], [66, B]
108   // which means, Function A inlines function B at call site with a probe id of
109   // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
110   // A], [88, B], [66, C]} to locate the tree node where the probe should be
111   // added. Note that the edge [0, A] means A is the top-level function we are
112   // emitting probes for.
113 
114   // Make a [0, A] edge.
115   // An empty inline stack means the function that the probe originates from
116   // is a top-level function.
117   InlineSite Top;
118   if (InlineStack.empty()) {
119     Top = InlineSite(Probe.getGuid(), 0);
120   } else {
121     Top = InlineSite(std::get<0>(InlineStack.front()), 0);
122   }
123 
124   auto *Cur = getOrAddNode(Top);
125 
126   // Make interior edges by walking the inline stack. Once it's done, Cur should
127   // point to the node that the probe originates from.
128   if (!InlineStack.empty()) {
129     auto Iter = InlineStack.begin();
130     auto Index = std::get<1>(*Iter);
131     Iter++;
132     for (; Iter != InlineStack.end(); Iter++) {
133       // Make an edge by using the previous probe id and current GUID.
134       Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));
135       Index = std::get<1>(*Iter);
136     }
137     Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));
138   }
139 
140   Cur->Probes.push_back(Probe);
141 }
142 
emit(MCObjectStreamer * MCOS,const MCPseudoProbe * & LastProbe)143 void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
144                                    const MCPseudoProbe *&LastProbe) {
145   LLVM_DEBUG({
146     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
147     dbgs() << "Group [\n";
148     MCPseudoProbeTable::DdgPrintIndent += 2;
149   });
150   assert(!isRoot() && "Root should be handled separately");
151 
152   // Emit probes grouped by GUID.
153   LLVM_DEBUG({
154     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
155     dbgs() << "GUID: " << Guid << "\n";
156   });
157   // Emit Guid
158   MCOS->emitInt64(Guid);
159   // Emit number of probes in this node, including a sentinel probe for
160   // top-level functions if needed.
161   bool NeedSentinel = false;
162   if (Parent->isRoot()) {
163     assert(isSentinelProbe(LastProbe->getAttributes()) &&
164            "Starting probe of a top-level function should be a sentinel probe");
165     // The main body of a split function doesn't need a sentinel probe.
166     if (LastProbe->getGuid() != Guid)
167       NeedSentinel = true;
168   }
169 
170   MCOS->emitULEB128IntValue(Probes.size() + NeedSentinel);
171   // Emit number of direct inlinees
172   MCOS->emitULEB128IntValue(Children.size());
173   // Emit sentinel probe for top-level functions
174   if (NeedSentinel)
175     LastProbe->emit(MCOS, nullptr);
176 
177   // Emit probes in this group
178   for (const auto &Probe : Probes) {
179     Probe.emit(MCOS, LastProbe);
180     LastProbe = &Probe;
181   }
182 
183   // Emit sorted descendant. InlineSite is unique for each pair, so there will
184   // be no ordering of Inlinee based on MCPseudoProbeInlineTree*
185   using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
186   std::vector<InlineeType> Inlinees;
187   for (const auto &Child : Children)
188     Inlinees.emplace_back(Child.first, Child.second.get());
189   llvm::sort(Inlinees, llvm::less_first());
190 
191   for (const auto &Inlinee : Inlinees) {
192     // Emit probe index
193     MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));
194     LLVM_DEBUG({
195       dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
196       dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";
197     });
198     // Emit the group
199     Inlinee.second->emit(MCOS, LastProbe);
200   }
201 
202   LLVM_DEBUG({
203     MCPseudoProbeTable::DdgPrintIndent -= 2;
204     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
205     dbgs() << "]\n";
206   });
207 }
208 
emit(MCObjectStreamer * MCOS)209 void MCPseudoProbeSections::emit(MCObjectStreamer *MCOS) {
210   MCContext &Ctx = MCOS->getContext();
211   SmallVector<std::pair<MCSymbol *, MCPseudoProbeInlineTree *>> Vec;
212   Vec.reserve(MCProbeDivisions.size());
213   for (auto &ProbeSec : MCProbeDivisions)
214     Vec.emplace_back(ProbeSec.first, &ProbeSec.second);
215   for (auto I : llvm::enumerate(MCOS->getAssembler()))
216     I.value().setOrdinal(I.index());
217   llvm::sort(Vec, [](auto A, auto B) {
218     return A.first->getSection().getOrdinal() <
219            B.first->getSection().getOrdinal();
220   });
221   for (auto [FuncSym, RootPtr] : Vec) {
222     const auto &Root = *RootPtr;
223     if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(
224             FuncSym->getSection())) {
225       // Switch to the .pseudoprobe section or a comdat group.
226       MCOS->switchSection(S);
227       // Emit probes grouped by GUID.
228       // Emit sorted descendant. InlineSite is unique for each pair, so there
229       // will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
230       using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
231       std::vector<InlineeType> Inlinees;
232       for (const auto &Child : Root.getChildren())
233         Inlinees.emplace_back(Child.first, Child.second.get());
234       llvm::sort(Inlinees, llvm::less_first());
235 
236       for (const auto &Inlinee : Inlinees) {
237         // Emit the group guarded by a sentinel probe.
238         MCPseudoProbe SentinelProbe(
239             const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),
240             (uint32_t)PseudoProbeReservedId::Invalid,
241             (uint32_t)PseudoProbeType::Block,
242             (uint32_t)PseudoProbeAttributes::Sentinel, 0);
243         const MCPseudoProbe *Probe = &SentinelProbe;
244         Inlinee.second->emit(MCOS, Probe);
245       }
246     }
247   }
248 }
249 
250 //
251 // This emits the pseudo probe tables.
252 //
emit(MCObjectStreamer * MCOS)253 void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {
254   MCContext &Ctx = MCOS->getContext();
255   auto &ProbeTable = Ctx.getMCPseudoProbeTable();
256 
257   // Bail out early so we don't switch to the pseudo_probe section needlessly
258   // and in doing so create an unnecessary (if empty) section.
259   auto &ProbeSections = ProbeTable.getProbeSections();
260   if (ProbeSections.empty())
261     return;
262 
263   LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0);
264 
265   // Put out the probe.
266   ProbeSections.emit(MCOS);
267 }
268 
getProbeFNameForGUID(const GUIDProbeFunctionMap & GUID2FuncMAP,uint64_t GUID)269 static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
270                                       uint64_t GUID) {
271   auto It = GUID2FuncMAP.find(GUID);
272   assert(It != GUID2FuncMAP.end() &&
273          "Probe function must exist for a valid GUID");
274   return It->second.FuncName;
275 }
276 
print(raw_ostream & OS)277 void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
278   OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
279   OS << "Hash: " << FuncHash << "\n";
280 }
281 
getInlineContext(SmallVectorImpl<MCPseudoProbeFrameLocation> & ContextStack,const GUIDProbeFunctionMap & GUID2FuncMAP) const282 void MCDecodedPseudoProbe::getInlineContext(
283     SmallVectorImpl<MCPseudoProbeFrameLocation> &ContextStack,
284     const GUIDProbeFunctionMap &GUID2FuncMAP) const {
285   uint32_t Begin = ContextStack.size();
286   MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
287   // It will add the string of each node's inline site during iteration.
288   // Note that it won't include the probe's belonging function(leaf location)
289   while (Cur->hasInlineSite()) {
290     StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Cur->Parent->Guid);
291     ContextStack.emplace_back(
292         MCPseudoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));
293     Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
294   }
295   // Make the ContextStack in caller-callee order
296   std::reverse(ContextStack.begin() + Begin, ContextStack.end());
297 }
298 
getInlineContextStr(const GUIDProbeFunctionMap & GUID2FuncMAP) const299 std::string MCDecodedPseudoProbe::getInlineContextStr(
300     const GUIDProbeFunctionMap &GUID2FuncMAP) const {
301   std::ostringstream OContextStr;
302   SmallVector<MCPseudoProbeFrameLocation, 16> ContextStack;
303   getInlineContext(ContextStack, GUID2FuncMAP);
304   for (auto &Cxt : ContextStack) {
305     if (OContextStr.str().size())
306       OContextStr << " @ ";
307     OContextStr << Cxt.first.str() << ":" << Cxt.second;
308   }
309   return OContextStr.str();
310 }
311 
312 static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
313                                             "DirectCall"};
314 
print(raw_ostream & OS,const GUIDProbeFunctionMap & GUID2FuncMAP,bool ShowName) const315 void MCDecodedPseudoProbe::print(raw_ostream &OS,
316                                  const GUIDProbeFunctionMap &GUID2FuncMAP,
317                                  bool ShowName) const {
318   OS << "FUNC: ";
319   if (ShowName) {
320     StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);
321     OS << FuncName.str() << " ";
322   } else {
323     OS << Guid << " ";
324   }
325   OS << "Index: " << Index << "  ";
326   if (Discriminator)
327     OS << "Discriminator: " << Discriminator << "  ";
328   OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << "  ";
329   std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
330   if (InlineContextStr.size()) {
331     OS << "Inlined: @ ";
332     OS << InlineContextStr;
333   }
334   OS << "\n";
335 }
336 
readUnencodedNumber()337 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
338   if (Data + sizeof(T) > End) {
339     return std::error_code();
340   }
341   T Val = endian::readNext<T, llvm::endianness::little>(Data);
342   return ErrorOr<T>(Val);
343 }
344 
readUnsignedNumber()345 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
346   unsigned NumBytesRead = 0;
347   uint64_t Val = decodeULEB128(Data, &NumBytesRead);
348   if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
349     return std::error_code();
350   }
351   Data += NumBytesRead;
352   return ErrorOr<T>(static_cast<T>(Val));
353 }
354 
readSignedNumber()355 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
356   unsigned NumBytesRead = 0;
357   int64_t Val = decodeSLEB128(Data, &NumBytesRead);
358   if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
359     return std::error_code();
360   }
361   Data += NumBytesRead;
362   return ErrorOr<T>(static_cast<T>(Val));
363 }
364 
readString(uint32_t Size)365 ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
366   StringRef Str(reinterpret_cast<const char *>(Data), Size);
367   if (Data + Size > End) {
368     return std::error_code();
369   }
370   Data += Size;
371   return ErrorOr<StringRef>(Str);
372 }
373 
buildGUID2FuncDescMap(const uint8_t * Start,std::size_t Size)374 bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
375                                                  std::size_t Size) {
376   // The pseudo_probe_desc section has a format like:
377   // .section .pseudo_probe_desc,"",@progbits
378   // .quad -5182264717993193164   // GUID
379   // .quad 4294967295             // Hash
380   // .uleb 3                      // Name size
381   // .ascii "foo"                 // Name
382   // .quad -2624081020897602054
383   // .quad 174696971957
384   // .uleb 34
385   // .ascii "main"
386 
387   Data = Start;
388   End = Data + Size;
389 
390   while (Data < End) {
391     auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
392     if (!ErrorOrGUID)
393       return false;
394 
395     auto ErrorOrHash = readUnencodedNumber<uint64_t>();
396     if (!ErrorOrHash)
397       return false;
398 
399     auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
400     if (!ErrorOrNameSize)
401       return false;
402     uint32_t NameSize = std::move(*ErrorOrNameSize);
403 
404     auto ErrorOrName = readString(NameSize);
405     if (!ErrorOrName)
406       return false;
407 
408     uint64_t GUID = std::move(*ErrorOrGUID);
409     uint64_t Hash = std::move(*ErrorOrHash);
410     StringRef Name = std::move(*ErrorOrName);
411 
412     // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
413     GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
414   }
415   assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
416   return true;
417 }
418 
buildAddress2ProbeMap(MCDecodedPseudoProbeInlineTree * Cur,uint64_t & LastAddr,const Uint64Set & GuidFilter,const Uint64Map & FuncStartAddrs)419 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
420     MCDecodedPseudoProbeInlineTree *Cur, uint64_t &LastAddr,
421     const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs) {
422   // The pseudo_probe section encodes an inline forest and each tree has a
423   // format defined in MCPseudoProbe.h
424 
425   uint32_t Index = 0;
426   bool IsTopLevelFunc = Cur == &DummyInlineRoot;
427   if (IsTopLevelFunc) {
428     // Use a sequential id for top level inliner.
429     Index = Cur->getChildren().size();
430   } else {
431     // Read inline site for inlinees
432     auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
433     if (!ErrorOrIndex)
434       return false;
435     Index = std::move(*ErrorOrIndex);
436   }
437 
438   // Read guid
439   auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
440   if (!ErrorOrCurGuid)
441     return false;
442   uint64_t Guid = std::move(*ErrorOrCurGuid);
443 
444   // Decide if top-level node should be disgarded.
445   if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))
446     Cur = nullptr;
447 
448   // If the incoming node is null, all its children nodes should be disgarded.
449   if (Cur) {
450     // Switch/add to a new tree node(inlinee)
451     Cur = Cur->getOrAddNode(std::make_tuple(Guid, Index));
452     Cur->Guid = Guid;
453     if (IsTopLevelFunc && !EncodingIsAddrBased) {
454       if (auto V = FuncStartAddrs.lookup(Guid))
455         LastAddr = V;
456     }
457   }
458 
459   // Read number of probes in the current node.
460   auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
461   if (!ErrorOrNodeCount)
462     return false;
463   uint32_t NodeCount = std::move(*ErrorOrNodeCount);
464   // Read number of direct inlinees
465   auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
466   if (!ErrorOrCurChildrenToProcess)
467     return false;
468   // Read all probes in this node
469   for (std::size_t I = 0; I < NodeCount; I++) {
470     // Read index
471     auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
472     if (!ErrorOrIndex)
473       return false;
474     uint32_t Index = std::move(*ErrorOrIndex);
475     // Read type | flag.
476     auto ErrorOrValue = readUnencodedNumber<uint8_t>();
477     if (!ErrorOrValue)
478       return false;
479     uint8_t Value = std::move(*ErrorOrValue);
480     uint8_t Kind = Value & 0xf;
481     uint8_t Attr = (Value & 0x70) >> 4;
482     // Read address
483     uint64_t Addr = 0;
484     if (Value & 0x80) {
485       auto ErrorOrOffset = readSignedNumber<int64_t>();
486       if (!ErrorOrOffset)
487         return false;
488       int64_t Offset = std::move(*ErrorOrOffset);
489       Addr = LastAddr + Offset;
490     } else {
491       auto ErrorOrAddr = readUnencodedNumber<int64_t>();
492       if (!ErrorOrAddr)
493         return false;
494       Addr = std::move(*ErrorOrAddr);
495       if (isSentinelProbe(Attr)) {
496         // For sentinel probe, the addr field actually stores the GUID of the
497         // split function. Convert it to the real address.
498         if (auto V = FuncStartAddrs.lookup(Addr))
499           Addr = V;
500       } else {
501         // For now we assume all probe encoding should be either based on
502         // leading probe address or function start address.
503         // The scheme is for downwards compatibility.
504         // TODO: retire this scheme once compatibility is no longer an issue.
505         EncodingIsAddrBased = true;
506       }
507     }
508 
509     uint32_t Discriminator = 0;
510     if (hasDiscriminator(Attr)) {
511       auto ErrorOrDiscriminator = readUnsignedNumber<uint32_t>();
512       if (!ErrorOrDiscriminator)
513         return false;
514       Discriminator = std::move(*ErrorOrDiscriminator);
515     }
516 
517     if (Cur && !isSentinelProbe(Attr)) {
518       // Populate Address2ProbesMap
519       auto &Probes = Address2ProbesMap[Addr];
520       Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,
521                           Discriminator, Cur);
522       Cur->addProbes(&Probes.back());
523     }
524     LastAddr = Addr;
525   }
526 
527   uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
528   for (uint32_t I = 0; I < ChildrenToProcess; I++) {
529     buildAddress2ProbeMap(Cur, LastAddr, GuidFilter, FuncStartAddrs);
530   }
531 
532   return true;
533 }
534 
buildAddress2ProbeMap(const uint8_t * Start,std::size_t Size,const Uint64Set & GuidFilter,const Uint64Map & FuncStartAddrs)535 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
536     const uint8_t *Start, std::size_t Size, const Uint64Set &GuidFilter,
537     const Uint64Map &FuncStartAddrs) {
538   Data = Start;
539   End = Data + Size;
540   uint64_t LastAddr = 0;
541   while (Data < End)
542     buildAddress2ProbeMap(&DummyInlineRoot, LastAddr, GuidFilter,
543                           FuncStartAddrs);
544   assert(Data == End && "Have unprocessed data in pseudo_probe section");
545   return true;
546 }
547 
printGUID2FuncDescMap(raw_ostream & OS)548 void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
549   OS << "Pseudo Probe Desc:\n";
550   // Make the output deterministic
551   std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
552                                                        GUID2FuncDescMap.end());
553   for (auto &I : OrderedMap) {
554     I.second.print(OS);
555   }
556 }
557 
printProbeForAddress(raw_ostream & OS,uint64_t Address)558 void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
559                                                 uint64_t Address) {
560   auto It = Address2ProbesMap.find(Address);
561   if (It != Address2ProbesMap.end()) {
562     for (auto &Probe : It->second) {
563       OS << " [Probe]:\t";
564       Probe.print(OS, GUID2FuncDescMap, true);
565     }
566   }
567 }
568 
printProbesForAllAddresses(raw_ostream & OS)569 void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {
570   auto Entries = make_first_range(Address2ProbesMap);
571   SmallVector<uint64_t, 0> Addresses(Entries.begin(), Entries.end());
572   llvm::sort(Addresses);
573   for (auto K : Addresses) {
574     OS << "Address:\t";
575     OS << K;
576     OS << "\n";
577     printProbeForAddress(OS, K);
578   }
579 }
580 
581 const MCDecodedPseudoProbe *
getCallProbeForAddr(uint64_t Address) const582 MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
583   auto It = Address2ProbesMap.find(Address);
584   if (It == Address2ProbesMap.end())
585     return nullptr;
586   const auto &Probes = It->second;
587 
588   const MCDecodedPseudoProbe *CallProbe = nullptr;
589   for (const auto &Probe : Probes) {
590     if (Probe.isCall()) {
591       // Disabling the assert and returning first call probe seen so far.
592       // Subsequent call probes, if any, are ignored. Due to the the way
593       // .pseudo_probe section is decoded, probes of the same-named independent
594       // static functions are merged thus multiple call probes may be seen for a
595       // callsite. This should only happen to compiler-generated statics, with
596       // -funique-internal-linkage-names where user statics get unique names.
597       //
598       // TODO: re-enable or narrow down the assert to static functions only.
599       //
600       // assert(!CallProbe &&
601       //        "There should be only one call probe corresponding to address "
602       //        "which is a callsite.");
603       CallProbe = &Probe;
604       break;
605     }
606   }
607   return CallProbe;
608 }
609 
610 const MCPseudoProbeFuncDesc *
getFuncDescForGUID(uint64_t GUID) const611 MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
612   auto It = GUID2FuncDescMap.find(GUID);
613   assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
614   return &It->second;
615 }
616 
getInlineContextForProbe(const MCDecodedPseudoProbe * Probe,SmallVectorImpl<MCPseudoProbeFrameLocation> & InlineContextStack,bool IncludeLeaf) const617 void MCPseudoProbeDecoder::getInlineContextForProbe(
618     const MCDecodedPseudoProbe *Probe,
619     SmallVectorImpl<MCPseudoProbeFrameLocation> &InlineContextStack,
620     bool IncludeLeaf) const {
621   Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
622   if (!IncludeLeaf)
623     return;
624   // Note that the context from probe doesn't include leaf frame,
625   // hence we need to retrieve and prepend leaf if requested.
626   const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
627   InlineContextStack.emplace_back(
628       MCPseudoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
629 }
630 
getInlinerDescForProbe(const MCDecodedPseudoProbe * Probe) const631 const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(
632     const MCDecodedPseudoProbe *Probe) const {
633   MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();
634   if (!InlinerNode->hasInlineSite())
635     return nullptr;
636   return getFuncDescForGUID(InlinerNode->Parent->Guid);
637 }
638