File indexing completed on 2026-05-10 08:44:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 #ifndef LLVM_MC_MCPSEUDOPROBE_H
0055 #define LLVM_MC_MCPSEUDOPROBE_H
0056
0057 #include "llvm/ADT/ArrayRef.h"
0058 #include "llvm/ADT/DenseMap.h"
0059 #include "llvm/ADT/DenseSet.h"
0060 #include "llvm/ADT/SmallVector.h"
0061 #include "llvm/ADT/StringRef.h"
0062 #include "llvm/ADT/iterator.h"
0063 #include "llvm/IR/PseudoProbe.h"
0064 #include "llvm/Support/Allocator.h"
0065 #include "llvm/Support/ErrorOr.h"
0066 #include <functional>
0067 #include <memory>
0068 #include <string>
0069 #include <tuple>
0070 #include <type_traits>
0071 #include <unordered_map>
0072 #include <vector>
0073
0074 namespace llvm {
0075
0076 class MCSymbol;
0077 class MCObjectStreamer;
0078 class raw_ostream;
0079
0080 enum class MCPseudoProbeFlag {
0081
0082
0083 AddressDelta = 0x1,
0084 };
0085
0086
0087 struct MCPseudoProbeFuncDesc {
0088 uint64_t FuncGUID = 0;
0089 uint64_t FuncHash = 0;
0090 StringRef FuncName;
0091
0092 MCPseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
0093 : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
0094
0095 void print(raw_ostream &OS);
0096 };
0097
0098 class MCDecodedPseudoProbe;
0099
0100
0101 using InlineSite = std::tuple<uint64_t, uint32_t>;
0102 using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
0103
0104 class GUIDProbeFunctionMap : public std::vector<MCPseudoProbeFuncDesc> {
0105 public:
0106 auto find(uint64_t GUID) const {
0107 auto CompareDesc = [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) {
0108 return Desc.FuncGUID < GUID;
0109 };
0110 auto It = llvm::lower_bound(*this, GUID, CompareDesc);
0111 if (It->FuncGUID != GUID)
0112 return end();
0113 return It;
0114 }
0115 };
0116
0117 class MCDecodedPseudoProbeInlineTree;
0118
0119 class MCPseudoProbeBase {
0120 protected:
0121 uint32_t Index;
0122 uint32_t Discriminator;
0123 uint8_t Attributes;
0124 uint8_t Type;
0125
0126
0127
0128 const static uint32_t PseudoProbeFirstId = 1;
0129
0130 public:
0131 MCPseudoProbeBase(uint64_t I, uint64_t At, uint8_t T, uint32_t D)
0132 : Index(I), Discriminator(D), Attributes(At), Type(T) {}
0133
0134 bool isEntry() const { return Index == PseudoProbeFirstId; }
0135
0136 uint32_t getIndex() const { return Index; }
0137
0138 uint32_t getDiscriminator() const { return Discriminator; }
0139
0140 uint8_t getAttributes() const { return Attributes; }
0141
0142 uint8_t getType() const { return Type; }
0143
0144 bool isBlock() const {
0145 return Type == static_cast<uint8_t>(PseudoProbeType::Block);
0146 }
0147
0148 bool isIndirectCall() const {
0149 return Type == static_cast<uint8_t>(PseudoProbeType::IndirectCall);
0150 }
0151
0152 bool isDirectCall() const {
0153 return Type == static_cast<uint8_t>(PseudoProbeType::DirectCall);
0154 }
0155
0156 bool isCall() const { return isIndirectCall() || isDirectCall(); }
0157
0158 void setAttributes(uint8_t Attr) { Attributes = Attr; }
0159 };
0160
0161
0162
0163
0164
0165 class MCPseudoProbe : public MCPseudoProbeBase {
0166 uint64_t Guid;
0167 MCSymbol *Label;
0168
0169 public:
0170 MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type,
0171 uint64_t Attributes, uint32_t Discriminator)
0172 : MCPseudoProbeBase(Index, Attributes, Type, Discriminator), Guid(Guid),
0173 Label(Label) {
0174 assert(Type <= 0xFF && "Probe type too big to encode, exceeding 2^8");
0175 assert(Attributes <= 0xFF &&
0176 "Probe attributes too big to encode, exceeding 2^16");
0177 }
0178
0179 uint64_t getGuid() const { return Guid; };
0180 MCSymbol *getLabel() const { return Label; }
0181 void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const;
0182 };
0183
0184
0185 using MCPseudoProbeFrameLocation = std::pair<StringRef, uint32_t>;
0186
0187 class MCDecodedPseudoProbe : public MCPseudoProbeBase {
0188 uint64_t Address;
0189 MCDecodedPseudoProbeInlineTree *InlineTree;
0190
0191 public:
0192 MCDecodedPseudoProbe(uint64_t Ad, uint32_t I, PseudoProbeType K, uint8_t At,
0193 uint32_t D, MCDecodedPseudoProbeInlineTree *Tree)
0194 : MCPseudoProbeBase(I, At, static_cast<uint8_t>(K), D), Address(Ad),
0195 InlineTree(Tree){};
0196 uint64_t getGuid() const;
0197
0198 uint64_t getAddress() const { return Address; }
0199
0200 void setAddress(uint64_t Addr) { Address = Addr; }
0201
0202 MCDecodedPseudoProbeInlineTree *getInlineTreeNode() const {
0203 return InlineTree;
0204 }
0205
0206
0207
0208
0209 void
0210 getInlineContext(SmallVectorImpl<MCPseudoProbeFrameLocation> &ContextStack,
0211 const GUIDProbeFunctionMap &GUID2FuncMAP) const;
0212
0213
0214 std::string
0215 getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const;
0216
0217
0218 void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
0219 bool ShowName) const;
0220 };
0221
0222
0223 class AddressProbesMap
0224 : public std::vector<std::reference_wrapper<MCDecodedPseudoProbe>> {
0225 auto getIt(uint64_t Addr) const {
0226 auto CompareProbe = [](const MCDecodedPseudoProbe &Probe, uint64_t Addr) {
0227 return Probe.getAddress() < Addr;
0228 };
0229 return llvm::lower_bound(*this, Addr, CompareProbe);
0230 }
0231
0232 public:
0233
0234 auto find(uint64_t From, uint64_t To) const {
0235 return llvm::make_range(getIt(From), getIt(To));
0236 }
0237
0238 auto find(uint64_t Address) const {
0239 auto FromIt = getIt(Address);
0240 if (FromIt == end() || FromIt->get().getAddress() != Address)
0241 return llvm::make_range(end(), end());
0242 auto ToIt = getIt(Address + 1);
0243 return llvm::make_range(FromIt, ToIt);
0244 }
0245 };
0246
0247 template <typename ProbesType, typename DerivedProbeInlineTreeType,
0248 typename InlinedProbeTreeMap>
0249 class MCPseudoProbeInlineTreeBase {
0250 protected:
0251
0252 InlinedProbeTreeMap Children;
0253
0254 ProbesType Probes;
0255 MCPseudoProbeInlineTreeBase() {
0256 static_assert(std::is_base_of<MCPseudoProbeInlineTreeBase,
0257 DerivedProbeInlineTreeType>::value,
0258 "DerivedProbeInlineTreeType must be subclass of "
0259 "MCPseudoProbeInlineTreeBase");
0260 }
0261
0262 public:
0263 uint64_t Guid = 0;
0264
0265
0266 bool isRoot() const { return Guid == 0; }
0267 InlinedProbeTreeMap &getChildren() { return Children; }
0268 const InlinedProbeTreeMap &getChildren() const { return Children; }
0269 const ProbesType &getProbes() const { return Probes; }
0270
0271 MCPseudoProbeInlineTreeBase<ProbesType, DerivedProbeInlineTreeType,
0272 InlinedProbeTreeMap> *Parent = nullptr;
0273 DerivedProbeInlineTreeType *getOrAddNode(const InlineSite &Site) {
0274 auto Ret = Children.emplace(
0275 Site, std::make_unique<DerivedProbeInlineTreeType>(Site));
0276 Ret.first->second->Parent = this;
0277 return Ret.first->second.get();
0278 };
0279 };
0280
0281
0282
0283
0284
0285
0286 struct InlineSiteHash {
0287 uint64_t operator()(const InlineSite &Site) const {
0288 return std::get<0>(Site) ^ std::get<1>(Site);
0289 }
0290 };
0291 class MCPseudoProbeInlineTree
0292 : public MCPseudoProbeInlineTreeBase<
0293 std::vector<MCPseudoProbe>, MCPseudoProbeInlineTree,
0294 std::unordered_map<InlineSite,
0295 std::unique_ptr<MCPseudoProbeInlineTree>,
0296 InlineSiteHash>> {
0297 public:
0298 MCPseudoProbeInlineTree() = default;
0299 MCPseudoProbeInlineTree(uint64_t Guid) { this->Guid = Guid; }
0300 MCPseudoProbeInlineTree(const InlineSite &Site) {
0301 this->Guid = std::get<0>(Site);
0302 }
0303
0304
0305 void addPseudoProbe(const MCPseudoProbe &Probe,
0306 const MCPseudoProbeInlineStack &InlineStack);
0307 void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe);
0308 };
0309
0310
0311 class MCDecodedPseudoProbeInlineTree
0312 : public MCPseudoProbeInlineTreeBase<
0313 MCDecodedPseudoProbe *, MCDecodedPseudoProbeInlineTree,
0314 MutableArrayRef<MCDecodedPseudoProbeInlineTree>> {
0315 uint32_t NumProbes = 0;
0316 uint32_t ProbeId = 0;
0317
0318 public:
0319 MCDecodedPseudoProbeInlineTree() = default;
0320 MCDecodedPseudoProbeInlineTree(const InlineSite &Site,
0321 MCDecodedPseudoProbeInlineTree *Parent)
0322 : ProbeId(std::get<1>(Site)) {
0323 this->Guid = std::get<0>(Site);
0324 this->Parent = Parent;
0325 }
0326
0327
0328 bool hasInlineSite() const { return !isRoot() && !Parent->isRoot(); }
0329 InlineSite getInlineSite() const { return InlineSite(Guid, ProbeId); }
0330 void setProbes(MutableArrayRef<MCDecodedPseudoProbe> ProbesRef) {
0331 Probes = ProbesRef.data();
0332 NumProbes = ProbesRef.size();
0333 }
0334 auto getProbes() const {
0335 return MutableArrayRef<MCDecodedPseudoProbe>(Probes, NumProbes);
0336 }
0337 };
0338
0339
0340
0341 class MCPseudoProbeSections {
0342 public:
0343 void addPseudoProbe(MCSymbol *FuncSym, const MCPseudoProbe &Probe,
0344 const MCPseudoProbeInlineStack &InlineStack) {
0345 MCProbeDivisions[FuncSym].addPseudoProbe(Probe, InlineStack);
0346 }
0347
0348
0349
0350 using MCProbeDivisionMap = std::unordered_map<MCSymbol *, MCPseudoProbeInlineTree>;
0351
0352 private:
0353
0354
0355
0356 MCProbeDivisionMap MCProbeDivisions;
0357
0358 public:
0359 const MCProbeDivisionMap &getMCProbes() const { return MCProbeDivisions; }
0360
0361 bool empty() const { return MCProbeDivisions.empty(); }
0362
0363 void emit(MCObjectStreamer *MCOS);
0364 };
0365
0366 class MCPseudoProbeTable {
0367
0368
0369
0370
0371
0372
0373 MCPseudoProbeSections MCProbeSections;
0374
0375 public:
0376 static void emit(MCObjectStreamer *MCOS);
0377
0378 MCPseudoProbeSections &getProbeSections() { return MCProbeSections; }
0379
0380 #ifndef NDEBUG
0381 static int DdgPrintIndent;
0382 #endif
0383 };
0384
0385 class MCPseudoProbeDecoder {
0386
0387 std::vector<MCDecodedPseudoProbe> PseudoProbeVec;
0388
0389
0390
0391
0392
0393
0394 std::unordered_map<const MCDecodedPseudoProbeInlineTree *,
0395 std::vector<MCDecodedPseudoProbe>>
0396 InjectedProbeMap;
0397
0398 std::vector<MCDecodedPseudoProbeInlineTree> InlineTreeVec;
0399
0400
0401 GUIDProbeFunctionMap GUID2FuncDescMap;
0402
0403 BumpPtrAllocator FuncNameAllocator;
0404
0405
0406 AddressProbesMap Address2ProbesMap;
0407
0408
0409
0410
0411
0412 MCDecodedPseudoProbeInlineTree DummyInlineRoot;
0413
0414
0415 const uint8_t *Data = nullptr;
0416
0417
0418 const uint8_t *End = nullptr;
0419
0420
0421 bool EncodingIsAddrBased = false;
0422
0423
0424 template <typename T> ErrorOr<T> readUnencodedNumber();
0425 template <typename T> ErrorOr<T> readUnsignedNumber();
0426 template <typename T> ErrorOr<T> readSignedNumber();
0427 ErrorOr<StringRef> readString(uint32_t Size);
0428
0429 public:
0430 using Uint64Set = DenseSet<uint64_t>;
0431 using Uint64Map = DenseMap<uint64_t, uint64_t>;
0432
0433
0434
0435
0436 bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size,
0437 bool IsMMapped = false);
0438
0439
0440
0441 template <bool IsTopLevelFunc>
0442 bool countRecords(bool &Discard, uint32_t &ProbeCount, uint32_t &InlinedCount,
0443 const Uint64Set &GuidFilter);
0444
0445
0446
0447 bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size,
0448 const Uint64Set &GuildFilter,
0449 const Uint64Map &FuncStartAddrs);
0450
0451
0452 void printGUID2FuncDescMap(raw_ostream &OS);
0453
0454
0455 void printProbeForAddress(raw_ostream &OS, uint64_t Address);
0456
0457
0458 void printProbesForAllAddresses(raw_ostream &OS);
0459
0460
0461 const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const;
0462
0463 const MCPseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
0464
0465
0466
0467
0468
0469
0470
0471
0472 void getInlineContextForProbe(
0473 const MCDecodedPseudoProbe *Probe,
0474 SmallVectorImpl<MCPseudoProbeFrameLocation> &InlineContextStack,
0475 bool IncludeLeaf) const;
0476
0477 const AddressProbesMap &getAddress2ProbesMap() const {
0478 return Address2ProbesMap;
0479 }
0480
0481 AddressProbesMap &getAddress2ProbesMap() { return Address2ProbesMap; }
0482
0483 const GUIDProbeFunctionMap &getGUID2FuncDescMap() const {
0484 return GUID2FuncDescMap;
0485 }
0486
0487 const MCPseudoProbeFuncDesc *
0488 getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const;
0489
0490 const MCDecodedPseudoProbeInlineTree &getDummyInlineRoot() const {
0491 return DummyInlineRoot;
0492 }
0493
0494 void addInjectedProbe(const MCDecodedPseudoProbe &Probe, uint64_t Address) {
0495 const MCDecodedPseudoProbeInlineTree *Parent = Probe.getInlineTreeNode();
0496 InjectedProbeMap[Parent].emplace_back(Probe).setAddress(Address);
0497 }
0498
0499 size_t
0500 getNumInjectedProbes(const MCDecodedPseudoProbeInlineTree *Parent) const {
0501 auto It = InjectedProbeMap.find(Parent);
0502 if (It == InjectedProbeMap.end())
0503 return 0;
0504 return It->second.size();
0505 }
0506
0507 auto getInjectedProbes(MCDecodedPseudoProbeInlineTree *Parent) {
0508 auto It = InjectedProbeMap.find(Parent);
0509 assert(It != InjectedProbeMap.end());
0510 return iterator_range(It->second);
0511 }
0512
0513 const ArrayRef<MCDecodedPseudoProbeInlineTree> getInlineTreeVec() const {
0514 return InlineTreeVec;
0515 }
0516
0517 private:
0518
0519
0520 template <bool IsTopLevelFunc>
0521 bool buildAddress2ProbeMap(MCDecodedPseudoProbeInlineTree *Cur,
0522 uint64_t &LastAddr, const Uint64Set &GuildFilter,
0523 const Uint64Map &FuncStartAddrs,
0524 const uint32_t CurChildIndex);
0525 };
0526
0527 }
0528
0529 #endif