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