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