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