LLVM: lib/ProfileData/InstrProfCorrelator.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21#include

22

23#define DEBUG_TYPE "correlator"

24

25using namespace llvm;

26

27

30

31

32

34 auto StripSuffix = [ObjFormat](StringRef N) {

35 return ObjFormat == Triple::COFF ? N.split('$').first : N;

36 };

37 std::string ExpectedSectionName =

39 false);

40 ExpectedSectionName = StripSuffix(ExpectedSectionName);

41 for (auto &Section : Obj.sections()) {

44 return Section;

45 }

48 "could not find section (" + Twine(ExpectedSectionName) + ")");

49}

50

54

59 auto C = std::make_unique();

61 if (auto Err = CountersSection.takeError())

62 return std::move(Err);

65 if (auto Err = DataSection.takeError())

66 return std::move(Err);

67 auto DataOrErr = DataSection->getContents();

68 if (!DataOrErr)

69 return DataOrErr.takeError();

71 if (auto Err = NameSection.takeError())

72 return std::move(Err);

73 auto NameOrErr = NameSection->getContents();

74 if (!NameOrErr)

75 return NameOrErr.takeError();

76 C->DataStart = DataOrErr->data();

77 C->DataEnd = DataOrErr->data() + DataOrErr->size();

78 C->NameStart = NameOrErr->data();

79 C->NameSize = NameOrErr->size();

80 }

81 C->Buffer = std::move(Buffer);

82 C->CountersSectionStart = CountersSection->getAddress();

83 C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();

84

85

86 if (Obj.getTripleObjectFormat() == Triple::COFF)

87 ++C->CountersSectionStart;

88

91}

92

97 std::optionalstd::string Path;

98 if (BIDFetcher) {

102 "unsupported profile binary correlation when there is no build ID "

103 "in a profile");

104 if (BIs.size() > 1)

107 "unsupported profile binary correlation when there are multiple "

108 "build IDs in a profile");

109

110 Path = BIDFetcher->fetch(BIs.front());

111 if (!Path)

115 true));

116 Filename = *Path;

117 }

118

120 auto DsymObjectsOrErr =

122 if (auto Err = DsymObjectsOrErr.takeError())

123 return std::move(Err);

124 if (!DsymObjectsOrErr->empty()) {

125

126

127 if (DsymObjectsOrErr->size() > 1)

130 "using multiple objects is not yet supported");

131 Filename = *DsymObjectsOrErr->begin();

132 }

134 if (auto Err = BufferOrErr.takeError())

135 return std::move(Err);

136

137 return get(std::move(*BufferOrErr), FileKind);

138 }

139 if (FileKind == BINARY) {

141 if (auto Err = BufferOrErr.takeError())

142 return std::move(Err);

143

144 return get(std::move(*BufferOrErr), FileKind);

145 }

148 "unsupported correlation kind (only DWARF debug info and Binary format "

149 "(ELF/COFF) are supported)");

150}

151

154 ProfCorrelatorKind FileKind) {

156 if (auto Err = BinOrErr.takeError())

157 return std::move(Err);

158

160 auto CtxOrErr = Context::get(std::move(Buffer), *Obj, FileKind);

161 if (auto Err = CtxOrErr.takeError())

162 return std::move(Err);

163 auto T = Obj->makeTriple();

164 if (T.isArch64Bit())

166 FileKind);

167 if (T.isArch32Bit())

169 FileKind);

170 }

173}

174

177 return C->getDataSize();

179 return C->getDataSize();

180 return {};

181}

182

183namespace llvm {

184

185template <>

187 std::unique_ptrInstrProfCorrelator::Context Ctx)

190template <>

192 std::unique_ptrInstrProfCorrelator::Context Ctx)

195template <>

199template <>

203

204}

205

206template

209 std::unique_ptrInstrProfCorrelator::Context Ctx,

212 if (Obj.isELF() || Obj.isMachO()) {

214 return std::make_unique<DwarfInstrProfCorrelator>(

215 std::move(DICtx), std::move(Ctx));

216 }

219 "unsupported debug info format (only DWARF is supported)");

220 }

221 if (Obj.isELF() || Obj.isCOFF())

222 return std::make_unique<BinaryInstrProfCorrelator>(std::move(Ctx));

225 "unsupported binary format (only ELF and COFF are supported)");

226}

227

228template

232 if (this->Data.empty())

235 "could not find any profile data metadata in correlated file");

237 this->CounterOffsets.clear();

239 return Result;

240}

241

248

260

262 static const bool flow = false;

263};

264

265template

270 if (Data.Probes.empty())

273 "could not find any profile data metadata in debug info");

275 YamlOS << Data;

277}

278

279template

282 IntPtrT CounterOffset,

283 IntPtrT FunctionPtr,

285

286 if (!CounterOffsets.insert(CounterOffset).second)

287 return;

288 Data.push_back({

291

292

294

297

301

303 });

304}

305

306template

307std::optional<uint64_t>

308DwarfInstrProfCorrelator::getLocation(const DWARFDie &Die) const {

309 auto Locations = Die.getLocations(dwarf::DW_AT_location);

310 if (!Locations) {

312 return {};

313 }

316 for (auto &Location : *Locations) {

317 DataExtractor Data(Location.Expr, DICtx->isLittleEndian(), AddressSize);

319 for (auto &Op : Expr) {

320 if (Op.getCode() == dwarf::DW_OP_addr)

321 return Op.getRawOperand(0);

322 if (Op.getCode() == dwarf::DW_OP_addrx) {

323 uint64_t Index = Op.getRawOperand(0);

324 if (auto SA = DU.getAddrOffsetSectionItem(Index))

325 return SA->Address;

326 }

327 }

328 }

329 return {};

330}

331

332template

333bool DwarfInstrProfCorrelator::isDIEOfProbe(const DWARFDie &Die) {

334 const auto &ParentDie = Die.getParent();

335 if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())

336 return false;

337 if (Die.getTag() != dwarf::DW_TAG_variable)

338 return false;

339 if (!ParentDie.isSubprogramDIE())

340 return false;

342 return false;

345 return false;

346}

347

348template

349void DwarfInstrProfCorrelator::correlateProfileDataImpl(

351 bool UnlimitedWarnings = (MaxWarnings == 0);

352

353 int NumSuppressedWarnings = -MaxWarnings;

354 auto MaybeAddProbe = [&](DWARFDie Die) {

355 if (!isDIEOfProbe(Die))

356 return;

357 std::optional<const char *> FunctionName;

358 std::optional<uint64_t> CFGHash;

359 std::optional<uint64_t> CounterPtr = getLocation(Die);

361 auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));

364 if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)

365 continue;

366 auto AnnotationFormName = Child.find(dwarf::DW_AT_name);

367 auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);

368 if (!AnnotationFormName || !AnnotationFormValue)

369 continue;

370 auto AnnotationNameOrErr = AnnotationFormName->getAsCString();

371 if (auto Err = AnnotationNameOrErr.takeError()) {

373 continue;

374 }

375 StringRef AnnotationName = *AnnotationNameOrErr;

377 if (auto EC =

378 AnnotationFormValue->getAsCString().moveInto(FunctionName))

381 CFGHash = AnnotationFormValue->getAsUnsignedConstant();

382 } else if (AnnotationName ==

384 NumCounters = AnnotationFormValue->getAsUnsignedConstant();

385 }

386 }

387

388 if (!FunctionPtr && !CounterPtr)

389 return;

390 if (!FunctionName || !CFGHash || !CounterPtr || NumCounters) {

391 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {

393 << "Incomplete DIE for function " << FunctionName

394 << ": CFGHash=" << CFGHash << " CounterPtr=" << CounterPtr

395 << " NumCounters=" << NumCounters << "\n";

397 }

398 return;

399 }

400 uint64_t CountersStart = this->Ctx->CountersSectionStart;

401 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;

402 if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {

403 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {

405 << format("CounterPtr out of range for function %s: Actual=0x%x "

406 "Expected=[0x%x, 0x%x)\n",

407 *FunctionName, *CounterPtr, CountersStart, CountersEnd);

409 }

410 return;

411 }

412 if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {

414 *FunctionName);

416 }

417

418

419 IntPtrT CounterOffset = *CounterPtr - CountersStart;

422 P.FunctionName = *FunctionName;

424 P.LinkageName = Name;

425 P.CFGHash = *CFGHash;

426 P.CounterOffset = CounterOffset;

428 auto FilePath = FnDie.getDeclFile(

430 if (!FilePath.empty())

431 P.FilePath = FilePath;

432 if (auto LineNumber = FnDie.getDeclLine())

433 P.LineNumber = LineNumber;

434 Data->Probes.push_back(P);

435 } else {

437 CounterOffset, FunctionPtr.value_or(0), *NumCounters);

438 this->NamesVec.push_back(*FunctionName);

439 }

440 };

441 for (auto &CU : DICtx->normal_units())

442 for (const auto &Entry : CU->dies())

443 MaybeAddProbe(DWARFDie(CU.get(), &Entry));

444 for (auto &CU : DICtx->dwo_units())

445 for (const auto &Entry : CU->dies())

446 MaybeAddProbe(DWARFDie(CU.get(), &Entry));

447

448 if (!UnlimitedWarnings && NumSuppressedWarnings > 0)

450 NumSuppressedWarnings);

451}

452

453template

454Error DwarfInstrProfCorrelator::correlateProfileNameImpl() {

455 if (this->NamesVec.empty()) {

458 "could not find any profile name metadata in debug info");

459 }

462 false, this->Names);

464}

465

466template

467void BinaryInstrProfCorrelator::correlateProfileDataImpl(

470 bool UnlimitedWarnings = (MaxWarnings == 0);

471

472 int NumSuppressedWarnings = -MaxWarnings;

473

474 const RawProfData *DataStart = (const RawProfData *)this->Ctx->DataStart;

475 const RawProfData *DataEnd = (const RawProfData *)this->Ctx->DataEnd;

476

477 for (const RawProfData *I = DataStart; I < DataEnd; ++I) {

478 uint64_t CounterPtr = this->template maybeSwap(I->CounterPtr);

479 uint64_t CountersStart = this->Ctx->CountersSectionStart;

480 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;

481 if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {

482 if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {

484 << format("CounterPtr out of range for function: Actual=0x%x "

485 "Expected=[0x%x, 0x%x) at data offset=0x%x\n",

486 CounterPtr, CountersStart, CountersEnd,

487 (I - DataStart) * sizeof(RawProfData));

488 }

489 }

490

491

492 IntPtrT CounterOffset = CounterPtr - CountersStart;

493 this->addDataProbe(I->NameRef, I->FuncHash, CounterOffset,

494 I->FunctionPointer, I->NumCounters);

495 }

496}

497

498template

499Error BinaryInstrProfCorrelator::correlateProfileNameImpl() {

500 if (this->Ctx->NameSize == 0) {

503 "could not find any profile data metadata in object file");

504 }

505 this->Names.append(this->Ctx->NameStart, this->Ctx->NameSize);

507}

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

static Expected< object::SectionRef > getInstrProfSection(const object::ObjectFile &Obj, InstrProfSectKind IPSK)

Get profile section.

Definition InstrProfCorrelator.cpp:29

static MemoryLocation getLocation(Instruction *I)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

const T & front() const

front - Get the first element.

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

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.

iterator_range< iterator > children() const

LLVM_ABI DWARFDie getParent() const

Get the parent of this DIE object.

DWARFUnit * getDwarfUnit() const

LLVM_ABI const char * getName(DINameKind Kind) const

Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.

dwarf::Tag getTag() const

LLVM_ABI Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const

bool isNULL() const

Returns true for a valid DIE that terminates a sibling chain.

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.

uint8_t getAddressByteSize() const

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

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)

Definition InstrProfCorrelator.cpp:208

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.

Definition InstrProfCorrelator.cpp:229

static bool classof(const InstrProfCorrelator *C)

InstrProfCorrelatorImpl(std::unique_ptr< InstrProfCorrelator::Context > Ctx)

void addDataProbe(uint64_t FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, IntPtrT FunctionPtr, uint32_t NumCounters)

Definition InstrProfCorrelator.cpp:280

T maybeSwap(T Value) const

Error dumpYaml(int MaxWarnings, raw_ostream &OS) override

Process debug info and dump the correlation data.

Definition InstrProfCorrelator.cpp:266

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.

Definition InstrProfCorrelator.cpp:175

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={})

Definition InstrProfCorrelator.cpp:94

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,...

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

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

static LLVM_ABI raw_ostream & warning()

Convenience method for printing "warning: " to stderr.

BuildIDFetcher searches local cache directories for debug info.

virtual std::optional< std::string > fetch(BuildIDRef BuildID) const

Returns the path to the debug file with the given build ID.

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.

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

void mapOptional(StringRef Key, T &Val)

void mapRequired(StringRef Key, T &Val)

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.

uint64_t ComputeHash(StringRef K)

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.

constexpr bool IsLittleEndianHost

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)

Return the name of the profile section corresponding to IPSK.

StringRef getInstrProfCountersVarPrefix()

Return the name prefix of profile counter variables.

LLVM_ABI raw_ostream & dbgs()

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

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

@ unable_to_correlate_profile

DWARFExpression::Operation Op

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

Convert an ErrorOr to an Expected.

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.

void consumeError(Error Err)

Consume a Error without doing anything.

Implement std::hash so that hash_code can be used in STL containers.

std::unique_ptr< MemoryBuffer > Buffer

static LLVM_ABI llvm::Expected< std::unique_ptr< Context > > get(std::unique_ptr< MemoryBuffer > Buffer, const object::ObjectFile &Obj, ProfCorrelatorKind FileKind)

Definition InstrProfCorrelator.cpp:56

This class should be specialized by any type that needs to be converted to/from a YAML mapping.

This class should be specialized by any type for which vectors of that type need to be converted to/f...

static void mapping(yaml::IO &io, InstrProfCorrelator::CorrelationData &Data)

Definition InstrProfCorrelator.cpp:243

static void mapping(yaml::IO &io, InstrProfCorrelator::Probe &P)

Definition InstrProfCorrelator.cpp:250

static const bool flow

Definition InstrProfCorrelator.cpp:262