MCPseudoProbe.cpp 19 KB

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