1 //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===// 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 // This file contains support for reading profiling data for clang's 10 // instrumentation based PGO and coverage. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ProfileData/InstrProfReader.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/IR/ProfileSummary.h" 20 #include "llvm/ProfileData/InstrProf.h" 21 #include "llvm/ProfileData/MemProf.h" 22 #include "llvm/ProfileData/ProfileCommon.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/ErrorOr.h" 26 #include "llvm/Support/MemoryBuffer.h" 27 #include "llvm/Support/SwapByteOrder.h" 28 #include "llvm/Support/SymbolRemappingReader.h" 29 #include <algorithm> 30 #include <cstddef> 31 #include <cstdint> 32 #include <limits> 33 #include <memory> 34 #include <system_error> 35 #include <utility> 36 #include <vector> 37 38 using namespace llvm; 39 40 // Extracts the variant information from the top 8 bits in the version and 41 // returns an enum specifying the variants present. 42 static InstrProfKind getProfileKindFromVersion(uint64_t Version) { 43 InstrProfKind ProfileKind = InstrProfKind::Unknown; 44 if (Version & VARIANT_MASK_IR_PROF) { 45 ProfileKind |= InstrProfKind::IRInstrumentation; 46 } 47 if (Version & VARIANT_MASK_CSIR_PROF) { 48 ProfileKind |= InstrProfKind::ContextSensitive; 49 } 50 if (Version & VARIANT_MASK_INSTR_ENTRY) { 51 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; 52 } 53 if (Version & VARIANT_MASK_BYTE_COVERAGE) { 54 ProfileKind |= InstrProfKind::SingleByteCoverage; 55 } 56 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) { 57 ProfileKind |= InstrProfKind::FunctionEntryOnly; 58 } 59 if (Version & VARIANT_MASK_MEMPROF) { 60 ProfileKind |= InstrProfKind::MemProf; 61 } 62 return ProfileKind; 63 } 64 65 static Expected<std::unique_ptr<MemoryBuffer>> 66 setupMemoryBuffer(const Twine &Path) { 67 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 68 MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true); 69 if (std::error_code EC = BufferOrErr.getError()) 70 return errorCodeToError(EC); 71 return std::move(BufferOrErr.get()); 72 } 73 74 static Error initializeReader(InstrProfReader &Reader) { 75 return Reader.readHeader(); 76 } 77 78 /// Read a list of binary ids from a profile that consist of 79 /// a. uint64_t binary id length 80 /// b. uint8_t binary id data 81 /// c. uint8_t padding (if necessary) 82 /// This function is shared between raw and indexed profiles. 83 /// Raw profiles are in host-endian format, and indexed profiles are in 84 /// little-endian format. So, this function takes an argument indicating the 85 /// associated endian format to read the binary ids correctly. 86 static Error 87 readBinaryIdsInternal(const MemoryBuffer &DataBuffer, 88 const uint64_t BinaryIdsSize, 89 const uint8_t *BinaryIdsStart, 90 std::vector<llvm::object::BuildID> &BinaryIds, 91 const llvm::support::endianness Endian) { 92 using namespace support; 93 94 if (BinaryIdsSize == 0) 95 return Error::success(); 96 97 const uint8_t *BI = BinaryIdsStart; 98 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize; 99 const uint8_t *End = 100 reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd()); 101 102 while (BI < BIEnd) { 103 size_t Remaining = BIEnd - BI; 104 // There should be enough left to read the binary id length. 105 if (Remaining < sizeof(uint64_t)) 106 return make_error<InstrProfError>( 107 instrprof_error::malformed, 108 "not enough data to read binary id length"); 109 110 uint64_t BILen = 0; 111 if (Endian == little) 112 BILen = endian::readNext<uint64_t, little, unaligned>(BI); 113 else 114 BILen = endian::readNext<uint64_t, big, unaligned>(BI); 115 116 if (BILen == 0) 117 return make_error<InstrProfError>(instrprof_error::malformed, 118 "binary id length is 0"); 119 120 Remaining = BIEnd - BI; 121 // There should be enough left to read the binary id data. 122 if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t))) 123 return make_error<InstrProfError>( 124 instrprof_error::malformed, "not enough data to read binary id data"); 125 126 // Add binary id to the binary ids list. 127 BinaryIds.push_back(object::BuildID(BI, BI + BILen)); 128 129 // Increment by binary id data length, which aligned to the size of uint64. 130 BI += alignToPowerOf2(BILen, sizeof(uint64_t)); 131 if (BI > End) 132 return make_error<InstrProfError>( 133 instrprof_error::malformed, 134 "binary id section is greater than buffer size"); 135 } 136 137 return Error::success(); 138 } 139 140 static Error printBinaryIdsInternal(raw_ostream &OS, 141 const MemoryBuffer &DataBuffer, 142 uint64_t BinaryIdsSize, 143 const uint8_t *BinaryIdsStart, 144 llvm::support::endianness Endian) { 145 if (BinaryIdsSize == 0) 146 return Error::success(); 147 148 std::vector<llvm::object::BuildID> BinaryIds; 149 if (Error E = readBinaryIdsInternal(DataBuffer, BinaryIdsSize, BinaryIdsStart, 150 BinaryIds, Endian)) 151 return E; 152 153 OS << "Binary IDs: \n"; 154 for (auto BI : BinaryIds) { 155 for (uint64_t I = 0; I < BI.size(); I++) 156 OS << format("%02x", BI[I]); 157 OS << "\n"; 158 } 159 160 return Error::success(); 161 } 162 163 Expected<std::unique_ptr<InstrProfReader>> 164 InstrProfReader::create(const Twine &Path, 165 const InstrProfCorrelator *Correlator) { 166 // Set up the buffer to read. 167 auto BufferOrError = setupMemoryBuffer(Path); 168 if (Error E = BufferOrError.takeError()) 169 return std::move(E); 170 return InstrProfReader::create(std::move(BufferOrError.get()), Correlator); 171 } 172 173 Expected<std::unique_ptr<InstrProfReader>> 174 InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer, 175 const InstrProfCorrelator *Correlator) { 176 // Sanity check the buffer. 177 if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max()) 178 return make_error<InstrProfError>(instrprof_error::too_large); 179 180 if (Buffer->getBufferSize() == 0) 181 return make_error<InstrProfError>(instrprof_error::empty_raw_profile); 182 183 std::unique_ptr<InstrProfReader> Result; 184 // Create the reader. 185 if (IndexedInstrProfReader::hasFormat(*Buffer)) 186 Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 187 else if (RawInstrProfReader64::hasFormat(*Buffer)) 188 Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator)); 189 else if (RawInstrProfReader32::hasFormat(*Buffer)) 190 Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator)); 191 else if (TextInstrProfReader::hasFormat(*Buffer)) 192 Result.reset(new TextInstrProfReader(std::move(Buffer))); 193 else 194 return make_error<InstrProfError>(instrprof_error::unrecognized_format); 195 196 // Initialize the reader and return the result. 197 if (Error E = initializeReader(*Result)) 198 return std::move(E); 199 200 return std::move(Result); 201 } 202 203 Expected<std::unique_ptr<IndexedInstrProfReader>> 204 IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) { 205 // Set up the buffer to read. 206 auto BufferOrError = setupMemoryBuffer(Path); 207 if (Error E = BufferOrError.takeError()) 208 return std::move(E); 209 210 // Set up the remapping buffer if requested. 211 std::unique_ptr<MemoryBuffer> RemappingBuffer; 212 std::string RemappingPathStr = RemappingPath.str(); 213 if (!RemappingPathStr.empty()) { 214 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr); 215 if (Error E = RemappingBufferOrError.takeError()) 216 return std::move(E); 217 RemappingBuffer = std::move(RemappingBufferOrError.get()); 218 } 219 220 return IndexedInstrProfReader::create(std::move(BufferOrError.get()), 221 std::move(RemappingBuffer)); 222 } 223 224 Expected<std::unique_ptr<IndexedInstrProfReader>> 225 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer, 226 std::unique_ptr<MemoryBuffer> RemappingBuffer) { 227 if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max()) 228 return make_error<InstrProfError>(instrprof_error::too_large); 229 230 // Create the reader. 231 if (!IndexedInstrProfReader::hasFormat(*Buffer)) 232 return make_error<InstrProfError>(instrprof_error::bad_magic); 233 auto Result = std::make_unique<IndexedInstrProfReader>( 234 std::move(Buffer), std::move(RemappingBuffer)); 235 236 // Initialize the reader and return the result. 237 if (Error E = initializeReader(*Result)) 238 return std::move(E); 239 240 return std::move(Result); 241 } 242 243 bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { 244 // Verify that this really looks like plain ASCII text by checking a 245 // 'reasonable' number of characters (up to profile magic size). 246 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t)); 247 StringRef buffer = Buffer.getBufferStart(); 248 return count == 0 || 249 std::all_of(buffer.begin(), buffer.begin() + count, 250 [](char c) { return isPrint(c) || isSpace(c); }); 251 } 252 253 // Read the profile variant flag from the header: ":FE" means this is a FE 254 // generated profile. ":IR" means this is an IR level profile. Other strings 255 // with a leading ':' will be reported an error format. 256 Error TextInstrProfReader::readHeader() { 257 Symtab.reset(new InstrProfSymtab()); 258 259 while (Line->startswith(":")) { 260 StringRef Str = Line->substr(1); 261 if (Str.equals_insensitive("ir")) 262 ProfileKind |= InstrProfKind::IRInstrumentation; 263 else if (Str.equals_insensitive("fe")) 264 ProfileKind |= InstrProfKind::FrontendInstrumentation; 265 else if (Str.equals_insensitive("csir")) { 266 ProfileKind |= InstrProfKind::IRInstrumentation; 267 ProfileKind |= InstrProfKind::ContextSensitive; 268 } else if (Str.equals_insensitive("entry_first")) 269 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; 270 else if (Str.equals_insensitive("not_entry_first")) 271 ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation; 272 else 273 return error(instrprof_error::bad_header); 274 ++Line; 275 } 276 return success(); 277 } 278 279 Error 280 TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { 281 282 #define CHECK_LINE_END(Line) \ 283 if (Line.is_at_end()) \ 284 return error(instrprof_error::truncated); 285 #define READ_NUM(Str, Dst) \ 286 if ((Str).getAsInteger(10, (Dst))) \ 287 return error(instrprof_error::malformed); 288 #define VP_READ_ADVANCE(Val) \ 289 CHECK_LINE_END(Line); \ 290 uint32_t Val; \ 291 READ_NUM((*Line), (Val)); \ 292 Line++; 293 294 if (Line.is_at_end()) 295 return success(); 296 297 uint32_t NumValueKinds; 298 if (Line->getAsInteger(10, NumValueKinds)) { 299 // No value profile data 300 return success(); 301 } 302 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1) 303 return error(instrprof_error::malformed, 304 "number of value kinds is invalid"); 305 Line++; 306 307 for (uint32_t VK = 0; VK < NumValueKinds; VK++) { 308 VP_READ_ADVANCE(ValueKind); 309 if (ValueKind > IPVK_Last) 310 return error(instrprof_error::malformed, "value kind is invalid"); 311 ; 312 VP_READ_ADVANCE(NumValueSites); 313 if (!NumValueSites) 314 continue; 315 316 Record.reserveSites(VK, NumValueSites); 317 for (uint32_t S = 0; S < NumValueSites; S++) { 318 VP_READ_ADVANCE(NumValueData); 319 320 std::vector<InstrProfValueData> CurrentValues; 321 for (uint32_t V = 0; V < NumValueData; V++) { 322 CHECK_LINE_END(Line); 323 std::pair<StringRef, StringRef> VD = Line->rsplit(':'); 324 uint64_t TakenCount, Value; 325 if (ValueKind == IPVK_IndirectCallTarget) { 326 if (InstrProfSymtab::isExternalSymbol(VD.first)) { 327 Value = 0; 328 } else { 329 if (Error E = Symtab->addFuncName(VD.first)) 330 return E; 331 Value = IndexedInstrProf::ComputeHash(VD.first); 332 } 333 } else { 334 READ_NUM(VD.first, Value); 335 } 336 READ_NUM(VD.second, TakenCount); 337 CurrentValues.push_back({Value, TakenCount}); 338 Line++; 339 } 340 Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData, 341 nullptr); 342 } 343 } 344 return success(); 345 346 #undef CHECK_LINE_END 347 #undef READ_NUM 348 #undef VP_READ_ADVANCE 349 } 350 351 Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 352 // Skip empty lines and comments. 353 while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) 354 ++Line; 355 // If we hit EOF while looking for a name, we're done. 356 if (Line.is_at_end()) { 357 return error(instrprof_error::eof); 358 } 359 360 // Read the function name. 361 Record.Name = *Line++; 362 if (Error E = Symtab->addFuncName(Record.Name)) 363 return error(std::move(E)); 364 365 // Read the function hash. 366 if (Line.is_at_end()) 367 return error(instrprof_error::truncated); 368 if ((Line++)->getAsInteger(0, Record.Hash)) 369 return error(instrprof_error::malformed, 370 "function hash is not a valid integer"); 371 372 // Read the number of counters. 373 uint64_t NumCounters; 374 if (Line.is_at_end()) 375 return error(instrprof_error::truncated); 376 if ((Line++)->getAsInteger(10, NumCounters)) 377 return error(instrprof_error::malformed, 378 "number of counters is not a valid integer"); 379 if (NumCounters == 0) 380 return error(instrprof_error::malformed, "number of counters is zero"); 381 382 // Read each counter and fill our internal storage with the values. 383 Record.Clear(); 384 Record.Counts.reserve(NumCounters); 385 for (uint64_t I = 0; I < NumCounters; ++I) { 386 if (Line.is_at_end()) 387 return error(instrprof_error::truncated); 388 uint64_t Count; 389 if ((Line++)->getAsInteger(10, Count)) 390 return error(instrprof_error::malformed, "count is invalid"); 391 Record.Counts.push_back(Count); 392 } 393 394 // Check if value profile data exists and read it if so. 395 if (Error E = readValueProfileData(Record)) 396 return error(std::move(E)); 397 398 return success(); 399 } 400 401 template <class IntPtrT> 402 InstrProfKind RawInstrProfReader<IntPtrT>::getProfileKind() const { 403 return getProfileKindFromVersion(Version); 404 } 405 406 template <class IntPtrT> 407 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 408 if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 409 return false; 410 uint64_t Magic = 411 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 412 return RawInstrProf::getMagic<IntPtrT>() == Magic || 413 sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; 414 } 415 416 template <class IntPtrT> 417 Error RawInstrProfReader<IntPtrT>::readHeader() { 418 if (!hasFormat(*DataBuffer)) 419 return error(instrprof_error::bad_magic); 420 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)) 421 return error(instrprof_error::bad_header); 422 auto *Header = reinterpret_cast<const RawInstrProf::Header *>( 423 DataBuffer->getBufferStart()); 424 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); 425 return readHeader(*Header); 426 } 427 428 template <class IntPtrT> 429 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 430 const char *End = DataBuffer->getBufferEnd(); 431 // Skip zero padding between profiles. 432 while (CurrentPos != End && *CurrentPos == 0) 433 ++CurrentPos; 434 // If there's nothing left, we're done. 435 if (CurrentPos == End) 436 return make_error<InstrProfError>(instrprof_error::eof); 437 // If there isn't enough space for another header, this is probably just 438 // garbage at the end of the file. 439 if (CurrentPos + sizeof(RawInstrProf::Header) > End) 440 return make_error<InstrProfError>(instrprof_error::malformed, 441 "not enough space for another header"); 442 // The writer ensures each profile is padded to start at an aligned address. 443 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)) 444 return make_error<InstrProfError>(instrprof_error::malformed, 445 "insufficient padding"); 446 // The magic should have the same byte order as in the previous header. 447 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 448 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) 449 return make_error<InstrProfError>(instrprof_error::bad_magic); 450 451 // There's another profile to read, so we need to process the header. 452 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); 453 return readHeader(*Header); 454 } 455 456 template <class IntPtrT> 457 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 458 if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart))) 459 return error(std::move(E)); 460 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 461 const IntPtrT FPtr = swap(I->FunctionPointer); 462 if (!FPtr) 463 continue; 464 Symtab.mapAddress(FPtr, I->NameRef); 465 } 466 return success(); 467 } 468 469 template <class IntPtrT> 470 Error RawInstrProfReader<IntPtrT>::readHeader( 471 const RawInstrProf::Header &Header) { 472 Version = swap(Header.Version); 473 if (GET_VERSION(Version) != RawInstrProf::Version) 474 return error(instrprof_error::unsupported_version); 475 if (useDebugInfoCorrelate() && !Correlator) 476 return error(instrprof_error::missing_debug_info_for_correlation); 477 if (!useDebugInfoCorrelate() && Correlator) 478 return error(instrprof_error::unexpected_debug_info_for_correlation); 479 480 BinaryIdsSize = swap(Header.BinaryIdsSize); 481 if (BinaryIdsSize % sizeof(uint64_t)) 482 return error(instrprof_error::bad_header); 483 484 CountersDelta = swap(Header.CountersDelta); 485 NamesDelta = swap(Header.NamesDelta); 486 auto NumData = swap(Header.DataSize); 487 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters); 488 auto CountersSize = swap(Header.CountersSize) * getCounterTypeSize(); 489 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters); 490 auto NamesSize = swap(Header.NamesSize); 491 ValueKindLast = swap(Header.ValueKindLast); 492 493 auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>); 494 auto PaddingSize = getNumPaddingBytes(NamesSize); 495 496 // Profile data starts after profile header and binary ids if exist. 497 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize; 498 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters; 499 ptrdiff_t NamesOffset = 500 CountersOffset + CountersSize + PaddingBytesAfterCounters; 501 ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; 502 503 auto *Start = reinterpret_cast<const char *>(&Header); 504 if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) 505 return error(instrprof_error::bad_header); 506 507 if (Correlator) { 508 // These sizes in the raw file are zero because we constructed them in the 509 // Correlator. 510 assert(DataSize == 0 && NamesSize == 0); 511 assert(CountersDelta == 0 && NamesDelta == 0); 512 Data = Correlator->getDataPointer(); 513 DataEnd = Data + Correlator->getDataSize(); 514 NamesStart = Correlator->getNamesPointer(); 515 NamesEnd = NamesStart + Correlator->getNamesSize(); 516 } else { 517 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 518 Start + DataOffset); 519 DataEnd = Data + NumData; 520 NamesStart = Start + NamesOffset; 521 NamesEnd = NamesStart + NamesSize; 522 } 523 524 // Binary ids start just after the header. 525 BinaryIdsStart = 526 reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header); 527 CountersStart = Start + CountersOffset; 528 CountersEnd = CountersStart + CountersSize; 529 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 530 531 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd(); 532 if (BinaryIdsStart + BinaryIdsSize > BufferEnd) 533 return error(instrprof_error::bad_header); 534 535 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>(); 536 if (Error E = createSymtab(*NewSymtab)) 537 return E; 538 539 Symtab = std::move(NewSymtab); 540 return success(); 541 } 542 543 template <class IntPtrT> 544 Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { 545 Record.Name = getName(Data->NameRef); 546 return success(); 547 } 548 549 template <class IntPtrT> 550 Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { 551 Record.Hash = swap(Data->FuncHash); 552 return success(); 553 } 554 555 template <class IntPtrT> 556 Error RawInstrProfReader<IntPtrT>::readRawCounts( 557 InstrProfRecord &Record) { 558 uint32_t NumCounters = swap(Data->NumCounters); 559 if (NumCounters == 0) 560 return error(instrprof_error::malformed, "number of counters is zero"); 561 562 ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta; 563 if (CounterBaseOffset < 0) 564 return error( 565 instrprof_error::malformed, 566 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str()); 567 568 if (CounterBaseOffset >= CountersEnd - CountersStart) 569 return error(instrprof_error::malformed, 570 ("counter offset " + Twine(CounterBaseOffset) + 571 " is greater than the maximum counter offset " + 572 Twine(CountersEnd - CountersStart - 1)) 573 .str()); 574 575 uint64_t MaxNumCounters = 576 (CountersEnd - (CountersStart + CounterBaseOffset)) / 577 getCounterTypeSize(); 578 if (NumCounters > MaxNumCounters) 579 return error(instrprof_error::malformed, 580 ("number of counters " + Twine(NumCounters) + 581 " is greater than the maximum number of counters " + 582 Twine(MaxNumCounters)) 583 .str()); 584 585 Record.Counts.clear(); 586 Record.Counts.reserve(NumCounters); 587 for (uint32_t I = 0; I < NumCounters; I++) { 588 const char *Ptr = 589 CountersStart + CounterBaseOffset + I * getCounterTypeSize(); 590 if (hasSingleByteCoverage()) { 591 // A value of zero signifies the block is covered. 592 Record.Counts.push_back(*Ptr == 0 ? 1 : 0); 593 } else { 594 const auto *CounterValue = reinterpret_cast<const uint64_t *>(Ptr); 595 Record.Counts.push_back(swap(*CounterValue)); 596 } 597 } 598 599 return success(); 600 } 601 602 template <class IntPtrT> 603 Error RawInstrProfReader<IntPtrT>::readValueProfilingData( 604 InstrProfRecord &Record) { 605 Record.clearValueData(); 606 CurValueDataSize = 0; 607 // Need to match the logic in value profile dumper code in compiler-rt: 608 uint32_t NumValueKinds = 0; 609 for (uint32_t I = 0; I < IPVK_Last + 1; I++) 610 NumValueKinds += (Data->NumValueSites[I] != 0); 611 612 if (!NumValueKinds) 613 return success(); 614 615 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 616 ValueProfData::getValueProfData( 617 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), 618 getDataEndianness()); 619 620 if (Error E = VDataPtrOrErr.takeError()) 621 return E; 622 623 // Note that besides deserialization, this also performs the conversion for 624 // indirect call targets. The function pointers from the raw profile are 625 // remapped into function name hashes. 626 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get()); 627 CurValueDataSize = VDataPtrOrErr.get()->getSize(); 628 return success(); 629 } 630 631 template <class IntPtrT> 632 Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { 633 // Keep reading profiles that consist of only headers and no profile data and 634 // counters. 635 while (atEnd()) 636 // At this point, ValueDataStart field points to the next header. 637 if (Error E = readNextHeader(getNextHeaderPos())) 638 return error(std::move(E)); 639 640 // Read name ad set it in Record. 641 if (Error E = readName(Record)) 642 return error(std::move(E)); 643 644 // Read FuncHash and set it in Record. 645 if (Error E = readFuncHash(Record)) 646 return error(std::move(E)); 647 648 // Read raw counts and set Record. 649 if (Error E = readRawCounts(Record)) 650 return error(std::move(E)); 651 652 // Read value data and set Record. 653 if (Error E = readValueProfilingData(Record)) 654 return error(std::move(E)); 655 656 // Iterate. 657 advanceData(); 658 return success(); 659 } 660 661 template <class IntPtrT> 662 Error RawInstrProfReader<IntPtrT>::readBinaryIds( 663 std::vector<llvm::object::BuildID> &BinaryIds) { 664 return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart, 665 BinaryIds, getDataEndianness()); 666 } 667 668 template <class IntPtrT> 669 Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) { 670 return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart, 671 getDataEndianness()); 672 } 673 674 namespace llvm { 675 676 template class RawInstrProfReader<uint32_t>; 677 template class RawInstrProfReader<uint64_t>; 678 679 } // end namespace llvm 680 681 InstrProfLookupTrait::hash_value_type 682 InstrProfLookupTrait::ComputeHash(StringRef K) { 683 return IndexedInstrProf::ComputeHash(HashType, K); 684 } 685 686 using data_type = InstrProfLookupTrait::data_type; 687 using offset_type = InstrProfLookupTrait::offset_type; 688 689 bool InstrProfLookupTrait::readValueProfilingData( 690 const unsigned char *&D, const unsigned char *const End) { 691 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 692 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 693 694 if (VDataPtrOrErr.takeError()) 695 return false; 696 697 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 698 D += VDataPtrOrErr.get()->TotalSize; 699 700 return true; 701 } 702 703 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 704 offset_type N) { 705 using namespace support; 706 707 // Check if the data is corrupt. If so, don't try to read it. 708 if (N % sizeof(uint64_t)) 709 return data_type(); 710 711 DataBuffer.clear(); 712 std::vector<uint64_t> CounterBuffer; 713 714 const unsigned char *End = D + N; 715 while (D < End) { 716 // Read hash. 717 if (D + sizeof(uint64_t) >= End) 718 return data_type(); 719 uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); 720 721 // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 722 uint64_t CountsSize = N / sizeof(uint64_t) - 1; 723 // If format version is different then read the number of counters. 724 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 725 if (D + sizeof(uint64_t) > End) 726 return data_type(); 727 CountsSize = endian::readNext<uint64_t, little, unaligned>(D); 728 } 729 // Read counter values. 730 if (D + CountsSize * sizeof(uint64_t) > End) 731 return data_type(); 732 733 CounterBuffer.clear(); 734 CounterBuffer.reserve(CountsSize); 735 for (uint64_t J = 0; J < CountsSize; ++J) 736 CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); 737 738 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); 739 740 // Read value profiling data. 741 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 742 !readValueProfilingData(D, End)) { 743 DataBuffer.clear(); 744 return data_type(); 745 } 746 } 747 return DataBuffer; 748 } 749 750 template <typename HashTableImpl> 751 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 752 StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) { 753 auto Iter = HashTable->find(FuncName); 754 if (Iter == HashTable->end()) 755 return make_error<InstrProfError>(instrprof_error::unknown_function); 756 757 Data = (*Iter); 758 if (Data.empty()) 759 return make_error<InstrProfError>(instrprof_error::malformed, 760 "profile data is empty"); 761 762 return Error::success(); 763 } 764 765 template <typename HashTableImpl> 766 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 767 ArrayRef<NamedInstrProfRecord> &Data) { 768 if (atEnd()) 769 return make_error<InstrProfError>(instrprof_error::eof); 770 771 Data = *RecordIterator; 772 773 if (Data.empty()) 774 return make_error<InstrProfError>(instrprof_error::malformed, 775 "profile data is empty"); 776 777 return Error::success(); 778 } 779 780 template <typename HashTableImpl> 781 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 782 const unsigned char *Buckets, const unsigned char *const Payload, 783 const unsigned char *const Base, IndexedInstrProf::HashT HashType, 784 uint64_t Version) { 785 FormatVersion = Version; 786 HashTable.reset(HashTableImpl::Create( 787 Buckets, Payload, Base, 788 typename HashTableImpl::InfoType(HashType, Version))); 789 RecordIterator = HashTable->data_begin(); 790 } 791 792 template <typename HashTableImpl> 793 InstrProfKind InstrProfReaderIndex<HashTableImpl>::getProfileKind() const { 794 return getProfileKindFromVersion(FormatVersion); 795 } 796 797 namespace { 798 /// A remapper that does not apply any remappings. 799 class InstrProfReaderNullRemapper : public InstrProfReaderRemapper { 800 InstrProfReaderIndexBase &Underlying; 801 802 public: 803 InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying) 804 : Underlying(Underlying) {} 805 806 Error getRecords(StringRef FuncName, 807 ArrayRef<NamedInstrProfRecord> &Data) override { 808 return Underlying.getRecords(FuncName, Data); 809 } 810 }; 811 } // namespace 812 813 /// A remapper that applies remappings based on a symbol remapping file. 814 template <typename HashTableImpl> 815 class llvm::InstrProfReaderItaniumRemapper 816 : public InstrProfReaderRemapper { 817 public: 818 InstrProfReaderItaniumRemapper( 819 std::unique_ptr<MemoryBuffer> RemapBuffer, 820 InstrProfReaderIndex<HashTableImpl> &Underlying) 821 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) { 822 } 823 824 /// Extract the original function name from a PGO function name. 825 static StringRef extractName(StringRef Name) { 826 // We can have multiple :-separated pieces; there can be pieces both 827 // before and after the mangled name. Find the first part that starts 828 // with '_Z'; we'll assume that's the mangled name we want. 829 std::pair<StringRef, StringRef> Parts = {StringRef(), Name}; 830 while (true) { 831 Parts = Parts.second.split(':'); 832 if (Parts.first.startswith("_Z")) 833 return Parts.first; 834 if (Parts.second.empty()) 835 return Name; 836 } 837 } 838 839 /// Given a mangled name extracted from a PGO function name, and a new 840 /// form for that mangled name, reconstitute the name. 841 static void reconstituteName(StringRef OrigName, StringRef ExtractedName, 842 StringRef Replacement, 843 SmallVectorImpl<char> &Out) { 844 Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size()); 845 Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin()); 846 Out.insert(Out.end(), Replacement.begin(), Replacement.end()); 847 Out.insert(Out.end(), ExtractedName.end(), OrigName.end()); 848 } 849 850 Error populateRemappings() override { 851 if (Error E = Remappings.read(*RemapBuffer)) 852 return E; 853 for (StringRef Name : Underlying.HashTable->keys()) { 854 StringRef RealName = extractName(Name); 855 if (auto Key = Remappings.insert(RealName)) { 856 // FIXME: We could theoretically map the same equivalence class to 857 // multiple names in the profile data. If that happens, we should 858 // return NamedInstrProfRecords from all of them. 859 MappedNames.insert({Key, RealName}); 860 } 861 } 862 return Error::success(); 863 } 864 865 Error getRecords(StringRef FuncName, 866 ArrayRef<NamedInstrProfRecord> &Data) override { 867 StringRef RealName = extractName(FuncName); 868 if (auto Key = Remappings.lookup(RealName)) { 869 StringRef Remapped = MappedNames.lookup(Key); 870 if (!Remapped.empty()) { 871 if (RealName.begin() == FuncName.begin() && 872 RealName.end() == FuncName.end()) 873 FuncName = Remapped; 874 else { 875 // Try rebuilding the name from the given remapping. 876 SmallString<256> Reconstituted; 877 reconstituteName(FuncName, RealName, Remapped, Reconstituted); 878 Error E = Underlying.getRecords(Reconstituted, Data); 879 if (!E) 880 return E; 881 882 // If we failed because the name doesn't exist, fall back to asking 883 // about the original name. 884 if (Error Unhandled = handleErrors( 885 std::move(E), [](std::unique_ptr<InstrProfError> Err) { 886 return Err->get() == instrprof_error::unknown_function 887 ? Error::success() 888 : Error(std::move(Err)); 889 })) 890 return Unhandled; 891 } 892 } 893 } 894 return Underlying.getRecords(FuncName, Data); 895 } 896 897 private: 898 /// The memory buffer containing the remapping configuration. Remappings 899 /// holds pointers into this buffer. 900 std::unique_ptr<MemoryBuffer> RemapBuffer; 901 902 /// The mangling remapper. 903 SymbolRemappingReader Remappings; 904 905 /// Mapping from mangled name keys to the name used for the key in the 906 /// profile data. 907 /// FIXME: Can we store a location within the on-disk hash table instead of 908 /// redoing lookup? 909 DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames; 910 911 /// The real profile data reader. 912 InstrProfReaderIndex<HashTableImpl> &Underlying; 913 }; 914 915 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 916 using namespace support; 917 918 if (DataBuffer.getBufferSize() < 8) 919 return false; 920 uint64_t Magic = 921 endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 922 // Verify that it's magical. 923 return Magic == IndexedInstrProf::Magic; 924 } 925 926 const unsigned char * 927 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 928 const unsigned char *Cur, bool UseCS) { 929 using namespace IndexedInstrProf; 930 using namespace support; 931 932 if (Version >= IndexedInstrProf::Version4) { 933 const IndexedInstrProf::Summary *SummaryInLE = 934 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 935 uint64_t NFields = 936 endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); 937 uint64_t NEntries = 938 endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); 939 uint32_t SummarySize = 940 IndexedInstrProf::Summary::getSize(NFields, NEntries); 941 std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 942 IndexedInstrProf::allocSummary(SummarySize); 943 944 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 945 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 946 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 947 Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); 948 949 SummaryEntryVector DetailedSummary; 950 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) { 951 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); 952 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, 953 Ent.NumBlocks); 954 } 955 std::unique_ptr<llvm::ProfileSummary> &Summary = 956 UseCS ? this->CS_Summary : this->Summary; 957 958 // initialize InstrProfSummary using the SummaryData from disk. 959 Summary = std::make_unique<ProfileSummary>( 960 UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr, 961 DetailedSummary, SummaryData->get(Summary::TotalBlockCount), 962 SummaryData->get(Summary::MaxBlockCount), 963 SummaryData->get(Summary::MaxInternalBlockCount), 964 SummaryData->get(Summary::MaxFunctionCount), 965 SummaryData->get(Summary::TotalNumBlocks), 966 SummaryData->get(Summary::TotalNumFunctions)); 967 return Cur + SummarySize; 968 } else { 969 // The older versions do not support a profile summary. This just computes 970 // an empty summary, which will not result in accurate hot/cold detection. 971 // We would need to call addRecord for all NamedInstrProfRecords to get the 972 // correct summary. However, this version is old (prior to early 2016) and 973 // has not been supporting an accurate summary for several years. 974 InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); 975 Summary = Builder.getSummary(); 976 return Cur; 977 } 978 } 979 980 Error IndexedInstrProfReader::readHeader() { 981 using namespace support; 982 983 const unsigned char *Start = 984 (const unsigned char *)DataBuffer->getBufferStart(); 985 const unsigned char *Cur = Start; 986 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 987 return error(instrprof_error::truncated); 988 989 auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start); 990 if (!HeaderOr) 991 return HeaderOr.takeError(); 992 993 const IndexedInstrProf::Header *Header = &HeaderOr.get(); 994 Cur += Header->size(); 995 996 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur, 997 /* UseCS */ false); 998 if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF) 999 Cur = 1000 readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur, 1001 /* UseCS */ true); 1002 // Read the hash type and start offset. 1003 IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 1004 endian::byte_swap<uint64_t, little>(Header->HashType)); 1005 if (HashType > IndexedInstrProf::HashT::Last) 1006 return error(instrprof_error::unsupported_hash_type); 1007 1008 uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); 1009 1010 // The hash table with profile counts comes next. 1011 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>( 1012 Start + HashOffset, Cur, Start, HashType, Header->formatVersion()); 1013 1014 // The MemProfOffset field in the header is only valid when the format 1015 // version is higher than 8 (when it was introduced). 1016 if (GET_VERSION(Header->formatVersion()) >= 8 && 1017 Header->formatVersion() & VARIANT_MASK_MEMPROF) { 1018 uint64_t MemProfOffset = 1019 endian::byte_swap<uint64_t, little>(Header->MemProfOffset); 1020 1021 const unsigned char *Ptr = Start + MemProfOffset; 1022 // The value returned from RecordTableGenerator.Emit. 1023 const uint64_t RecordTableOffset = 1024 support::endian::readNext<uint64_t, little, unaligned>(Ptr); 1025 // The offset in the stream right before invoking 1026 // FrameTableGenerator.Emit. 1027 const uint64_t FramePayloadOffset = 1028 support::endian::readNext<uint64_t, little, unaligned>(Ptr); 1029 // The value returned from FrameTableGenerator.Emit. 1030 const uint64_t FrameTableOffset = 1031 support::endian::readNext<uint64_t, little, unaligned>(Ptr); 1032 1033 // Read the schema. 1034 auto SchemaOr = memprof::readMemProfSchema(Ptr); 1035 if (!SchemaOr) 1036 return SchemaOr.takeError(); 1037 Schema = SchemaOr.get(); 1038 1039 // Now initialize the table reader with a pointer into data buffer. 1040 MemProfRecordTable.reset(MemProfRecordHashTable::Create( 1041 /*Buckets=*/Start + RecordTableOffset, 1042 /*Payload=*/Ptr, 1043 /*Base=*/Start, memprof::RecordLookupTrait(Schema))); 1044 1045 // Initialize the frame table reader with the payload and bucket offsets. 1046 MemProfFrameTable.reset(MemProfFrameHashTable::Create( 1047 /*Buckets=*/Start + FrameTableOffset, 1048 /*Payload=*/Start + FramePayloadOffset, 1049 /*Base=*/Start, memprof::FrameLookupTrait())); 1050 } 1051 1052 // BinaryIdOffset field in the header is only valid when the format version 1053 // is higher than 9 (when it was introduced). 1054 if (GET_VERSION(Header->formatVersion()) >= 9) { 1055 uint64_t BinaryIdOffset = 1056 endian::byte_swap<uint64_t, little>(Header->BinaryIdOffset); 1057 const unsigned char *Ptr = Start + BinaryIdOffset; 1058 // Read binary ids size. 1059 BinaryIdsSize = support::endian::readNext<uint64_t, little, unaligned>(Ptr); 1060 if (BinaryIdsSize % sizeof(uint64_t)) 1061 return error(instrprof_error::bad_header); 1062 // Set the binary ids start. 1063 BinaryIdsStart = Ptr; 1064 if (BinaryIdsStart > (const unsigned char *)DataBuffer->getBufferEnd()) 1065 return make_error<InstrProfError>(instrprof_error::malformed, 1066 "corrupted binary ids"); 1067 } 1068 1069 // Load the remapping table now if requested. 1070 if (RemappingBuffer) { 1071 Remapper = 1072 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>( 1073 std::move(RemappingBuffer), *IndexPtr); 1074 if (Error E = Remapper->populateRemappings()) 1075 return E; 1076 } else { 1077 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr); 1078 } 1079 Index = std::move(IndexPtr); 1080 1081 return success(); 1082 } 1083 1084 InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 1085 if (Symtab) 1086 return *Symtab; 1087 1088 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>(); 1089 if (Error E = Index->populateSymtab(*NewSymtab)) { 1090 consumeError(error(InstrProfError::take(std::move(E)))); 1091 } 1092 1093 Symtab = std::move(NewSymtab); 1094 return *Symtab; 1095 } 1096 1097 Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord( 1098 StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum) { 1099 ArrayRef<NamedInstrProfRecord> Data; 1100 uint64_t FuncSum = 0; 1101 Error Err = Remapper->getRecords(FuncName, Data); 1102 if (Err) 1103 return std::move(Err); 1104 // Found it. Look for counters with the right hash. 1105 1106 // A flag to indicate if the records are from the same type 1107 // of profile (i.e cs vs nocs). 1108 bool CSBitMatch = false; 1109 auto getFuncSum = [](const std::vector<uint64_t> &Counts) { 1110 uint64_t ValueSum = 0; 1111 for (uint64_t CountValue : Counts) { 1112 if (CountValue == (uint64_t)-1) 1113 continue; 1114 // Handle overflow -- if that happens, return max. 1115 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum) 1116 return std::numeric_limits<uint64_t>::max(); 1117 ValueSum += CountValue; 1118 } 1119 return ValueSum; 1120 }; 1121 1122 for (const NamedInstrProfRecord &I : Data) { 1123 // Check for a match and fill the vector if there is one. 1124 if (I.Hash == FuncHash) 1125 return std::move(I); 1126 if (NamedInstrProfRecord::hasCSFlagInHash(I.Hash) == 1127 NamedInstrProfRecord::hasCSFlagInHash(FuncHash)) { 1128 CSBitMatch = true; 1129 if (MismatchedFuncSum == nullptr) 1130 continue; 1131 FuncSum = std::max(FuncSum, getFuncSum(I.Counts)); 1132 } 1133 } 1134 if (CSBitMatch) { 1135 if (MismatchedFuncSum != nullptr) 1136 *MismatchedFuncSum = FuncSum; 1137 return error(instrprof_error::hash_mismatch); 1138 } 1139 return error(instrprof_error::unknown_function); 1140 } 1141 1142 Expected<memprof::MemProfRecord> 1143 IndexedInstrProfReader::getMemProfRecord(const uint64_t FuncNameHash) { 1144 // TODO: Add memprof specific errors. 1145 if (MemProfRecordTable == nullptr) 1146 return make_error<InstrProfError>(instrprof_error::invalid_prof, 1147 "no memprof data available in profile"); 1148 auto Iter = MemProfRecordTable->find(FuncNameHash); 1149 if (Iter == MemProfRecordTable->end()) 1150 return make_error<InstrProfError>( 1151 instrprof_error::unknown_function, 1152 "memprof record not found for function hash " + Twine(FuncNameHash)); 1153 1154 // Setup a callback to convert from frame ids to frame using the on-disk 1155 // FrameData hash table. 1156 memprof::FrameId LastUnmappedFrameId = 0; 1157 bool HasFrameMappingError = false; 1158 auto IdToFrameCallback = [&](const memprof::FrameId Id) { 1159 auto FrIter = MemProfFrameTable->find(Id); 1160 if (FrIter == MemProfFrameTable->end()) { 1161 LastUnmappedFrameId = Id; 1162 HasFrameMappingError = true; 1163 return memprof::Frame(0, 0, 0, false); 1164 } 1165 return *FrIter; 1166 }; 1167 1168 memprof::MemProfRecord Record(*Iter, IdToFrameCallback); 1169 1170 // Check that all frame ids were successfully converted to frames. 1171 if (HasFrameMappingError) { 1172 return make_error<InstrProfError>(instrprof_error::hash_mismatch, 1173 "memprof frame not found for frame id " + 1174 Twine(LastUnmappedFrameId)); 1175 } 1176 return Record; 1177 } 1178 1179 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, 1180 uint64_t FuncHash, 1181 std::vector<uint64_t> &Counts) { 1182 Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 1183 if (Error E = Record.takeError()) 1184 return error(std::move(E)); 1185 1186 Counts = Record.get().Counts; 1187 return success(); 1188 } 1189 1190 Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 1191 ArrayRef<NamedInstrProfRecord> Data; 1192 1193 Error E = Index->getRecords(Data); 1194 if (E) 1195 return error(std::move(E)); 1196 1197 Record = Data[RecordIndex++]; 1198 if (RecordIndex >= Data.size()) { 1199 Index->advanceToNextKey(); 1200 RecordIndex = 0; 1201 } 1202 return success(); 1203 } 1204 1205 Error IndexedInstrProfReader::readBinaryIds( 1206 std::vector<llvm::object::BuildID> &BinaryIds) { 1207 return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart, 1208 BinaryIds, llvm::support::little); 1209 } 1210 1211 Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) { 1212 return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart, 1213 llvm::support::little); 1214 } 1215 1216 void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) { 1217 uint64_t NumFuncs = 0; 1218 for (const auto &Func : *this) { 1219 if (isIRLevelProfile()) { 1220 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash); 1221 if (FuncIsCS != IsCS) 1222 continue; 1223 } 1224 Func.accumulateCounts(Sum); 1225 ++NumFuncs; 1226 } 1227 Sum.NumEntries = NumFuncs; 1228 } 1229