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