MCPseudoProbe.cpp 21 KB

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