LLVM 22.0.0git
MCPseudoProbe.cpp
Go to the documentation of this file.
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
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"
18#include "llvm/MC/MCSymbol.h"
19#include "llvm/Support/Endian.h"
20#include "llvm/Support/Error.h"
21#include "llvm/Support/LEB128.h"
22#include "llvm/Support/MD5.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
33using namespace llvm;
34using namespace support;
35
36#ifndef NDEBUG
38#endif
39
40static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,
41 const MCSymbol *B) {
42 MCContext &Context = MCOS->getContext();
45 const MCExpr *AddrDelta =
47 return AddrDelta;
48}
49
50uint64_t MCDecodedPseudoProbe::getGuid() const { return InlineTree->Guid; }
51
53 const MCPseudoProbe *LastProbe) const {
54 bool IsSentinel = isSentinelProbe(getAttributes());
55 assert((LastProbe || IsSentinel) &&
56 "Last probe should not be null for non-sentinel probes");
57
58 // Emit Index
60 // Emit Type and the flag:
61 // Type (bit 0 to 3), with bit 4 to 6 for attributes.
62 // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
63 // the following field is a symbolic code address or an address delta.
64 // Emit FS discriminator
65 assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");
66 auto NewAttributes = Attributes;
67 if (Discriminator)
69 assert(NewAttributes <= 0x7 &&
70 "Probe attributes too big to encode, exceeding 7");
71 uint8_t PackedType = Type | (NewAttributes << 4);
72 uint8_t Flag =
73 !IsSentinel ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;
74 MCOS->emitInt8(Flag | PackedType);
75
76 if (!IsSentinel) {
77 // Emit the delta between the address label and LastProbe.
78 const MCExpr *AddrDelta =
79 buildSymbolDiff(MCOS, Label, LastProbe->getLabel());
80 int64_t Delta;
81 if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {
82 MCOS->emitSLEB128IntValue(Delta);
83 } else {
84 auto *F = MCOS->getCurrentFragment();
85 F->makeLEB(true, AddrDelta);
86 MCOS->newFragment();
87 }
88 } else {
89 // Emit the GUID of the split function that the sentinel probe represents.
90 MCOS->emitInt64(Guid);
91 }
92
93 if (Discriminator)
95
98 dbgs() << "Probe: " << Index << "\n";
99 });
100}
101
103 const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
104 // The function should not be called on the root.
105 assert(isRoot() && "Should only be called on root");
106
107 // When it comes here, the input look like:
108 // Probe: GUID of C, ...
109 // InlineStack: [88, A], [66, B]
110 // which means, Function A inlines function B at call site with a probe id of
111 // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
112 // A], [88, B], [66, C]} to locate the tree node where the probe should be
113 // added. Note that the edge [0, A] means A is the top-level function we are
114 // emitting probes for.
115
116 // Make a [0, A] edge.
117 // An empty inline stack means the function that the probe originates from
118 // is a top-level function.
119 InlineSite Top;
120 if (InlineStack.empty()) {
121 Top = InlineSite(Probe.getGuid(), 0);
122 } else {
123 Top = InlineSite(std::get<0>(InlineStack.front()), 0);
124 }
125
126 auto *Cur = getOrAddNode(Top);
127
128 // Make interior edges by walking the inline stack. Once it's done, Cur should
129 // point to the node that the probe originates from.
130 if (!InlineStack.empty()) {
131 auto Iter = InlineStack.begin();
132 auto Index = std::get<1>(*Iter);
133 Iter++;
134 for (; Iter != InlineStack.end(); Iter++) {
135 // Make an edge by using the previous probe id and current GUID.
136 Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));
137 Index = std::get<1>(*Iter);
138 }
139 Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));
140 }
141
142 Cur->Probes.push_back(Probe);
143}
144
146 const MCPseudoProbe *&LastProbe) {
147 LLVM_DEBUG({
149 dbgs() << "Group [\n";
151 });
152 assert(!isRoot() && "Root should be handled separately");
153
154 // Emit probes grouped by GUID.
155 LLVM_DEBUG({
157 dbgs() << "GUID: " << Guid << "\n";
158 });
159 // Emit Guid
160 MCOS->emitInt64(Guid);
161 // Emit number of probes in this node, including a sentinel probe for
162 // top-level functions if needed.
163 bool NeedSentinel = false;
164 if (Parent->isRoot()) {
165 assert(isSentinelProbe(LastProbe->getAttributes()) &&
166 "Starting probe of a top-level function should be a sentinel probe");
167 // The main body of a split function doesn't need a sentinel probe.
168 if (LastProbe->getGuid() != Guid)
169 NeedSentinel = true;
170 }
171
172 MCOS->emitULEB128IntValue(Probes.size() + NeedSentinel);
173 // Emit number of direct inlinees
174 MCOS->emitULEB128IntValue(Children.size());
175 // Emit sentinel probe for top-level functions
176 if (NeedSentinel)
177 LastProbe->emit(MCOS, nullptr);
178
179 // Emit probes in this group
180 for (const auto &Probe : Probes) {
181 Probe.emit(MCOS, LastProbe);
182 LastProbe = &Probe;
183 }
184
185 // Emit sorted descendant. InlineSite is unique for each pair, so there will
186 // be no ordering of Inlinee based on MCPseudoProbeInlineTree*
187 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
188 std::vector<InlineeType> Inlinees;
189 for (const auto &Child : Children)
190 Inlinees.emplace_back(Child.first, Child.second.get());
191 llvm::sort(Inlinees, llvm::less_first());
192
193 for (const auto &Inlinee : Inlinees) {
194 // Emit probe index
195 MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));
196 LLVM_DEBUG({
198 dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";
199 });
200 // Emit the group
201 Inlinee.second->emit(MCOS, LastProbe);
202 }
203
204 LLVM_DEBUG({
207 dbgs() << "]\n";
208 });
209}
210
212 MCContext &Ctx = MCOS->getContext();
214 Vec.reserve(MCProbeDivisions.size());
215 for (auto &ProbeSec : MCProbeDivisions)
216 Vec.emplace_back(ProbeSec.first, &ProbeSec.second);
217 for (auto I : llvm::enumerate(MCOS->getAssembler()))
218 I.value().setOrdinal(I.index());
219 llvm::sort(Vec, [](auto A, auto B) {
220 return A.first->getSection().getOrdinal() <
221 B.first->getSection().getOrdinal();
222 });
223 for (auto [FuncSym, RootPtr] : Vec) {
224 const auto &Root = *RootPtr;
225 if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(
226 FuncSym->getSection())) {
227 // Switch to the .pseudoprobe section or a comdat group.
228 MCOS->switchSection(S);
229 // Emit probes grouped by GUID.
230 // Emit sorted descendant. InlineSite is unique for each pair, so there
231 // will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
232 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
233 std::vector<InlineeType> Inlinees;
234 for (const auto &Child : Root.getChildren())
235 Inlinees.emplace_back(Child.first, Child.second.get());
236 llvm::sort(Inlinees, llvm::less_first());
237
238 for (const auto &Inlinee : Inlinees) {
239 // Emit the group guarded by a sentinel probe.
240 MCPseudoProbe SentinelProbe(
241 const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),
245 const MCPseudoProbe *Probe = &SentinelProbe;
246 Inlinee.second->emit(MCOS, Probe);
247 }
248 }
249 }
250}
251
252//
253// This emits the pseudo probe tables.
254//
256 MCContext &Ctx = MCOS->getContext();
257 auto &ProbeTable = Ctx.getMCPseudoProbeTable();
258
259 // Bail out early so we don't switch to the pseudo_probe section needlessly
260 // and in doing so create an unnecessary (if empty) section.
261 auto &ProbeSections = ProbeTable.getProbeSections();
262 if (ProbeSections.empty())
263 return;
264
266
267 // Put out the probe.
268 ProbeSections.emit(MCOS);
269}
270
272 uint64_t GUID) {
273 auto It = GUID2FuncMAP.find(GUID);
274 assert(It != GUID2FuncMAP.end() &&
275 "Probe function must exist for a valid GUID");
276 return It->FuncName;
277}
278
280 OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
281 OS << "Hash: " << FuncHash << "\n";
282}
283
286 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
287 uint32_t Begin = ContextStack.size();
288 MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
289 // It will add the string of each node's inline site during iteration.
290 // Note that it won't include the probe's belonging function(leaf location)
291 while (Cur->hasInlineSite()) {
292 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Cur->Parent->Guid);
294 FuncName, std::get<1>(Cur->getInlineSite())));
295 Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
296 }
297 // Make the ContextStack in caller-callee order
298 std::reverse(ContextStack.begin() + Begin, ContextStack.end());
299}
300
302 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
303 std::ostringstream OContextStr;
305 getInlineContext(ContextStack, GUID2FuncMAP);
306 for (auto &Cxt : ContextStack) {
307 if (OContextStr.str().size())
308 OContextStr << " @ ";
309 OContextStr << Cxt.first.str() << ":" << Cxt.second;
310 }
311 return OContextStr.str();
312}
313
314static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
315 "DirectCall"};
316
318 const GUIDProbeFunctionMap &GUID2FuncMAP,
319 bool ShowName) const {
320 OS << "FUNC: ";
321 if (ShowName) {
322 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, getGuid());
323 OS << FuncName.str() << " ";
324 } else {
325 OS << getGuid() << " ";
326 }
327 OS << "Index: " << Index << " ";
328 if (Discriminator)
329 OS << "Discriminator: " << Discriminator << " ";
330 OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << " ";
331 std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
332 if (InlineContextStr.size()) {
333 OS << "Inlined: @ ";
334 OS << InlineContextStr;
335 }
336 OS << "\n";
337}
338
339template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
340 if (Data + sizeof(T) > End) {
341 return std::error_code();
342 }
343 T Val = endian::readNext<T, llvm::endianness::little>(Data);
344 return ErrorOr<T>(Val);
345}
346
347template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
348 unsigned NumBytesRead = 0;
349 uint64_t Val = decodeULEB128(Data, &NumBytesRead);
350 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
351 return std::error_code();
352 }
353 Data += NumBytesRead;
354 return ErrorOr<T>(static_cast<T>(Val));
355}
356
357template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
358 unsigned NumBytesRead = 0;
359 int64_t Val = decodeSLEB128(Data, &NumBytesRead);
360 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
361 return std::error_code();
362 }
363 Data += NumBytesRead;
364 return ErrorOr<T>(static_cast<T>(Val));
365}
366
367ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
368 StringRef Str(reinterpret_cast<const char *>(Data), Size);
369 if (Data + Size > End) {
370 return std::error_code();
371 }
372 Data += Size;
373 return ErrorOr<StringRef>(Str);
374}
375
377 std::size_t Size,
378 bool IsMMapped) {
379 // The pseudo_probe_desc section has a format like:
380 // .section .pseudo_probe_desc,"",@progbits
381 // .quad -5182264717993193164 // GUID
382 // .quad 4294967295 // Hash
383 // .uleb 3 // Name size
384 // .ascii "foo" // Name
385 // .quad -2624081020897602054
386 // .quad 174696971957
387 // .uleb 34
388 // .ascii "main"
389
390 Data = Start;
391 End = Data + Size;
392
393 uint32_t FuncDescCount = 0;
394 while (Data < End) {
395 // GUID
396 if (!readUnencodedNumber<uint64_t>())
397 return false;
398 // Hash
399 if (!readUnencodedNumber<uint64_t>())
400 return false;
401
402 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
403 if (!ErrorOrNameSize)
404 return false;
405 // Function name
406 if (!readString(*ErrorOrNameSize))
407 return false;
408 ++FuncDescCount;
409 }
410 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
411 GUID2FuncDescMap.reserve(FuncDescCount);
412
413 Data = Start;
414 End = Data + Size;
415 while (Data < End) {
416 uint64_t GUID =
417 cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
418 uint64_t Hash =
419 cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
421 cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
423
424 // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
425 GUID2FuncDescMap.emplace_back(
426 GUID, Hash, IsMMapped ? Name : Name.copy(FuncNameAllocator));
427 }
428 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
429 assert(GUID2FuncDescMap.size() == FuncDescCount &&
430 "Mismatching function description count pre- and post-parsing");
431 llvm::sort(GUID2FuncDescMap, [](const auto &LHS, const auto &RHS) {
432 return LHS.FuncGUID < RHS.FuncGUID;
433 });
434 return true;
435}
436
437template <bool IsTopLevelFunc>
440 const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs,
441 const uint32_t CurChildIndex) {
442 // The pseudo_probe section encodes an inline forest and each tree has a
443 // format defined in MCPseudoProbe.h
444
445 uint32_t Index = 0;
446 if (IsTopLevelFunc) {
447 // Use a sequential id for top level inliner.
448 Index = CurChildIndex;
449 } else {
450 // Read inline site for inlinees
451 Index = cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
452 }
453
454 // Read guid
455 uint64_t Guid = cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
456
457 // Decide if top-level node should be disgarded.
458 if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))
459 Cur = nullptr;
460
461 // If the incoming node is null, all its children nodes should be disgarded.
462 if (Cur) {
463 // Switch/add to a new tree node(inlinee)
464 Cur->getChildren()[CurChildIndex] =
466 Cur = &Cur->getChildren()[CurChildIndex];
467 if (IsTopLevelFunc && !EncodingIsAddrBased) {
468 if (auto V = FuncStartAddrs.lookup(Guid))
469 LastAddr = V;
470 }
471 }
472
473 // Read number of probes in the current node.
474 uint32_t NodeCount =
475 cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
476 uint32_t CurrentProbeCount = 0;
477 // Read number of direct inlinees
478 uint32_t ChildrenToProcess =
479 cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
480 // Read all probes in this node
481 for (std::size_t I = 0; I < NodeCount; I++) {
482 // Read index
484 cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
485 // Read type | flag.
486 uint8_t Value = cantFail(errorOrToExpected(readUnencodedNumber<uint8_t>()));
487 uint8_t Kind = Value & 0xf;
488 uint8_t Attr = (Value & 0x70) >> 4;
489 // Read address
490 uint64_t Addr = 0;
491 if (Value & 0x80) {
492 int64_t Offset = cantFail(errorOrToExpected(readSignedNumber<int64_t>()));
493 Addr = LastAddr + Offset;
494 } else {
495 Addr = cantFail(errorOrToExpected(readUnencodedNumber<int64_t>()));
496 if (isSentinelProbe(Attr)) {
497 // For sentinel probe, the addr field actually stores the GUID of the
498 // split function. Convert it to the real address.
499 if (auto V = FuncStartAddrs.lookup(Addr))
500 Addr = V;
501 } else {
502 // For now we assume all probe encoding should be either based on
503 // leading probe address or function start address.
504 // The scheme is for downwards compatibility.
505 // TODO: retire this scheme once compatibility is no longer an issue.
506 EncodingIsAddrBased = true;
507 }
508 }
509
511 if (hasDiscriminator(Attr)) {
513 cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
514 }
515
516 if (Cur && !isSentinelProbe(Attr)) {
517 PseudoProbeVec.emplace_back(Addr, Index, PseudoProbeType(Kind), Attr,
518 Discriminator, Cur);
519 ++CurrentProbeCount;
520 }
521 LastAddr = Addr;
522 }
523
524 if (Cur) {
525 Cur->setProbes(
526 MutableArrayRef(PseudoProbeVec).take_back(CurrentProbeCount));
527 InlineTreeVec.resize(InlineTreeVec.size() + ChildrenToProcess);
528 Cur->getChildren() =
529 MutableArrayRef(InlineTreeVec).take_back(ChildrenToProcess);
530 }
531 for (uint32_t I = 0; I < ChildrenToProcess; I++) {
532 buildAddress2ProbeMap<false>(Cur, LastAddr, GuidFilter, FuncStartAddrs, I);
533 }
534 return Cur;
535}
536
537template <bool IsTopLevelFunc>
538bool MCPseudoProbeDecoder::countRecords(bool &Discard, uint32_t &ProbeCount,
539 uint32_t &InlinedCount,
540 const Uint64Set &GuidFilter) {
541 if (!IsTopLevelFunc)
542 // Read inline site for inlinees
543 if (!readUnsignedNumber<uint32_t>())
544 return false;
545
546 // Read guid
547 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
548 if (!ErrorOrCurGuid)
549 return false;
550 uint64_t Guid = std::move(*ErrorOrCurGuid);
551
552 // Decide if top-level node should be disgarded.
553 if (IsTopLevelFunc) {
554 Discard = !GuidFilter.empty() && !GuidFilter.count(Guid);
555 if (!Discard)
556 // Allocate an entry for top-level function record.
557 ++InlinedCount;
558 }
559
560 // Read number of probes in the current node.
561 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
562 if (!ErrorOrNodeCount)
563 return false;
564 uint32_t NodeCount = std::move(*ErrorOrNodeCount);
565 uint32_t CurrentProbeCount = 0;
566
567 // Read number of direct inlinees
568 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
569 if (!ErrorOrCurChildrenToProcess)
570 return false;
571 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
572
573 // Read all probes in this node
574 for (std::size_t I = 0; I < NodeCount; I++) {
575 // Read index
576 if (!readUnsignedNumber<uint32_t>())
577 return false;
578
579 // Read type | flag.
580 auto ErrorOrValue = readUnencodedNumber<uint8_t>();
581 if (!ErrorOrValue)
582 return false;
583 uint8_t Value = std::move(*ErrorOrValue);
584
585 uint8_t Attr = (Value & 0x70) >> 4;
586 if (Value & 0x80) {
587 // Offset
588 if (!readSignedNumber<int64_t>())
589 return false;
590 } else {
591 // Addr
592 if (!readUnencodedNumber<int64_t>())
593 return false;
594 }
595
596 if (hasDiscriminator(Attr))
597 // Discriminator
598 if (!readUnsignedNumber<uint32_t>())
599 return false;
600
601 if (!Discard && !isSentinelProbe(Attr))
602 ++CurrentProbeCount;
603 }
604
605 if (!Discard) {
606 ProbeCount += CurrentProbeCount;
607 InlinedCount += ChildrenToProcess;
608 }
609
610 for (uint32_t I = 0; I < ChildrenToProcess; I++)
611 if (!countRecords<false>(Discard, ProbeCount, InlinedCount, GuidFilter))
612 return false;
613 return true;
614}
615
617 const uint8_t *Start, std::size_t Size, const Uint64Set &GuidFilter,
618 const Uint64Map &FuncStartAddrs) {
619 // For function records in the order of their appearance in the encoded data
620 // (DFS), count the number of contained probes and inlined function records.
621 uint32_t ProbeCount = 0;
622 uint32_t InlinedCount = 0;
623 uint32_t TopLevelFuncs = 0;
624 Data = Start;
625 End = Data + Size;
626 bool Discard = false;
627 while (Data < End) {
628 if (!countRecords<true>(Discard, ProbeCount, InlinedCount, GuidFilter))
629 return false;
630 TopLevelFuncs += !Discard;
631 }
632 assert(Data == End && "Have unprocessed data in pseudo_probe section");
633 PseudoProbeVec.reserve(ProbeCount);
634 InlineTreeVec.reserve(InlinedCount);
635
636 // Allocate top-level function records as children of DummyInlineRoot.
637 InlineTreeVec.resize(TopLevelFuncs);
638 DummyInlineRoot.getChildren() = MutableArrayRef(InlineTreeVec);
639
640 Data = Start;
641 End = Data + Size;
642 uint64_t LastAddr = 0;
643 uint32_t CurChildIndex = 0;
644 while (Data < End)
645 CurChildIndex += buildAddress2ProbeMap<true>(
646 &DummyInlineRoot, LastAddr, GuidFilter, FuncStartAddrs, CurChildIndex);
647 assert(Data == End && "Have unprocessed data in pseudo_probe section");
648 assert(PseudoProbeVec.size() == ProbeCount &&
649 "Mismatching probe count pre- and post-parsing");
650 assert(InlineTreeVec.size() == InlinedCount &&
651 "Mismatching function records count pre- and post-parsing");
652
653 std::vector<std::pair<uint64_t, uint32_t>> SortedA2P(ProbeCount);
654 for (const auto &[I, Probe] : llvm::enumerate(PseudoProbeVec))
655 SortedA2P[I] = {Probe.getAddress(), I};
656 llvm::sort(SortedA2P);
657 Address2ProbesMap.reserve(ProbeCount);
658 for (const uint32_t I : llvm::make_second_range(SortedA2P))
659 Address2ProbesMap.emplace_back(PseudoProbeVec[I]);
660 SortedA2P.clear();
661 return true;
662}
663
665 OS << "Pseudo Probe Desc:\n";
666 for (auto &I : GUID2FuncDescMap)
667 I.print(OS);
668}
669
672 for (const MCDecodedPseudoProbe &Probe : Address2ProbesMap.find(Address)) {
673 OS << " [Probe]:\t";
674 Probe.print(OS, GUID2FuncDescMap, true);
675 }
676}
677
679 uint64_t PrevAddress = INT64_MAX;
680 for (MCDecodedPseudoProbe &Probe : Address2ProbesMap) {
681 uint64_t Address = Probe.getAddress();
682 if (Address != PrevAddress) {
683 PrevAddress = Address;
684 OS << "Address:\t" << Address << '\n';
685 }
686 OS << " [Probe]:\t";
687 Probe.print(OS, GUID2FuncDescMap, true);
688 }
689}
690
693 const MCDecodedPseudoProbe *CallProbe = nullptr;
694 for (const MCDecodedPseudoProbe &Probe : Address2ProbesMap.find(Address)) {
695 if (Probe.isCall()) {
696 // Disabling the assert and returning first call probe seen so far.
697 // Subsequent call probes, if any, are ignored. Due to the the way
698 // .pseudo_probe section is decoded, probes of the same-named independent
699 // static functions are merged thus multiple call probes may be seen for a
700 // callsite. This should only happen to compiler-generated statics, with
701 // -funique-internal-linkage-names where user statics get unique names.
702 //
703 // TODO: re-enable or narrow down the assert to static functions only.
704 //
705 // assert(!CallProbe &&
706 // "There should be only one call probe corresponding to address "
707 // "which is a callsite.");
708 CallProbe = &Probe;
709 break;
710 }
711 }
712 return CallProbe;
713}
714
717 auto It = GUID2FuncDescMap.find(GUID);
718 assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
719 return &*It;
720}
721
723 const MCDecodedPseudoProbe *Probe,
725 bool IncludeLeaf) const {
726 Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
727 if (!IncludeLeaf)
728 return;
729 // Note that the context from probe doesn't include leaf frame,
730 // hence we need to retrieve and prepend leaf if requested.
731 const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
732 InlineContextStack.emplace_back(
733 MCPseudoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
734}
735
737 const MCDecodedPseudoProbe *Probe) const {
739 if (!InlinerNode->hasInlineSite())
740 return nullptr;
741 return getFuncDescForGUID(InlinerNode->Parent->Guid);
742}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
uint64_t Addr
std::string Name
uint64_t Size
static const MCExpr * buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, const MCSymbol *B, SMLoc Loc)
static const char * PseudoProbeTypeStr[3]
static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP, uint64_t GUID)
static const MCExpr * buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A, const MCSymbol *B)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Value * RHS
Value * LHS
auto find(uint64_t From, uint64_t To) const
Represents either an error or a value T.
Definition: ErrorOr.h:56
auto find(uint64_t GUID) const
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:201
@ Sub
Subtraction.
Definition: MCExpr.h:324
Context object for machine code objects.
Definition: MCContext.h:83
MCPseudoProbeTable & getMCPseudoProbeTable()
Definition: MCContext.h:855
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:416
void setProbes(MutableArrayRef< MCDecodedPseudoProbe > ProbesRef)
LLVM_ABI void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP, bool ShowName) const
LLVM_ABI uint64_t getGuid() const
LLVM_ABI std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const
MCDecodedPseudoProbeInlineTree * getInlineTreeNode() const
LLVM_ABI void getInlineContext(SmallVectorImpl< MCPseudoProbeFrameLocation > &ContextStack, const GUIDProbeFunctionMap &GUID2FuncMAP) const
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
MCSection * getPseudoProbeSection(const MCSection &TextSec) const
Streaming object file generation interface.
MCAssembler & getAssembler()
MCAssembler * getAssemblerPtr() override
uint32_t getIndex() const
uint8_t getAttributes() const
LLVM_ABI bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size, const Uint64Set &GuildFilter, const Uint64Map &FuncStartAddrs)
LLVM_ABI void printProbesForAllAddresses(raw_ostream &OS)
LLVM_ABI void printGUID2FuncDescMap(raw_ostream &OS)
LLVM_ABI bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size, bool IsMMapped=false)
LLVM_ABI void printProbeForAddress(raw_ostream &OS, uint64_t Address)
LLVM_ABI void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe, SmallVectorImpl< MCPseudoProbeFrameLocation > &InlineContextStack, bool IncludeLeaf) const
LLVM_ABI const MCPseudoProbeFuncDesc * getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const
bool countRecords(bool &Discard, uint32_t &ProbeCount, uint32_t &InlinedCount, const Uint64Set &GuidFilter)
LLVM_ABI const MCDecodedPseudoProbe * getCallProbeForAddr(uint64_t Address) const
LLVM_ABI const MCPseudoProbeFuncDesc * getFuncDescForGUID(uint64_t GUID) const
MCPseudoProbeInlineTreeBase< std::vector< MCPseudoProbe >, MCPseudoProbeInlineTree, std::unordered_map< InlineSite, std::unique_ptr< MCPseudoProbeInlineTree >, InlineSiteHash > > * Parent
InlinedProbeTreeMap & getChildren()
LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe)
LLVM_ABI void addPseudoProbe(const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack)
LLVM_ABI void emit(MCObjectStreamer *MCOS)
MCPseudoProbeSections & getProbeSections()
static LLVM_ABI void emit(MCObjectStreamer *MCOS)
Instances of this class represent a pseudo probe instance for a pseudo probe table entry,...
MCSymbol * getLabel() const
LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const
uint64_t getGuid() const
MCFragment * getCurrentFragment() const
Definition: MCStreamer.h:432
MCContext & getContext() const
Definition: MCStreamer.h:314
unsigned emitULEB128IntValue(uint64_t Value, unsigned PadTo=0)
Special case of EmitULEB128Value that avoids the client having to pass in a MCExpr for constant integ...
Definition: MCStreamer.cpp:160
void emitInt64(uint64_t Value)
Definition: MCStreamer.h:751
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
unsigned emitSLEB128IntValue(int64_t Value)
Special case of EmitSLEB128Value that avoids the client having to pass in a MCExpr for constant integ...
Definition: MCStreamer.cpp:170
void emitInt8(uint64_t Value)
Definition: MCStreamer.h:748
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:303
MutableArrayRef< T > take_back(size_t N=1) const
Return a copy of *this with only the last N elements.
Definition: ArrayRef.h:424
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void reserve(size_type N)
Definition: SmallVector.h:664
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:233
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:174
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define INT64_MAX
Definition: DataTypes.h:71
constexpr size_t NameSize
Definition: XCOFF.h:30
uint64_t MD5Hash(const FunctionId &Obj)
Definition: FunctionId.h:167
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
PseudoProbeType
Definition: PseudoProbe.h:30
static bool isSentinelProbe(uint32_t Flags)
Definition: PseudoProbe.h:129
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2491
std::tuple< uint64_t, uint32_t > InlineSite
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:132
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:166
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
static bool hasDiscriminator(uint32_t Flags)
Definition: PseudoProbe.h:133
std::pair< StringRef, uint32_t > MCPseudoProbeFrameLocation
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:769
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition: Error.h:1245
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition: STLExtras.h:1454
LLVM_ABI void print(raw_ostream &OS)
Function object to check whether the first component of a container supported by std::get (like std::...
Definition: STLExtras.h:1472