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