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/MC/MCAsmInfo.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCObjectFileInfo.h"
13 #include "llvm/MC/MCObjectStreamer.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/Support/Endian.h"
16 #include "llvm/Support/LEB128.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <limits>
19 #include <memory>
20 #include <sstream>
21 
22 #define DEBUG_TYPE "mcpseudoprobe"
23 
24 using namespace llvm;
25 using namespace support;
26 
27 #ifndef NDEBUG
28 int MCPseudoProbeTable::DdgPrintIndent = 0;
29 #endif
30 
buildSymbolDiff(MCObjectStreamer * MCOS,const MCSymbol * A,const MCSymbol * B)31 static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,
32                                      const MCSymbol *B) {
33   MCContext &Context = MCOS->getContext();
34   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
35   const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
36   const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
37   const MCExpr *AddrDelta =
38       MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
39   return AddrDelta;
40 }
41 
emit(MCObjectStreamer * MCOS,const MCPseudoProbe * LastProbe) const42 void MCPseudoProbe::emit(MCObjectStreamer *MCOS,
43                          const MCPseudoProbe *LastProbe) const {
44   // Emit Index
45   MCOS->emitULEB128IntValue(Index);
46   // Emit Type and the flag:
47   // Type (bit 0 to 3), with bit 4 to 6 for attributes.
48   // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
49   // the following field is a symbolic code address or an address delta.
50   assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");
51   assert(Attributes <= 0x7 &&
52          "Probe attributes too big to encode, exceeding 7");
53   uint8_t PackedType = Type | (Attributes << 4);
54   uint8_t Flag = LastProbe ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;
55   MCOS->emitInt8(Flag | PackedType);
56 
57   if (LastProbe) {
58     // Emit the delta between the address label and LastProbe.
59     const MCExpr *AddrDelta =
60         buildSymbolDiff(MCOS, Label, LastProbe->getLabel());
61     int64_t Delta;
62     if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {
63       MCOS->emitSLEB128IntValue(Delta);
64     } else {
65       MCOS->insert(new MCPseudoProbeAddrFragment(AddrDelta));
66     }
67   } else {
68     // Emit label as a symbolic code address.
69     MCOS->emitSymbolValue(
70         Label, MCOS->getContext().getAsmInfo()->getCodePointerSize());
71   }
72 
73   LLVM_DEBUG({
74     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
75     dbgs() << "Probe: " << Index << "\n";
76   });
77 }
78 
addPseudoProbe(const MCPseudoProbe & Probe,const MCPseudoProbeInlineStack & InlineStack)79 void MCPseudoProbeInlineTree::addPseudoProbe(
80     const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
81   // The function should not be called on the root.
82   assert(isRoot() && "Should not be called on root");
83 
84   // When it comes here, the input look like:
85   //    Probe: GUID of C, ...
86   //    InlineStack: [88, A], [66, B]
87   // which means, Function A inlines function B at call site with a probe id of
88   // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
89   // A], [88, B], [66, C]} to locate the tree node where the probe should be
90   // added. Note that the edge [0, A] means A is the top-level function we are
91   // emitting probes for.
92 
93   // Make a [0, A] edge.
94   // An empty inline stack means the function that the probe originates from
95   // is a top-level function.
96   InlineSite Top;
97   if (InlineStack.empty()) {
98     Top = InlineSite(Probe.getGuid(), 0);
99   } else {
100     Top = InlineSite(std::get<0>(InlineStack.front()), 0);
101   }
102 
103   auto *Cur = getOrAddNode(Top);
104 
105   // Make interior edges by walking the inline stack. Once it's done, Cur should
106   // point to the node that the probe originates from.
107   if (!InlineStack.empty()) {
108     auto Iter = InlineStack.begin();
109     auto Index = std::get<1>(*Iter);
110     Iter++;
111     for (; Iter != InlineStack.end(); Iter++) {
112       // Make an edge by using the previous probe id and current GUID.
113       Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));
114       Index = std::get<1>(*Iter);
115     }
116     Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));
117   }
118 
119   Cur->Probes.push_back(Probe);
120 }
121 
emit(MCObjectStreamer * MCOS,const MCPseudoProbe * & LastProbe)122 void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
123                                    const MCPseudoProbe *&LastProbe) {
124   LLVM_DEBUG({
125     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
126     dbgs() << "Group [\n";
127     MCPseudoProbeTable::DdgPrintIndent += 2;
128   });
129   // Emit probes grouped by GUID.
130   if (Guid != 0) {
131     LLVM_DEBUG({
132       dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
133       dbgs() << "GUID: " << Guid << "\n";
134     });
135     // Emit Guid
136     MCOS->emitInt64(Guid);
137     // Emit number of probes in this node
138     MCOS->emitULEB128IntValue(Probes.size());
139     // Emit number of direct inlinees
140     MCOS->emitULEB128IntValue(Children.size());
141     // Emit probes in this group
142     for (const auto &Probe : Probes) {
143       Probe.emit(MCOS, LastProbe);
144       LastProbe = &Probe;
145     }
146   } else {
147     assert(Probes.empty() && "Root should not have probes");
148   }
149 
150   // Emit sorted descendant
151   // InlineSite is unique for each pair,
152   // so there will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
153   std::map<InlineSite, MCPseudoProbeInlineTree *> Inlinees;
154   for (auto Child = Children.begin(); Child != Children.end(); ++Child)
155     Inlinees[Child->first] = Child->second.get();
156 
157   for (const auto &Inlinee : Inlinees) {
158     if (Guid) {
159       // Emit probe index
160       MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));
161       LLVM_DEBUG({
162         dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
163         dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";
164       });
165     }
166     // Emit the group
167     Inlinee.second->emit(MCOS, LastProbe);
168   }
169 
170   LLVM_DEBUG({
171     MCPseudoProbeTable::DdgPrintIndent -= 2;
172     dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
173     dbgs() << "]\n";
174   });
175 }
176 
emit(MCObjectStreamer * MCOS)177 void MCPseudoProbeSection::emit(MCObjectStreamer *MCOS) {
178   MCContext &Ctx = MCOS->getContext();
179 
180   for (auto &ProbeSec : MCProbeDivisions) {
181     const MCPseudoProbe *LastProbe = nullptr;
182     if (auto *S =
183             Ctx.getObjectFileInfo()->getPseudoProbeSection(ProbeSec.first)) {
184       // Switch to the .pseudoprobe section or a comdat group.
185       MCOS->SwitchSection(S);
186       // Emit probes grouped by GUID.
187       ProbeSec.second.emit(MCOS, LastProbe);
188     }
189   }
190 }
191 
192 //
193 // This emits the pseudo probe tables.
194 //
emit(MCObjectStreamer * MCOS)195 void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {
196   MCContext &Ctx = MCOS->getContext();
197   auto &ProbeTable = Ctx.getMCPseudoProbeTable();
198 
199   // Bail out early so we don't switch to the pseudo_probe section needlessly
200   // and in doing so create an unnecessary (if empty) section.
201   auto &ProbeSections = ProbeTable.getProbeSections();
202   if (ProbeSections.empty())
203     return;
204 
205   LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0);
206 
207   // Put out the probe.
208   ProbeSections.emit(MCOS);
209 }
210 
getProbeFNameForGUID(const GUIDProbeFunctionMap & GUID2FuncMAP,uint64_t GUID)211 static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
212                                       uint64_t GUID) {
213   auto It = GUID2FuncMAP.find(GUID);
214   assert(It != GUID2FuncMAP.end() &&
215          "Probe function must exist for a valid GUID");
216   return It->second.FuncName;
217 }
218 
print(raw_ostream & OS)219 void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
220   OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
221   OS << "Hash: " << FuncHash << "\n";
222 }
223 
getInlineContext(SmallVectorImpl<MCPseduoProbeFrameLocation> & ContextStack,const GUIDProbeFunctionMap & GUID2FuncMAP) const224 void MCDecodedPseudoProbe::getInlineContext(
225     SmallVectorImpl<MCPseduoProbeFrameLocation> &ContextStack,
226     const GUIDProbeFunctionMap &GUID2FuncMAP) const {
227   uint32_t Begin = ContextStack.size();
228   MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
229   // It will add the string of each node's inline site during iteration.
230   // Note that it won't include the probe's belonging function(leaf location)
231   while (Cur->hasInlineSite()) {
232     StringRef FuncName =
233         getProbeFNameForGUID(GUID2FuncMAP, std::get<0>(Cur->ISite));
234     ContextStack.emplace_back(
235         MCPseduoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));
236     Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
237   }
238   // Make the ContextStack in caller-callee order
239   std::reverse(ContextStack.begin() + Begin, ContextStack.end());
240 }
241 
getInlineContextStr(const GUIDProbeFunctionMap & GUID2FuncMAP) const242 std::string MCDecodedPseudoProbe::getInlineContextStr(
243     const GUIDProbeFunctionMap &GUID2FuncMAP) const {
244   std::ostringstream OContextStr;
245   SmallVector<MCPseduoProbeFrameLocation, 16> ContextStack;
246   getInlineContext(ContextStack, GUID2FuncMAP);
247   for (auto &Cxt : ContextStack) {
248     if (OContextStr.str().size())
249       OContextStr << " @ ";
250     OContextStr << Cxt.first.str() << ":" << Cxt.second;
251   }
252   return OContextStr.str();
253 }
254 
255 static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
256                                             "DirectCall"};
257 
print(raw_ostream & OS,const GUIDProbeFunctionMap & GUID2FuncMAP,bool ShowName) const258 void MCDecodedPseudoProbe::print(raw_ostream &OS,
259                                  const GUIDProbeFunctionMap &GUID2FuncMAP,
260                                  bool ShowName) const {
261   OS << "FUNC: ";
262   if (ShowName) {
263     StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);
264     OS << FuncName.str() << " ";
265   } else {
266     OS << Guid << " ";
267   }
268   OS << "Index: " << Index << "  ";
269   OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << "  ";
270   std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
271   if (InlineContextStr.size()) {
272     OS << "Inlined: @ ";
273     OS << InlineContextStr;
274   }
275   OS << "\n";
276 }
277 
readUnencodedNumber()278 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
279   if (Data + sizeof(T) > End) {
280     return std::error_code();
281   }
282   T Val = endian::readNext<T, little, unaligned>(Data);
283   return ErrorOr<T>(Val);
284 }
285 
readUnsignedNumber()286 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
287   unsigned NumBytesRead = 0;
288   uint64_t Val = decodeULEB128(Data, &NumBytesRead);
289   if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
290     return std::error_code();
291   }
292   Data += NumBytesRead;
293   return ErrorOr<T>(static_cast<T>(Val));
294 }
295 
readSignedNumber()296 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
297   unsigned NumBytesRead = 0;
298   int64_t Val = decodeSLEB128(Data, &NumBytesRead);
299   if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
300     return std::error_code();
301   }
302   Data += NumBytesRead;
303   return ErrorOr<T>(static_cast<T>(Val));
304 }
305 
readString(uint32_t Size)306 ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
307   StringRef Str(reinterpret_cast<const char *>(Data), Size);
308   if (Data + Size > End) {
309     return std::error_code();
310   }
311   Data += Size;
312   return ErrorOr<StringRef>(Str);
313 }
314 
buildGUID2FuncDescMap(const uint8_t * Start,std::size_t Size)315 bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
316                                                  std::size_t Size) {
317   // The pseudo_probe_desc section has a format like:
318   // .section .pseudo_probe_desc,"",@progbits
319   // .quad -5182264717993193164   // GUID
320   // .quad 4294967295             // Hash
321   // .uleb 3                      // Name size
322   // .ascii "foo"                 // Name
323   // .quad -2624081020897602054
324   // .quad 174696971957
325   // .uleb 34
326   // .ascii "main"
327 
328   Data = Start;
329   End = Data + Size;
330 
331   while (Data < End) {
332     auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
333     if (!ErrorOrGUID)
334       return false;
335 
336     auto ErrorOrHash = readUnencodedNumber<uint64_t>();
337     if (!ErrorOrHash)
338       return false;
339 
340     auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
341     if (!ErrorOrNameSize)
342       return false;
343     uint32_t NameSize = std::move(*ErrorOrNameSize);
344 
345     auto ErrorOrName = readString(NameSize);
346     if (!ErrorOrName)
347       return false;
348 
349     uint64_t GUID = std::move(*ErrorOrGUID);
350     uint64_t Hash = std::move(*ErrorOrHash);
351     StringRef Name = std::move(*ErrorOrName);
352 
353     // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
354     GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
355   }
356   assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
357   return true;
358 }
359 
buildAddress2ProbeMap(const uint8_t * Start,std::size_t Size)360 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(const uint8_t *Start,
361                                                  std::size_t Size) {
362   // The pseudo_probe section encodes an inline forest and each tree has a
363   // format like:
364   //  FUNCTION BODY (one for each uninlined function present in the text
365   //  section)
366   //     GUID (uint64)
367   //         GUID of the function
368   //     NPROBES (ULEB128)
369   //         Number of probes originating from this function.
370   //     NUM_INLINED_FUNCTIONS (ULEB128)
371   //         Number of callees inlined into this function, aka number of
372   //         first-level inlinees
373   //     PROBE RECORDS
374   //         A list of NPROBES entries. Each entry contains:
375   //           INDEX (ULEB128)
376   //           TYPE (uint4)
377   //             0 - block probe, 1 - indirect call, 2 - direct call
378   //           ATTRIBUTE (uint3)
379   //             1 - tail call, 2 - dangling
380   //           ADDRESS_TYPE (uint1)
381   //             0 - code address, 1 - address delta
382   //           CODE_ADDRESS (uint64 or ULEB128)
383   //             code address or address delta, depending on Flag
384   //     INLINED FUNCTION RECORDS
385   //         A list of NUM_INLINED_FUNCTIONS entries describing each of the
386   //         inlined callees.  Each record contains:
387   //           INLINE SITE
388   //             Index of the callsite probe (ULEB128)
389   //           FUNCTION BODY
390   //             A FUNCTION BODY entry describing the inlined function.
391 
392   Data = Start;
393   End = Data + Size;
394 
395   MCDecodedPseudoProbeInlineTree *Root = &DummyInlineRoot;
396   MCDecodedPseudoProbeInlineTree *Cur = &DummyInlineRoot;
397   uint64_t LastAddr = 0;
398   uint32_t Index = 0;
399   // A DFS-based decoding
400   while (Data < End) {
401     if (Root == Cur) {
402       // Use a sequential id for top level inliner.
403       Index = Root->getChildren().size();
404     } else {
405       // Read inline site for inlinees
406       auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
407       if (!ErrorOrIndex)
408         return false;
409       Index = std::move(*ErrorOrIndex);
410     }
411     // Switch/add to a new tree node(inlinee)
412     Cur = Cur->getOrAddNode(std::make_tuple(Cur->Guid, Index));
413     // Read guid
414     auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
415     if (!ErrorOrCurGuid)
416       return false;
417     Cur->Guid = std::move(*ErrorOrCurGuid);
418     // Read number of probes in the current node.
419     auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
420     if (!ErrorOrNodeCount)
421       return false;
422     uint32_t NodeCount = std::move(*ErrorOrNodeCount);
423     // Read number of direct inlinees
424     auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
425     if (!ErrorOrCurChildrenToProcess)
426       return false;
427     Cur->ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
428     // Read all probes in this node
429     for (std::size_t I = 0; I < NodeCount; I++) {
430       // Read index
431       auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
432       if (!ErrorOrIndex)
433         return false;
434       uint32_t Index = std::move(*ErrorOrIndex);
435       // Read type | flag.
436       auto ErrorOrValue = readUnencodedNumber<uint8_t>();
437       if (!ErrorOrValue)
438         return false;
439       uint8_t Value = std::move(*ErrorOrValue);
440       uint8_t Kind = Value & 0xf;
441       uint8_t Attr = (Value & 0x70) >> 4;
442       // Read address
443       uint64_t Addr = 0;
444       if (Value & 0x80) {
445         auto ErrorOrOffset = readSignedNumber<int64_t>();
446         if (!ErrorOrOffset)
447           return false;
448         int64_t Offset = std::move(*ErrorOrOffset);
449         Addr = LastAddr + Offset;
450       } else {
451         auto ErrorOrAddr = readUnencodedNumber<int64_t>();
452         if (!ErrorOrAddr)
453           return false;
454         Addr = std::move(*ErrorOrAddr);
455       }
456       // Populate Address2ProbesMap
457       auto &Probes = Address2ProbesMap[Addr];
458       Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,
459                           Cur);
460       Cur->addProbes(&Probes.back());
461       LastAddr = Addr;
462     }
463 
464     // Look for the parent for the next node by subtracting the current
465     // node count from tree counts along the parent chain. The first node
466     // in the chain that has a non-zero tree count is the target.
467     while (Cur != Root) {
468       if (Cur->ChildrenToProcess == 0) {
469         Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
470         if (Cur != Root) {
471           assert(Cur->ChildrenToProcess > 0 &&
472                  "Should have some unprocessed nodes");
473           Cur->ChildrenToProcess -= 1;
474         }
475       } else {
476         break;
477       }
478     }
479   }
480 
481   assert(Data == End && "Have unprocessed data in pseudo_probe section");
482   assert(Cur == Root &&
483          " Cur should point to root when the forest is fully built up");
484   return true;
485 }
486 
printGUID2FuncDescMap(raw_ostream & OS)487 void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
488   OS << "Pseudo Probe Desc:\n";
489   // Make the output deterministic
490   std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
491                                                        GUID2FuncDescMap.end());
492   for (auto &I : OrderedMap) {
493     I.second.print(OS);
494   }
495 }
496 
printProbeForAddress(raw_ostream & OS,uint64_t Address)497 void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
498                                                 uint64_t Address) {
499   auto It = Address2ProbesMap.find(Address);
500   if (It != Address2ProbesMap.end()) {
501     for (auto &Probe : It->second) {
502       OS << " [Probe]:\t";
503       Probe.print(OS, GUID2FuncDescMap, true);
504     }
505   }
506 }
507 
printProbesForAllAddresses(raw_ostream & OS)508 void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {
509   std::vector<uint64_t> Addresses;
510   for (auto Entry : Address2ProbesMap)
511     Addresses.push_back(Entry.first);
512   std::sort(Addresses.begin(), Addresses.end());
513   for (auto K : Addresses) {
514     OS << "Address:\t";
515     OS << K;
516     OS << "\n";
517     printProbeForAddress(OS, K);
518   }
519 }
520 
521 const MCDecodedPseudoProbe *
getCallProbeForAddr(uint64_t Address) const522 MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
523   auto It = Address2ProbesMap.find(Address);
524   if (It == Address2ProbesMap.end())
525     return nullptr;
526   const auto &Probes = It->second;
527 
528   const MCDecodedPseudoProbe *CallProbe = nullptr;
529   for (const auto &Probe : Probes) {
530     if (Probe.isCall()) {
531       assert(!CallProbe &&
532              "There should be only one call probe corresponding to address "
533              "which is a callsite.");
534       CallProbe = &Probe;
535     }
536   }
537   return CallProbe;
538 }
539 
540 const MCPseudoProbeFuncDesc *
getFuncDescForGUID(uint64_t GUID) const541 MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
542   auto It = GUID2FuncDescMap.find(GUID);
543   assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
544   return &It->second;
545 }
546 
getInlineContextForProbe(const MCDecodedPseudoProbe * Probe,SmallVectorImpl<MCPseduoProbeFrameLocation> & InlineContextStack,bool IncludeLeaf) const547 void MCPseudoProbeDecoder::getInlineContextForProbe(
548     const MCDecodedPseudoProbe *Probe,
549     SmallVectorImpl<MCPseduoProbeFrameLocation> &InlineContextStack,
550     bool IncludeLeaf) const {
551   Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
552   if (!IncludeLeaf)
553     return;
554   // Note that the context from probe doesn't include leaf frame,
555   // hence we need to retrieve and prepend leaf if requested.
556   const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
557   InlineContextStack.emplace_back(
558       MCPseduoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
559 }
560 
getInlinerDescForProbe(const MCDecodedPseudoProbe * Probe) const561 const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(
562     const MCDecodedPseudoProbe *Probe) const {
563   MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();
564   if (!InlinerNode->hasInlineSite())
565     return nullptr;
566   return getFuncDescForGUID(std::get<0>(InlinerNode->ISite));
567 }
568