LLVM 23.0.0git
InstrProfCorrelator.cpp
Go to the documentation of this file.
1//===-- InstrProfCorrelator.cpp -------------------------------------------===//
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
17#include "llvm/Object/MachO.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/Format.h"
21#include <optional>
22
23#define DEBUG_TYPE "correlator"
24
25using namespace llvm;
26
27/// Get profile section.
30 // On COFF, the getInstrProfSectionName returns the section names may followed
31 // by "$M". The linker removes the dollar and everything after it in the final
32 // binary. Do the same to match.
33 Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
34 auto StripSuffix = [ObjFormat](StringRef N) {
35 return ObjFormat == Triple::COFF ? N.split('$').first : N;
36 };
37 std::string ExpectedSectionName =
38 getInstrProfSectionName(IPSK, ObjFormat,
39 /*AddSegmentInfo=*/false);
40 ExpectedSectionName = StripSuffix(ExpectedSectionName);
41 for (auto &Section : Obj.sections()) {
42 if (auto SectionName = Section.getName())
43 if (*SectionName == ExpectedSectionName)
44 return Section;
45 }
48 "could not find section (" + Twine(ExpectedSectionName) + ")");
49}
50
51const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
52const char *InstrProfCorrelator::CFGHashAttributeName = "CFG Hash";
53const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
54const char *InstrProfCorrelator::NumBitmapBitsAttributeName = "Num BitmapBits";
55
57InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
59 ProfCorrelatorKind FileKind) {
60 auto C = std::make_unique<Context>();
61 auto CountersSection = getInstrProfSection(Obj, IPSK_cnts);
62 if (auto Err = CountersSection.takeError())
63 return std::move(Err);
64 Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
65 if (FileKind == InstrProfCorrelator::BINARY) {
66 auto DataSection = getInstrProfSection(Obj, IPSK_covdata);
67 if (auto Err = DataSection.takeError())
68 return std::move(Err);
69 auto DataOrErr = DataSection->getContents();
70 if (!DataOrErr)
71 return DataOrErr.takeError();
72 auto NameSection = getInstrProfSection(Obj, IPSK_covname);
73 if (auto Err = NameSection.takeError())
74 return std::move(Err);
75 auto NameOrErr = NameSection->getContents();
76 if (!NameOrErr)
77 return NameOrErr.takeError();
78 C->DataStart = DataOrErr->data();
79 C->DataEnd = DataOrErr->data() + DataOrErr->size();
80 C->NameStart = NameOrErr->data();
81 C->NameSize = NameOrErr->size();
82
83 if (ObjFormat == Triple::MachO) {
84 std::string FullSectionName =
85 getInstrProfSectionName(IPSK_covdata, ObjFormat);
86 SmallVector<StringRef, 3> SegmentAndSection;
87 StringRef(FullSectionName).split(SegmentAndSection, ',', 2);
88 auto *MachO = static_cast<object::MachOObjectFile *>(&Obj);
89 Error Err = Error::success();
90 for (const object::MachOChainedFixupEntry &Entry :
91 MachO->fixupTable(Err)) {
92 if (Entry.isRebase() && Entry.segmentName() == SegmentAndSection[0] &&
93 Entry.sectionName() == SegmentAndSection[1]) {
94 C->MachOFixups[Entry.address() - DataSection->getAddress()] =
95 Entry.pointerValue();
96 }
97 }
98 if (Err)
99 return std::move(Err);
100 }
101 }
102 C->Buffer = std::move(Buffer);
103 C->CountersSectionStart = CountersSection->getAddress();
104 C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();
105
106 auto BitmapSection = getInstrProfSection(Obj, IPSK_bitmap);
107 if (auto E = BitmapSection.takeError()) {
108 // It is not an error if NumBitmapBytes of each function is zero.
109 consumeError(std::move(E));
110 C->BitmapSectionStart = 0;
111 C->BitmapSectionEnd = 0;
112 } else {
113 C->BitmapSectionStart = BitmapSection->getAddress();
114 C->BitmapSectionEnd = C->BitmapSectionStart + BitmapSection->getSize();
115 }
116 // In COFF object file, there's a null byte at the beginning of both the
117 // counter and bitmap sections which doesn't exist in raw profile.
118 if (ObjFormat == Triple::COFF) {
119 ++C->CountersSectionStart;
120 if (C->BitmapSectionStart)
121 ++C->BitmapSectionStart;
122 }
123
124 C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
125 return Expected<std::unique_ptr<Context>>(std::move(C));
126}
127
130 const object::BuildIDFetcher *BIDFetcher,
131 const ArrayRef<object::BuildID> BIs) {
132 std::optional<std::string> Path;
133 if (BIDFetcher) {
134 if (BIs.empty())
137 "unsupported profile binary correlation when there is no build ID "
138 "in a profile");
139 if (BIs.size() > 1)
142 "unsupported profile binary correlation when there are multiple "
143 "build IDs in a profile");
144
145 Path = BIDFetcher->fetch(BIs.front());
146 if (!Path)
149 "Missing build ID: " + llvm::toHex(BIs.front(),
150 /*LowerCase=*/true));
151 Filename = *Path;
152 }
153
154 if (FileKind == DEBUG_INFO) {
155 auto DsymObjectsOrErr =
157 if (auto Err = DsymObjectsOrErr.takeError())
158 return std::move(Err);
159 if (!DsymObjectsOrErr->empty()) {
160 // TODO: Enable profile correlation when there are multiple objects in a
161 // dSYM bundle.
162 if (DsymObjectsOrErr->size() > 1)
165 "using multiple objects is not yet supported");
166 Filename = *DsymObjectsOrErr->begin();
167 }
169 if (auto Err = BufferOrErr.takeError())
170 return std::move(Err);
171
172 return get(std::move(*BufferOrErr), FileKind);
173 }
174 if (FileKind == BINARY) {
176 if (auto Err = BufferOrErr.takeError())
177 return std::move(Err);
178
179 return get(std::move(*BufferOrErr), FileKind);
180 }
183 "unsupported correlation kind (only DWARF debug info and Binary format "
184 "(ELF/COFF) are supported)");
185}
186
188InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
189 ProfCorrelatorKind FileKind) {
190 auto BinOrErr = object::createBinary(*Buffer);
191 if (auto Err = BinOrErr.takeError())
192 return std::move(Err);
193
194 if (auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
195 auto CtxOrErr = Context::get(std::move(Buffer), *Obj, FileKind);
196 if (auto Err = CtxOrErr.takeError())
197 return std::move(Err);
198 auto T = Obj->makeTriple();
199 if (T.isArch64Bit())
200 return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj,
201 FileKind);
202 if (T.isArch32Bit())
203 return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj,
204 FileKind);
205 }
208}
209
210std::optional<size_t> InstrProfCorrelator::getDataSize() const {
212 return C->getDataSize();
214 return C->getDataSize();
215 return {};
216}
217
218namespace llvm {
219
220template <>
225template <>
230template <>
234template <>
238
239} // end namespace llvm
240
241template <class IntPtrT>
244 std::unique_ptr<InstrProfCorrelator::Context> Ctx,
245 const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) {
246 if (FileKind == DEBUG_INFO) {
247 if (Obj.isELF() || Obj.isMachO()) {
248 auto DICtx = DWARFContext::create(Obj);
249 return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
250 std::move(DICtx), std::move(Ctx));
251 }
254 "unsupported debug info format (only DWARF is supported)");
255 }
256 if (Obj.isELF() || Obj.isCOFF() || Obj.isMachO())
257 return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(std::move(Ctx));
260 "unsupported binary format (only ELF, COFF, and Mach-O are supported)");
261}
262
263template <class IntPtrT>
265 assert(Data.empty() && Names.empty() && NamesVec.empty());
266 correlateProfileDataImpl(MaxWarnings);
267 if (this->Data.empty())
270 "could not find any profile data metadata in correlated file");
272 this->CounterOffsets.clear();
273 this->BitmapOffsets.clear();
274 this->NamesVec.clear();
275 return Result;
276}
277
278template <> struct yaml::MappingTraits<InstrProfCorrelator::CorrelationData> {
279 static void mapping(yaml::IO &io,
281 io.mapRequired("Probes", Data.Probes);
282 }
283};
284
285template <> struct yaml::MappingTraits<InstrProfCorrelator::Probe> {
287 io.mapRequired("Function Name", P.FunctionName);
288 io.mapOptional("Linkage Name", P.LinkageName);
289 io.mapRequired("CFG Hash", P.CFGHash);
290 io.mapRequired("Counter Offset", P.CounterOffset);
291 io.mapRequired("Num Counters", P.NumCounters);
292 io.mapRequired("Bitmap Offset", P.BitmapOffset);
293 io.mapRequired("Num BitmapBytes", P.NumBitmapBytes);
294 io.mapOptional("File", P.FilePath);
295 io.mapOptional("Line", P.LineNumber);
296 }
297};
298
300 static const bool flow = false;
301};
302
303template <class IntPtrT>
305 raw_ostream &OS) {
307 correlateProfileDataImpl(MaxWarnings, &Data);
308 if (Data.Probes.empty())
311 "could not find any profile data metadata in debug info");
312 yaml::Output YamlOS(OS);
313 YamlOS << Data;
314 return Error::success();
315}
316
317template <class IntPtrT>
319 uint64_t NameRef, uint64_t CFGHash, IntPtrT CounterOffset,
320 IntPtrT BitmapOffset, IntPtrT FunctionPtr, uint32_t NumCounters,
322 // Check if a probe was already added for this counter offset.
323 if (NumCounters && !CounterOffsets.insert(CounterOffset).second)
324 return;
325 // Check if a probe was already added for this bitmap offset.
326 if (NumBitmapBytes && !BitmapOffsets.insert(BitmapOffset).second)
327 return;
328 Data.push_back({
329 maybeSwap<uint64_t>(NameRef),
330 maybeSwap<uint64_t>(CFGHash),
331 // In this mode, CounterPtr actually stores the section relative address
332 // of the counter.
333 maybeSwap<IntPtrT>(CounterOffset),
334 /*UniformCounterPtr=*/maybeSwap<IntPtrT>(0),
335 maybeSwap<IntPtrT>(BitmapOffset),
336 maybeSwap<IntPtrT>(FunctionPtr),
337 // TODO: Value profiling is not yet supported.
338 /*ValuesPtr=*/maybeSwap<IntPtrT>(0),
339 maybeSwap<uint32_t>(NumCounters),
340 /*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
341 /*OffloadDeviceWaveSize=*/maybeSwap<uint16_t>(0),
343 });
344}
345
346template <class IntPtrT>
347std::optional<uint64_t>
348DwarfInstrProfCorrelator<IntPtrT>::getLocation(const DWARFDie &Die) const {
349 auto Locations = Die.getLocations(dwarf::DW_AT_location);
350 if (!Locations) {
351 consumeError(Locations.takeError());
352 return {};
353 }
354 auto &DU = *Die.getDwarfUnit();
355 auto AddressSize = DU.getAddressByteSize();
356 for (auto &Location : *Locations) {
357 DataExtractor Data(Location.Expr, DICtx->isLittleEndian());
358 DWARFExpression Expr(Data, AddressSize);
359 for (auto &Op : Expr) {
360 if (Op.getCode() == dwarf::DW_OP_addr)
361 return Op.getRawOperand(0);
362 if (Op.getCode() == dwarf::DW_OP_addrx) {
363 uint64_t Index = Op.getRawOperand(0);
364 if (auto SA = DU.getAddrOffsetSectionItem(Index))
365 return SA->Address;
366 }
367 }
368 }
369 return {};
370}
371
372template <class IntPtrT>
373bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die,
374 StringRef Prefix) {
375 const auto &ParentDie = Die.getParent();
376 if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())
377 return false;
378 if (Die.getTag() != dwarf::DW_TAG_variable)
379 return false;
380 if (!ParentDie.isSubprogramDIE())
381 return false;
382 if (!Die.hasChildren())
383 return false;
384 if (const char *Name = Die.getName(DINameKind::ShortName))
385 return StringRef(Name).starts_with(Prefix);
386 return false;
387}
388
389template <class IntPtrT>
390std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
391DwarfInstrProfCorrelator<IntPtrT>::addCountersToDataProbe(
392 const DWARFDie &Die, const bool UnlimitedWarnings,
393 int &NumSuppressedWarnings) {
394 std::optional<const char *> FunctionName;
395 std::optional<uint64_t> CFGHash;
396 std::optional<uint64_t> CounterPtr = getLocation(Die);
397 auto FnDie = Die.getParent();
398 auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));
399 std::optional<uint64_t> NumCounters;
400 for (const DWARFDie &Child : Die.children()) {
401 if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
402 continue;
403 auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
404 auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
405 if (!AnnotationFormName || !AnnotationFormValue)
406 continue;
407 auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
408 if (auto Err = AnnotationNameOrErr.takeError()) {
409 consumeError(std::move(Err));
410 continue;
411 }
412 StringRef AnnotationName = *AnnotationNameOrErr;
414 if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
415 consumeError(std::move(EC));
416 } else if (AnnotationName == InstrProfCorrelator::CFGHashAttributeName) {
417 CFGHash = AnnotationFormValue->getAsUnsignedConstant();
418 } else if (AnnotationName ==
420 NumCounters = AnnotationFormValue->getAsUnsignedConstant();
421 }
422 }
423 // If there is no function and no counter, assume it was dead-stripped
424 if (!FunctionPtr && !CounterPtr)
425 return std::nullopt;
426 if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
427 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
428 WithColor::warning() << "Incomplete DIE for function " << FunctionName
429 << ": CFGHash=" << CFGHash
430 << " CounterPtr=" << CounterPtr
431 << " NumCounters=" << NumCounters << "\n";
432 LLVM_DEBUG(Die.dump(dbgs()));
433 }
434 return std::nullopt;
435 }
436 uint64_t CountersStart = this->Ctx->CountersSectionStart;
437 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
438 if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
439 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
441 "CounterPtr out of range for function %s: Actual=0x%x "
442 "Expected=[0x%x, 0x%x)\n",
443 *FunctionName, *CounterPtr, CountersStart, CountersEnd);
444 LLVM_DEBUG(Die.dump(dbgs()));
445 }
446 return std::nullopt;
447 }
448 if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {
449 WithColor::warning() << format("Could not find address of function %s\n",
450 *FunctionName);
451 LLVM_DEBUG(Die.dump(dbgs()));
452 }
453 // In debug info correlation mode, the CounterPtr is an absolute address
454 // of the counter, but it's expected to be relative later when iterating
455 // Data.
456 IntPtrT CounterOffset = *CounterPtr - CountersStart;
458 P.FunctionName = *FunctionName;
459 if (const char *Name = FnDie.getName(DINameKind::LinkageName))
460 P.LinkageName = Name;
461 P.CFGHash = *CFGHash;
462 P.CounterOffset = CounterOffset;
463 P.NumCounters = *NumCounters;
464 auto FilePath = FnDie.getDeclFile(
466 if (!FilePath.empty())
467 P.FilePath = FilePath;
468 if (auto LineNumber = FnDie.getDeclLine())
469 P.LineNumber = LineNumber;
470
471 return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>(
472 {P, FunctionPtr.value_or(0)});
473}
474
475template <class IntPtrT>
476std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
477DwarfInstrProfCorrelator<IntPtrT>::addBitmapToDataProbe(
478 const DWARFDie &Die, const bool UnlimitedWarnings,
479 int &NumSuppressedWarnings) {
480 std::optional<const char *> FunctionName;
481 std::optional<uint64_t> BitmapPtr = getLocation(Die);
483 for (const DWARFDie &Child : Die.children()) {
484 if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
485 continue;
486 auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
487 auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
488 if (!AnnotationFormName || !AnnotationFormValue)
489 continue;
490 auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
491 if (auto Err = AnnotationNameOrErr.takeError()) {
492 consumeError(std::move(Err));
493 continue;
494 }
495 StringRef AnnotationName = *AnnotationNameOrErr;
497 if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
498 consumeError(std::move(EC));
499 } else if (AnnotationName ==
501 std::optional<uint64_t> NumBitmapBits =
502 AnnotationFormValue->getAsUnsignedConstant();
503 NumBitmapBytes = alignTo(*NumBitmapBits, CHAR_BIT) / CHAR_BIT;
504 }
505 }
506 if (!FunctionName || !BitmapPtr || !NumBitmapBytes) {
507 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
508 WithColor::warning() << "Incomplete DIE for function " << FunctionName
509 << " BitmapPtr=" << BitmapPtr
510 << " NumBitmapBytes=" << NumBitmapBytes << "\n";
511 LLVM_DEBUG(Die.dump(dbgs()));
512 }
513 return std::nullopt;
514 }
515 uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
516 uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
517 if (!BitmapStart && !BitmapEnd && NumBitmapBytes) {
520 "could not find profile bitmap section in correlated file");
521 return std::nullopt;
522 }
523 if (*BitmapPtr < BitmapStart || (*BitmapPtr >= BitmapEnd && NumBitmapBytes)) {
524 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
526 "BitmapPtr out of range for function %s: Actual=0x%x "
527 "Expected=[0x%x, 0x%x)\n",
528 *FunctionName, *BitmapPtr, BitmapStart, BitmapEnd);
529 LLVM_DEBUG(Die.dump(dbgs()));
530 }
531 return std::nullopt;
532 }
533 // In debug info correlation mode, the BitmapPtr is an absolute address of
534 // the bitmap, but it's expected to be relative later when iterating Data.
535 IntPtrT BitmapOffset = *BitmapPtr - BitmapStart;
537 P.FunctionName = *FunctionName;
538 P.BitmapOffset = BitmapOffset;
539 P.NumBitmapBytes = NumBitmapBytes;
540
541 return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>({P, 0});
542}
543
544template <class IntPtrT>
545void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
546 int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) {
547 // Map from FunctionName string to (Probe, FunctionPtr) pair.
548 // We use it to collect data from all functions Counter and Bitmap DIEs.
551 Probes;
552 bool UnlimitedWarnings = (MaxWarnings == 0);
553 // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
554 int NumSuppressedWarnings = -MaxWarnings;
555
556 auto MaybeAddProbe = [&](DWARFDie Die) {
557 std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>> ProbeData;
558 if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix()))
559 ProbeData =
560 addCountersToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
561 else if (isDIEOfProbe(Die, getInstrProfBitmapVarPrefix()))
562 ProbeData =
563 addBitmapToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
564 if (!ProbeData)
565 return;
566 auto [Probe, FunctionPtr] = *ProbeData;
567
568 auto [It, Inserted] =
569 Probes.try_emplace(Probe.FunctionName, Probe, FunctionPtr);
570 if (!Inserted) {
571 auto &P = It->second.first;
572 if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix())) {
573 P.LinkageName = Probe.LinkageName;
574 P.CFGHash = Probe.CFGHash;
575 P.CounterOffset = Probe.CounterOffset;
576 P.NumCounters = Probe.NumCounters;
577 P.FilePath = Probe.FilePath;
578 P.LineNumber = Probe.LineNumber;
579 } else {
580 P.BitmapOffset = Probe.BitmapOffset;
581 P.NumBitmapBytes = Probe.NumBitmapBytes;
582 }
583 }
584 };
585 for (auto &CU : DICtx->normal_units())
586 for (const auto &Entry : CU->dies())
587 MaybeAddProbe(DWARFDie(CU.get(), &Entry));
588 for (auto &CU : DICtx->dwo_units())
589 for (const auto &Entry : CU->dies())
590 MaybeAddProbe(DWARFDie(CU.get(), &Entry));
591
592 for (const auto &[FunctionName, ProbeData] : Probes) {
593 const auto &[Probe, FunctionPtr] = ProbeData;
594 if (Data)
595 Data->Probes.push_back(Probe);
596 else {
597 this->NamesVec.push_back(FunctionName);
598 uint64_t NameRef = IndexedInstrProf::ComputeHash(FunctionName);
599 this->addDataProbe(NameRef, Probe.CFGHash, Probe.CounterOffset,
600 Probe.BitmapOffset, FunctionPtr, Probe.NumCounters,
601 Probe.NumBitmapBytes);
602 }
603 }
604 if (!UnlimitedWarnings && NumSuppressedWarnings > 0)
605 WithColor::warning() << format("Suppressed %d additional warnings\n",
606 NumSuppressedWarnings);
607}
608
609template <class IntPtrT>
610Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
611 if (this->NamesVec.empty()) {
614 "could not find any profile name metadata in debug info");
615 }
616 auto Result =
617 collectGlobalObjectNameStrings(this->NamesVec,
618 /*doCompression=*/false, this->Names);
619 return Result;
620}
621
622template <class IntPtrT>
623void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
624 int MaxWarnings, InstrProfCorrelator::CorrelationData *CorrelateData) {
625 using RawProfData = RawInstrProf::ProfileData<IntPtrT>;
626 bool UnlimitedWarnings = (MaxWarnings == 0);
627 // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
628 int NumSuppressedWarnings = -MaxWarnings;
629
630 const RawProfData *DataStart = (const RawProfData *)this->Ctx->DataStart;
631 const RawProfData *DataEnd = (const RawProfData *)this->Ctx->DataEnd;
632 // We need to use < here because the last data record may have no padding.
633 for (const RawProfData *I = DataStart; I < DataEnd; ++I) {
634 uint64_t CounterPtr = this->template maybeSwap<IntPtrT>(I->CounterPtr);
635 uint64_t CountersStart = this->Ctx->CountersSectionStart;
636 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
637
638 uint64_t BitmapPtr = this->template maybeSwap<IntPtrT>(I->BitmapPtr);
639 uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
640 uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
641 if (!BitmapStart && !BitmapEnd && I->NumBitmapBytes) {
644 "could not find profile bitmap section in correlated file");
645 return;
646 }
647 if (!this->Ctx->MachOFixups.empty()) {
648 auto GetPtrByOffset = [&](uint64_t Offset, uint64_t &Ptr) {
649 auto It = this->Ctx->MachOFixups.find(Offset);
650 if (It != this->Ctx->MachOFixups.end()) {
651 Ptr = It->second;
652 } else if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
654 "Mach-O fixup not found for covdata offset 0x%llx\n", Offset);
655 }
656 };
657 uint64_t CounterOffset = (uint64_t)&I->CounterPtr - (uint64_t)DataStart;
658 uint64_t BitmapOffset = (uint64_t)&I->BitmapPtr - (uint64_t)DataStart;
659 GetPtrByOffset(CounterOffset, CounterPtr);
660 GetPtrByOffset(BitmapOffset, BitmapPtr);
661 }
662 if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {
663 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
665 << format("CounterPtr out of range for function: Actual=0x%x "
666 "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
667 CounterPtr, CountersStart, CountersEnd,
668 (I - DataStart) * sizeof(RawProfData));
669 }
670 }
671 if (I->NumBitmapBytes &&
672 (BitmapPtr < BitmapStart || BitmapPtr >= BitmapEnd)) {
673 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
675 << format("BitmapPtr out of range for function: Actual=0x%x "
676 "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
677 BitmapPtr, BitmapStart, BitmapEnd,
678 (I - DataStart) * sizeof(RawProfData));
679 }
680 }
681 // In binary correlation mode, CounterPtr and BitmapPtr are absolute
682 // addresses, but they're expected to be relative later when iterating Data.
683 IntPtrT CounterOffset = CounterPtr - CountersStart;
684 IntPtrT BitmapOffset = BitmapPtr - BitmapStart;
685 this->addDataProbe(I->NameRef, I->FuncHash, CounterOffset, BitmapOffset,
686 I->FunctionPointer, I->NumCounters, I->NumBitmapBytes);
687 }
688}
689
690template <class IntPtrT>
691Error BinaryInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
692 if (this->Ctx->NameSize == 0) {
695 "could not find any profile data metadata in object file");
696 }
697 this->Names.append(this->Ctx->NameStart, this->Ctx->NameSize);
698 return Error::success();
699}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Expected< object::SectionRef > getInstrProfSection(const object::ObjectFile &Obj, InstrProfSectKind IPSK)
Get profile section.
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static constexpr StringLiteral Filename
#define P(N)
static MemoryLocation getLocation(Instruction *I)
#define LLVM_DEBUG(...)
Definition Debug.h:119
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
iterator_range< iterator > children() const
Definition DWARFDie.h:406
LLVM_ABI DWARFDie getParent() const
Get the parent of this DIE object.
Definition DWARFDie.cpp:724
DWARFUnit * getDwarfUnit() const
Definition DWARFDie.h:55
bool hasChildren() const
Definition DWARFDie.h:80
LLVM_ABI const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
Definition DWARFDie.cpp:530
dwarf::Tag getTag() const
Definition DWARFDie.h:73
LLVM_ABI Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
Definition DWARFDie.cpp:494
bool isNULL() const
Returns true for a valid DIE that terminates a sibling chain.
Definition DWARFDie.h:86
bool isValid() const
Definition DWARFDie.h:52
LLVM_ABI void dump(raw_ostream &OS, unsigned indent=0, DIDumpOptions DumpOpts=DIDumpOptions()) const
Dump the DIE and all of its attributes to the supplied stream.
Definition DWARFDie.cpp:662
uint8_t getAddressByteSize() const
Definition DWARFUnit.h:333
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template pointer type so that the Pro...
static llvm::Expected< std::unique_ptr< InstrProfCorrelatorImpl< IntPtrT > > > get(std::unique_ptr< InstrProfCorrelator::Context > Ctx, const object::ObjectFile &Obj, ProfCorrelatorKind FileKind)
virtual Error correlateProfileNameImpl()=0
virtual void correlateProfileDataImpl(int MaxWarnings, InstrProfCorrelator::CorrelationData *Data=nullptr)=0
std::vector< RawInstrProf::ProfileData< IntPtrT > > Data
Error correlateProfileData(int MaxWarnings) override
Construct a ProfileData vector used to correlate raw instrumentation data to their functions.
static bool classof(const InstrProfCorrelator *C)
InstrProfCorrelatorImpl(std::unique_ptr< InstrProfCorrelator::Context > Ctx)
void addDataProbe(uint64_t FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, IntPtrT BitmapOffset, IntPtrT FunctionPtr, uint32_t NumCounters, uint32_t NumBitmapBytes)
Error dumpYaml(int MaxWarnings, raw_ostream &OS) override
Process debug info and dump the correlation data.
InstrProfCorrelator - A base class used to create raw instrumentation data to their functions.
static LLVM_ABI const char * FunctionNameAttributeName
static LLVM_ABI const char * CFGHashAttributeName
InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr< Context > Ctx)
std::vector< std::string > NamesVec
static LLVM_ABI const char * NumCountersAttributeName
ProfCorrelatorKind
Indicate if we should use the debug info or profile metadata sections to correlate.
const std::unique_ptr< Context > Ctx
LLVM_ABI std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static LLVM_ABI llvm::Expected< std::unique_ptr< InstrProfCorrelator > > get(StringRef Filename, ProfCorrelatorKind FileKind, const object::BuildIDFetcher *BIDFetcher=nullptr, const ArrayRef< llvm::object::BuildID > BIs={})
static LLVM_ABI const char * NumBitmapBitsAttributeName
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition MapVector.h:118
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:128
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition WithColor.cpp:86
BuildIDFetcher searches local cache directories for debug info.
Definition BuildID.h:40
virtual std::optional< std::string > fetch(BuildIDRef BuildID) const
Returns the path to the debug file with the given build ID.
Definition BuildID.cpp:82
static Expected< std::vector< std::string > > findDsymObjectMembers(StringRef Path)
If the input path is a .dSYM bundle (as created by the dsymutil tool), return the paths to the object...
This class is the base class for all object file types.
Definition ObjectFile.h:231
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
void mapOptional(StringRef Key, T &Val)
Definition YAMLTraits.h:800
void mapRequired(StringRef Key, T &Val)
Definition YAMLTraits.h:790
The Output class is used to generate a yaml document from in-memory structs and vectors.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
uint64_t ComputeHash(StringRef K)
Definition InstrProf.h:1239
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
Definition Binary.cpp:45
constexpr bool IsLittleEndianHost
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:573
RelativeUniformCounterPtr ValuesPtrExpr NumBitmapBytes
Definition InstrProf.h:101
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
StringRef getInstrProfBitmapVarPrefix()
Return the name prefix of profile bitmap variables.
Definition InstrProf.h:143
LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
InstrProfSectKind
Definition InstrProf.h:91
StringRef getInstrProfCountersVarPrefix()
Return the name prefix of profile counter variables.
Definition InstrProf.h:140
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr CountersStart
Definition InstrProf.h:167
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:94
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition Error.h:1261
LLVM_ABI Error collectGlobalObjectNameStrings(ArrayRef< std::string > NameStrs, bool doCompression, std::string &Result)
Given a vector of strings (names of global objects like functions or, virtual tables) NameStrs,...
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr DataStart
Definition InstrProf.h:173
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
#define N
std::unique_ptr< MemoryBuffer > Buffer
static LLVM_ABI llvm::Expected< std::unique_ptr< Context > > get(std::unique_ptr< MemoryBuffer > Buffer, object::ObjectFile &Obj, ProfCorrelatorKind FileKind)
This class should be specialized by any type that needs to be converted to/from a YAML mapping.
Definition YAMLTraits.h:63
This class should be specialized by any type for which vectors of that type need to be converted to/f...
Definition YAMLTraits.h:258
static void mapping(yaml::IO &io, InstrProfCorrelator::CorrelationData &Data)
static void mapping(yaml::IO &io, InstrProfCorrelator::Probe &P)