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