LLVM: lib/MC/MCPseudoProbe.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

24#include

25#include

26#include

27#include

28#include

29

30#define DEBUG_TYPE "mcpseudoprobe"

31

32using namespace llvm;

34

35#ifndef NDEBUG

37#endif

38

44 const MCExpr *AddrDelta =

46 return AddrDelta;

47}

48

50

54 assert((LastProbe || IsSentinel) &&

55 "Last probe should not be null for non-sentinel probes");

56

57

59

60

61

62

63

64 assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");

68 assert(NewAttributes <= 0x7 &&

69 "Probe attributes too big to encode, exceeding 7");

70 uint8_t PackedType = Type | (NewAttributes << 4);

73 MCOS->emitInt8(Flag | PackedType);

74

75 if (!IsSentinel) {

76

77 const MCExpr *AddrDelta =

79 int64_t Delta;

80 if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {

82 } else {

84 F->makeLEB(true, AddrDelta);

86 }

87 } else {

88

90 }

91

94

97 dbgs() << "Probe: " << Index << "\n";

98 });

99}

100

103

104 assert(isRoot() && "Should only be called on root");

105

106

107

108

109

110

111

112

113

114

115

116

117

119 if (InlineStack.empty()) {

121 } else {

123 }

124

126

127

128

129 if (!InlineStack.empty()) {

130 auto Iter = InlineStack.begin();

131 auto Index = std::get<1>(*Iter);

132 Iter++;

133 for (; Iter != InlineStack.end(); Iter++) {

134

135 Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));

136 Index = std::get<1>(*Iter);

137 }

139 }

140

141 Cur->Probes.push_back(Probe);

142}

143

148 dbgs() << "Group [\n";

150 });

151 assert(isRoot() && "Root should be handled separately");

152

153

156 dbgs() << "GUID: " << Guid << "\n";

157 });

158

160

161

162 bool NeedSentinel = false;

163 if (Parent->isRoot()) {

165 "Starting probe of a top-level function should be a sentinel probe");

166

168 NeedSentinel = true;

169 }

170

172

174

175 if (NeedSentinel)

176 LastProbe->emit(MCOS, nullptr);

177

178

179 for (const auto &Probe : Probes) {

180 Probe.emit(MCOS, LastProbe);

181 LastProbe = &Probe;

182 }

183

184

185

186 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;

187 std::vector Inlinees;

188 for (const auto &Child : Children)

189 Inlinees.emplace_back(Child.first, Child.second.get());

191

192 for (const auto &Inlinee : Inlinees) {

193

197 dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";

198 });

199

200 Inlinee.second->emit(MCOS, LastProbe);

201 }

202

206 dbgs() << "]\n";

207 });

208}

209

213 Vec.reserve(MCProbeDivisions.size());

214 for (auto &ProbeSec : MCProbeDivisions)

215 Vec.emplace_back(ProbeSec.first, &ProbeSec.second);

217 I.value().setOrdinal(I.index());

219 return A.first->getSection().getOrdinal() <

220 B.first->getSection().getOrdinal();

221 });

222 for (auto [FuncSym, RootPtr] : Vec) {

223 const auto &Root = *RootPtr;

224 if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(

225 FuncSym->getSection())) {

226

228

229

230

231 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;

232 std::vector Inlinees;

233 for (const auto &Child : Root.getChildren())

234 Inlinees.emplace_back(Child.first, Child.second.get());

236

237 for (const auto &Inlinee : Inlinees) {

238

240 const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),

245 Inlinee.second->emit(MCOS, Probe);

246 }

247 }

248 }

249}

250

251

252

253

257

258

259

261 if (ProbeSections.empty())

262 return;

263

265

266

267 ProbeSections.emit(MCOS);

268}

269

272 auto It = GUID2FuncMAP.find(GUID);

273 assert(It != GUID2FuncMAP.end() &&

274 "Probe function must exist for a valid GUID");

275 return It->FuncName;

276}

277

280 OS << "Hash: " << FuncHash << "\n";

281}

282

288

289

295 }

296

297 std::reverse(ContextStack.begin() + Begin, ContextStack.end());

298}

299

302 std::ostringstream OContextStr;

305 for (auto &Cxt : ContextStack) {

306 if (OContextStr.str().size())

307 OContextStr << " @ ";

308 OContextStr << Cxt.first.str() << ":" << Cxt.second;

309 }

310 return OContextStr.str();

311}

312

315

318 bool ShowName) const {

319 OS << "FUNC: ";

320 if (ShowName) {

322 OS << FuncName.str() << " ";

323 } else {

325 }

326 OS << "Index: " << Index << " ";

331 if (InlineContextStr.size()) {

332 OS << "Inlined: @ ";

333 OS << InlineContextStr;

334 }

335 OS << "\n";

336}

337

338template ErrorOr MCPseudoProbeDecoder::readUnencodedNumber() {

339 if (Data + sizeof(T) > End) {

340 return std::error_code();

341 }

344}

345

346template ErrorOr MCPseudoProbeDecoder::readUnsignedNumber() {

347 unsigned NumBytesRead = 0;

348 uint64_t Val = decodeULEB128(Data, &NumBytesRead);

349 if (Val > std::numeric_limits::max() || (Data + NumBytesRead > End)) {

350 return std::error_code();

351 }

352 Data += NumBytesRead;

353 return ErrorOr(static_cast<T>(Val));

354}

355

356template ErrorOr MCPseudoProbeDecoder::readSignedNumber() {

357 unsigned NumBytesRead = 0;

358 int64_t Val = decodeSLEB128(Data, &NumBytesRead);

359 if (Val > std::numeric_limits::max() || (Data + NumBytesRead > End)) {

360 return std::error_code();

361 }

362 Data += NumBytesRead;

363 return ErrorOr(static_cast<T>(Val));

364}

365

367 StringRef Str(reinterpret_cast<const char *>(Data), Size);

368 if (Data + Size > End) {

369 return std::error_code();

370 }

371 Data += Size;

372 return ErrorOr(Str);

373}

374

376 std::size_t Size,

377 bool IsMMapped) {

378

379

380

381

382

383

384

385

386

387

388

389 Data = Start;

390 End = Data + Size;

391

393 while (Data < End) {

394

395 if (!readUnencodedNumber<uint64_t>())

396 return false;

397

398 if (!readUnencodedNumber<uint64_t>())

399 return false;

400

401 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();

402 if (!ErrorOrNameSize)

403 return false;

404

405 if (!readString(*ErrorOrNameSize))

406 return false;

407 ++FuncDescCount;

408 }

409 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");

410 GUID2FuncDescMap.reserve(FuncDescCount);

411

412 Data = Start;

413 End = Data + Size;

414 while (Data < End) {

422

423

424 GUID2FuncDescMap.emplace_back(

425 GUID, Hash, IsMMapped ? Name : Name.copy(FuncNameAllocator));

426 }

427 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");

428 assert(GUID2FuncDescMap.size() == FuncDescCount &&

429 "Mismatching function description count pre- and post-parsing");

430 llvm::sort(GUID2FuncDescMap, [](const auto &LHS, const auto &RHS) {

431 return LHS.FuncGUID < RHS.FuncGUID;

432 });

433 return true;

434}

435

436template

439 const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs,

440 const uint32_t CurChildIndex) {

441

442

443

445 if (IsTopLevelFunc) {

446

447 Index = CurChildIndex;

448 } else {

449

451 }

452

453

455

456

457 if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))

458 Cur = nullptr;

459

460

461 if (Cur) {

462

464 MCDecodedPseudoProbeInlineTree(InlineSite(Guid, Index), Cur);

465 Cur = &Cur->getChildren()[CurChildIndex];

466 if (IsTopLevelFunc && !EncodingIsAddrBased) {

467 if (auto V = FuncStartAddrs.lookup(Guid))

468 LastAddr = V;

469 }

470 }

471

472

473 uint32_t NodeCount =

475 uint32_t CurrentProbeCount = 0;

476

477 uint32_t ChildrenToProcess =

479

480 for (std::size_t I = 0; I < NodeCount; I++) {

481

484

487 uint8_t Attr = (Value & 0x70) >> 4;

488

489 uint64_t Addr = 0;

490 if (Value & 0x80) {

492 Addr = LastAddr + Offset;

493 } else {

496

497

498 if (auto V = FuncStartAddrs.lookup(Addr))

499 Addr = V;

500 } else {

501

502

503

504

505 EncodingIsAddrBased = true;

506 }

507 }

508

513 }

514

516 PseudoProbeVec.emplace_back(Addr, Index, PseudoProbeType(Kind), Attr,

517 Discriminator, Cur);

518 ++CurrentProbeCount;

519 }

520 LastAddr = Addr;

521 }

522

523 if (Cur) {

525 MutableArrayRef(PseudoProbeVec).take_back(CurrentProbeCount));

526 InlineTreeVec.resize(InlineTreeVec.size() + ChildrenToProcess);

529 }

530 for (uint32_t I = 0; I < ChildrenToProcess; I++) {

532 }

533 return Cur;

534}

535

536template

540 if (!IsTopLevelFunc)

541

542 if (!readUnsignedNumber<uint32_t>())

543 return false;

544

545

546 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();

547 if (!ErrorOrCurGuid)

548 return false;

550

551

552 if (IsTopLevelFunc) {

553 Discard = !GuidFilter.empty() && !GuidFilter.count(Guid);

554 if (!Discard)

555

556 ++InlinedCount;

557 }

558

559

560 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();

561 if (!ErrorOrNodeCount)

562 return false;

563 uint32_t NodeCount = std::move(*ErrorOrNodeCount);

564 uint32_t CurrentProbeCount = 0;

565

566

567 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();

568 if (!ErrorOrCurChildrenToProcess)

569 return false;

570 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);

571

572

573 for (std::size_t I = 0; I < NodeCount; I++) {

574

575 if (!readUnsignedNumber<uint32_t>())

576 return false;

577

578

579 auto ErrorOrValue = readUnencodedNumber<uint8_t>();

580 if (!ErrorOrValue)

581 return false;

583

585 if (Value & 0x80) {

586

587 if (!readSignedNumber<int64_t>())

588 return false;

589 } else {

590

591 if (!readUnencodedNumber<int64_t>())

592 return false;

593 }

594

596

597 if (!readUnsignedNumber<uint32_t>())

598 return false;

599

601 ++CurrentProbeCount;

602 }

603

604 if (!Discard) {

605 ProbeCount += CurrentProbeCount;

606 InlinedCount += ChildrenToProcess;

607 }

608

609 for (uint32_t I = 0; I < ChildrenToProcess; I++)

611 return false;

612 return true;

613}

614

617 const Uint64Map &FuncStartAddrs) {

618

619

623 Data = Start;

624 End = Data + Size;

625 bool Discard = false;

626 while (Data < End) {

627 if (countRecords<true>(Discard, ProbeCount, InlinedCount, GuidFilter))

628 return false;

629 TopLevelFuncs += !Discard;

630 }

631 assert(Data == End && "Have unprocessed data in pseudo_probe section");

632 PseudoProbeVec.reserve(ProbeCount);

633 InlineTreeVec.reserve(InlinedCount);

634

635

636 InlineTreeVec.resize(TopLevelFuncs);

637 DummyInlineRoot.getChildren() = MutableArrayRef(InlineTreeVec);

638

639 Data = Start;

640 End = Data + Size;

643 while (Data < End)

645 &DummyInlineRoot, LastAddr, GuidFilter, FuncStartAddrs, CurChildIndex);

646 assert(Data == End && "Have unprocessed data in pseudo_probe section");

647 assert(PseudoProbeVec.size() == ProbeCount &&

648 "Mismatching probe count pre- and post-parsing");

649 assert(InlineTreeVec.size() == InlinedCount &&

650 "Mismatching function records count pre- and post-parsing");

651

652 std::vector<std::pair<uint64_t, uint32_t>> SortedA2P(ProbeCount);

653 for (const auto &[I, Probe] : llvm::enumerate(PseudoProbeVec))

654 SortedA2P[I] = {Probe.getAddress(), I};

656 Address2ProbesMap.reserve(ProbeCount);

658 Address2ProbesMap.emplace_back(PseudoProbeVec[I]);

659 SortedA2P.clear();

660 return true;

661}

662

664 OS << "Pseudo Probe Desc:\n";

665 for (auto &I : GUID2FuncDescMap)

666 I.print(OS);

667}

668

672 OS << " [Probe]:\t";

673 Probe.print(OS, GUID2FuncDescMap, true);

674 }

675}

676

681 if (Address != PrevAddress) {

683 OS << "Address:\t" << Address << '\n';

684 }

685 OS << " [Probe]:\t";

686 Probe.print(OS, GUID2FuncDescMap, true);

687 }

688}

689

694 if (Probe.isCall()) {

695

696

697

698

699

700

701

702

703

704

705

706

707 CallProbe = &Probe;

708 break;

709 }

710 }

711 return CallProbe;

712}

713

716 auto It = GUID2FuncDescMap.find(GUID);

717 assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");

718 return &*It;

719}

720

724 bool IncludeLeaf) const {

725 Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);

726 if (!IncludeLeaf)

727 return;

728

729

733}

734

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static const MCExpr * buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, const MCSymbol *B, SMLoc Loc)

static const char * PseudoProbeTypeStr[3]

Definition MCPseudoProbe.cpp:313

static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP, uint64_t GUID)

Definition MCPseudoProbe.cpp:270

static const MCExpr * buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A, const MCSymbol *B)

Definition MCPseudoProbe.cpp:39

Represents either an error or a value T.

auto find(uint64_t GUID) const

static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

Context object for machine code objects.

MCPseudoProbeTable & getMCPseudoProbeTable()

InlineSite getInlineSite() const

bool hasInlineSite() const

void setProbes(MutableArrayRef< MCDecodedPseudoProbe > ProbesRef)

LLVM_ABI void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP, bool ShowName) const

Definition MCPseudoProbe.cpp:316

LLVM_ABI uint64_t getGuid() const

Definition MCPseudoProbe.cpp:49

LLVM_ABI std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const

Definition MCPseudoProbe.cpp:300

MCDecodedPseudoProbeInlineTree * getInlineTreeNode() const

LLVM_ABI void getInlineContext(SmallVectorImpl< MCPseudoProbeFrameLocation > &ContextStack, const GUIDProbeFunctionMap &GUID2FuncMAP) const

Definition MCPseudoProbe.cpp:283

Base class for the full range of assembler expressions which are needed for parsing.

Streaming object file generation interface.

MCAssembler & getAssembler()

MCAssembler * getAssemblerPtr() override

uint32_t getIndex() const

uint8_t getAttributes() const

DenseSet< uint64_t > Uint64Set

LLVM_ABI bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size, const Uint64Set &GuildFilter, const Uint64Map &FuncStartAddrs)

Definition MCPseudoProbe.cpp:615

LLVM_ABI void printProbesForAllAddresses(raw_ostream &OS)

Definition MCPseudoProbe.cpp:677

LLVM_ABI void printGUID2FuncDescMap(raw_ostream &OS)

Definition MCPseudoProbe.cpp:663

DenseMap< uint64_t, uint64_t > Uint64Map

LLVM_ABI bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size, bool IsMMapped=false)

Definition MCPseudoProbe.cpp:375

LLVM_ABI void printProbeForAddress(raw_ostream &OS, uint64_t Address)

Definition MCPseudoProbe.cpp:669

LLVM_ABI void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe, SmallVectorImpl< MCPseudoProbeFrameLocation > &InlineContextStack, bool IncludeLeaf) const

Definition MCPseudoProbe.cpp:721

LLVM_ABI const MCPseudoProbeFuncDesc * getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const

Definition MCPseudoProbe.cpp:735

bool countRecords(bool &Discard, uint32_t &ProbeCount, uint32_t &InlinedCount, const Uint64Set &GuidFilter)

Definition MCPseudoProbe.cpp:537

LLVM_ABI const MCDecodedPseudoProbe * getCallProbeForAddr(uint64_t Address) const

Definition MCPseudoProbe.cpp:691

LLVM_ABI const MCPseudoProbeFuncDesc * getFuncDescForGUID(uint64_t GUID) const

Definition MCPseudoProbe.cpp:715

std::unordered_map< InlineSite, std::unique_ptr< MCPseudoProbeInlineTree >, InlineSiteHash > Children

MCPseudoProbeInlineTree * getOrAddNode(const InlineSite &Site)

std::vector< MCPseudoProbe > Probes

MCPseudoProbeInlineTreeBase< std::vector< MCPseudoProbe >, MCPseudoProbeInlineTree, std::unordered_map< InlineSite, std::unique_ptr< MCPseudoProbeInlineTree >, InlineSiteHash > > * Parent

InlinedProbeTreeMap & getChildren()

LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe)

Definition MCPseudoProbe.cpp:144

LLVM_ABI void addPseudoProbe(const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack)

Definition MCPseudoProbe.cpp:101

LLVM_ABI void emit(MCObjectStreamer *MCOS)

Definition MCPseudoProbe.cpp:210

MCPseudoProbeSections & getProbeSections()

static int DdgPrintIndent

static LLVM_ABI void emit(MCObjectStreamer *MCOS)

Definition MCPseudoProbe.cpp:254

Instances of this class represent a pseudo probe instance for a pseudo probe table entry,...

MCSymbol * getLabel() const

LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const

Definition MCPseudoProbe.cpp:51

MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attributes, uint32_t Discriminator)

MCFragment * getCurrentFragment() const

MCContext & getContext() const

unsigned emitULEB128IntValue(uint64_t Value, unsigned PadTo=0)

Special case of EmitULEB128Value that avoids the client having to pass in a MCExpr for constant integ...

void emitInt64(uint64_t Value)

virtual void switchSection(MCSection *Section, uint32_t Subsec=0)

Set the current section where code is being emitted to Section.

unsigned emitSLEB128IntValue(int64_t Value)

Special case of EmitSLEB128Value that avoids the client having to pass in a MCExpr for constant integ...

void emitInt8(uint64_t Value)

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

MutableArrayRef< T > take_back(size_t N=1) const

Return a copy of *this with only the last N elements.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

LLVM Value Representation.

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

constexpr size_t NameSize

uint64_t MD5Hash(const FunctionId &Obj)

value_type readNext(const CharT *&memory, endianness endian)

Read a value of a particular endianness from a buffer, and increment the buffer past that value.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

static bool isSentinelProbe(uint32_t Flags)

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

std::tuple< uint64_t, uint32_t > InlineSite

uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)

Utility function to decode a ULEB128 value.

int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)

Utility function to decode a SLEB128 value.

std::pair< StringRef, uint32_t > MCPseudoProbeFrameLocation

void sort(IteratorTy Start, IteratorTy End)

SmallVector< InlineSite, 8 > MCPseudoProbeInlineStack

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

static bool hasDiscriminator(uint32_t Flags)

MutableArrayRef(T &OneElt) -> MutableArrayRef< T >

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

Expected< T > errorOrToExpected(ErrorOr< T > &&EO)

Convert an ErrorOr to an Expected.

auto make_second_range(ContainerTy &&c)

Given a container of pairs, return a range over the second elements.

LLVM_ABI void print(raw_ostream &OS)

Definition MCPseudoProbe.cpp:278

Function object to check whether the first component of a container supported by std::get (like std::...